@@ -25,6 +25,7 @@ import {
2525} from '#/tui/controllers/editor-keyboard' ;
2626import { ImageAttachmentStore } from '#/tui/utils/image-attachment-store' ;
2727import { parseImageMeta } from '#/utils/image/image-mime' ;
28+ import { ImageLimits , type KimiHarness } from '@moonshot-ai/kimi-code-sdk' ;
2829
2930// vitest hoists vi.mock/vi.hoisted above the imports above, so the mock still
3031// applies to the editor-keyboard module that pulls in readClipboardMedia.
@@ -41,7 +42,7 @@ interface PasteHarness {
4142 pasteImage ( ) : Promise < void > ;
4243}
4344
44- function createPasteHarness ( options : { sessionDir ?: string } = { } ) : PasteHarness {
45+ function createPasteHarness ( options : { sessionDir ?: string ; imageLimits ?: ImageLimits } = { } ) : PasteHarness {
4546 const editor : Record < string , ( ( ...args : never [ ] ) => unknown ) | undefined > = {
4647 setHistoryFilter : vi . fn ( ) as unknown as ( ...args : never [ ] ) => unknown ,
4748 } ;
@@ -65,6 +66,11 @@ function createPasteHarness(options: { sessionDir?: string } = {}): PasteHarness
6566 openUndoSelector : vi . fn ( ) ,
6667 cancelRunningShellCommand : vi . fn ( ) ,
6768 } as unknown as EditorKeyboardHost ;
69+ if ( options . imageLimits !== undefined ) {
70+ ( host as unknown as { harness : KimiHarness } ) . harness = {
71+ imageLimits : options . imageLimits ,
72+ } as unknown as KimiHarness ;
73+ }
6874
6975 const controller = new EditorKeyboardController ( host , store ) ;
7076 controller . install ( ) ;
@@ -151,6 +157,25 @@ describe('clipboard image paste compression', () => {
151157 expect ( Math . max ( dims ! . width , dims ! . height ) ) . toBeLessThanOrEqual ( 2000 ) ;
152158 } ) ;
153159
160+ it ( 'honors the harness [image] max_edge_px when pasting' , async ( ) => {
161+ const big = await solidPng ( 3600 , 1800 ) ;
162+ readClipboardMedia . mockResolvedValue ( { kind : 'image' , bytes : big , mimeType : 'image/png' } ) ;
163+
164+ const { store, pasteImage } = createPasteHarness ( {
165+ imageLimits : new ImageLimits ( process . env , { maxEdgePx : 800 } ) ,
166+ } ) ;
167+ await pasteImage ( ) ;
168+
169+ const att = store . get ( 1 ) ;
170+ if ( att ?. kind !== 'image' ) throw new Error ( 'expected image attachment' ) ;
171+ // The harness [image] config — not the built-in 2000px — drives ingestion.
172+ expect ( Math . max ( att . width , att . height ) ) . toBe ( 800 ) ;
173+ expect ( att . placeholder ) . toContain ( '800×400' ) ;
174+ const dims = parseImageMeta ( att . bytes ) ;
175+ expect ( dims ) . not . toBeNull ( ) ;
176+ expect ( Math . max ( dims ! . width , dims ! . height ) ) . toBe ( 800 ) ;
177+ } ) ;
178+
154179 it ( 'records and persists the pre-compression original for an oversized paste' , async ( ) => {
155180 const big = await solidPng ( 3600 , 1800 ) ;
156181 readClipboardMedia . mockResolvedValue ( { kind : 'image' , bytes : big , mimeType : 'image/png' } ) ;
0 commit comments