1- import { describe , it , expect } from "vitest" ;
1+ import fs from "node:fs" ;
2+ import { beforeEach , describe , it , expect } from "vitest" ;
3+ import { PROJECTS_ROOT } from "../src/config.ts" ;
4+ import { resolvePaths } from "../src/projects.ts" ;
25import { makeNotebookTool } from "../src/agent/notebook.ts" ;
36import { readNotebookEntries } from "../src/agent/notebook-store.ts" ;
47
58const run = ( tool : ReturnType < typeof makeNotebookTool > , id : string , params : unknown ) =>
69 tool . execute ( id , params as never , undefined as never ) ;
710
11+ beforeEach ( ( ) => {
12+ fs . rmSync ( PROJECTS_ROOT , { recursive : true , force : true } ) ;
13+ fs . mkdirSync ( PROJECTS_ROOT , { recursive : true } ) ;
14+ } ) ;
15+
816describe ( "notebook tool" , ( ) => {
917 it ( "persists a stamped entry and returns a non-blocking ack" , async ( ) => {
1018 const s = "sess-tool-a" ;
@@ -31,6 +39,25 @@ describe("notebook tool", () => {
3139 expect ( typeof entries [ 0 ] . timestamp ) . toBe ( "number" ) ;
3240 } ) ;
3341
42+ it ( "normalizes an absolute sandbox path in artifacts to sandbox-relative" , async ( ) => {
43+ const s = "sess-tool-artifacts" ;
44+ const projectId = "default" ;
45+ const tool = makeNotebookTool ( projectId , ( ) => s ) ;
46+ const sandbox = resolvePaths ( projectId ) . sandbox ;
47+ await run ( tool , "tc_art" , {
48+ type : "method" ,
49+ title : "Ran PCA" ,
50+ artifacts : [ `${ sandbox } /figures/fig01.png` , "figures/already-relative.png" ] ,
51+ } ) ;
52+
53+ const entries = readNotebookEntries ( s , projectId ) ;
54+ expect ( entries ) . toHaveLength ( 1 ) ;
55+ expect ( entries [ 0 ] . artifacts ) . toEqual ( [
56+ "figures/fig01.png" ,
57+ "figures/already-relative.png" ,
58+ ] ) ;
59+ } ) ;
60+
3461 it ( "rejects an empty title" , async ( ) => {
3562 const tool = makeNotebookTool ( "default" , ( ) => "sess-tool-b" ) ;
3663 await expect ( run ( tool , "tc_x" , { type : "note" , title : " " } ) ) . rejects . toThrow ( / t i t l e / i) ;
0 commit comments