mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
refactor: canonicalize aliases and classify test suites (#122407)
* refactor: use canonical re-export names * fix(test): classify suite support as test source * fix(agents): retarget gateway stub session-entry import * test(gateway): retarget session-utils mock keys after alias removal
This commit is contained in:
committed by
GitHub
parent
6b0be0215f
commit
f6fff4f7fd
+9
-16
@@ -262,8 +262,8 @@
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"**/*.test.ts",
|
||||
"**/*.test.tsx",
|
||||
"**/*.{test,suite}.ts",
|
||||
"**/*.{test,suite}.tsx",
|
||||
"**/*.e2e.test.ts",
|
||||
"**/*.live.test.ts",
|
||||
"**/*test-harness.ts",
|
||||
@@ -282,8 +282,7 @@
|
||||
"extensions/**/*.{js,ts,mts,cts}"
|
||||
],
|
||||
"excludeFiles": [
|
||||
"**/*.test.*",
|
||||
"**/*.spec.*",
|
||||
"**/*.{test,spec,suite}.*",
|
||||
"**/__generated__/**",
|
||||
"**/generated/**",
|
||||
"**/protocol-gen/**",
|
||||
@@ -304,8 +303,7 @@
|
||||
"extensions/**/*.{jsx,tsx}"
|
||||
],
|
||||
"excludeFiles": [
|
||||
"**/*.test.*",
|
||||
"**/*.spec.*",
|
||||
"**/*.{test,spec,suite}.*",
|
||||
"**/__generated__/**",
|
||||
"**/generated/**",
|
||||
"**/protocol-gen/**",
|
||||
@@ -326,8 +324,7 @@
|
||||
"extensions/**/*.{mjs,cjs}"
|
||||
],
|
||||
"excludeFiles": [
|
||||
"**/*.test.*",
|
||||
"**/*.spec.*",
|
||||
"**/*.{test,spec,suite}.*",
|
||||
"**/__generated__/**",
|
||||
"**/generated/**",
|
||||
"**/protocol-gen/**",
|
||||
@@ -342,14 +339,10 @@
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"src/**/*.test.*",
|
||||
"src/**/*.spec.*",
|
||||
"ui/src/**/*.test.*",
|
||||
"ui/src/**/*.spec.*",
|
||||
"packages/**/*.test.*",
|
||||
"packages/**/*.spec.*",
|
||||
"extensions/**/*.test.*",
|
||||
"extensions/**/*.spec.*"
|
||||
"src/**/*.{test,spec,suite}.*",
|
||||
"ui/src/**/*.{test,spec,suite}.*",
|
||||
"packages/**/*.{test,spec,suite}.*",
|
||||
"extensions/**/*.{test,spec,suite}.*"
|
||||
],
|
||||
"excludeFiles": [
|
||||
"**/__generated__/**",
|
||||
|
||||
@@ -23,9 +23,9 @@ const SURFACE_PATTERNS = [
|
||||
["legacyRootAsset", /^assets\//u],
|
||||
];
|
||||
const CHANGED_LANE_TEST_PATH_RE =
|
||||
/(?:^|\/)(?:test|__tests__)\/|(?:\.|\/)(?:test|spec|e2e|browser\.test)\.[cm]?[jt]sx?$|(?:^|\/)[^/]+\.test-(?:helpers|support)\.[cm]?[jt]sx?$/u;
|
||||
/(?:^|\/)(?:test|__tests__)\/|(?:\.|\/)(?:test|spec|suite|e2e|browser\.test)\.[cm]?[jt]sx?$|(?:^|\/)[^/]+\.test-(?:helpers|support)\.[cm]?[jt]sx?$/u;
|
||||
const TEST_ONLY_PATH_RE =
|
||||
/(^test\/|\/test\/|\/tests\/|(?:^|\/)[^/]+\.(?:test|spec|test-utils|test-(?:helpers|support|harness)|e2e-harness)\.[cm]?[jt]sx?$)/u;
|
||||
/(^test\/|\/test\/|\/tests\/|(?:^|\/)[^/]+\.(?:test|spec|suite|test-utils|test-(?:helpers|support|harness)|e2e-harness)\.[cm]?[jt]sx?$)/u;
|
||||
const NATIVE_ONLY_PATH_RE =
|
||||
/^(?:apps\/android\/|apps\/ios\/|apps\/macos\/|apps\/macos-mlx-tts\/|apps\/shared\/|apps\/swabble\/|Swabble\/|appcast\.xml$)/u;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
findUnmatchedExplicitTestTargets,
|
||||
hasImportGraphImpactOnTargets,
|
||||
isTestFileTarget,
|
||||
isTestSupportFileTarget,
|
||||
resolveChangedTestTargetPlan,
|
||||
} from "../test-projects.test-support.mts";
|
||||
import {
|
||||
@@ -53,7 +54,11 @@ const splitNodeTestConfigs = new Set(
|
||||
);
|
||||
|
||||
function isTestOnlyPath(changedPath: string) {
|
||||
return isTestFileTarget(changedPath) || changedPath.startsWith("test/");
|
||||
return (
|
||||
isTestFileTarget(changedPath) ||
|
||||
isTestSupportFileTarget(changedPath) ||
|
||||
changedPath.startsWith("test/")
|
||||
);
|
||||
}
|
||||
|
||||
// Inputs `build:ci-artifacts` consumes: runtime/plugin/package sources plus
|
||||
|
||||
@@ -1000,12 +1000,12 @@ export function isTestFileTarget(arg: string) {
|
||||
return /\.(?:test|spec)\.[cm]?[jt]sx?$/u.test(arg);
|
||||
}
|
||||
|
||||
function isTestSupportFileTarget(arg: string) {
|
||||
export function isTestSupportFileTarget(arg: string) {
|
||||
if (/(?:^|\/)(?:test-helpers|test-support)(?:\/|$)/u.test(arg)) {
|
||||
return true;
|
||||
}
|
||||
const basename = path.posix.basename(arg).replace(/\.[cm]?[jt]sx?$/u, "");
|
||||
return /(?:^|[._-])test-(?:helpers|support)(?:[._-]|$)/u.test(basename);
|
||||
return /(?:^|[._-])(?:suite|test-(?:helpers|support))(?:[._-]|$)/u.test(basename);
|
||||
}
|
||||
|
||||
function isLikelyFileTarget(arg: string) {
|
||||
|
||||
@@ -34,7 +34,7 @@ export {
|
||||
export {
|
||||
listSessionsFromStoreAsync,
|
||||
loadCombinedSessionStoreForGatewayCore,
|
||||
loadSessionEntryReadOnly as loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly as loadSessionEntry,
|
||||
resolveSessionModelRef,
|
||||
} from "../../gateway/session-utils.js";
|
||||
export { resolveSessionKeyFromResolveParams } from "../../gateway/sessions-resolve.js";
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
type SessionPullRequestGitContext,
|
||||
type SessionPullRequestLocalGitDeps,
|
||||
} from "./control-ui-session-prs-local-git.js";
|
||||
import { loadSessionEntryReadOnly } from "./session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "./session-utils.js";
|
||||
|
||||
const SUCCESS_CACHE_MS = 60_000;
|
||||
// Back off refetches while GitHub reports quota exhaustion; the UI keeps
|
||||
@@ -94,9 +94,12 @@ type LoadSessionPullRequestDeps = SessionPullRequestLocalGitDeps & {
|
||||
function resolveSessionPullRequestGitRoot(
|
||||
params: ControlUiSessionPullRequestsParams,
|
||||
): string | null {
|
||||
const { cfg, entry, storePath, canonicalKey } = loadSessionEntryReadOnly(params.sessionKey, {
|
||||
const { cfg, entry, storePath, canonicalKey } = loadGatewaySessionEntryReadOnly(
|
||||
params.sessionKey,
|
||||
{
|
||||
agentId: params.agentId,
|
||||
});
|
||||
},
|
||||
);
|
||||
// Same session/agent scoping as sessions.files.*: a missing entry means an
|
||||
// unknown or deleted session, which must not fall back to some agent
|
||||
// workspace and surface another checkout's PRs.
|
||||
|
||||
@@ -67,7 +67,7 @@ vi.mock("./http-utils.js", () => ({
|
||||
|
||||
vi.mock("./session-utils.js", () => ({
|
||||
loadSessionEntry: loadSessionEntryMock,
|
||||
loadSessionEntryReadOnly: loadSessionEntryMock,
|
||||
loadGatewaySessionEntryReadOnly: loadSessionEntryMock,
|
||||
resolveSessionHistoryTranscriptPathAsync: resolveSessionHistoryTranscriptPathMock,
|
||||
}));
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ import {
|
||||
import { authorizeOperatorScopesForMethod } from "./method-scopes.js";
|
||||
import { readSessionMessagesWithSourceAsync } from "./session-transcript-readers.js";
|
||||
import {
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
resolveSessionHistoryTranscriptPathAsync,
|
||||
} from "./session-utils.js";
|
||||
|
||||
@@ -974,7 +974,7 @@ async function getSessionManagedOutgoingAttachmentIndex(
|
||||
}
|
||||
const usesRuntimeState = !stateDir || path.resolve(stateDir) === path.resolve(resolveStateDir());
|
||||
const env = stateDir ? { ...process.env, OPENCLAW_STATE_DIR: stateDir } : process.env;
|
||||
type SessionEntry = ReturnType<typeof loadSessionEntryReadOnly>["entry"];
|
||||
type SessionEntry = ReturnType<typeof loadGatewaySessionEntryReadOnly>["entry"];
|
||||
let matched: { entry: NonNullable<SessionEntry>; storePath: string } | undefined;
|
||||
for (const target of discovery.targets) {
|
||||
const exact = loadExactSessionEntryReadOnlyResult({
|
||||
@@ -1014,7 +1014,7 @@ async function getSessionManagedOutgoingAttachmentIndex(
|
||||
let entry: SessionEntry = matched?.entry;
|
||||
let storePath = matched?.storePath ?? discovery.targets[0]?.storePath ?? "";
|
||||
if (!entry && usesRuntimeState) {
|
||||
const loaded = loadSessionEntryReadOnly(sessionKey, { agentId: ownerAgentId });
|
||||
const loaded = loadGatewaySessionEntryReadOnly(sessionKey, { agentId: ownerAgentId });
|
||||
const exact = loadExactSessionEntryReadOnlyResult({
|
||||
agentId: ownerAgentId,
|
||||
clone: false,
|
||||
|
||||
@@ -30,7 +30,7 @@ vi.mock("./session-transcript-readers.js", () => ({
|
||||
}));
|
||||
vi.mock("./session-utils.js", () => ({
|
||||
loadSessionEntry: mocks.loadSessionEntry,
|
||||
loadSessionEntryReadOnly: mocks.loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: mocks.loadSessionEntry,
|
||||
}));
|
||||
|
||||
import { mintMcpAppViewFromTranscript, restoreMcpAppView } from "./mcp-app-reconstruction.js";
|
||||
|
||||
@@ -14,7 +14,7 @@ import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
|
||||
import { getOrCreatePromise } from "../shared/lazy-promise.js";
|
||||
import { visitSessionMessagesAsync } from "./session-transcript-readers.js";
|
||||
import { loadSessionEntryReadOnly } from "./session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "./session-utils.js";
|
||||
|
||||
const MCP_APP_RESTORE_IN_FLIGHT_KEY = Symbol.for("openclaw.mcpAppRestoreInFlight");
|
||||
|
||||
@@ -252,7 +252,7 @@ async function reconstructMcpAppView(params: {
|
||||
viewId?: string;
|
||||
}): Promise<ReconstructionResult | undefined> {
|
||||
const agentId = resolveAgentIdFromSessionKey(params.sessionKey);
|
||||
const loaded = loadSessionEntryReadOnly(params.sessionKey, { agentId });
|
||||
const loaded = loadGatewaySessionEntryReadOnly(params.sessionKey, { agentId });
|
||||
const sessionId = loaded.entry?.sessionId;
|
||||
if (!sessionId) {
|
||||
return undefined;
|
||||
|
||||
@@ -75,7 +75,7 @@ vi.mock("./session-utils.js", () => {
|
||||
}));
|
||||
return {
|
||||
loadSessionEntry,
|
||||
loadSessionEntryReadOnly: loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: loadSessionEntry,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ import {
|
||||
resolveSessionSubscriptionKey,
|
||||
resolveSessionSubscriptionKeys,
|
||||
} from "./session-subscription-keys.js";
|
||||
import { loadSessionEntryReadOnly } from "./session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "./session-utils.js";
|
||||
import { formatForLog } from "./ws-log.js";
|
||||
|
||||
export {
|
||||
@@ -522,7 +522,7 @@ export function createAgentEventHandler({
|
||||
event: AgentEventPayload,
|
||||
): { suppress: boolean } => {
|
||||
try {
|
||||
const { entry } = loadSessionEntryReadOnly(sessionKey, {
|
||||
const { entry } = loadGatewaySessionEntryReadOnly(sessionKey, {
|
||||
...(agentId ? { agentId } : {}),
|
||||
clone: false,
|
||||
});
|
||||
@@ -1341,7 +1341,7 @@ export function createAgentEventHandler({
|
||||
return runVerbose ?? "off";
|
||||
}
|
||||
try {
|
||||
const { cfg, entry } = loadSessionEntryReadOnly(sessionKey);
|
||||
const { cfg, entry } = loadGatewaySessionEntryReadOnly(sessionKey);
|
||||
const sessionVerbose = normalizeVerboseLevel(entry?.verboseLevel);
|
||||
const sessionUpdatedAt = typeof entry?.updatedAt === "number" ? entry.updatedAt : undefined;
|
||||
const sessionChangedAfterRunStarted =
|
||||
|
||||
@@ -10,7 +10,7 @@ export { getRegisteredAgentHarness } from "../../../agents/harness/registry.js";
|
||||
export { resolveReplyToMode } from "../../../auto-reply/reply/reply-threading.js";
|
||||
export { resolveRuntimeConfigCacheKey } from "../../../config/config.js";
|
||||
export { deliveryContextFromSession } from "../../../utils/delivery-context.shared.js";
|
||||
export { loadSessionEntryReadOnly, resolveSessionModelRef } from "../../session-utils.js";
|
||||
export { loadGatewaySessionEntryReadOnly, resolveSessionModelRef } from "../../session-utils.js";
|
||||
|
||||
export const toolsEffectiveGlobalAgentRuntimeMocks = {
|
||||
resolveEffectiveToolInventory: vi.fn(
|
||||
|
||||
@@ -22,7 +22,7 @@ vi.mock("../session-utils.js", async () => {
|
||||
return {
|
||||
...actual,
|
||||
loadSessionEntry: hoisted.loadSessionEntry,
|
||||
loadSessionEntryReadOnly: hoisted.loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: hoisted.loadSessionEntry,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
resolveStoredSessionKeyForAgentStore,
|
||||
} from "../session-store-key.js";
|
||||
import { visitSessionMessagesAsync } from "../session-transcript-readers.js";
|
||||
import { loadSessionEntryReadOnly } from "../session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../session-utils.js";
|
||||
import type { GatewayRequestHandlers, RespondFn } from "./types.js";
|
||||
import { assertValidParams } from "./validation.js";
|
||||
|
||||
@@ -526,8 +526,8 @@ async function loadArtifacts(
|
||||
const scopedGlobalAgentId =
|
||||
cfg?.session?.scope === "global" && sessionKey === "global" ? resolved.agentId : undefined;
|
||||
const { storePath, entry } = scopedGlobalAgentId
|
||||
? loadSessionEntryReadOnly(sessionKey, { agentId: scopedGlobalAgentId })
|
||||
: loadSessionEntryReadOnly(sessionKey);
|
||||
? loadGatewaySessionEntryReadOnly(sessionKey, { agentId: scopedGlobalAgentId })
|
||||
: loadGatewaySessionEntryReadOnly(sessionKey);
|
||||
const sessionId = entry?.sessionId;
|
||||
if (!sessionId || !storePath) {
|
||||
return { sessionKey, artifacts: [] };
|
||||
|
||||
@@ -36,7 +36,7 @@ import { capArrayByJsonBytes } from "../session-transcript-readers.js";
|
||||
import {
|
||||
buildGatewaySessionInfo,
|
||||
getSessionDefaults,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
listAgentsForGateway,
|
||||
resolveSessionModelRef,
|
||||
resolveSessionStoreKey,
|
||||
@@ -203,7 +203,7 @@ async function handleChatHistoryRequest({
|
||||
const { cfg, storePath, store, entry, canonicalKey } = measureDiagnosticsTimelineSpanSync(
|
||||
`gateway.${method}.session_entry`,
|
||||
() =>
|
||||
loadSessionEntryReadOnly(sessionKey, {
|
||||
loadGatewaySessionEntryReadOnly(sessionKey, {
|
||||
...sessionLoadOptions,
|
||||
includeStoreChildEntries: true,
|
||||
}),
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
readSessionMessageByIdAsync,
|
||||
readSessionMessagesAsync,
|
||||
} from "../session-transcript-readers.js";
|
||||
import { loadSessionEntryReadOnly } from "../session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../session-utils.js";
|
||||
import { readChatHistoryMessageId } from "./chat-history-pages.js";
|
||||
import { resolveRequestedChatAgentId, validateChatSelectedAgent } from "./chat-origin-routing.js";
|
||||
import { normalizeOptionalChatText as normalizeOptionalText } from "./chat-text-normalization.js";
|
||||
@@ -74,7 +74,10 @@ export const chatMessageGetHandlers: GatewayRequestHandlers = {
|
||||
agentId: agentIdOverride,
|
||||
});
|
||||
const sessionLoadOptions = requestedAgentId ? { agentId: requestedAgentId } : undefined;
|
||||
const { cfg, storePath, entry } = loadSessionEntryReadOnly(sessionKey, sessionLoadOptions);
|
||||
const { cfg, storePath, entry } = loadGatewaySessionEntryReadOnly(
|
||||
sessionKey,
|
||||
sessionLoadOptions,
|
||||
);
|
||||
const selectedAgent = validateChatSelectedAgent({
|
||||
cfg,
|
||||
requestedSessionKey: sessionKey,
|
||||
|
||||
@@ -256,7 +256,7 @@ vi.mock("../session-utils.js", async () => {
|
||||
return {
|
||||
...original,
|
||||
loadSessionEntry,
|
||||
loadSessionEntryReadOnly: loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: loadSessionEntry,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
import { resolveSessionSubscriptionKeys } from "../session-subscription-keys.js";
|
||||
import {
|
||||
loadSessionEntry,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
resolveSessionModelRef,
|
||||
} from "../session-utils.js";
|
||||
import { formatForLog } from "../ws-log.js";
|
||||
@@ -84,7 +84,7 @@ export const chatHandlers: GatewayRequestHandlers = {
|
||||
// Session entry carries per-session model overrides; utility routing must
|
||||
// derive its small-model default from the provider this session actually
|
||||
// uses, not the agent's configured default.
|
||||
const { cfg: sessionCfg, entry } = loadSessionEntryReadOnly(
|
||||
const { cfg: sessionCfg, entry } = loadGatewaySessionEntryReadOnly(
|
||||
params.sessionKey,
|
||||
selectedAgent.agentId ? { agentId: selectedAgent.agentId } : undefined,
|
||||
);
|
||||
|
||||
@@ -54,7 +54,7 @@ import {
|
||||
import { parseAgentSessionKey } from "../../sessions/session-key-utils.js";
|
||||
import { consumeCronCreatorAuthorityGrant } from "../cron-creator-authority-grant.js";
|
||||
import { getGatewayProcessInstanceId } from "../process-instance.js";
|
||||
import { loadSessionEntryReadOnly } from "../session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../session-utils.js";
|
||||
import {
|
||||
assertActiveAgentRuntimeAuthority,
|
||||
hasActiveAgentRuntimeAuthority,
|
||||
@@ -342,7 +342,7 @@ function assertCronDoesNotTargetAgentHarness(input: {
|
||||
return;
|
||||
}
|
||||
|
||||
const loaded = loadSessionEntryReadOnly(
|
||||
const loaded = loadGatewaySessionEntryReadOnly(
|
||||
targetSessionKey,
|
||||
input.agentId?.trim() ? { agentId: input.agentId.trim() } : {},
|
||||
);
|
||||
@@ -405,7 +405,7 @@ export const cronHandlers: GatewayRequestHandlers = {
|
||||
const sessionKey = p.sessionKey?.trim() || undefined;
|
||||
const agentId = p.agentId?.trim() || undefined;
|
||||
if (sessionKey && isAgentHarnessSessionKey(sessionKey)) {
|
||||
const loaded = loadSessionEntryReadOnly(sessionKey, agentId ? { agentId } : {});
|
||||
const loaded = loadGatewaySessionEntryReadOnly(sessionKey, agentId ? { agentId } : {});
|
||||
const harnessSessionError = loaded.entry
|
||||
? resolveAgentHarnessSessionStoreEntryError(loaded.canonicalKey, loaded.entry)
|
||||
: AGENT_HARNESS_SESSION_KEY_RESERVED_MESSAGE;
|
||||
|
||||
@@ -52,7 +52,7 @@ vi.mock("../../config/config.js", async () => {
|
||||
|
||||
vi.mock("../session-utils.js", () => ({
|
||||
loadSessionEntry: loadGatewaySessionEntry,
|
||||
loadSessionEntryReadOnly: loadGatewaySessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: loadGatewaySessionEntry,
|
||||
}));
|
||||
|
||||
import { cronHandlers } from "./cron.js";
|
||||
|
||||
@@ -5,20 +5,20 @@ import { vi } from "vitest";
|
||||
|
||||
const deletedAgentSessionMocks = vi.hoisted(() => ({
|
||||
loadSessionEntry: vi.fn(),
|
||||
loadSessionEntryReadOnly: vi.fn(),
|
||||
loadGatewaySessionEntryReadOnly: vi.fn(),
|
||||
resolveDeletedAgentIdFromSessionKey: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../session-utils.js", () => ({
|
||||
loadSessionEntry: deletedAgentSessionMocks.loadSessionEntry,
|
||||
loadSessionEntryReadOnly: deletedAgentSessionMocks.loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly: deletedAgentSessionMocks.loadGatewaySessionEntryReadOnly,
|
||||
resolveDeletedAgentIdFromSessionKey: deletedAgentSessionMocks.resolveDeletedAgentIdFromSessionKey,
|
||||
}));
|
||||
|
||||
/** Resets mocked deleted-agent session lookups between tests. */
|
||||
export function resetDeletedAgentSessionMocks(): void {
|
||||
deletedAgentSessionMocks.loadSessionEntry.mockReset();
|
||||
deletedAgentSessionMocks.loadSessionEntryReadOnly.mockReset();
|
||||
deletedAgentSessionMocks.loadGatewaySessionEntryReadOnly.mockReset();
|
||||
deletedAgentSessionMocks.resolveDeletedAgentIdFromSessionKey.mockReset();
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@ import type { PrepareGatewaySessionLifecycle } from "../session-lifecycle-prepar
|
||||
import { resolveRequestedSessionAgentId as resolveRequestedGlobalAgentId } from "../session-request-agent.js";
|
||||
import { resolveSessionStoreAgentId } from "../session-store-key.js";
|
||||
import { readSessionMessageCountAsync } from "../session-transcript-readers.js";
|
||||
import { loadSessionEntryReadOnly, resolveGatewaySessionStoreTarget } from "../session-utils.js";
|
||||
import {
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
resolveGatewaySessionStoreTarget,
|
||||
} from "../session-utils.js";
|
||||
import { resolveSessionPatchModelSelection } from "../sessions-patch.js";
|
||||
import { createAgentRuntimeAuthorityGuard } from "./agent-runtime-authority.js";
|
||||
import { chatHandlers } from "./chat.js";
|
||||
@@ -288,7 +291,7 @@ export const sessionCreateHandlers: GatewayRequestHandlers = {
|
||||
!hasInitialTurn &&
|
||||
cfg.session?.dmScope === "main"
|
||||
) {
|
||||
const parent = loadSessionEntryReadOnly(
|
||||
const parent = loadGatewaySessionEntryReadOnly(
|
||||
parentSessionKey,
|
||||
requestedAgent.agentId ? { agentId: requestedAgent.agentId } : undefined,
|
||||
);
|
||||
|
||||
@@ -25,7 +25,7 @@ const hoisted = vi.hoisted(() => ({
|
||||
|
||||
vi.mock("../session-utils.js", () => ({
|
||||
loadSessionEntry: hoisted.loadSessionEntry,
|
||||
loadSessionEntryReadOnly: hoisted.loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: hoisted.loadSessionEntry,
|
||||
}));
|
||||
|
||||
vi.mock("../../agents/agent-scope.js", () => ({
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js";
|
||||
import { normalizeAgentId, parseAgentSessionKey } from "../../routing/session-key.js";
|
||||
import { applySessionDiffBaseline, loadCheckoutDiff } from "../../sessions/session-diff.js";
|
||||
import { loadSessionEntryReadOnly } from "../session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../session-utils.js";
|
||||
import type { GatewayRequestHandlers } from "./types.js";
|
||||
import { assertValidParams } from "./validation.js";
|
||||
|
||||
@@ -25,9 +25,12 @@ export async function loadSessionDiff(params: SessionsDiffParams): Promise<Sessi
|
||||
deletions: 0,
|
||||
...(unavailableReason ? { unavailableReason } : {}),
|
||||
});
|
||||
const { cfg, entry, storePath, canonicalKey } = loadSessionEntryReadOnly(params.sessionKey, {
|
||||
const { cfg, entry, storePath, canonicalKey } = loadGatewaySessionEntryReadOnly(
|
||||
params.sessionKey,
|
||||
{
|
||||
agentId: params.agentId,
|
||||
});
|
||||
},
|
||||
);
|
||||
// Same session scoping as sessions.files.*: an unknown session must not fall
|
||||
// back to some agent workspace and surface another checkout's diff.
|
||||
if (!entry?.sessionId || !storePath) {
|
||||
|
||||
@@ -42,7 +42,7 @@ vi.mock("../session-utils.js", async () => {
|
||||
return {
|
||||
...actual,
|
||||
loadSessionEntry: hoisted.loadSessionEntry,
|
||||
loadSessionEntryReadOnly: hoisted.loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: hoisted.loadSessionEntry,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ vi.mock("../session-utils.js", async () => {
|
||||
return {
|
||||
...actual,
|
||||
loadSessionEntry: hoisted.loadSessionEntry,
|
||||
loadSessionEntryReadOnly: hoisted.loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: hoisted.loadSessionEntry,
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
toTranscriptReadScope,
|
||||
type SessionTranscriptReadScope,
|
||||
} from "../session-transcript-readers.js";
|
||||
import { loadSessionEntryReadOnly } from "../session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../session-utils.js";
|
||||
import {
|
||||
execOpenPath,
|
||||
formatOpenPathError,
|
||||
@@ -526,7 +526,7 @@ async function toSessionFileEntry(
|
||||
}
|
||||
|
||||
function loadSessionFileRoot(params: { sessionKey: string; agentId?: string }) {
|
||||
const loaded = loadSessionEntryReadOnly(params.sessionKey, { agentId: params.agentId });
|
||||
const loaded = loadGatewaySessionEntryReadOnly(params.sessionKey, { agentId: params.agentId });
|
||||
if (!loaded.entry?.sessionId) {
|
||||
return { ...loaded, agentId: undefined, root: undefined, fileRoot: undefined };
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { reactivateCompletedSubagentSession } from "../session-subagent-reactiva
|
||||
import { readSessionMessageCountAsync } from "../session-transcript-readers.js";
|
||||
import {
|
||||
loadSessionEntry,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
resolveDeletedAgentIdFromSessionKey,
|
||||
} from "../session-utils.js";
|
||||
import { asWorkerInferenceControl } from "../worker-environments/inference-control.js";
|
||||
@@ -193,7 +193,7 @@ async function createAgentMainSessionForSend(params: {
|
||||
}
|
||||
|
||||
const createdKey = normalizeOptionalString(createResult.payload?.key) ?? params.canonicalKey;
|
||||
const loaded = loadSessionEntryReadOnly(createdKey);
|
||||
const loaded = loadGatewaySessionEntryReadOnly(createdKey);
|
||||
if (!loaded.entry?.sessionId) {
|
||||
return {
|
||||
ok: false,
|
||||
|
||||
@@ -49,7 +49,7 @@ vi.mock("../session-utils.js", async () => {
|
||||
loadCombinedSessionStoreForGatewayMock(...args),
|
||||
loadSessionEntry: (...args: unknown[]) =>
|
||||
loadSessionEntryMock(...(args as [string, { agentId?: string }?])),
|
||||
loadSessionEntryReadOnly: (...args: unknown[]) =>
|
||||
loadGatewaySessionEntryReadOnly: (...args: unknown[]) =>
|
||||
loadSessionEntryMock(...(args as [string, { agentId?: string }?])),
|
||||
loadGatewaySessionRow: (...args: unknown[]) => loadGatewaySessionRowMock(...args),
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ vi.mock("../session-utils.js", async () => {
|
||||
...actual,
|
||||
loadSessionEntry: (...args: unknown[]) =>
|
||||
loadSessionEntryMock(...(args as [string, { agentId?: string }?])),
|
||||
loadSessionEntryReadOnly: (...args: unknown[]) =>
|
||||
loadGatewaySessionEntryReadOnly: (...args: unknown[]) =>
|
||||
loadSessionEntryMock(...(args as [string, { agentId?: string }?])),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ import { expectSubagentFollowupReactivation } from "./subagent-followup.test-hel
|
||||
import type { GatewayRequestContext, RespondFn } from "./types.js";
|
||||
|
||||
const loadSessionEntryMock = vi.fn();
|
||||
const loadSessionEntryReadOnlyMock = vi.fn();
|
||||
const loadGatewaySessionEntryReadOnlyMock = vi.fn();
|
||||
const readSessionMessageCountAsyncMock = vi.fn();
|
||||
const loadGatewaySessionRowMock = vi.fn();
|
||||
const resolveDeletedAgentIdFromSessionKeyMock = vi.fn();
|
||||
@@ -49,7 +49,8 @@ vi.mock("../../auto-reply/reply/queue/cleanup.js", async () => {
|
||||
|
||||
vi.mock("../session-utils.js", () => ({
|
||||
loadSessionEntry: (...args: unknown[]) => loadSessionEntryMock(...args),
|
||||
loadSessionEntryReadOnly: (...args: unknown[]) => loadSessionEntryReadOnlyMock(...args),
|
||||
loadGatewaySessionEntryReadOnly: (...args: unknown[]) =>
|
||||
loadGatewaySessionEntryReadOnlyMock(...args),
|
||||
loadGatewaySessionRow: (...args: unknown[]) => loadGatewaySessionRowMock(...args),
|
||||
resolveDeletedAgentIdFromSessionKey: (...args: unknown[]) =>
|
||||
resolveDeletedAgentIdFromSessionKeyMock(...args),
|
||||
@@ -113,7 +114,7 @@ function createRequestContext(overrides: Record<string, unknown> = {}): GatewayR
|
||||
describe("sessions.send completed subagent follow-up status", () => {
|
||||
beforeEach(() => {
|
||||
loadSessionEntryMock.mockReset();
|
||||
loadSessionEntryReadOnlyMock.mockReset();
|
||||
loadGatewaySessionEntryReadOnlyMock.mockReset();
|
||||
readSessionMessageCountAsyncMock.mockReset().mockResolvedValue(0);
|
||||
loadGatewaySessionRowMock.mockReset();
|
||||
resolveDeletedAgentIdFromSessionKeyMock.mockReset().mockReturnValue(null);
|
||||
|
||||
@@ -23,11 +23,13 @@ vi.mock("../session-utils.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../session-utils.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadSessionEntryReadOnly: (...args: Parameters<typeof actual.loadSessionEntryReadOnly>) => {
|
||||
loadGatewaySessionEntryReadOnly: (
|
||||
...args: Parameters<typeof actual.loadGatewaySessionEntryReadOnly>
|
||||
) => {
|
||||
if (sessionReadState.mode === "throw") {
|
||||
throw new Error("session inspection unavailable");
|
||||
}
|
||||
const loaded = actual.loadSessionEntryReadOnly(...args);
|
||||
const loaded = actual.loadGatewaySessionEntryReadOnly(...args);
|
||||
return sessionReadState.mode === "present"
|
||||
? { ...loaded, entry: { sessionId: "surviving-session", updatedAt: 1 } }
|
||||
: loaded;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { resolveSessionWorkStartError } from "../../config/sessions.js";
|
||||
import { formatErrorMessage } from "../../infra/errors.js";
|
||||
import { normalizeAgentId, parseAgentSessionKey } from "../../routing/session-key.js";
|
||||
import { buildDashboardSessionKey } from "../session-create-service.js";
|
||||
import { loadSessionEntryReadOnly } from "../session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../session-utils.js";
|
||||
import {
|
||||
abandonTaskSuggestionAcceptance,
|
||||
beginTaskSuggestionAcceptance,
|
||||
@@ -107,7 +107,7 @@ async function rollbackSuggestedTaskSession(params: {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return !loadSessionEntryReadOnly(params.key, { agentId: params.agentId }).entry;
|
||||
return !loadGatewaySessionEntryReadOnly(params.key, { agentId: params.agentId }).entry;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
@@ -358,9 +358,9 @@ async function deliverSuggestedTaskToSourceSession(params: {
|
||||
const agentId = resolveSuggestionAgentId(params.suggestion, params.options);
|
||||
const fail = (error: NonNullable<Parameters<RespondFn>[2]>) =>
|
||||
failSuggestedTaskDelivery({ taskId: params.taskId, options: params.options, error });
|
||||
let source: ReturnType<typeof loadSessionEntryReadOnly>;
|
||||
let source: ReturnType<typeof loadGatewaySessionEntryReadOnly>;
|
||||
try {
|
||||
source = loadSessionEntryReadOnly(params.suggestion.sessionKey, { agentId });
|
||||
source = loadGatewaySessionEntryReadOnly(params.suggestion.sessionKey, { agentId });
|
||||
} catch (error) {
|
||||
return fail(errorShape(ErrorCodes.UNAVAILABLE, formatErrorMessage(error)));
|
||||
}
|
||||
|
||||
@@ -25,4 +25,4 @@ export {
|
||||
getActivePluginRegistryVersion,
|
||||
} from "../../plugins/runtime.js";
|
||||
export { deliveryContextFromSession } from "../../utils/delivery-context.shared.js";
|
||||
export { loadSessionEntryReadOnly, resolveSessionModelRef } from "../session-utils.js";
|
||||
export { loadGatewaySessionEntryReadOnly, resolveSessionModelRef } from "../session-utils.js";
|
||||
|
||||
@@ -75,7 +75,7 @@ const runtimeMocks = vi.hoisted(() => ({
|
||||
|
||||
vi.mock("./tools-effective.runtime.js", () => ({
|
||||
...runtimeMocks,
|
||||
loadSessionEntryReadOnly: runtimeMocks.loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: runtimeMocks.loadSessionEntry,
|
||||
}));
|
||||
|
||||
const nodePluginToolSnapshotMocks = vi.hoisted(() => ({
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
getActivePluginRegistryVersion,
|
||||
getRegisteredAgentHarness,
|
||||
listAgentIds,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
peekSessionMcpRuntime,
|
||||
resolveAgentDir,
|
||||
resolveAgentWorkspaceDir,
|
||||
@@ -531,7 +531,7 @@ function resolveTrustedToolsEffectiveContext(params: {
|
||||
}) {
|
||||
// The effective tools request is read-only but security-sensitive. Derive
|
||||
// routing/account/model context from the persisted session, not client params.
|
||||
const loaded = loadSessionEntryReadOnly(
|
||||
const loaded = loadGatewaySessionEntryReadOnly(
|
||||
params.sessionKey,
|
||||
params.requestedAgentId ? { agentId: params.requestedAgentId } : undefined,
|
||||
);
|
||||
|
||||
@@ -23,7 +23,7 @@ vi.mock("../session-utils.js", async () => {
|
||||
const actual = await vi.importActual<typeof import("../session-utils.js")>("../session-utils.js");
|
||||
return {
|
||||
...actual,
|
||||
loadSessionEntryReadOnly: vi.fn(actual.loadSessionEntryReadOnly),
|
||||
loadGatewaySessionEntryReadOnly: vi.fn(actual.loadGatewaySessionEntryReadOnly),
|
||||
loadCombinedSessionStoreForGatewayCore: vi.fn(() => ({ storePath: "(multiple)", store: {} })),
|
||||
};
|
||||
});
|
||||
@@ -106,7 +106,7 @@ import {
|
||||
} from "../../infra/session-cost-usage.js";
|
||||
import {
|
||||
loadCombinedSessionStoreForGatewayCore,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
} from "../session-utils.js";
|
||||
import { testApi, usageHandlers } from "./usage.js";
|
||||
|
||||
@@ -190,7 +190,7 @@ function expectSuccessfulSessionsUsage(
|
||||
|
||||
function mockStoredSession(key: string, sessionId: string) {
|
||||
const entry = { sessionId, updatedAt: 1_000 };
|
||||
vi.mocked(loadSessionEntryReadOnly).mockReturnValueOnce({
|
||||
vi.mocked(loadGatewaySessionEntryReadOnly).mockReturnValueOnce({
|
||||
cfg: TEST_RUNTIME_CONFIG,
|
||||
canonicalKey: key,
|
||||
entry,
|
||||
|
||||
@@ -68,7 +68,7 @@ import {
|
||||
} from "../session-store-key.js";
|
||||
import {
|
||||
loadCombinedSessionStoreForGatewayCore,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
} from "../session-utils.js";
|
||||
import { loadUsageStatusStaleWhileRevalidate } from "./models-auth-status-usage-cache.js";
|
||||
import type { GatewayRequestHandlers, RespondFn } from "./types.js";
|
||||
@@ -135,7 +135,7 @@ function resolveSessionUsageTarget(
|
||||
config: OpenClawConfig,
|
||||
agentIdHint?: string,
|
||||
): ResolvedSessionUsageTarget | undefined {
|
||||
const { canonicalKey, entry, storePath } = loadSessionEntryReadOnly(
|
||||
const { canonicalKey, entry, storePath } = loadGatewaySessionEntryReadOnly(
|
||||
key,
|
||||
agentIdHint ? { agentId: agentIdHint } : undefined,
|
||||
);
|
||||
|
||||
@@ -35,7 +35,7 @@ vi.mock("./session-utils.js", () => ({
|
||||
attachOpenClawTranscriptMeta: (message: unknown) => message,
|
||||
loadGatewaySessionRow: loadGatewaySessionRowMock,
|
||||
loadSessionEntry: () => ({ entry: undefined, storePath: "" }),
|
||||
loadSessionEntryReadOnly: loadGatewaySessionEntryReadOnlyMock,
|
||||
loadGatewaySessionEntryReadOnly: loadGatewaySessionEntryReadOnlyMock,
|
||||
}));
|
||||
vi.mock("./session-transcript-readers.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("./session-transcript-readers.js")>();
|
||||
|
||||
@@ -35,7 +35,7 @@ import {
|
||||
} from "./session-transcript-readers.js";
|
||||
import {
|
||||
loadGatewaySessionRow,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
type GatewaySessionRow,
|
||||
} from "./session-utils.js";
|
||||
|
||||
@@ -84,7 +84,7 @@ function readTranscriptUpdateLifecycleOwner(
|
||||
const storePath = normalizeOptionalString(update.target?.storePath) ?? marker?.storePath;
|
||||
const entry = storePath
|
||||
? loadAccessorSessionEntryReadOnly({ agentId, sessionKey, storePath })
|
||||
: loadSessionEntryReadOnly(sessionKey, agentId ? { agentId } : undefined)?.entry;
|
||||
: loadGatewaySessionEntryReadOnly(sessionKey, agentId ? { agentId } : undefined)?.entry;
|
||||
if (!entry || (sessionId && entry.sessionId !== sessionId)) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -300,7 +300,7 @@ async function handleTranscriptUpdateBroadcast(
|
||||
}),
|
||||
storePath: updateStorePath,
|
||||
}
|
||||
: loadSessionEntryReadOnly(sessionKey, { agentId: routingAgentId });
|
||||
: loadGatewaySessionEntryReadOnly(sessionKey, { agentId: routingAgentId });
|
||||
const entry = fallbackTarget?.entry;
|
||||
const messageSessionId =
|
||||
compatibleLegacyMarker?.sessionId ??
|
||||
|
||||
@@ -12,7 +12,7 @@ import type {
|
||||
SessionCompanionContextMessage,
|
||||
SessionCompanionPreparedContext,
|
||||
} from "./session-companion-state.js";
|
||||
import { loadSessionEntryReadOnly } from "./session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "./session-utils.js";
|
||||
|
||||
const CONTEXT_MAX_MESSAGES = 40;
|
||||
const CONTEXT_MAX_BYTES = 24 * 1024;
|
||||
@@ -123,7 +123,7 @@ async function readSessionCompanionContext(params: {
|
||||
sessionKey: string;
|
||||
signal?: AbortSignal;
|
||||
}): Promise<SessionCompanionContextReadResult> {
|
||||
const loaded = loadSessionEntryReadOnly(params.sessionKey, { agentId: params.agentId });
|
||||
const loaded = loadGatewaySessionEntryReadOnly(params.sessionKey, { agentId: params.agentId });
|
||||
const sessionId = loaded.entry?.sessionId?.trim();
|
||||
if (!sessionId) {
|
||||
return { kind: "missing" };
|
||||
@@ -229,6 +229,6 @@ async function readSessionCompanionContext(params: {
|
||||
|
||||
export const defaultSessionCompanionContextReader: SessionCompanionContextReader = {
|
||||
currentSessionId: ({ agentId, sessionKey }) =>
|
||||
loadSessionEntryReadOnly(sessionKey, { agentId }).entry?.sessionId?.trim() || undefined,
|
||||
loadGatewaySessionEntryReadOnly(sessionKey, { agentId }).entry?.sessionId?.trim() || undefined,
|
||||
read: readSessionCompanionContext,
|
||||
};
|
||||
|
||||
@@ -85,7 +85,10 @@ import { resolvePluginSessionOwnershipError } from "./session-plugin-ownership.j
|
||||
import { resolveRequestedSessionAgentId } from "./session-request-agent.js";
|
||||
import { isSessionVisibilityAllowed, resolveSessionVisibility } from "./session-sharing.js";
|
||||
import { resolveSessionStoreKey } from "./session-store-key.js";
|
||||
import { loadSessionEntryReadOnly, resolveGatewaySessionStoreTarget } from "./session-utils.js";
|
||||
import {
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
resolveGatewaySessionStoreTarget,
|
||||
} from "./session-utils.js";
|
||||
import { projectSessionsPatchEntry, resolveSessionPatchModelSelection } from "./sessions-patch.js";
|
||||
|
||||
type TrustedCatalogSessionTarget = {
|
||||
@@ -384,7 +387,7 @@ export async function createGatewaySession(params: {
|
||||
agentId,
|
||||
storePath: durableStorePath,
|
||||
}).some(({ sessionKey }) => sessionKey === explicitTargetKey);
|
||||
if (durableEntryExists || loadSessionEntryReadOnly(explicitTargetKey).entry) {
|
||||
if (durableEntryExists || loadGatewaySessionEntryReadOnly(explicitTargetKey).entry) {
|
||||
return {
|
||||
ok: false,
|
||||
error: errorShape(
|
||||
@@ -491,7 +494,7 @@ export async function createGatewaySession(params: {
|
||||
}
|
||||
parentSelectedAgentId = parentRequestedAgent.agentId;
|
||||
}
|
||||
const parent = loadSessionEntryReadOnly(
|
||||
const parent = loadGatewaySessionEntryReadOnly(
|
||||
parentSessionKey,
|
||||
parentSelectedAgentId ? { agentId: parentSelectedAgentId } : undefined,
|
||||
);
|
||||
@@ -708,7 +711,7 @@ export async function createGatewaySession(params: {
|
||||
params.fork === true ||
|
||||
params.authorizedPluginId !== undefined)
|
||||
) {
|
||||
const currentParent = loadSessionEntryReadOnly(
|
||||
const currentParent = loadGatewaySessionEntryReadOnly(
|
||||
canonicalParentSessionKey,
|
||||
parentSelectedAgentId ? { agentId: parentSelectedAgentId } : undefined,
|
||||
);
|
||||
@@ -793,7 +796,7 @@ export async function createGatewaySession(params: {
|
||||
}
|
||||
|
||||
const target = creationTarget;
|
||||
const currentTargetEntry = loadSessionEntryReadOnly(target.canonicalKey, {
|
||||
const currentTargetEntry = loadGatewaySessionEntryReadOnly(target.canonicalKey, {
|
||||
agentId: target.agentId,
|
||||
}).entry;
|
||||
const preparationResult = params.prepareLifecycle
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
listSessionsFromStore,
|
||||
listSessionsFromStoreAsync,
|
||||
loadSessionEntry,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
resolveCanonicalGatewaySessionStoreKey,
|
||||
resolveDeletedAgentIdFromSessionKey,
|
||||
resolveGatewayModelSupportsImages,
|
||||
@@ -2210,7 +2210,7 @@ describe("gateway session utils", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("loadSessionEntryReadOnly does not materialize a missing configured agent", async () => {
|
||||
test("loadGatewaySessionEntryReadOnly does not materialize a missing configured agent", async () => {
|
||||
resetConfigRuntimeState();
|
||||
try {
|
||||
await withStateDirEnv("session-utils-load-entry-read-only-", async ({ stateDir }) => {
|
||||
@@ -2223,7 +2223,7 @@ describe("gateway session utils", () => {
|
||||
} as OpenClawConfig;
|
||||
setRuntimeConfigSnapshot(cfg, cfg);
|
||||
|
||||
const loaded = loadSessionEntryReadOnly("agent:missing:main");
|
||||
const loaded = loadGatewaySessionEntryReadOnly("agent:missing:main");
|
||||
|
||||
expect(loaded.entry).toBeUndefined();
|
||||
expect(fs.existsSync(path.join(stateDir, "agents", "missing"))).toBe(false);
|
||||
@@ -2233,7 +2233,7 @@ describe("gateway session utils", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("loadSessionEntryReadOnly clones only the selected row and direct children", async () => {
|
||||
test("loadGatewaySessionEntryReadOnly clones only the selected row and direct children", async () => {
|
||||
resetConfigRuntimeState();
|
||||
try {
|
||||
await withStateDirEnv("session-utils-exact-read-only-", async ({ stateDir }) => {
|
||||
@@ -2261,7 +2261,7 @@ describe("gateway session utils", () => {
|
||||
).toContain(childKey);
|
||||
const cloneSpy = vi.spyOn(globalThis, "structuredClone");
|
||||
try {
|
||||
expect(loadSessionEntryReadOnly(childKey, { clone: false }).entry).toMatchObject({
|
||||
expect(loadGatewaySessionEntryReadOnly(childKey, { clone: false }).entry).toMatchObject({
|
||||
sessionId: "child",
|
||||
spawnedBy: parentKey,
|
||||
});
|
||||
@@ -2273,7 +2273,7 @@ describe("gateway session utils", () => {
|
||||
storePath,
|
||||
}).map((item) => item.sessionKey),
|
||||
).toEqual([childKey]);
|
||||
const loaded = loadSessionEntryReadOnly("main", {
|
||||
const loaded = loadGatewaySessionEntryReadOnly("main", {
|
||||
includeStoreChildEntries: true,
|
||||
});
|
||||
|
||||
@@ -2322,7 +2322,7 @@ describe("gateway session utils", () => {
|
||||
expect(spawnedByReads).toBe(1);
|
||||
});
|
||||
|
||||
test("loadSessionEntryReadOnly rejects a persisted main alias", async () => {
|
||||
test("loadGatewaySessionEntryReadOnly rejects a persisted main alias", async () => {
|
||||
resetConfigRuntimeState();
|
||||
try {
|
||||
await withStateDirEnv("session-utils-exact-alias-children-", async ({ stateDir }) => {
|
||||
@@ -2345,7 +2345,7 @@ describe("gateway session utils", () => {
|
||||
setRuntimeConfigSnapshot(cfg, cfg);
|
||||
|
||||
expect(() =>
|
||||
loadSessionEntryReadOnly("main", {
|
||||
loadGatewaySessionEntryReadOnly("main", {
|
||||
clone: false,
|
||||
includeStoreChildEntries: true,
|
||||
}),
|
||||
|
||||
@@ -15,7 +15,7 @@ export { loadCombinedSessionStoreForGatewayCore } from "../config/sessions/combi
|
||||
export { deriveSessionTitle } from "./session-utils-core.js";
|
||||
export { resolveDeletedAgentIdFromSessionKey } from "./session-utils-store.js";
|
||||
export { loadGatewaySessionEntry as loadSessionEntry } from "./session-utils-store.js";
|
||||
export { loadGatewaySessionEntryReadOnly as loadSessionEntryReadOnly } from "./session-utils-store.js";
|
||||
export { loadGatewaySessionEntryReadOnly } from "./session-utils-store.js";
|
||||
export { resolveCanonicalSessionStoreMatchFromStoreKeys } from "./session-utils-store.js";
|
||||
export { resolveCanonicalSessionEntryFromStoreKeys } from "./session-utils-store.js";
|
||||
export { resolveCanonicalGatewaySessionStoreKey } from "./session-utils-store.js";
|
||||
|
||||
@@ -28,7 +28,7 @@ vi.mock("../session-utils.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../session-utils.js")>();
|
||||
return {
|
||||
...actual,
|
||||
loadSessionEntryReadOnly: (sessionKey: string) => ({
|
||||
loadGatewaySessionEntryReadOnly: (sessionKey: string) => ({
|
||||
canonicalKey: sessionKey,
|
||||
entry: structuredClone(sessionEntries.get(sessionKey)),
|
||||
}),
|
||||
|
||||
@@ -23,7 +23,7 @@ import { sha256Base64Url } from "../../infra/crypto-digest.js";
|
||||
import { redactSensitiveText } from "../../logging/redact.js";
|
||||
import { normalizeAgentId } from "../../routing/session-key.js";
|
||||
import { WORKER_TOOL_NAMES } from "../../worker/tool-authority.js";
|
||||
import { loadSessionEntryReadOnly } from "../session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../session-utils.js";
|
||||
import type { WorkerConnectionIdentity } from "./connection-identity.js";
|
||||
import type { WorkerSessionPlacementStore } from "./placement-store.js";
|
||||
import type { WorkerPlacementDispatchContract } from "./service-contract.js";
|
||||
@@ -150,7 +150,9 @@ export function createWorkerSessionToolExecutor(params: {
|
||||
}
|
||||
throwIfAborted(operation.signal);
|
||||
exactSource({ identity: operation.identity, placements: params.placements });
|
||||
let loaded = loadSessionEntryReadOnly(operation.childSessionKey, { agentId: targetAgentId });
|
||||
let loaded = loadGatewaySessionEntryReadOnly(operation.childSessionKey, {
|
||||
agentId: targetAgentId,
|
||||
});
|
||||
let createResponse: Record<string, unknown>;
|
||||
let creationAttempted = false;
|
||||
if (loaded.entry?.sessionId) {
|
||||
@@ -192,7 +194,7 @@ export function createWorkerSessionToolExecutor(params: {
|
||||
},
|
||||
);
|
||||
} catch (error) {
|
||||
loaded = loadSessionEntryReadOnly(operation.childSessionKey, {
|
||||
loaded = loadGatewaySessionEntryReadOnly(operation.childSessionKey, {
|
||||
agentId: targetAgentId,
|
||||
});
|
||||
if (!loaded.entry?.sessionId) {
|
||||
@@ -205,7 +207,9 @@ export function createWorkerSessionToolExecutor(params: {
|
||||
entry: loaded.entry,
|
||||
};
|
||||
}
|
||||
loaded = loadSessionEntryReadOnly(operation.childSessionKey, { agentId: targetAgentId });
|
||||
loaded = loadGatewaySessionEntryReadOnly(operation.childSessionKey, {
|
||||
agentId: targetAgentId,
|
||||
});
|
||||
}
|
||||
const childSessionId = loaded.entry?.sessionId;
|
||||
if (!childSessionId) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { loadSessionEntryReadOnly } from "../session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../session-utils.js";
|
||||
import type { WorkerConnectionIdentity } from "./connection-identity.js";
|
||||
import type { WorkerSessionPlacementStore } from "./placement-store.js";
|
||||
|
||||
@@ -14,7 +14,7 @@ export type WorkerSessionToolSource = {
|
||||
ownerEpoch: number;
|
||||
runId: string;
|
||||
};
|
||||
entry: NonNullable<ReturnType<typeof loadSessionEntryReadOnly>["entry"]>;
|
||||
entry: NonNullable<ReturnType<typeof loadGatewaySessionEntryReadOnly>["entry"]>;
|
||||
};
|
||||
|
||||
export type WorkerSessionToolTarget = {
|
||||
@@ -54,7 +54,9 @@ export function resolveWorkerSessionToolSource(params: {
|
||||
) {
|
||||
throw new Error("Worker source session placement changed");
|
||||
}
|
||||
const loaded = loadSessionEntryReadOnly(placement.sessionKey, { agentId: placement.agentId });
|
||||
const loaded = loadGatewaySessionEntryReadOnly(placement.sessionKey, {
|
||||
agentId: placement.agentId,
|
||||
});
|
||||
if (
|
||||
loaded.canonicalKey !== placement.sessionKey ||
|
||||
loaded.entry?.sessionId !== identity.sessionId ||
|
||||
@@ -83,7 +85,7 @@ export function resolveWorkerSessionToolTarget(params: {
|
||||
requestedSessionKey: string;
|
||||
placements: WorkerSessionPlacementStore;
|
||||
}): WorkerSessionToolTarget {
|
||||
const loaded = loadSessionEntryReadOnly(params.requestedSessionKey);
|
||||
const loaded = loadGatewaySessionEntryReadOnly(params.requestedSessionKey);
|
||||
const entry = loaded.entry;
|
||||
const targetSessionId = entry?.sessionId;
|
||||
if (
|
||||
@@ -111,7 +113,7 @@ export function resolveWorkerSessionToolTarget(params: {
|
||||
);
|
||||
const parent =
|
||||
sharedParentIncarnation && sourceParent && sourceParentId
|
||||
? loadSessionEntryReadOnly(sourceParent)
|
||||
? loadGatewaySessionEntryReadOnly(sourceParent)
|
||||
: undefined;
|
||||
const siblingToSibling = Boolean(
|
||||
parent &&
|
||||
@@ -147,7 +149,7 @@ export function assertWorkerSessionToolChild(params: {
|
||||
sourceSessionId: string;
|
||||
targetAgentId: string;
|
||||
}): void {
|
||||
const loaded = loadSessionEntryReadOnly(params.childSessionKey, {
|
||||
const loaded = loadGatewaySessionEntryReadOnly(params.childSessionKey, {
|
||||
agentId: params.targetAgentId,
|
||||
});
|
||||
const parent =
|
||||
|
||||
@@ -10,19 +10,19 @@ type WriteTextAtomicBeforeRename = (params: {
|
||||
export {
|
||||
JsonFileReadError,
|
||||
readJson,
|
||||
readJson as readJsonFileStrict,
|
||||
readJson as readJsonFileStrict, // Sanctioned domain alias.
|
||||
readJsonIfExists,
|
||||
readJsonIfExists as readDurableJsonFile,
|
||||
readJsonIfExists as readDurableJsonFile, // Sanctioned domain alias.
|
||||
readJsonSync,
|
||||
readRootJsonObjectSync,
|
||||
readRootJsonSync,
|
||||
readRootStructuredFileSync,
|
||||
tryReadJson,
|
||||
tryReadJson as readJsonFile,
|
||||
tryReadJson as readJsonFile, // Sanctioned domain alias.
|
||||
tryReadJsonSync,
|
||||
tryReadJsonSync as readJsonFileSync,
|
||||
tryReadJsonSync as readJsonFileSync, // Sanctioned domain alias.
|
||||
writeJson,
|
||||
writeJson as writeJsonAtomic,
|
||||
writeJson as writeJsonAtomic, // Sanctioned domain alias.
|
||||
writeJsonSync,
|
||||
} from "@openclaw/fs-safe/json";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// OpenClaw root resolution imports fs through this facade so tests can replace
|
||||
// filesystem behavior without mocking node:fs globally.
|
||||
export { default as openClawRootFsSync } from "node:fs";
|
||||
export { default as openClawRootFs } from "node:fs/promises";
|
||||
export { default as openClawRootFsSync } from "node:fs"; // Sanctioned domain alias.
|
||||
export { default as openClawRootFs } from "node:fs/promises"; // Sanctioned domain alias.
|
||||
|
||||
@@ -17,7 +17,7 @@ export {
|
||||
readSecretFileSync,
|
||||
type SecretFileReadOptions,
|
||||
} from "@openclaw/fs-safe/secret";
|
||||
export { writeSecretFileAtomic as writePrivateSecretFileAtomic } from "@openclaw/fs-safe/secret";
|
||||
export { writeSecretFileAtomic as writePrivateSecretFileAtomic } from "@openclaw/fs-safe/secret"; // Sanctioned domain alias.
|
||||
|
||||
export type SecretFileReadResult =
|
||||
| {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
} from "./state-migrations.receipts.js";
|
||||
import type { LegacyWorkspaceStateSource } from "./state-migrations.workspace-setup.types.js";
|
||||
|
||||
export { markLegacyMigrationSourceRemoved as markSourceRemoved } from "./state-migrations.receipts.js";
|
||||
export { markLegacyMigrationSourceRemoved } from "./state-migrations.receipts.js";
|
||||
|
||||
export type MigrationReceipt = {
|
||||
sourceKey: string;
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
} from "./state-migrations.source-snapshot.js";
|
||||
import type { MigrationMessages } from "./state-migrations.types.js";
|
||||
import {
|
||||
markSourceRemoved,
|
||||
markLegacyMigrationSourceRemoved,
|
||||
readReceipt,
|
||||
type MigrationReceipt,
|
||||
} from "./state-migrations.workspace-setup-receipts.js";
|
||||
@@ -386,7 +386,7 @@ async function cleanupReceiptSource(params: {
|
||||
const hasClaim = await sourceClaim.exists(true);
|
||||
if (!hasSource && !hasClaim) {
|
||||
if (!params.receipt.removedSource) {
|
||||
markSourceRemoved(params.receipt.sourceKey, params.env);
|
||||
markLegacyMigrationSourceRemoved(params.receipt.sourceKey, params.env);
|
||||
}
|
||||
return { changes: [], warnings: [] };
|
||||
}
|
||||
@@ -433,7 +433,7 @@ async function cleanupReceiptSource(params: {
|
||||
}
|
||||
assertConfiguredWorkspaceIdentity(params.source);
|
||||
await sourceClaim.remove({ skipSourceCheck: true });
|
||||
markSourceRemoved(params.receipt.sourceKey, params.env);
|
||||
markLegacyMigrationSourceRemoved(params.receipt.sourceKey, params.env);
|
||||
return {
|
||||
changes: [],
|
||||
warnings: [],
|
||||
@@ -564,7 +564,7 @@ async function migrateOneSource(params: {
|
||||
throw new Error("legacy workspace claim changed after import");
|
||||
}
|
||||
await sourceClaim.remove({ removeSource: params.removeSource, skipSourceCheck: true });
|
||||
markSourceRemoved(result.sourceKey, params.env);
|
||||
markLegacyMigrationSourceRemoved(result.sourceKey, params.env);
|
||||
} catch (error) {
|
||||
return {
|
||||
changes: [],
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export { parseGenerationModelRef as parseImageGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js";
|
||||
export { parseGenerationModelRef as parseMusicGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js";
|
||||
export { parseGenerationModelRef as parseVideoGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js";
|
||||
export { parseGenerationModelRef as parseImageGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js"; // Sanctioned domain alias.
|
||||
export { parseGenerationModelRef as parseMusicGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js"; // Sanctioned domain alias.
|
||||
export { parseGenerationModelRef as parseVideoGenerationModelRef } from "../../packages/media-generation-core/src/model-ref.js"; // Sanctioned domain alias.
|
||||
|
||||
@@ -17,7 +17,7 @@ vi.mock("../auto-reply/reply/commands-status.js", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../gateway/session-utils.js", () => ({
|
||||
loadSessionEntryReadOnly: loadSessionEntry,
|
||||
loadGatewaySessionEntryReadOnly: loadSessionEntry,
|
||||
}));
|
||||
|
||||
vi.mock("../agents/agent-scope.js", () => ({
|
||||
|
||||
@@ -8,7 +8,7 @@ import { resolveCurrentDirectiveLevels } from "../auto-reply/reply/directive-han
|
||||
import { createModelSelectionState } from "../auto-reply/reply/model-selection.js";
|
||||
import type { ReplyPayload } from "../auto-reply/types.js";
|
||||
import type { OpenClawConfig } from "../config/types.openclaw.js";
|
||||
import { loadSessionEntryReadOnly } from "../gateway/session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../gateway/session-utils.js";
|
||||
|
||||
/** Inputs for rendering direct-session status replies outside the active channel turn. */
|
||||
export type ResolveDirectStatusReplyForSessionParams = {
|
||||
@@ -43,7 +43,7 @@ export async function resolveDirectStatusReplyForSessionCore(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const statusLoaded = loadSessionEntryReadOnly(requestedSessionKey);
|
||||
const statusLoaded = loadGatewaySessionEntryReadOnly(requestedSessionKey);
|
||||
const statusCfg = statusLoaded.cfg ?? params.cfg;
|
||||
const statusSessionKey = statusLoaded.canonicalKey;
|
||||
const statusEntry = statusLoaded.entry;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createMediaProviderRegistry } from "../media-generation/provider-registry.js";
|
||||
export { normalizeCapabilityProviderId as normalizeTranscriptSourceProviderId } from "../plugins/provider-registry-shared.js";
|
||||
export { normalizeCapabilityProviderId as normalizeTranscriptSourceProviderId } from "../plugins/provider-registry-shared.js"; // Sanctioned domain alias.
|
||||
|
||||
/** Transcript providers use targeted lookup to avoid broad capability discovery. */
|
||||
export const {
|
||||
|
||||
@@ -232,7 +232,7 @@ vi.mock("../gateway/session-utils.js", () => ({
|
||||
loadCombinedSessionStoreForGatewayMock(...args),
|
||||
loadSessionEntry: (sessionKey: string, opts?: { agentId?: string }) =>
|
||||
loadSessionEntryMock(sessionKey, opts),
|
||||
loadSessionEntryReadOnly: (sessionKey: string, opts?: { agentId?: string }) =>
|
||||
loadGatewaySessionEntryReadOnly: (sessionKey: string, opts?: { agentId?: string }) =>
|
||||
loadSessionEntryMock(sessionKey, opts),
|
||||
resolveCanonicalGatewaySessionStoreKey: ({ key }: { key: string }) => ({
|
||||
primaryKey: key,
|
||||
|
||||
@@ -75,7 +75,7 @@ import {
|
||||
listSessionsFromStoreAsync,
|
||||
loadCombinedSessionStoreForGatewayCore,
|
||||
loadSessionEntry,
|
||||
loadSessionEntryReadOnly,
|
||||
loadGatewaySessionEntryReadOnly,
|
||||
resolveCanonicalGatewaySessionStoreKey,
|
||||
resolveGatewaySessionStoreTargetWithStore,
|
||||
resolveSessionModelRef,
|
||||
@@ -627,7 +627,7 @@ export class EmbeddedTuiBackend implements TuiBackend {
|
||||
async loadHistory(opts: { sessionKey: string; agentId?: string; limit?: number }) {
|
||||
await this.ready;
|
||||
const loadOptions = opts.agentId ? { agentId: opts.agentId } : undefined;
|
||||
const { cfg, storePath, store, entry, canonicalKey } = loadSessionEntryReadOnly(
|
||||
const { cfg, storePath, store, entry, canonicalKey } = loadGatewaySessionEntryReadOnly(
|
||||
opts.sessionKey,
|
||||
{ ...loadOptions, includeStoreChildEntries: true },
|
||||
);
|
||||
@@ -807,7 +807,7 @@ export class EmbeddedTuiBackend implements TuiBackend {
|
||||
|
||||
async resetSession(key: string, reason?: "new" | "reset", opts?: { agentId?: string }) {
|
||||
await this.ready;
|
||||
if (loadSessionEntryReadOnly(key, opts).entry?.incognito === true) {
|
||||
if (loadGatewaySessionEntryReadOnly(key, opts).entry?.incognito === true) {
|
||||
throw new Error("Incognito sessions cannot reset in place.");
|
||||
}
|
||||
const result = await performGatewaySessionReset({
|
||||
|
||||
@@ -15,7 +15,7 @@ import { READ_SCOPE } from "../../../../src/gateway/method-scopes.js";
|
||||
import { clearModelAuthStatusUsageCache } from "../../../../src/gateway/server-methods/models-auth-status-usage-cache.js";
|
||||
import { testApi as usageTestApi } from "../../../../src/gateway/server-methods/usage.js";
|
||||
import { startGatewayServer } from "../../../../src/gateway/server.js";
|
||||
import { loadSessionEntryReadOnly } from "../../../../src/gateway/session-utils.js";
|
||||
import { loadGatewaySessionEntryReadOnly } from "../../../../src/gateway/session-utils.js";
|
||||
import {
|
||||
connectGatewayClient,
|
||||
disconnectGatewayClient,
|
||||
@@ -204,7 +204,7 @@ describe("gateway usage and memory APIs", () => {
|
||||
sessionId: FIXTURE_SESSION_ID,
|
||||
storePath: databasePath,
|
||||
});
|
||||
const storedSession = loadSessionEntryReadOnly(FIXTURE_SESSION_KEY);
|
||||
const storedSession = loadGatewaySessionEntryReadOnly(FIXTURE_SESSION_KEY);
|
||||
expect(storedSession).toMatchObject({
|
||||
entry: {
|
||||
sessionId: FIXTURE_SESSION_ID,
|
||||
|
||||
@@ -41,6 +41,12 @@ describe("changed path facts", () => {
|
||||
isTestOnly: true,
|
||||
isNativeOnly: false,
|
||||
});
|
||||
expect(getChangedPathFacts("src/gateway/server.auth.control-ui.suite.ts")).toMatchObject({
|
||||
surface: "source",
|
||||
isChangedLaneTest: true,
|
||||
isTestOnly: true,
|
||||
isNativeOnly: false,
|
||||
});
|
||||
expect(getChangedPathFacts("apps/shared/OpenClawKit/Sources/Foo.swift")).toMatchObject({
|
||||
surface: "app",
|
||||
isChangedLaneTest: false,
|
||||
|
||||
@@ -78,6 +78,9 @@ describe("CI changed Node test plan", () => {
|
||||
expect(hasBuildArtifactAffectingChange(["src/agents/foo.test.ts", "test/helpers/x.ts"])).toBe(
|
||||
false,
|
||||
);
|
||||
expect(hasBuildArtifactAffectingChange(["src/gateway/server.auth.control-ui.suite.ts"])).toBe(
|
||||
false,
|
||||
);
|
||||
expect(hasBuildArtifactAffectingChange(["src/agents/foo.ts"])).toBe(true);
|
||||
// Build-input classification: only sources and the build pipeline can
|
||||
// change dist bytes; repo scripts, workflows, and qa scenarios cannot.
|
||||
|
||||
@@ -210,8 +210,8 @@ describe("oxlint config", () => {
|
||||
},
|
||||
{
|
||||
files: [
|
||||
"**/*.test.ts",
|
||||
"**/*.test.tsx",
|
||||
"**/*.{test,suite}.ts",
|
||||
"**/*.{test,suite}.tsx",
|
||||
"**/*.e2e.test.ts",
|
||||
"**/*.live.test.ts",
|
||||
"**/*test-harness.ts",
|
||||
@@ -246,6 +246,17 @@ describe("oxlint config", () => {
|
||||
expect(override.excludeFiles).toContain("ui/src/i18n/locales/**");
|
||||
expect(override.excludeFiles).toContain("src/wizard/i18n/locales/**");
|
||||
}
|
||||
for (const override of scopedBudgets.slice(0, 3)) {
|
||||
expect(override.excludeFiles).toContain("**/*.{test,spec,suite}.*");
|
||||
}
|
||||
expect(scopedBudgets[3]?.files).toEqual(
|
||||
expect.arrayContaining([
|
||||
"src/**/*.{test,spec,suite}.*",
|
||||
"ui/src/**/*.{test,spec,suite}.*",
|
||||
"packages/**/*.{test,spec,suite}.*",
|
||||
"extensions/**/*.{test,spec,suite}.*",
|
||||
]),
|
||||
);
|
||||
expect(exactExceptions).toEqual([
|
||||
{
|
||||
files: ["extensions/copilot/src/event-bridge.ts"],
|
||||
|
||||
Reference in New Issue
Block a user