Skip to content

Commit 310b5e4

Browse files
committed
test: reduce core command hotspots
1 parent 418056f commit 310b5e4

92 files changed

Lines changed: 5299 additions & 7887 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/agents/agent-command.ts

Lines changed: 119 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import { getAcpSessionManager } from "../acp/control-plane/manager.js";
2-
import { resolveAcpAgentPolicyError, resolveAcpDispatchPolicyError } from "../acp/policy.js";
3-
import { toAcpRuntimeError } from "../acp/runtime/errors.js";
4-
import { resolveAcpSessionCwd } from "../acp/runtime/session-identifiers.js";
51
import {
62
formatThinkingLevels,
73
formatXHighModelHint,
@@ -11,7 +7,7 @@ import {
117
type VerboseLevel,
128
} from "../auto-reply/thinking.js";
139
import { formatCliCommand } from "../cli/command-format.js";
14-
import { type CliDeps, createDefaultDeps } from "../cli/deps.js";
10+
import type { CliDeps } from "../cli/deps.types.js";
1511
import type { SessionEntry } from "../config/sessions/types.js";
1612
import {
1713
clearAgentRunContext,
@@ -20,7 +16,6 @@ import {
2016
} from "../infra/agent-events.js";
2117
import { formatErrorMessage } from "../infra/errors.js";
2218
import { buildOutboundSessionContext } from "../infra/outbound/session-context.js";
23-
import { getRemoteSkillEligibility } from "../infra/skills-remote.js";
2419
import { createSubsystemLogger } from "../logging/subsystem.js";
2520
import { normalizeAgentId } from "../routing/session-key.js";
2621
import { resolveAgentIdFromSessionKey } from "../routing/session-key.js";
@@ -40,8 +35,8 @@ import {
4035
resolveAgentSkillsFilter,
4136
resolveAgentWorkspaceDir,
4237
} from "./agent-scope.js";
43-
import { ensureAuthProfileStore } from "./auth-profiles.js";
4438
import { clearSessionAuthProfileOverride } from "./auth-profiles/session-override.js";
39+
import { ensureAuthProfileStore } from "./auth-profiles/store.js";
4540
import {
4641
persistSessionEntry as persistSessionEntryBase,
4742
prependInternalEventContext,
@@ -50,7 +45,6 @@ import { resolveAgentRunContext } from "./command/run-context.js";
5045
import { resolveSession } from "./command/session.js";
5146
import type { AgentCommandIngressOpts, AgentCommandOpts } from "./command/types.js";
5247
import { DEFAULT_MODEL, DEFAULT_PROVIDER } from "./defaults.js";
53-
import { canExecRequestNode } from "./exec-defaults.js";
5448
import { AGENT_LANE_SUBAGENT } from "./lanes.js";
5549
import { LiveSessionModelSwitchError } from "./live-model-switch.js";
5650
import { loadModelCatalog } from "./model-catalog.js";
@@ -64,29 +58,66 @@ import {
6458
resolveDefaultModelForAgent,
6559
resolveThinkingDefault,
6660
} from "./model-selection.js";
67-
import { buildWorkspaceSkillSnapshot } from "./skills.js";
68-
import { matchesSkillFilter } from "./skills/filter.js";
69-
import { getSkillsSnapshotVersion, shouldRefreshSnapshotForVersion } from "./skills/refresh.js";
7061
import { normalizeSpawnedRunMetadata } from "./spawned-context.js";
7162
import { resolveAgentTimeoutMs } from "./timeout.js";
7263
import { ensureAgentWorkspace } from "./workspace.js";
7364

7465
const log = createSubsystemLogger("agents/agent-command");
7566
type AttemptExecutionRuntime = typeof import("./command/attempt-execution.runtime.js");
67+
type AcpManagerRuntime = typeof import("../acp/control-plane/manager.js");
68+
type AcpPolicyRuntime = typeof import("../acp/policy.js");
69+
type AcpRuntimeErrorsRuntime = typeof import("../acp/runtime/errors.js");
70+
type AcpSessionIdentifiersRuntime = typeof import("../acp/runtime/session-identifiers.js");
7671
type DeliveryRuntime = typeof import("./command/delivery.runtime.js");
7772
type SessionStoreRuntime = typeof import("./command/session-store.runtime.js");
7873
type TranscriptResolveRuntime = typeof import("../config/sessions/transcript-resolve.runtime.js");
74+
type CliDepsRuntime = typeof import("../cli/deps.js");
75+
type ExecDefaultsRuntime = typeof import("./exec-defaults.js");
76+
type SkillsRuntime = typeof import("./skills.js");
77+
type SkillsFilterRuntime = typeof import("./skills/filter.js");
78+
type SkillsRefreshStateRuntime = typeof import("./skills/refresh-state.js");
79+
type SkillsRemoteRuntime = typeof import("../infra/skills-remote.js");
7980

8081
let attemptExecutionRuntimePromise: Promise<AttemptExecutionRuntime> | undefined;
82+
let acpManagerRuntimePromise: Promise<AcpManagerRuntime> | undefined;
83+
let acpPolicyRuntimePromise: Promise<AcpPolicyRuntime> | undefined;
84+
let acpRuntimeErrorsRuntimePromise: Promise<AcpRuntimeErrorsRuntime> | undefined;
85+
let acpSessionIdentifiersRuntimePromise: Promise<AcpSessionIdentifiersRuntime> | undefined;
8186
let deliveryRuntimePromise: Promise<DeliveryRuntime> | undefined;
8287
let sessionStoreRuntimePromise: Promise<SessionStoreRuntime> | undefined;
8388
let transcriptResolveRuntimePromise: Promise<TranscriptResolveRuntime> | undefined;
89+
let cliDepsRuntimePromise: Promise<CliDepsRuntime> | undefined;
90+
let execDefaultsRuntimePromise: Promise<ExecDefaultsRuntime> | undefined;
91+
let skillsRuntimePromise: Promise<SkillsRuntime> | undefined;
92+
let skillsFilterRuntimePromise: Promise<SkillsFilterRuntime> | undefined;
93+
let skillsRefreshStateRuntimePromise: Promise<SkillsRefreshStateRuntime> | undefined;
94+
let skillsRemoteRuntimePromise: Promise<SkillsRemoteRuntime> | undefined;
8495

8596
function loadAttemptExecutionRuntime(): Promise<AttemptExecutionRuntime> {
8697
attemptExecutionRuntimePromise ??= import("./command/attempt-execution.runtime.js");
8798
return attemptExecutionRuntimePromise;
8899
}
89100

101+
function loadAcpManagerRuntime(): Promise<AcpManagerRuntime> {
102+
acpManagerRuntimePromise ??= import("../acp/control-plane/manager.js");
103+
return acpManagerRuntimePromise;
104+
}
105+
106+
function loadAcpPolicyRuntime(): Promise<AcpPolicyRuntime> {
107+
acpPolicyRuntimePromise ??= import("../acp/policy.js");
108+
return acpPolicyRuntimePromise;
109+
}
110+
111+
function loadAcpRuntimeErrorsRuntime(): Promise<AcpRuntimeErrorsRuntime> {
112+
acpRuntimeErrorsRuntimePromise ??= import("../acp/runtime/errors.js");
113+
return acpRuntimeErrorsRuntimePromise;
114+
}
115+
116+
function loadAcpSessionIdentifiersRuntime(): Promise<AcpSessionIdentifiersRuntime> {
117+
acpSessionIdentifiersRuntimePromise ??= import("../acp/runtime/session-identifiers.js");
118+
return acpSessionIdentifiersRuntimePromise;
119+
}
120+
90121
function loadDeliveryRuntime(): Promise<DeliveryRuntime> {
91122
deliveryRuntimePromise ??= import("./command/delivery.runtime.js");
92123
return deliveryRuntimePromise;
@@ -102,6 +133,44 @@ function loadTranscriptResolveRuntime(): Promise<TranscriptResolveRuntime> {
102133
return transcriptResolveRuntimePromise;
103134
}
104135

136+
function loadCliDepsRuntime(): Promise<CliDepsRuntime> {
137+
cliDepsRuntimePromise ??= import("../cli/deps.js");
138+
return cliDepsRuntimePromise;
139+
}
140+
141+
function loadExecDefaultsRuntime(): Promise<ExecDefaultsRuntime> {
142+
execDefaultsRuntimePromise ??= import("./exec-defaults.js");
143+
return execDefaultsRuntimePromise;
144+
}
145+
146+
function loadSkillsRuntime(): Promise<SkillsRuntime> {
147+
skillsRuntimePromise ??= import("./skills.js");
148+
return skillsRuntimePromise;
149+
}
150+
151+
function loadSkillsFilterRuntime(): Promise<SkillsFilterRuntime> {
152+
skillsFilterRuntimePromise ??= import("./skills/filter.js");
153+
return skillsFilterRuntimePromise;
154+
}
155+
156+
function loadSkillsRefreshStateRuntime(): Promise<SkillsRefreshStateRuntime> {
157+
skillsRefreshStateRuntimePromise ??= import("./skills/refresh-state.js");
158+
return skillsRefreshStateRuntimePromise;
159+
}
160+
161+
function loadSkillsRemoteRuntime(): Promise<SkillsRemoteRuntime> {
162+
skillsRemoteRuntimePromise ??= import("../infra/skills-remote.js");
163+
return skillsRemoteRuntimePromise;
164+
}
165+
166+
async function resolveAgentCommandDeps(deps: CliDeps | undefined): Promise<CliDeps> {
167+
if (deps) {
168+
return deps;
169+
}
170+
const { createDefaultDeps } = await loadCliDepsRuntime();
171+
return createDefaultDeps();
172+
}
173+
105174
type PersistSessionEntryParams = {
106175
sessionStore: Record<string, SessionEntry>;
107176
sessionKey: string;
@@ -287,6 +356,7 @@ async function prepareAgentCommandExecution(
287356
});
288357
const workspaceDir = workspace.dir;
289358
const runId = opts.runId?.trim() || sessionId;
359+
const { getAcpSessionManager } = await loadAcpManagerRuntime();
290360
const acpManager = getAcpSessionManager();
291361
const acpResolution = sessionKey
292362
? acpManager.resolveSession({
@@ -325,8 +395,9 @@ async function prepareAgentCommandExecution(
325395
async function agentCommandInternal(
326396
opts: AgentCommandOpts & { senderIsOwner: boolean },
327397
runtime: RuntimeEnv = defaultRuntime,
328-
deps: CliDeps = createDefaultDeps(),
398+
deps?: CliDeps,
329399
) {
400+
const resolvedDeps = await resolveAgentCommandDeps(deps);
330401
const prepared = await prepareAgentCommandExecution(opts, runtime);
331402
const {
332403
body,
@@ -383,6 +454,8 @@ async function agentCommandInternal(
383454
const visibleTextAccumulator = attemptExecutionRuntime.createAcpVisibleTextAccumulator();
384455
let stopReason: string | undefined;
385456
try {
457+
const { resolveAcpAgentPolicyError, resolveAcpDispatchPolicyError } =
458+
await loadAcpPolicyRuntime();
386459
const dispatchPolicyError = resolveAcpDispatchPolicyError(cfg);
387460
if (dispatchPolicyError) {
388461
throw dispatchPolicyError;
@@ -428,6 +501,7 @@ async function agentCommandInternal(
428501
},
429502
});
430503
} catch (error) {
504+
const { toAcpRuntimeError } = await loadAcpRuntimeErrorsRuntime();
431505
const acpError = toAcpRuntimeError({
432506
error,
433507
fallbackCode: "ACP_TURN_FAILED",
@@ -445,6 +519,7 @@ async function agentCommandInternal(
445519
const finalTextRaw = visibleTextAccumulator.finalizeRaw();
446520
const finalText = visibleTextAccumulator.finalize();
447521
try {
522+
const { resolveAcpSessionCwd } = await loadAcpSessionIdentifiersRuntime();
448523
sessionEntry = await attemptExecutionRuntime.persistAcpTurnTranscript({
449524
body,
450525
finalText: finalTextRaw,
@@ -474,7 +549,7 @@ async function agentCommandInternal(
474549

475550
return await deliverAgentCommandResult({
476551
cfg,
477-
deps,
552+
deps: resolvedDeps,
478553
runtime,
479554
opts,
480555
outboundSession,
@@ -495,6 +570,8 @@ async function agentCommandInternal(
495570
});
496571
}
497572

573+
const [{ getSkillsSnapshotVersion, shouldRefreshSnapshotForVersion }, { matchesSkillFilter }] =
574+
await Promise.all([loadSkillsRefreshStateRuntime(), loadSkillsFilterRuntime()]);
498575
const skillsSnapshotVersion = getSkillsSnapshotVersion(workspaceDir);
499576
const skillFilter = resolveAgentSkillsFilter(cfg, sessionAgentId);
500577
const currentSkillsSnapshot = sessionEntry?.skillsSnapshot;
@@ -504,22 +581,33 @@ async function agentCommandInternal(
504581
!matchesSkillFilter(currentSkillsSnapshot.skillFilter, skillFilter);
505582
const needsSkillsSnapshot = isNewSession || shouldRefreshSkillsSnapshot;
506583
const skillsSnapshot = needsSkillsSnapshot
507-
? buildWorkspaceSkillSnapshot(workspaceDir, {
508-
config: cfg,
509-
eligibility: {
510-
remote: getRemoteSkillEligibility({
511-
advertiseExecNode: canExecRequestNode({
512-
cfg,
513-
sessionEntry,
514-
sessionKey,
515-
agentId: sessionAgentId,
584+
? await (async () => {
585+
const [
586+
{ buildWorkspaceSkillSnapshot },
587+
{ getRemoteSkillEligibility },
588+
{ canExecRequestNode },
589+
] = await Promise.all([
590+
loadSkillsRuntime(),
591+
loadSkillsRemoteRuntime(),
592+
loadExecDefaultsRuntime(),
593+
]);
594+
return buildWorkspaceSkillSnapshot(workspaceDir, {
595+
config: cfg,
596+
eligibility: {
597+
remote: getRemoteSkillEligibility({
598+
advertiseExecNode: canExecRequestNode({
599+
cfg,
600+
sessionEntry,
601+
sessionKey,
602+
agentId: sessionAgentId,
603+
}),
516604
}),
517-
}),
518-
},
519-
snapshotVersion: skillsSnapshotVersion,
520-
skillFilter,
521-
agentId: sessionAgentId,
522-
})
605+
},
606+
snapshotVersion: skillsSnapshotVersion,
607+
skillFilter,
608+
agentId: sessionAgentId,
609+
});
610+
})()
523611
: currentSkillsSnapshot;
524612

525613
if (skillsSnapshot && sessionStore && sessionKey && needsSkillsSnapshot) {
@@ -971,7 +1059,7 @@ async function agentCommandInternal(
9711059
const { deliverAgentCommandResult } = await loadDeliveryRuntime();
9721060
return await deliverAgentCommandResult({
9731061
cfg,
974-
deps,
1062+
deps: resolvedDeps,
9751063
runtime,
9761064
opts,
9771065
outboundSession,
@@ -987,7 +1075,7 @@ async function agentCommandInternal(
9871075
export async function agentCommand(
9881076
opts: AgentCommandOpts,
9891077
runtime: RuntimeEnv = defaultRuntime,
990-
deps: CliDeps = createDefaultDeps(),
1078+
deps?: CliDeps,
9911079
) {
9921080
return await agentCommandInternal(
9931081
{
@@ -1007,7 +1095,7 @@ export async function agentCommand(
10071095
export async function agentCommandFromIngress(
10081096
opts: AgentCommandIngressOpts,
10091097
runtime: RuntimeEnv = defaultRuntime,
1010-
deps: CliDeps = createDefaultDeps(),
1098+
deps?: CliDeps,
10111099
) {
10121100
if (typeof opts.senderIsOwner !== "boolean") {
10131101
// HTTP/WS ingress must declare the trust level explicitly at the boundary.

src/agents/auth-health.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
import type { OpenClawConfig } from "../config/types.openclaw.js";
22
import {
33
type AuthCredentialReasonCode,
4-
type AuthProfileCredential,
5-
type AuthProfileStore,
6-
resolveAuthProfileDisplayLabel,
7-
} from "./auth-profiles.js";
8-
import {
94
evaluateStoredCredentialEligibility,
105
resolveTokenExpiryState,
116
} from "./auth-profiles/credential-state.js";
7+
import { resolveAuthProfileDisplayLabel } from "./auth-profiles/display.js";
8+
import type { AuthProfileCredential, AuthProfileStore } from "./auth-profiles/types.js";
129
import { normalizeProviderId } from "./provider-id.js";
1310

1411
export type AuthProfileSource = "store";

src/agents/auth-profiles/oauth.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,26 @@ describe("resolveApiKeyForProfile token expiry handling", () => {
299299
});
300300

301301
describe("resolveApiKeyForProfile secret refs", () => {
302+
it("ignores blank api_key credentials", async () => {
303+
const profileId = "openrouter:default";
304+
const result = await resolveApiKeyForProfile({
305+
cfg: cfgFor(profileId, "openrouter", "api_key"),
306+
store: {
307+
version: 1,
308+
profiles: {
309+
[profileId]: {
310+
type: "api_key",
311+
provider: "openrouter",
312+
key: " ",
313+
},
314+
},
315+
},
316+
profileId,
317+
});
318+
319+
expect(result).toBeNull();
320+
});
321+
302322
it("resolves api_key keyRef from env", async () => {
303323
const profileId = "openai:default";
304324
const previous = process.env.OPENAI_API_KEY;

src/agents/cli-runner/execute.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,10 @@ export async function executePreparedCliRun(
467467
...parsed,
468468
rawText,
469469
finalPromptText: prompt,
470-
text: applyPluginTextReplacements(rawText, context.backendResolved.textTransforms?.output),
470+
text: applyPluginTextReplacements(
471+
rawText,
472+
context.backendResolved.textTransforms?.output,
473+
),
471474
};
472475
} finally {
473476
restoreSkillEnv?.();

src/agents/command/attempt-execution.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,17 @@ describe("createAcpVisibleTextAccumulator", () => {
204204

205205
expect(acc.finalize()).toBe("NO_REPLY: explanation");
206206
});
207+
208+
it("buffers chunked NO_REPLY prefixes before emitting visible text", () => {
209+
const acc = createAcpVisibleTextAccumulator();
210+
211+
expect(acc.consume("NO")).toBeNull();
212+
expect(acc.consume("NO_")).toBeNull();
213+
expect(acc.consume("NO_RE")).toBeNull();
214+
expect(acc.consume("NO_REPLY")).toBeNull();
215+
expect(acc.consume("Actual answer")).toEqual({
216+
text: "Actual answer",
217+
delta: "Actual answer",
218+
});
219+
});
207220
});

0 commit comments

Comments
 (0)