Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/split-runtime-kaos.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@moonshot-ai/agent-core": patch
Comment thread
kermanx marked this conversation as resolved.
"@moonshot-ai/kimi-code": patch
---

Split `RuntimeConfig` into `Kaos` and `ToolServices` and update all references accordingly.
4 changes: 2 additions & 2 deletions packages/agent-core/src/agent/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class ConfigState {
private _systemPrompt: string = '';

constructor(protected readonly agent: Agent) {
this._cwd = agent.runtime.kaos.getcwd();
this._cwd = agent.kaos.getcwd();
this._modelAlias = agent.modelProvider?.defaultModel;
}

Expand All @@ -40,7 +40,7 @@ export class ConfigState {
});
if (changed.cwd) {
this._cwd = changed.cwd;
void this.agent.runtime.kaos.chdir(changed.cwd);
void this.agent.kaos.chdir(changed.cwd);
}
if (changed.modelAlias) {
this._modelAlias = changed.modelAlias;
Expand Down
14 changes: 9 additions & 5 deletions packages/agent-core/src/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type { EnabledPluginSessionStart } from '#/plugin';
import type { McpConnectionManager } from '../mcp';
import type { PreparedSystemPromptContext, ResolvedAgentProfile } from '../profile';
import type { ModelProvider } from '../session/provider-manager';
import type { RuntimeConfig } from '../runtime-types';
import type { ToolServices } from '../runtime-types';
import type { SessionSubagentHost } from '../session/subagent-host';
import type { SkillRegistry } from '../skill';
import { noopTelemetryClient, type TelemetryClient } from '../telemetry';
Expand Down Expand Up @@ -54,20 +54,22 @@ import {
} from './turn/kosong-llm';
import { UsageRecorder } from './usage';
import { resolveCompletionBudget } from '../utils/completion-budget';
import type { Kaos } from '@moonshot-ai/kaos';

export type { AgentRecord, AgentRecordPersistence } from './records';
export type { BuiltinTool, ToolInfo, ToolSource, UserToolRegistration } from './tool';

export type AgentType = 'main' | 'sub' | 'independent';

export interface AgentOptions {
readonly runtime: RuntimeConfig;
readonly kaos: Kaos;
readonly config?: KimiConfig;
readonly homedir?: string;
readonly rpc?: Partial<SDKAgentRPC>;
readonly persistence?: AgentRecordPersistence;
readonly type?: AgentType;
readonly generate?: typeof generate;
readonly toolServices?: ToolServices;
readonly compactionStrategy?: CompactionStrategy;
readonly modelProvider?: ModelProvider | undefined;
readonly subagentHost?: SessionSubagentHost | undefined;
Expand All @@ -82,10 +84,11 @@ export interface AgentOptions {

export class Agent {
readonly type: AgentType;
readonly runtime: RuntimeConfig;
readonly kaos: Kaos;
readonly kimiConfig?: KimiConfig;
readonly homedir?: string;
readonly rpc?: Partial<SDKAgentRPC>;
readonly toolServices?: ToolServices;
readonly pluginSessionStarts: readonly EnabledPluginSessionStart[];
readonly rawGenerate: typeof generate;
readonly modelProvider?: ModelProvider;
Expand Down Expand Up @@ -115,10 +118,11 @@ export class Agent {

constructor(options: AgentOptions) {
this.type = options.type ?? 'main';
this.runtime = options.runtime;
this.kaos = options.kaos;
this.kimiConfig = options.config;
this.homedir = options.homedir;
this.rpc = options.rpc;
this.toolServices = options.toolServices;
this.pluginSessionStarts = options.pluginSessionStarts ?? [];
this.rawGenerate = options.generate ?? generate;
this.modelProvider = options.modelProvider;
Expand Down Expand Up @@ -238,7 +242,7 @@ export class Agent {

useProfile(profile: ResolvedAgentProfile, context?: PreparedSystemPromptContext): void {
const systemPrompt = profile.systemPrompt({
osEnv: this.runtime.kaos.osEnv,
osEnv: this.kaos.osEnv,
cwd: this.config.cwd,
skills: this.skills?.registry,
cwdListing: context?.cwdListing,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class GitControlPathAccessAskPermissionPolicy implements PermissionPolicy
async evaluate(context: PermissionPolicyContext): Promise<PermissionPolicyResult | undefined> {
const cwd = this.agent.config.cwd;
if (cwd.length === 0) return;
const pathClass = this.agent.runtime.kaos.pathClass();
const pathClass = this.agent.kaos.pathClass();
const accesses = fileAccesses(context);
if (accesses.length === 0) return;

Expand All @@ -50,7 +50,7 @@ export class GitControlPathAccessAskPermissionPolicy implements PermissionPolicy
};
}

const marker = await findGitWorkTreeMarker(this.agent.runtime.kaos, cwd);
const marker = await findGitWorkTreeMarker(this.agent.kaos, cwd);
if (marker === null) return;
const access = accesses.find((fileAccess) => {
return isGitControlPath(fileAccess.path, marker, pathClass);
Expand All @@ -71,7 +71,7 @@ export class CwdOutsideFileWriteAskPermissionPolicy implements PermissionPolicy
evaluate(context: PermissionPolicyContext): PermissionPolicyResult | undefined {
const cwd = this.agent.config.cwd;
if (cwd.length === 0) return;
const pathClass = this.agent.runtime.kaos.pathClass();
const pathClass = this.agent.kaos.pathClass();
const access = writeFileAccesses(context).find((fileAccess) => {
return !isWithinDirectory(fileAccess.path, cwd, pathClass);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class GitCwdWriteApprovePermissionPolicy implements PermissionPolicy {
async evaluate(context: PermissionPolicyContext): Promise<PermissionPolicyResult | undefined> {
const toolName = context.toolCall.name;
if (toolName !== 'Write' && toolName !== 'Edit') return;
if (this.agent.runtime.kaos.pathClass() !== 'posix') return;
if (this.agent.kaos.pathClass() !== 'posix') return;

const cwd = this.agent.config.cwd;
if (cwd.length === 0) return;
Expand All @@ -23,7 +23,7 @@ export class GitCwdWriteApprovePermissionPolicy implements PermissionPolicy {
return;
}

const marker = await findGitWorkTreeMarker(this.agent.runtime.kaos, cwd);
const marker = await findGitWorkTreeMarker(this.agent.kaos, cwd);
if (marker === null) return;

return {
Expand Down
6 changes: 3 additions & 3 deletions packages/agent-core/src/agent/plan/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export class PlanMode {
if (!this._planId || !this._planFilePath) return null;
let content = '';
try {
content = await this.agent.runtime.kaos.readText(this._planFilePath);
content = await this.agent.kaos.readText(this._planFilePath);
} catch (error) {
if (!isMissingFileError(error)) throw error;
}
Expand All @@ -120,11 +120,11 @@ export class PlanMode {

private async writeEmptyPlanFile(path: string): Promise<void> {
await this.ensurePlanDirectory(path);
await this.agent.runtime.kaos.writeText(path, '');
await this.agent.kaos.writeText(path, '');
}

private async ensurePlanDirectory(path: string): Promise<void> {
await this.agent.runtime.kaos.mkdir(dirname(path), {
await this.agent.kaos.mkdir(dirname(path), {
parents: true,
existOk: true,
});
Expand Down
11 changes: 6 additions & 5 deletions packages/agent-core/src/agent/tool/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,10 @@ export class ToolManager {
return { ...this.store };
}

initializeBuiltinTools(): void {
initializeBuiltinTools() {
const {
runtime: { kaos, urlFetcher, webSearcher },
kaos,
toolServices,
config: { cwd, provider, modelCapabilities },
background,
} = this.agent;
Expand All @@ -365,7 +366,7 @@ export class ToolManager {
new b.EditTool(kaos, workspace),
new b.GrepTool(kaos, workspace),
new b.GlobTool(kaos, workspace),
new b.BashTool(kaos, cwd, kaos.osEnv, background, {
new b.BashTool(kaos, cwd, background, {
allowBackground,
}),
(modelCapabilities.image_in || modelCapabilities.video_in) &&
Expand All @@ -392,8 +393,8 @@ export class ToolManager {
log: this.agent.log,
},
),
webSearcher && new b.WebSearchTool(webSearcher),
urlFetcher && new b.FetchURLTool(urlFetcher),
toolServices?.webSearcher && new b.WebSearchTool(toolServices.webSearcher),
toolServices?.urlFetcher && new b.FetchURLTool(toolServices.urlFetcher),
]
.filter((tool) => !!tool)
.map((tool) => [tool.name, tool] as const),
Expand Down
2 changes: 1 addition & 1 deletion packages/agent-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export type {
BackgroundTaskKind,
BackgroundTaskStatus,
} from './tools/background/manager';
export type { RuntimeConfig } from './runtime-types';
export type { ToolServices } from './runtime-types';
export { SingleModelProvider } from './session/provider-manager';
export type {
BearerTokenProvider,
Expand Down
33 changes: 17 additions & 16 deletions packages/agent-core/src/rpc/core-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { MoonshotFetchURLProvider } from '#/tools/providers/moonshot-fetch-url';
import { MoonshotWebSearchProvider } from '#/tools/providers/moonshot-web-search';
import type { PromisableMethods } from '#/utils/types';
import { getCoreVersion } from '#/version';
import { KaosShellNotFoundError, LocalKaos } from '@moonshot-ai/kaos';
import { resolveThinkingLevel } from '../agent/config/thinking';
import {
ensureKimiHome,
Expand All @@ -23,7 +22,7 @@ import {
} from '../config';
import type { Logger } from '../logging/types';
import { resolveSessionMcpConfig, type SessionMcpConfig } from '../mcp';
import type { RuntimeConfig } from '../runtime-types';
import type { ToolServices } from '../runtime-types';
import { Session, type SessionMeta, type SessionSkillConfig } from '../session';
import { exportSessionDirectory } from '../session/export';
import {
Expand Down Expand Up @@ -84,6 +83,7 @@ import type {
import type { ResumedAgentState, ResumeSessionResult } from './resumed';
import type { SDKRPC } from './sdk-api';
import { proxyWithExtraPayload } from './types';
import { KaosShellNotFoundError, LocalKaos, type Kaos } from '@moonshot-ai/kaos';

const KIMI_CODE_PROVIDER_NAME = 'managed:kimi-code';

Expand All @@ -96,7 +96,7 @@ type UpdateSessionMetadataRequest = SessionScopedPayload<UpdateSessionMetadataPa
export interface KimiCoreOptions {
readonly homeDir?: string | undefined;
readonly configPath?: string | undefined;
readonly runtime?: RuntimeConfig | undefined;
readonly runtime?: ToolServices | undefined;
readonly kimiRequestHeaders?: Record<string, string> | undefined;
readonly resolveOAuthTokenProvider?: OAuthTokenProviderResolver | undefined;
readonly skillDirs?: readonly string[];
Expand All @@ -110,7 +110,8 @@ export class KimiCore implements PromisableMethods<CoreAPI> {
readonly sessions = new Map<string, Session>();
readonly telemetry: TelemetryClient;

private runtime: RuntimeConfig | undefined;
private kaos: Promise<Kaos>;
private runtime: ToolServices | undefined;
private config: KimiConfig;
private readonly userHomeDir: string;
private readonly kimiRequestHeaders: Record<string, string> | undefined;
Expand All @@ -131,6 +132,12 @@ export class KimiCore implements PromisableMethods<CoreAPI> {
homeDir: this.homeDir,
configPath: options.configPath,
});
this.kaos = LocalKaos.create().catch((error: unknown) => {
if (error instanceof KaosShellNotFoundError) {
throw new KimiError(ErrorCodes.SHELL_GIT_BASH_NOT_FOUND, error.message);
Comment thread
kermanx marked this conversation as resolved.
}
throw error;
});
this.runtime = options.runtime;
this.kimiRequestHeaders = options.kimiRequestHeaders;
this.resolveOAuthTokenProvider = options.resolveOAuthTokenProvider;
Expand Down Expand Up @@ -179,7 +186,8 @@ export class KimiCore implements PromisableMethods<CoreAPI> {
// ctor block throws, `session.close()` releases the sink (and mcp).
const runtime = await this.resolveRuntime(config);
const session = new Session({
runtime: { ...runtime, kaos: runtime.kaos.withCwd(workDir) },
kaos: (await this.kaos).withCwd(workDir),
toolServices: runtime,
config,
id,
homedir: summary.sessionDir,
Expand Down Expand Up @@ -259,7 +267,8 @@ export class KimiCore implements PromisableMethods<CoreAPI> {
const mcpConfig = this.mergePluginMcpConfig(baseMcpConfig);
const runtime = await this.resolveRuntime(config);
const session = new Session({
runtime: { ...runtime, kaos: runtime.kaos.withCwd(summary.workDir) },
kaos: (await this.kaos).withCwd(summary.workDir),
toolServices: runtime,
config,
id: summary.id,
homedir: summary.sessionDir,
Expand Down Expand Up @@ -632,7 +641,7 @@ export class KimiCore implements PromisableMethods<CoreAPI> {
);
}

private async resolveRuntime(config: KimiConfig): Promise<RuntimeConfig> {
private async resolveRuntime(config: KimiConfig): Promise<ToolServices> {
if (this.runtime !== undefined) return this.runtime;
const runtime = await createRuntimeConfig({
config,
Expand Down Expand Up @@ -729,20 +738,12 @@ async function createRuntimeConfig(input: {
readonly config: KimiConfig;
readonly kimiRequestHeaders?: Record<string, string> | undefined;
readonly resolveOAuthTokenProvider?: OAuthTokenProviderResolver | undefined;
}): Promise<RuntimeConfig> {
}): Promise<ToolServices> {
const localFetcher = new LocalFetchURLProvider();
const searchService = input.config.services?.moonshotSearch;
const fetchService = input.config.services?.moonshotFetch;

const kaos = await LocalKaos.create().catch((error: unknown) => {
if (error instanceof KaosShellNotFoundError) {
throw new KimiError(ErrorCodes.SHELL_GIT_BASH_NOT_FOUND, error.message);
}
throw error;
});

return {
kaos,
urlFetcher:
fetchService?.baseUrl === undefined
? localFetcher
Expand Down
5 changes: 1 addition & 4 deletions packages/agent-core/src/runtime-types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import type { Kaos } from '@moonshot-ai/kaos';

import type { UrlFetcher, WebSearchProvider } from './tools/builtin';

export interface RuntimeConfig {
readonly kaos: Kaos;
export interface ToolServices {
readonly urlFetcher?: UrlFetcher | undefined;
readonly webSearcher?: WebSearchProvider | undefined;
}
Loading
Loading