kimi-code / packages /agent-core-v2 /src /agent /toolPolicy /toolPolicyService.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
68d7816 verified
Raw History Blame Contribute Delete
3.56 kB
import { Disposable } from '#/_base/di/lifecycle';
import { LifecycleScope } from '#/app/scopes';
import { ScopeActivation, registerScopedService } from '#/_base/di/scope';
import { IAgentProfileService, ProfileError, ProfileErrors } from '#/agent/profile/profile';
import { TOOLS_SECTION, type ToolsConfig } from './configSection';
import { IAgentToolExecutorService } from '#/agent/toolExecutor/toolExecutor';
import { IConfigService } from '#/app/config/config';
import { ISessionToolPolicy } from '#/session/sessionToolPolicy/sessionToolPolicy';
import { ISessionToolPolicyGate } from '#/session/sessionToolPolicyGate/sessionToolPolicyGate';
import { SELECT_TOOLS_TOOL_NAME } from '#/agent/toolSelect/toolSelect';
import type { ToolSource } from '#/tool/toolContract';
import { isToolActiveComposed, type ToolActivationPolicy } from './evaluate';
import { IAgentToolPolicyService } from './toolPolicy';
export class AgentToolPolicyService extends Disposable implements IAgentToolPolicyService {
declare readonly _serviceBrand: undefined;
constructor(
@IAgentProfileService private readonly profile: IAgentProfileService,
@IConfigService private readonly config: IConfigService,
@ISessionToolPolicy private readonly sessionToolPolicy: ISessionToolPolicy,
@ISessionToolPolicyGate private readonly toolPolicyGate: ISessionToolPolicyGate,
@IAgentToolExecutorService toolExecutor: IAgentToolExecutorService,
) {
super();
this._register(
toolExecutor.registerToolCallGuard(({ name, source }) => {
const active =
name === SELECT_TOOLS_TOOL_NAME
? this.isToolActiveForDisclosure(name, source)
: this.isToolActive(name, source);
return active
? undefined
: `Tool "${name}" is disabled by the active tool policy`;
}),
);
}
isToolActive(name: string, source: ToolSource = 'builtin'): boolean {
const profile = this.profile.data();
return this.isToolActiveForProfile(
{
tools: profile.activeToolNames,
disallowedTools: profile.disallowedTools,
},
name,
source,
);
}
isToolActiveForDisclosure(name: string, source: ToolSource = 'builtin'): boolean {
const profile = this.profile.data();
return isToolActiveComposed(
{
workspaceDisabledTools: this.toolPolicyGate.disabledTools,
profile: { disallowedTools: profile.disallowedTools },
global: this.config.get<ToolsConfig>(TOOLS_SECTION),
sessionDisabledTools: this.sessionToolPolicy.disabledTools(),
},
name,
source,
);
}
isToolActiveForProfile(
profile: ToolActivationPolicy,
name: string,
source: ToolSource = 'builtin',
): boolean {
return isToolActiveComposed(
{
workspaceDisabledTools: this.toolPolicyGate.disabledTools,
profile,
global: this.config.get<ToolsConfig>(TOOLS_SECTION),
sessionDisabledTools: this.sessionToolPolicy.disabledTools(),
},
name,
source,
);
}
async setSessionDisabledTools(names: readonly string[]): Promise<void> {
if (this.profile.data().profileName === undefined) {
throw new ProfileError(
ProfileErrors.codes.PROFILE_NOT_BOUND,
'Cannot set session disabled tools: agent profile is not bound',
);
}
await this.sessionToolPolicy.setDisabledTools(names);
}
}
registerScopedService(
LifecycleScope.Agent,
IAgentToolPolicyService,
AgentToolPolicyService,
ScopeActivation.OnScopeCreated,
'toolPolicy',
);