refactor(agent-core-v2): move thinking helpers from config to profile

- Host resolveThinkingEffort/resolveThinkingLevel in the profile domain,
  the owner of the thinking/defaultThinking config sections, so they use
  the authoritative ThinkingConfig from configSection.ts.
- Drop the local ThinkingConfigDefaults structural duplicate that existed
  only to keep config (L2) from importing upward into profile (L4).
- Update profile/profileService consumers and the config barrel, and move
  the test alongside the helpers.
This commit is contained in:
haozhe.yang 2026-07-01 18:39:01 +08:00
parent b64539ddd7
commit b9259abd3f
6 changed files with 14 additions and 19 deletions

View file

@ -89,7 +89,7 @@ pass `ConfigTarget.Memory` for a per-run override that is never written to disk.
- `src/config/config.ts``IConfigRegistry` / `IConfigService` tokens, `ConfigSection`, `ConfigEffectiveOverlay`, event types.
- `src/config/configService.ts``ConfigRegistry` + `ConfigService` impl; self-registers at App scope.
- `src/config/toml.ts` — generic snake_case ↔ camelCase machinery plus the registry-aware `transformTomlData` / `applySectionToToml` entry points. Per-domain normalization lives in the section owner's `configSection.ts` (registered as `fromToml` / `toToml`); this module stays free of any other domain's semantics.
- `src/config/thinking.ts` — `resolveThinkingEffort` / `resolveThinkingLevel` helpers (own a local `ThinkingConfigDefaults` structural type; do not import `profile`).
- `src/profile/thinking.ts` (owner domain, not `config`) — `resolveThinkingEffort` / `resolveThinkingLevel` helpers; uses the authoritative `ThinkingConfig` from `configSection.ts`.
- `src/config/configPure.ts``isPlainObject`, `deepMerge`, `omitUndefined`, `describeUnknownError`.
A domain that owns a section keeps the schema in its own `configSection.ts` (e.g. `src/flag/flag.ts` for `experimental`, `src/profile/configSection.ts` for `thinking`, `src/loop/configSection.ts` for `loopControl`). A cross-section env overlay (e.g. the `KIMI_MODEL_*` synthesis) lives in the owning domain too (`src/provider/envOverlay.ts`) and is registered via `IConfigRegistry.registerEffectiveOverlay`.

View file

@ -2,10 +2,10 @@ import type {
ChatProvider,
ModelCapability,
ProviderConfig,
ThinkingEffort,
} from '@moonshot-ai/kosong';
import { createDecorator } from "#/_base/di";
import type { ThinkingEffort } from '#/app/config/thinking';
import type { ToolSource } from '#/agent/tool';
/**

View file

@ -16,13 +16,14 @@ import {
type ChatProvider,
type ModelCapability,
type ProviderConfig,
type ThinkingEffort,
} from '@moonshot-ai/kosong';
import picomatch from 'picomatch';
import { ErrorCodes, KimiError } from "#/errors";
import { IBootstrapService } from '#/app/bootstrap';
import { IConfigRegistry, IConfigService } from '#/app/config';
import { resolveThinkingEffort, type ThinkingEffort } from '#/app/config/thinking';
import { resolveThinkingEffort } from './thinking';
import { applyKimiModelOverrides, IChatProviderFactory, type KimiModelOverrides } from '#/app/chatProvider';
import type { LoopControl } from '#/agent/loop/configSection';
import { IKaos } from '#/app/kaos';

View file

@ -1,26 +1,21 @@
/**
* `config` domain (L2) thinking-level normalization helpers.
* `profile` domain thinking-level resolution helpers.
*
* Owns a local structural `ThinkingConfigDefaults` type so `config` does not
* reach upward into `profile`, which owns the authoritative
* `ThinkingConfigSchema`.
* Resolves the effective `ThinkingEffort` from a requested level, the
* `thinking` config section (`ThinkingConfig`, owned here in `profile`), and
* the `defaultThinking` toggle. Pure functions; own no scoped state.
*/
import type { ThinkingEffort } from '@moonshot-ai/kosong';
export type { ThinkingEffort };
export interface ThinkingConfigDefaults {
readonly mode?: 'auto' | 'on' | 'off' | undefined;
readonly effort?: string | undefined;
}
import type { ThinkingConfig } from './configSection';
const DEFAULT_THINKING_EFFORT: ThinkingEffort = 'high';
const THINKING_EFFORTS = new Set<ThinkingEffort>(['low', 'medium', 'high', 'xhigh', 'max']);
export interface ResolveThinkingLevelOptions {
readonly defaultThinking?: boolean | undefined;
readonly thinking?: ThinkingConfigDefaults | undefined;
readonly defaultThinking?: boolean;
readonly thinking?: ThinkingConfig;
}
export function resolveThinkingLevel(
@ -39,7 +34,7 @@ export function resolveThinkingLevel(
export function resolveThinkingEffort(
requested: string | undefined,
defaults: ThinkingConfigDefaults | undefined,
defaults: ThinkingConfig | undefined,
): ThinkingEffort {
const configEffort = parseEffort(defaults?.effort) ?? DEFAULT_THINKING_EFFORT;
const normalized = requested?.trim().toLowerCase();

View file

@ -6,4 +6,3 @@
export * from './config';
export * from './configService';
export * from './thinking';

View file

@ -3,9 +3,9 @@ import { describe, expect, it } from 'vitest';
import {
resolveThinkingEffort,
resolveThinkingLevel,
} from '#/app/config/thinking';
} from '#/agent/profile/thinking';
describe('config/thinking', () => {
describe('profile/thinking', () => {
describe('resolveThinkingEffort', () => {
it('returns config effort when no request', () => {
expect(resolveThinkingEffort(undefined, { effort: 'low' })).toBe('low');