From 8b6bc3030174503a350c616d7e8e8cdd1e45c31d Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Sun, 4 Jan 2026 17:16:49 +0100 Subject: [PATCH] fix(hooks): deep copy messages in context event before passing to hooks The context event handler documentation promised a deep copy but the implementation passed the original array reference. This could cause hooks to accidentally mutate session messages. Uses structuredClone() for fast native deep copying. --- packages/coding-agent/src/core/hooks/runner.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/coding-agent/src/core/hooks/runner.ts b/packages/coding-agent/src/core/hooks/runner.ts index d3589e31..eceb1d18 100644 --- a/packages/coding-agent/src/core/hooks/runner.ts +++ b/packages/coding-agent/src/core/hooks/runner.ts @@ -451,11 +451,11 @@ export class HookRunner { * Handlers are chained - each gets the previous handler's output (if any). * Returns the final modified messages, or the original if no modifications. * - * Note: Messages are already deep-copied by the caller (pi-ai preprocessor). + * Messages are deep-copied before passing to hooks, so mutations are safe. */ async emitContext(messages: AgentMessage[]): Promise { const ctx = this.createContext(); - let currentMessages = messages; + let currentMessages = structuredClone(messages); for (const hook of this.hooks) { const handlers = hook.handlers.get("context");