From 16499408d5891a779c1c240ab64fbf225dc560d0 Mon Sep 17 00:00:00 2001 From: Haozhe Date: Wed, 19 Aug 2026 16:52:51 +0800 Subject: [PATCH] refactor(agent-core-v2): extract externalHooks into a scope-organized feature (#2805) Move the external hook services out of app/externalHooksRunner, session/externalHooks, and agent/externalHooks into features/externalHooks, assembled as the ExternalHooksFeature unit: - services live under per-scope subdirectories (app/, session/, agent/); shared pure helpers (types, hook matching/dispatch, process spawn, prompt result rendering) live under internal/ - the runner and the two observers are contributed through the Feature seams (ScopeUnits materialization); the hooks config section stays on the static import=register channel - update the package entry leaf exports, the plugin domain imports, the kap-server events-zod import, and the affected tests; regenerate the state manifest --- apps/kimi-code/src/cli/v2/run-v2-print.ts | 2 +- packages/agent-core-v2/AGENTS.md | 2 +- .../agent-core-v2/docs/config-manifest.toml | 4 +- .../agent-core-v2/docs/state-manifest.d.ts | 6 +- .../src/app/externalHooksRunner/index.ts | 2 - .../agent-core-v2/src/app/plugin/manager.ts | 2 +- .../agent-core-v2/src/app/plugin/manifest.ts | 2 +- .../agent-core-v2/src/app/plugin/plugin.ts | 2 +- .../src/app/plugin/pluginService.ts | 2 +- .../agent-core-v2/src/app/plugin/types.ts | 2 +- .../agent/agentExternalHooks.ts} | 6 -- .../agent/agentExternalHooksService.ts} | 18 +--- .../externalHooks/app}/externalHooksRunner.ts | 2 +- .../app}/externalHooksRunnerService.ts | 18 +--- .../externalHooks/configSection.ts | 2 +- .../externalHooks/externalHooksFeature.ts | 32 +++++++ .../externalHooks/internal/matchHooks.ts} | 9 +- .../externalHooks/internal/runHook.ts} | 0 .../externalHooks/internal}/types.ts | 0 .../externalHooks/internal/userPrompt.ts} | 0 .../session/sessionExternalHooks.ts} | 0 .../session/sessionExternalHooksService.ts} | 14 +-- packages/agent-core-v2/src/index.ts | 15 ++-- .../src/session/externalHooks/index.ts | 2 - .../fullCompaction/fullCompaction.test.ts | 4 +- .../test/agent/task/rpc-events.test.ts | 2 +- .../externalHooksFeature.test.ts | 89 +++++++++++++++++++ .../externalHooksRunner.test.ts | 2 +- .../externalHooks}/integration.test.ts | 18 ++-- .../externalHooks/runner-stub.ts | 6 +- .../externalHooks/runner.test.ts | 2 +- packages/agent-core-v2/test/harness/agent.ts | 7 ++ packages/agent-core-v2/test/tool/tool.test.ts | 2 +- .../kap-server/src/protocol/events-zod.ts | 2 +- .../src/services/transcript/coreEventMap.ts | 2 +- .../klient/src/contract/global/plugins.ts | 2 +- 36 files changed, 186 insertions(+), 96 deletions(-) delete mode 100644 packages/agent-core-v2/src/app/externalHooksRunner/index.ts rename packages/agent-core-v2/src/{agent/externalHooks/externalHooks.ts => features/externalHooks/agent/agentExternalHooks.ts} (67%) rename packages/agent-core-v2/src/{agent/externalHooks/externalHooksService.ts => features/externalHooks/agent/agentExternalHooksService.ts} (96%) rename packages/agent-core-v2/src/{app/externalHooksRunner => features/externalHooks/app}/externalHooksRunner.ts (97%) rename packages/agent-core-v2/src/{app/externalHooksRunner => features/externalHooks/app}/externalHooksRunnerService.ts (84%) rename packages/agent-core-v2/src/{agent => features}/externalHooks/configSection.ts (95%) create mode 100644 packages/agent-core-v2/src/features/externalHooks/externalHooksFeature.ts rename packages/agent-core-v2/src/{app/externalHooksRunner/runner.ts => features/externalHooks/internal/matchHooks.ts} (95%) rename packages/agent-core-v2/src/{agent/externalHooks/runner.ts => features/externalHooks/internal/runHook.ts} (100%) rename packages/agent-core-v2/src/{agent/externalHooks => features/externalHooks/internal}/types.ts (100%) rename packages/agent-core-v2/src/{agent/externalHooks/user-prompt.ts => features/externalHooks/internal/userPrompt.ts} (100%) rename packages/agent-core-v2/src/{session/externalHooks/externalHooks.ts => features/externalHooks/session/sessionExternalHooks.ts} (100%) rename packages/agent-core-v2/src/{session/externalHooks/externalHooksService.ts => features/externalHooks/session/sessionExternalHooksService.ts} (92%) delete mode 100644 packages/agent-core-v2/src/session/externalHooks/index.ts create mode 100644 packages/agent-core-v2/test/features/externalHooks/externalHooksFeature.test.ts rename packages/agent-core-v2/test/{app/externalHooksRunner => features/externalHooks}/externalHooksRunner.test.ts (99%) rename packages/agent-core-v2/test/{app/externalHooksRunner => features/externalHooks}/integration.test.ts (98%) rename packages/agent-core-v2/test/{agent => features}/externalHooks/runner-stub.ts (84%) rename packages/agent-core-v2/test/{agent => features}/externalHooks/runner.test.ts (98%) diff --git a/apps/kimi-code/src/cli/v2/run-v2-print.ts b/apps/kimi-code/src/cli/v2/run-v2-print.ts index c6c955d18..d4f0a38e5 100644 --- a/apps/kimi-code/src/cli/v2/run-v2-print.ts +++ b/apps/kimi-code/src/cli/v2/run-v2-print.ts @@ -65,7 +65,7 @@ import type { ToolCallDelta, } from '@moonshot-ai/agent-core-v2/agent/loop/turnEvents'; import type { TurnStepRetrying } from '@moonshot-ai/agent-core-v2/agent/stepRetry/stepRetryService'; -import type { HookResult } from '@moonshot-ai/agent-core-v2/agent/externalHooks/externalHooksService'; +import type { HookResult } from '@moonshot-ai/agent-core-v2/features/externalHooks/agent/agentExternalHooksService'; import type { ToolCallStarted, ToolProgress, diff --git a/packages/agent-core-v2/AGENTS.md b/packages/agent-core-v2/AGENTS.md index 65426e7ae..e9cd9b809 100644 --- a/packages/agent-core-v2/AGENTS.md +++ b/packages/agent-core-v2/AGENTS.md @@ -19,7 +19,7 @@ The DI kernel (`src/_base/di/`) owns the unit layer on top of the scoped registr The four contribution seams (token → fold): config sections — `ConfigSectionContribution` → `ConfigRegistry` fold (`src/app/config/`; module-level `registerConfigSection` stays the static built-in channel drained at construction, a withdrawn runtime record unregisters the section while user TOML values survive); agent tools — `AgentToolContribution` → `AgentToolActivationService` fold (built-in records provided once at App scope by `builtinToolAssemblyService`; `registerAgentToolService` stays the static channel: Agent-scope DI `OnDemand` registration + module table); agent profiles — `AgentProfileContribution` → `IAgentProfileRegistry` fold (see Scopes); event/state vocabulary — `EventStateContribution` → `IEventDispatcher` fold (a record bundles `events`; `registerEvent2Class` stays the static channel drained at fold time, while `defineState(...).replayable(...)` keys are explicit owner-service contributions: each replayable key's owning service contributes it via `contributeState` at construction — Agent-scope owners are eager, the session-domain todo/cron/interaction keys bridge through `agentLifecycle.onDidCreate` before `restore()` — and replaying a withdrawn domain's history lands on the unknown-type skip-and-count path). A fifth seam: executable commands — `CommandContribution` → `IAgentCommandService` fold (`src/agent/command/`; a contributed command runs engine-side — `run(ctx)` gets `ctx.get` resolving through the agent container, valid only during the synchronous part of `run`; name-level dedup, last record wins; surfaced over RPC as `agentCommandService.list` / `run`). -`src/features/` — built-in capabilities authored as self-contained Feature units (`plan` was the first, extracted from `agent/plan` + `agent/tools/plan`; `swarm` followed, extracted from `agent/swarm` + `session/swarm` + `agent/tools/agent-swarm` into a scope-organized `agent/` + `session/` + `tools/` layout; `tower` lives here as `features/tower/` — protocol store, rate limit, tower-mode service, eleven `Tower*` tools, the `tower-worker` profile, and the `/tower` skill body). A `Feature` (`src/features/feature.ts`) is an App-scope unit recipe with a `static override readonly name` and `contribute*` helpers composing the seams: `contributeService(scope, id, ctor)` / `contributeAgentService` (per-scope materialization via `ScopeUnits` — provider death retracts everywhere, 连坐), `contributeTool` (per-agent `OnDemand` registration + the `AgentToolContribution` record), `contributeProfiles`, `contributeConfig`, `contributeCommand`, plus `onDispose`. Feature modules self-register at import (`registerFeature`, `src/features/featureRegistry.ts`); the App-scope `IFeatureAssemblyService` drains the table through `IFeatureManager.provideUnit`, so every feature is a named, introspectable, retractable managed unit. Built-in features keep user-facing static contracts — config sections, agent profiles, wire vocabulary — on the static import=register channels (the config/state manifest generators read static tables / call sites; wire records must stay replayable); the Feature unit carries the runtime capabilities (services, tools, commands). The string form of the unit `on(...)` capability (`this.on('turn.ended', …)`) is backed by the production `FiberEventResolver` registered in `src/app/event/fiberEventResolver.ts`, resolving against the scope's `IEventBus`. +`src/features/` — built-in capabilities authored as self-contained Feature units (`plan` was the first, extracted from `agent/plan` + `agent/tools/plan`; `externalHooks` from `app/externalHooksRunner` + `session/externalHooks` + `agent/externalHooks`; `swarm` followed, extracted from `agent/swarm` + `session/swarm` + `agent/tools/agent-swarm` into a scope-organized `agent/` + `session/` + `tools/` layout; `tower` lives here as `features/tower/` — protocol store, rate limit, tower-mode service, eleven `Tower*` tools, the `tower-worker` profile, and the `/tower` skill body). A `Feature` (`src/features/feature.ts`) is an App-scope unit recipe with a `static override readonly name` and `contribute*` helpers composing the seams: `contributeService(scope, id, ctor)` / `contributeAgentService` (per-scope materialization via `ScopeUnits` — provider death retracts everywhere, 连坐), `contributeTool` (per-agent `OnDemand` registration + the `AgentToolContribution` record), `contributeProfiles`, `contributeConfig`, `contributeCommand`, plus `onDispose`. Feature modules self-register at import (`registerFeature`, `src/features/featureRegistry.ts`); the App-scope `IFeatureAssemblyService` drains the table through `IFeatureManager.provideUnit`, so every feature is a named, introspectable, retractable managed unit. Built-in features keep user-facing static contracts — config sections, agent profiles, wire vocabulary — on the static import=register channels (the config/state manifest generators read static tables / call sites; wire records must stay replayable); the Feature unit carries the runtime capabilities (services, tools, commands). The string form of the unit `on(...)` capability (`this.on('turn.ended', …)`) is backed by the production `FiberEventResolver` registered in `src/app/event/fiberEventResolver.ts`, resolving against the scope's `IEventBus`. ## Ledger and cascade (L0/L2) diff --git a/packages/agent-core-v2/docs/config-manifest.toml b/packages/agent-core-v2/docs/config-manifest.toml index 99b6a14c4..f36724a39 100644 --- a/packages/agent-core-v2/docs/config-manifest.toml +++ b/packages/agent-core-v2/docs/config-manifest.toml @@ -17,7 +17,7 @@ # experimental src/app/flag/flag.ts # extraAgentDirs src/workspace/workspaceAgentProfileLoader/configSection.ts # extraSkillDirs src/app/skillCatalog/configSection.ts -# hooks src/agent/externalHooks/configSection.ts +# hooks src/features/externalHooks/configSection.ts # identity src/app/agentIdentity/configSection.ts # image src/agent/media/configSection.ts # loopControl src/agent/loop/configSection.ts @@ -135,7 +135,7 @@ extra_skill_dirs = [] # ########################################################################## # hooks -# owner: src/agent/externalHooks/configSection.ts +# owner: src/features/externalHooks/configSection.ts # scope: core # hooks: custom fromToml · custom toToml # ########################################################################## diff --git a/packages/agent-core-v2/docs/state-manifest.d.ts b/packages/agent-core-v2/docs/state-manifest.d.ts index 3400b04ee..81d2a4674 100644 --- a/packages/agent-core-v2/docs/state-manifest.d.ts +++ b/packages/agent-core-v2/docs/state-manifest.d.ts @@ -69,7 +69,7 @@ // contextProjector.lastRepairSignature src/agent/contextProjector/contextProjectorService.ts // cron src/session/cron/cronOps.ts // dateChange.seed src/features/dateChange/dateChangeService.ts -// externalHooks.stopHookContinuationUsed src/agent/externalHooks/externalHooksService.ts +// externalHooks.stopHookContinuationUsed src/features/externalHooks/agent/agentExternalHooksService.ts // fullCompaction src/agent/fullCompaction/compactionOps.ts // fullCompaction.activeTurnId src/agent/fullCompaction/fullCompactionService.ts // fullCompaction.compactionCountInTurn src/agent/fullCompaction/fullCompactionService.ts @@ -1188,8 +1188,6 @@ export interface AgentStateSnapshot { })[]; // src/agent/contextProjector/contextProjectorService.ts 'contextProjector.lastRepairSignature': string | null; - // src/agent/externalHooks/externalHooksService.ts - 'externalHooks.stopHookContinuationUsed': boolean; // src/agent/fullCompaction/compactionOps.ts // replayable · durable — folds: FullCompactionBegin, FullCompactionCancel, FullCompactionComplete 'fullCompaction': /* CompactionState — packages/agent-core-v2/src/agent/fullCompaction/compactionOps.ts */ { @@ -1575,6 +1573,8 @@ export interface AgentStateSnapshot { readonly timeZone: string; readonly renderGeneration: number; } | undefined; + // src/features/externalHooks/agent/agentExternalHooksService.ts + 'externalHooks.stopHookContinuationUsed': boolean; // src/features/plan/injection/planModeInjection.ts 'plan.wasActive': boolean; // src/features/plan/planOps.ts diff --git a/packages/agent-core-v2/src/app/externalHooksRunner/index.ts b/packages/agent-core-v2/src/app/externalHooksRunner/index.ts deleted file mode 100644 index 1d86c94a8..000000000 --- a/packages/agent-core-v2/src/app/externalHooksRunner/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './externalHooksRunner'; -export * from './externalHooksRunnerService'; diff --git a/packages/agent-core-v2/src/app/plugin/manager.ts b/packages/agent-core-v2/src/app/plugin/manager.ts index 83c797f7c..d041757b5 100644 --- a/packages/agent-core-v2/src/app/plugin/manager.ts +++ b/packages/agent-core-v2/src/app/plugin/manager.ts @@ -3,7 +3,7 @@ import { tmpdir } from 'node:os'; import path from 'node:path'; import { BugIndicatingError, Error2, ErrorCodes, PluginErrors } from '#/errors'; -import type { HookDef } from '#/agent/externalHooks/types'; +import type { HookDef } from '#/features/externalHooks/internal/types'; import type { McpServerConfig } from '#/mcpCore/config-schema'; import type { PluginAgentRoot } from './types'; import { discoverFileSkills } from '#/app/skillCatalog/fileSkillDiscovery'; diff --git a/packages/agent-core-v2/src/app/plugin/manifest.ts b/packages/agent-core-v2/src/app/plugin/manifest.ts index 8ceac789e..cc5ca205a 100644 --- a/packages/agent-core-v2/src/app/plugin/manifest.ts +++ b/packages/agent-core-v2/src/app/plugin/manifest.ts @@ -1,7 +1,7 @@ import { readdir, readFile, realpath, stat } from 'node:fs/promises'; import path from 'node:path'; -import { HookDefSchema, type HookDefConfig } from '#/agent/externalHooks/configSection'; +import { HookDefSchema, type HookDefConfig } from '#/features/externalHooks/configSection'; import { McpServerConfigSchema, type McpServerConfig } from '#/mcpCore/config-schema'; import { diff --git a/packages/agent-core-v2/src/app/plugin/plugin.ts b/packages/agent-core-v2/src/app/plugin/plugin.ts index 04579e6f0..fe2754b18 100644 --- a/packages/agent-core-v2/src/app/plugin/plugin.ts +++ b/packages/agent-core-v2/src/app/plugin/plugin.ts @@ -1,6 +1,6 @@ import { createDecorator, type ServiceIdentifier } from '#/_base/di/instantiation'; import type { Event } from '#/_base/event'; -import type { HookDef } from '#/agent/externalHooks/types'; +import type { HookDef } from '#/features/externalHooks/internal/types'; import type { McpServerConfig } from '#/mcpCore/config-schema'; import type { SkillRoot } from '#/app/skillCatalog/types'; diff --git a/packages/agent-core-v2/src/app/plugin/pluginService.ts b/packages/agent-core-v2/src/app/plugin/pluginService.ts index c5634d6a5..9de12b153 100644 --- a/packages/agent-core-v2/src/app/plugin/pluginService.ts +++ b/packages/agent-core-v2/src/app/plugin/pluginService.ts @@ -8,7 +8,7 @@ import { BugIndicatingError, Error2, PluginErrors } from '#/errors'; import { IBootstrapService } from '#/app/bootstrap/bootstrap'; import { IProviderService } from '#/kosong/provider/provider'; import { ISkillDiscovery } from '#/app/skillCatalog/skillDiscovery'; -import type { HookDef } from '#/agent/externalHooks/types'; +import type { HookDef } from '#/features/externalHooks/internal/types'; import type { McpServerConfig } from '#/mcpCore/config-schema'; import type { SkillRoot } from '#/app/skillCatalog/types'; diff --git a/packages/agent-core-v2/src/app/plugin/types.ts b/packages/agent-core-v2/src/app/plugin/types.ts index 1e2146e15..8ae8afbe2 100644 --- a/packages/agent-core-v2/src/app/plugin/types.ts +++ b/packages/agent-core-v2/src/app/plugin/types.ts @@ -1,4 +1,4 @@ -import type { HookDefConfig } from '#/agent/externalHooks/configSection'; +import type { HookDefConfig } from '#/features/externalHooks/configSection'; import type { McpServerConfig } from '#/mcpCore/config-schema'; export type PluginDiagnosticSeverity = 'error' | 'warn' | 'info'; diff --git a/packages/agent-core-v2/src/agent/externalHooks/externalHooks.ts b/packages/agent-core-v2/src/features/externalHooks/agent/agentExternalHooks.ts similarity index 67% rename from packages/agent-core-v2/src/agent/externalHooks/externalHooks.ts rename to packages/agent-core-v2/src/features/externalHooks/agent/agentExternalHooks.ts index 6aae3f2e5..6df416a69 100644 --- a/packages/agent-core-v2/src/agent/externalHooks/externalHooks.ts +++ b/packages/agent-core-v2/src/features/externalHooks/agent/agentExternalHooks.ts @@ -1,11 +1,5 @@ import { createDecorator } from '#/_base/di/instantiation'; -export interface RenderedExternalHookResult { - readonly event: string; - readonly message: string; - readonly text: string; -} - export interface IAgentExternalHooksService { readonly _serviceBrand: undefined; } diff --git a/packages/agent-core-v2/src/agent/externalHooks/externalHooksService.ts b/packages/agent-core-v2/src/features/externalHooks/agent/agentExternalHooksService.ts similarity index 96% rename from packages/agent-core-v2/src/agent/externalHooks/externalHooksService.ts rename to packages/agent-core-v2/src/features/externalHooks/agent/agentExternalHooksService.ts index 95a2bedf6..e7866de5c 100644 --- a/packages/agent-core-v2/src/agent/externalHooks/externalHooksService.ts +++ b/packages/agent-core-v2/src/features/externalHooks/agent/agentExternalHooksService.ts @@ -1,8 +1,6 @@ /* oxlint-disable typescript-eslint/no-unsafe-declaration-merging, eslint-plugin-import/namespace -- Event2 class+payload-interface declaration merging is the sanctioned event-declaration idiom. */ import { IInstantiationService } from '#/_base/di/instantiation'; import { Service } from '#/_base/di/service'; -import { LifecycleScope } from '#/app/scopes'; -import { ScopeActivation, registerScopedService } from '#/_base/di/scope'; import { defineState } from '#/state/state'; import { isPlainRecord } from '#/_base/utils/canonical-args'; import { IAgentStateService } from '#/agent/state/agentState'; @@ -39,13 +37,13 @@ import { ISessionContext } from '#/session/sessionContext/sessionContext'; import { ISessionMetadata } from '#/session/sessionMetadata/sessionMetadata'; import { IEventDispatcher } from '#/state/eventDispatcher'; -import { IAgentExternalHooksService } from './externalHooks'; -import { IExternalHooksRunnerService } from '#/app/externalHooksRunner/externalHooksRunner'; -import type { HookMatcherValue } from './types'; +import { IAgentExternalHooksService } from './agentExternalHooks'; +import { IExternalHooksRunnerService } from '../app/externalHooksRunner'; +import type { HookMatcherValue } from '../internal/types'; import { renderUserPromptHookBlockResult, renderUserPromptHookResult, -} from './user-prompt'; +} from '../internal/userPrompt'; export interface HookResultPayload { readonly turnId?: number; @@ -471,11 +469,3 @@ function toolOutputText(output: ExecutableToolResult['output']): string { .map((part) => part.text) .join(''); } - -registerScopedService( - LifecycleScope.Agent, - IAgentExternalHooksService, - AgentExternalHooksService, - ScopeActivation.OnScopeCreated, - 'externalHooks', -); diff --git a/packages/agent-core-v2/src/app/externalHooksRunner/externalHooksRunner.ts b/packages/agent-core-v2/src/features/externalHooks/app/externalHooksRunner.ts similarity index 97% rename from packages/agent-core-v2/src/app/externalHooksRunner/externalHooksRunner.ts rename to packages/agent-core-v2/src/features/externalHooks/app/externalHooksRunner.ts index 21a6ba106..9550e55fa 100644 --- a/packages/agent-core-v2/src/app/externalHooksRunner/externalHooksRunner.ts +++ b/packages/agent-core-v2/src/features/externalHooks/app/externalHooksRunner.ts @@ -1,6 +1,6 @@ import { createDecorator, type ServiceIdentifier } from '#/_base/di/instantiation'; import type { Event } from '#/_base/event'; -import type { HookBlockDecision, HookMatcherValue, HookResult } from '#/agent/externalHooks/types'; +import type { HookBlockDecision, HookMatcherValue, HookResult } from '../internal/types'; export interface ExternalHooksRunnerTriggerArgs { readonly matcherValue?: HookMatcherValue; diff --git a/packages/agent-core-v2/src/app/externalHooksRunner/externalHooksRunnerService.ts b/packages/agent-core-v2/src/features/externalHooks/app/externalHooksRunnerService.ts similarity index 84% rename from packages/agent-core-v2/src/app/externalHooksRunner/externalHooksRunnerService.ts rename to packages/agent-core-v2/src/features/externalHooks/app/externalHooksRunnerService.ts index b36cdbdde..cf0188c49 100644 --- a/packages/agent-core-v2/src/app/externalHooksRunner/externalHooksRunnerService.ts +++ b/packages/agent-core-v2/src/features/externalHooks/app/externalHooksRunnerService.ts @@ -1,20 +1,18 @@ import { Disposable } from '#/_base/di/lifecycle'; -import { LifecycleScope } from '#/app/scopes'; -import { ScopeActivation, registerScopedService } from '#/_base/di/scope'; import { Emitter, type Event } from '#/_base/event'; import { IBootstrapService } from '#/app/bootstrap/bootstrap'; import { IConfigService } from '#/app/config/config'; import { IPluginService } from '#/app/plugin/plugin'; -import { HOOKS_SECTION, type HookDefConfig } from '#/agent/externalHooks/configSection'; -import type { HookBlockDecision, HookDef, HookResult } from '#/agent/externalHooks/types'; import { IHostProcessService } from '#/os/interface/hostProcess'; +import { HOOKS_SECTION, type HookDefConfig } from '../configSection'; import { IExternalHooksRunnerService, type ExternalHooksRunnerTriggerArgs, } from './externalHooksRunner'; -import { blockDecision, indexHooks, runMatchedHooks } from './runner'; -import type { HookRunCallbacks } from './runner'; +import { blockDecision, indexHooks, runMatchedHooks } from '../internal/matchHooks'; +import type { HookRunCallbacks } from '../internal/matchHooks'; +import type { HookBlockDecision, HookDef, HookResult } from '../internal/types'; export class ExternalHooksRunnerService extends Disposable implements IExternalHooksRunnerService { declare readonly _serviceBrand: undefined; @@ -120,11 +118,3 @@ export class ExternalHooksRunnerService extends Disposable implements IExternalH this._onDidReload.fire(); } } - -registerScopedService( - LifecycleScope.App, - IExternalHooksRunnerService, - ExternalHooksRunnerService, - ScopeActivation.OnScopeCreated, - 'externalHooksRunner', -); diff --git a/packages/agent-core-v2/src/agent/externalHooks/configSection.ts b/packages/agent-core-v2/src/features/externalHooks/configSection.ts similarity index 95% rename from packages/agent-core-v2/src/agent/externalHooks/configSection.ts rename to packages/agent-core-v2/src/features/externalHooks/configSection.ts index e9550c4a2..8e397d549 100644 --- a/packages/agent-core-v2/src/agent/externalHooks/configSection.ts +++ b/packages/agent-core-v2/src/features/externalHooks/configSection.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import { registerConfigSection } from '#/app/config/configSectionContributions'; import { isPlainObject, plainObjectToToml, transformPlainObject } from '#/app/config/toml'; -import { HOOK_EVENT_TYPES } from './types'; +import { HOOK_EVENT_TYPES } from './internal/types'; export const HOOKS_SECTION = 'hooks'; diff --git a/packages/agent-core-v2/src/features/externalHooks/externalHooksFeature.ts b/packages/agent-core-v2/src/features/externalHooks/externalHooksFeature.ts new file mode 100644 index 000000000..5c4204e5c --- /dev/null +++ b/packages/agent-core-v2/src/features/externalHooks/externalHooksFeature.ts @@ -0,0 +1,32 @@ +import { LifecycleScope } from '#/app/scopes'; +import { Feature } from '#/features/feature'; +import { registerFeature } from '#/features/featureRegistry'; + +import './configSection'; +import { IAgentExternalHooksService } from './agent/agentExternalHooks'; +import { AgentExternalHooksService } from './agent/agentExternalHooksService'; +import { IExternalHooksRunnerService } from './app/externalHooksRunner'; +import { ExternalHooksRunnerService } from './app/externalHooksRunnerService'; +import { ISessionExternalHooksService } from './session/sessionExternalHooks'; +import { SessionExternalHooksService } from './session/sessionExternalHooksService'; + +export class ExternalHooksFeature extends Feature { + static override readonly name = 'externalHooks'; + + constructor() { + super(); + this.contributeService( + LifecycleScope.App, + IExternalHooksRunnerService, + ExternalHooksRunnerService, + ); + this.contributeService( + LifecycleScope.Session, + ISessionExternalHooksService, + SessionExternalHooksService, + ); + this.contributeAgentService(IAgentExternalHooksService, AgentExternalHooksService); + } +} + +registerFeature(ExternalHooksFeature); diff --git a/packages/agent-core-v2/src/app/externalHooksRunner/runner.ts b/packages/agent-core-v2/src/features/externalHooks/internal/matchHooks.ts similarity index 95% rename from packages/agent-core-v2/src/app/externalHooksRunner/runner.ts rename to packages/agent-core-v2/src/features/externalHooks/internal/matchHooks.ts index 60d4c7ee6..4266078c8 100644 --- a/packages/agent-core-v2/src/app/externalHooksRunner/runner.ts +++ b/packages/agent-core-v2/src/features/externalHooks/internal/matchHooks.ts @@ -1,13 +1,14 @@ -import { runHook } from '#/agent/externalHooks/runner'; +import type { IHostProcessService } from '#/os/interface/hostProcess'; + +import { runHook } from './runHook'; import type { HookBlockDecision, HookDef, HookMatcherValue, HookResult, -} from '#/agent/externalHooks/types'; -import type { IHostProcessService } from '#/os/interface/hostProcess'; +} from './types'; -import type { ExternalHooksRunnerTriggerArgs } from './externalHooksRunner'; +import type { ExternalHooksRunnerTriggerArgs } from '../app/externalHooksRunner'; const DEFAULT_HOOK_TIMEOUT_SECONDS = 30; diff --git a/packages/agent-core-v2/src/agent/externalHooks/runner.ts b/packages/agent-core-v2/src/features/externalHooks/internal/runHook.ts similarity index 100% rename from packages/agent-core-v2/src/agent/externalHooks/runner.ts rename to packages/agent-core-v2/src/features/externalHooks/internal/runHook.ts diff --git a/packages/agent-core-v2/src/agent/externalHooks/types.ts b/packages/agent-core-v2/src/features/externalHooks/internal/types.ts similarity index 100% rename from packages/agent-core-v2/src/agent/externalHooks/types.ts rename to packages/agent-core-v2/src/features/externalHooks/internal/types.ts diff --git a/packages/agent-core-v2/src/agent/externalHooks/user-prompt.ts b/packages/agent-core-v2/src/features/externalHooks/internal/userPrompt.ts similarity index 100% rename from packages/agent-core-v2/src/agent/externalHooks/user-prompt.ts rename to packages/agent-core-v2/src/features/externalHooks/internal/userPrompt.ts diff --git a/packages/agent-core-v2/src/session/externalHooks/externalHooks.ts b/packages/agent-core-v2/src/features/externalHooks/session/sessionExternalHooks.ts similarity index 100% rename from packages/agent-core-v2/src/session/externalHooks/externalHooks.ts rename to packages/agent-core-v2/src/features/externalHooks/session/sessionExternalHooks.ts diff --git a/packages/agent-core-v2/src/session/externalHooks/externalHooksService.ts b/packages/agent-core-v2/src/features/externalHooks/session/sessionExternalHooksService.ts similarity index 92% rename from packages/agent-core-v2/src/session/externalHooks/externalHooksService.ts rename to packages/agent-core-v2/src/features/externalHooks/session/sessionExternalHooksService.ts index f51cc3f42..9b6aa2251 100644 --- a/packages/agent-core-v2/src/session/externalHooks/externalHooksService.ts +++ b/packages/agent-core-v2/src/features/externalHooks/session/sessionExternalHooksService.ts @@ -1,8 +1,5 @@ import { Service } from '#/_base/di/service'; -import { LifecycleScope } from '#/app/scopes'; -import { ScopeActivation, registerScopedService } from '#/_base/di/scope'; import { IntervalTimer } from '#/_base/utils/timer'; -import { IExternalHooksRunnerService } from '#/app/externalHooksRunner/externalHooksRunner'; import { ISessionManager } from '#/app/sessionManager/sessionManager'; import { IModelService } from '#/kosong/model/model'; import { @@ -20,7 +17,8 @@ import { type SessionCreateSource, } from '#/workspace/sessionLifecycle/sessionLifecycle'; -import { ISessionExternalHooksService } from './externalHooks'; +import { IExternalHooksRunnerService } from '../app/externalHooksRunner'; +import { ISessionExternalHooksService } from './sessionExternalHooks'; type SessionStartHookSource = Exclude; @@ -183,11 +181,3 @@ export class SessionExternalHooksService }); } } - -registerScopedService( - LifecycleScope.Session, - ISessionExternalHooksService, - SessionExternalHooksService, - ScopeActivation.OnScopeCreated, - 'externalHooks', -); diff --git a/packages/agent-core-v2/src/index.ts b/packages/agent-core-v2/src/index.ts index 0995dc5b2..31db38ea9 100644 --- a/packages/agent-core-v2/src/index.ts +++ b/packages/agent-core-v2/src/index.ts @@ -322,6 +322,14 @@ export * from '#/features/plan/plan'; export * from '#/features/plan/planOps'; export * from '#/features/plan/planService'; import '#/features/plan/planFeature'; +export * from '#/features/externalHooks/configSection'; +export * from '#/features/externalHooks/app/externalHooksRunner'; +export * from '#/features/externalHooks/app/externalHooksRunnerService'; +export * from '#/features/externalHooks/session/sessionExternalHooks'; +export * from '#/features/externalHooks/session/sessionExternalHooksService'; +export * from '#/features/externalHooks/agent/agentExternalHooks'; +export * from '#/features/externalHooks/agent/agentExternalHooksService'; +import '#/features/externalHooks/externalHooksFeature'; export * from '#/features/debugEvents/debugEvents'; export * from '#/features/debugEvents/debugEventsService'; import '#/features/debugEvents/debugEventsFeature'; @@ -455,8 +463,6 @@ export * from '#/workspace/sessionLifecycle/sessionLifecycleEvents'; export * from '#/workspace/sessionLifecycle/sessionLifecycleService'; export * from '#/workspace/sessionLifecycle/coldSessionArchive'; export * from '#/workspace/sessionLifecycle/internal/addressing'; -export * from '#/session/externalHooks/externalHooks'; -export * from '#/session/externalHooks/externalHooksService'; import '#/app/sessionExport/errors'; export * from '#/app/sessionExport/sessionExport'; export * from '#/app/sessionExport/sessionExportService'; @@ -574,8 +580,6 @@ export * from '#/app/edit/editService'; export * from '#/app/edit/textModel'; export * from '#/agent/tools/edit/edit'; import '#/agent/tools/edit/editTool'; -export * from '#/app/externalHooksRunner/externalHooksRunner'; -export * from '#/app/externalHooksRunner/externalHooksRunnerService'; export * from '#/agent/tools/fetch-url/fetch-url'; import '#/agent/tools/fetch-url/fetchUrlTool'; export * from '#/app/web/web'; @@ -611,9 +615,6 @@ export * from '#/agent/contextInjector/contextInjectorService'; export * from '#/agent/plugin/agentPlugin'; export * from '#/agent/plugin/agentPluginOps'; export * from '#/agent/plugin/agentPluginService'; -import '#/agent/externalHooks/configSection'; -export * from '#/agent/externalHooks/externalHooks'; -export * from '#/agent/externalHooks/externalHooksService'; export * from '#/agent/fullCompaction/strategy'; export * from '#/agent/fullCompaction/fullCompaction'; export * from '#/agent/fullCompaction/fullCompactionService'; diff --git a/packages/agent-core-v2/src/session/externalHooks/index.ts b/packages/agent-core-v2/src/session/externalHooks/index.ts deleted file mode 100644 index 2d7b88785..000000000 --- a/packages/agent-core-v2/src/session/externalHooks/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './externalHooks'; -export * from './externalHooksService'; diff --git a/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts b/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts index d371f6847..ba95ede1d 100644 --- a/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts +++ b/packages/agent-core-v2/test/agent/fullCompaction/fullCompaction.test.ts @@ -18,8 +18,8 @@ import { DefaultCompactionStrategy, } from '#/agent/fullCompaction/strategy'; import { COMPACTION_SUMMARY_PREFIX } from '#/agent/contextMemory/compactionHandoff'; -import { makeHookRunner } from '../externalHooks/runner-stub'; -import type { IExternalHooksRunnerService } from '#/app/externalHooksRunner/externalHooksRunner'; +import { makeHookRunner } from '../../features/externalHooks/runner-stub'; +import type { IExternalHooksRunnerService } from '#/features/externalHooks/app/externalHooksRunner'; import { MASTER_ENV } from '#/app/flag/flagService'; import { estimateTokensForMessages } from '#/kosong/contract/tokens'; import { recordingTelemetry, type TelemetryRecord } from '../../app/telemetry/stubs'; diff --git a/packages/agent-core-v2/test/agent/task/rpc-events.test.ts b/packages/agent-core-v2/test/agent/task/rpc-events.test.ts index 3481607c3..262b79a57 100644 --- a/packages/agent-core-v2/test/agent/task/rpc-events.test.ts +++ b/packages/agent-core-v2/test/agent/task/rpc-events.test.ts @@ -19,7 +19,7 @@ import { import { ProcessTask } from '#/agent/tools/os/bash/process-task'; import { IAgentContextMemoryService } from '#/agent/contextMemory/contextMemory'; import { IEventBus } from '#/app/event/eventBus'; -import type { IExternalHooksRunnerService } from '#/app/externalHooksRunner/externalHooksRunner'; +import type { IExternalHooksRunnerService } from '#/features/externalHooks/app/externalHooksRunner'; import { IAgentLoopService } from '#/agent/loop/loop'; import { MessageStepRequest } from '#/agent/loop/stepRequest'; import { IAgentConversationUndoService } from '#/agent/undo/undo'; diff --git a/packages/agent-core-v2/test/features/externalHooks/externalHooksFeature.test.ts b/packages/agent-core-v2/test/features/externalHooks/externalHooksFeature.test.ts new file mode 100644 index 000000000..89f28c4e2 --- /dev/null +++ b/packages/agent-core-v2/test/features/externalHooks/externalHooksFeature.test.ts @@ -0,0 +1,89 @@ +import { beforeEach, describe, expect, it } from 'vitest'; + +import { type CollectionToken, type CollectionView } from '#/_base/di/collection'; +import { ScopeUnits } from '#/_base/di/fiber'; +import { ScopeActivation } from '#/_base/di/instantiation'; +import { type InstantiationService } from '#/_base/di/instantiationService'; +import { _clearScopedRegistryForTests, registerScopedService, type Scope } from '#/_base/di/scope'; +import { createScopedTestHost } from '#/_base/di/test'; +import { Event } from '#/_base/event'; +import { IBootstrapService } from '#/app/bootstrap/bootstrap'; +import { IConfigService } from '#/app/config/config'; +import { IFeatureManager } from '#/app/feature/featureManager'; +import { FeatureManagerService } from '#/app/feature/featureManagerService'; +import { IPluginService } from '#/app/plugin/plugin'; +import { LifecycleScope } from '#/app/scopes'; +import { IFeatureAssemblyService } from '#/features/featureAssembly'; +import { FeatureAssemblyService } from '#/features/featureAssemblyService'; +import { IAgentExternalHooksService } from '#/features/externalHooks/agent/agentExternalHooks'; +import { IExternalHooksRunnerService } from '#/features/externalHooks/app/externalHooksRunner'; +import { ExternalHooksRunnerService } from '#/features/externalHooks/app/externalHooksRunnerService'; +import '#/features/externalHooks/externalHooksFeature'; +import { ISessionExternalHooksService } from '#/features/externalHooks/session/sessionExternalHooks'; +import { IHostProcessService } from '#/os/interface/hostProcess'; + +import { stubBootstrap } from '../../app/bootstrap/stubs'; + +function collectionViewOf(scope: Scope, token: CollectionToken): CollectionView { + return (scope.instantiation as InstantiationService).fiberHost.collectionView(token); +} + +describe('ExternalHooksFeature — assembly (src/features/externalHooks)', () => { + beforeEach(() => { + _clearScopedRegistryForTests(); + registerScopedService( + LifecycleScope.App, + IFeatureManager, + FeatureManagerService, + ScopeActivation.OnScopeCreated, + 'feature', + ); + registerScopedService( + LifecycleScope.App, + IFeatureAssemblyService, + FeatureAssemblyService, + ScopeActivation.OnScopeCreated, + 'features', + ); + }); + + it('assembles the feature and retracts all contributions on unprovide', async () => { + const host = createScopedTestHost([ + [IBootstrapService, stubBootstrap()], + [ + IConfigService, + { _serviceBrand: undefined, ready: Promise.resolve(), get: () => undefined }, + ], + [ + IPluginService, + { _serviceBrand: undefined, enabledHooks: async () => [], onDidReload: Event.None }, + ], + [IHostProcessService, { _serviceBrand: undefined }], + ]); + const manager = host.app.accessor.get(IFeatureManager); + expect(manager.units().map((unit) => unit.name)).toContain('externalHooks'); + + const runner = host.app.accessor.get(IExternalHooksRunnerService); + expect(runner).toBeInstanceOf(ExternalHooksRunnerService); + + const sessionUnits = collectionViewOf(host.app, ScopeUnits(LifecycleScope.Session)); + expect(sessionUnits.items.map((item) => item.name)).toEqual([ + `externalHooks:${String(ISessionExternalHooksService)}`, + ]); + const agentUnits = collectionViewOf(host.app, ScopeUnits(LifecycleScope.Agent)); + expect(agentUnits.items.map((item) => item.name)).toEqual([ + `externalHooks:${String(IAgentExternalHooksService)}`, + ]); + + await manager.unprovideUnit('externalHooks'); + await host.app.instantiation.cascade.whenIdle(); + await new Promise((resolve) => setTimeout(resolve, 0)); + + expect(manager.units()).toHaveLength(0); + expect(() => host.app.accessor.get(IExternalHooksRunnerService)).toThrow(); + expect(sessionUnits.items).toHaveLength(0); + expect(agentUnits.items).toHaveLength(0); + + host.dispose(); + }); +}); diff --git a/packages/agent-core-v2/test/app/externalHooksRunner/externalHooksRunner.test.ts b/packages/agent-core-v2/test/features/externalHooks/externalHooksRunner.test.ts similarity index 99% rename from packages/agent-core-v2/test/app/externalHooksRunner/externalHooksRunner.test.ts rename to packages/agent-core-v2/test/features/externalHooks/externalHooksRunner.test.ts index 86809fa58..4d35a12ed 100644 --- a/packages/agent-core-v2/test/app/externalHooksRunner/externalHooksRunner.test.ts +++ b/packages/agent-core-v2/test/features/externalHooks/externalHooksRunner.test.ts @@ -4,7 +4,7 @@ import { tmpdir } from 'node:os'; import type { ContentPart } from '#/kosong/contract/message'; import { describe, expect, it, vi } from 'vitest'; -import { makeHookRunner } from '../../agent/externalHooks/runner-stub'; +import { makeHookRunner } from './runner-stub'; function nodeCommand(source: string): string { return `node -e ${JSON.stringify(source.replaceAll(/\s*\n\s*/g, ' '))}`; diff --git a/packages/agent-core-v2/test/app/externalHooksRunner/integration.test.ts b/packages/agent-core-v2/test/features/externalHooks/integration.test.ts similarity index 98% rename from packages/agent-core-v2/test/app/externalHooksRunner/integration.test.ts rename to packages/agent-core-v2/test/features/externalHooks/integration.test.ts index 4f9939e68..76e62dde9 100644 --- a/packages/agent-core-v2/test/app/externalHooksRunner/integration.test.ts +++ b/packages/agent-core-v2/test/features/externalHooks/integration.test.ts @@ -26,9 +26,9 @@ import { HOOKS_SECTION, hooksFromToml, hooksToToml, -} from '#/agent/externalHooks/configSection'; -import { IAgentExternalHooksService } from '#/agent/externalHooks/externalHooks'; -import { AgentExternalHooksService } from '#/agent/externalHooks/externalHooksService'; +} from '#/features/externalHooks/configSection'; +import { IAgentExternalHooksService } from '#/features/externalHooks/agent/agentExternalHooks'; +import { AgentExternalHooksService } from '#/features/externalHooks/agent/agentExternalHooksService'; import { IAgentFullCompactionService } from '#/agent/fullCompaction/fullCompaction'; import { IAgentLoopService, type AfterStepContext } from '#/agent/loop/loop'; import { TurnStarted } from '#/agent/loop/turnEvents'; @@ -43,9 +43,9 @@ import { PermissionApprovalResolved, } from '#/agent/toolApproval/toolApprovalService'; import { IAgentToolExecutorService } from '#/agent/toolExecutor/toolExecutor'; -import { IExternalHooksRunnerService } from '#/app/externalHooksRunner/externalHooksRunner'; -import { ExternalHooksRunnerService } from '#/app/externalHooksRunner/externalHooksRunnerService'; -import { makeHookRunner } from '../../agent/externalHooks/runner-stub'; +import { IExternalHooksRunnerService } from '#/features/externalHooks/app/externalHooksRunner'; +import { ExternalHooksRunnerService } from '#/features/externalHooks/app/externalHooksRunnerService'; +import { makeHookRunner } from './runner-stub'; import type { AgentTaskInfo } from '#/agent/task/task'; import { IBootstrapService } from '#/app/bootstrap/bootstrap'; import { IConfigService } from '#/app/config/config'; @@ -69,15 +69,15 @@ import { type AgentTaskStopHookContext, ISessionSubagentService, } from '#/session/subagent/subagent'; -import { ISessionExternalHooksService } from '#/session/externalHooks/externalHooks'; -import { SessionExternalHooksService } from '#/session/externalHooks/externalHooksService'; +import { ISessionExternalHooksService } from '#/features/externalHooks/session/sessionExternalHooks'; +import { SessionExternalHooksService } from '#/features/externalHooks/session/sessionExternalHooksService'; import { ISessionAgentProfileCatalog, } from '#/session/sessionAgentProfileCatalog/sessionAgentProfileCatalog'; import { ISessionMetadata } from '#/session/sessionMetadata/sessionMetadata'; import { IModelService } from '#/kosong/model/model'; -import { stubBootstrap } from '../bootstrap/stubs'; +import { stubBootstrap } from '../../app/bootstrap/stubs'; import { stubLoopWithHooks, stubToolExecutor } from '../../agent/loop/stubs'; import { registerStateServices } from '../../state/stubs'; import { registerTestAgentWireServices } from '../../wire/stubs'; diff --git a/packages/agent-core-v2/test/agent/externalHooks/runner-stub.ts b/packages/agent-core-v2/test/features/externalHooks/runner-stub.ts similarity index 84% rename from packages/agent-core-v2/test/agent/externalHooks/runner-stub.ts rename to packages/agent-core-v2/test/features/externalHooks/runner-stub.ts index 69b45fdd8..cc4599a52 100644 --- a/packages/agent-core-v2/test/agent/externalHooks/runner-stub.ts +++ b/packages/agent-core-v2/test/features/externalHooks/runner-stub.ts @@ -1,7 +1,7 @@ import { Event } from '#/_base/event'; -import { ExternalHooksRunnerService } from '#/app/externalHooksRunner/externalHooksRunnerService'; -import { HOOKS_SECTION } from '#/agent/externalHooks/configSection'; -import type { HookDef } from '#/agent/externalHooks/types'; +import { ExternalHooksRunnerService } from '#/features/externalHooks/app/externalHooksRunnerService'; +import { HOOKS_SECTION } from '#/features/externalHooks/configSection'; +import type { HookDef } from '#/features/externalHooks/internal/types'; import { IBootstrapService } from '#/app/bootstrap/bootstrap'; import { IConfigService } from '#/app/config/config'; import { IPluginService } from '#/app/plugin/plugin'; diff --git a/packages/agent-core-v2/test/agent/externalHooks/runner.test.ts b/packages/agent-core-v2/test/features/externalHooks/runner.test.ts similarity index 98% rename from packages/agent-core-v2/test/agent/externalHooks/runner.test.ts rename to packages/agent-core-v2/test/features/externalHooks/runner.test.ts index 853ff1076..58c029cff 100644 --- a/packages/agent-core-v2/test/agent/externalHooks/runner.test.ts +++ b/packages/agent-core-v2/test/features/externalHooks/runner.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { buildHookSpawnOptions, runHook } from '#/agent/externalHooks/runner'; +import { buildHookSpawnOptions, runHook } from '#/features/externalHooks/internal/runHook'; import { HostProcessService } from '#/os/backends/node-local/hostProcessService'; const hostProcess = new HostProcessService(); diff --git a/packages/agent-core-v2/test/harness/agent.ts b/packages/agent-core-v2/test/harness/agent.ts index e0ff7ac58..b277d82b8 100644 --- a/packages/agent-core-v2/test/harness/agent.ts +++ b/packages/agent-core-v2/test/harness/agent.ts @@ -1183,6 +1183,13 @@ export class AgentTestContext { 'app', ); this.root = createAppScope({ seeds: appSeeds }); + const hookRunnerSeed = appSeeds.find(([id]) => id === IExternalHooksRunnerService); + if (hookRunnerSeed !== undefined) { + this.root.instantiation.provide( + IExternalHooksRunnerService, + hookRunnerSeed[1] as IExternalHooksRunnerService, + ); + } const initialConfig = this.root.accessor.get(IConfigService); this.root.accessor diff --git a/packages/agent-core-v2/test/tool/tool.test.ts b/packages/agent-core-v2/test/tool/tool.test.ts index a89c4343a..f581c4d66 100644 --- a/packages/agent-core-v2/test/tool/tool.test.ts +++ b/packages/agent-core-v2/test/tool/tool.test.ts @@ -18,7 +18,7 @@ import { IAgentContextInjectorService } from '#/agent/contextInjector/contextInj import { IAgentTaskService } from '#/agent/task/task'; import { IAgentContextMemoryService } from '#/agent/contextMemory/contextMemory'; import { IAgentTokenCountingService } from '#/agent/tokenCounting/tokenCounting'; -import { makeHookRunner } from '../agent/externalHooks/runner-stub'; +import { makeHookRunner } from '../features/externalHooks/runner-stub'; import { IAgentProfileService, type ProfileData } from '#/agent/profile/profile'; import { IAgentPermissionModeService } from '#/agent/permissionMode/permissionMode'; import { IAgentRuntimeService } from '#/agent/runtimeBinding/agentRuntime'; diff --git a/packages/kap-server/src/protocol/events-zod.ts b/packages/kap-server/src/protocol/events-zod.ts index 4090490d4..06efcc927 100644 --- a/packages/kap-server/src/protocol/events-zod.ts +++ b/packages/kap-server/src/protocol/events-zod.ts @@ -19,7 +19,7 @@ import type { UserPromptOrigin, } from '@moonshot-ai/agent-core-v2/agent/contextMemory/types'; import { messageContentSchema } from './message'; -import type { HookResultPayload } from '@moonshot-ai/agent-core-v2/agent/externalHooks/externalHooksService'; +import type { HookResultPayload } from '@moonshot-ai/agent-core-v2/features/externalHooks/agent/agentExternalHooksService'; import type { CompactionBlockedPayload, CompactionCompletedPayload, diff --git a/packages/kap-server/src/services/transcript/coreEventMap.ts b/packages/kap-server/src/services/transcript/coreEventMap.ts index 04867cf3e..56f7cdd53 100644 --- a/packages/kap-server/src/services/transcript/coreEventMap.ts +++ b/packages/kap-server/src/services/transcript/coreEventMap.ts @@ -1,6 +1,6 @@ import type { AgentActivityUpdated } from '@moonshot-ai/agent-core-v2/agent/activityView/activityView'; import type { ContextSpliced } from '@moonshot-ai/agent-core-v2/agent/contextMemory/contextEvents'; -import type { HookResult } from '@moonshot-ai/agent-core-v2/agent/externalHooks/externalHooksService'; +import type { HookResult } from '@moonshot-ai/agent-core-v2/features/externalHooks/agent/agentExternalHooksService'; import type { CompactionBlocked, CompactionCancelled, diff --git a/packages/klient/src/contract/global/plugins.ts b/packages/klient/src/contract/global/plugins.ts index 112011221..604707362 100644 --- a/packages/klient/src/contract/global/plugins.ts +++ b/packages/klient/src/contract/global/plugins.ts @@ -2,7 +2,7 @@ * `pluginService` — plugin management and consumption. Mirrors * `agent-core-v2/app/plugin/plugin.ts` and `agent-core-v2/app/plugin/types.ts`; * nested `McpServerConfig` mirrors `agent-core-v2/mcpCore/config-schema.ts`, - * `HookDefConfig` mirrors `agent-core-v2/agent/externalHooks/configSection.ts`. + * `HookDefConfig` mirrors `agent-core-v2/features/externalHooks/configSection.ts`. * `pluginSkillRoots`, `enabledSessionStarts`, `enabledSystemPrompts`, * `enabledMcpServers`, and `enabledHooks` are excluded (not part of the * klient wire surface).