77 */
88
99import type { ExtensionAPI , ToolDefinition } from "@earendil-works/pi-coding-agent" ;
10+ import { Text } from "@earendil-works/pi-tui" ;
1011import { Type } from "typebox" ;
1112import type { AgenticodingState } from "../state.js" ;
12- import { formatEntryList , getEntryNames , saveLedgerEntry } from "./store.js" ;
13+ import { updateIndicators } from "../tui.js" ;
14+ import { formatEntryList , formatEntryPreview , getEntryNames , saveLedgerEntry } from "./store.js" ;
1315
1416// ── Factory ───────────────────────────────────────────────────────────
1517
@@ -62,18 +64,52 @@ export function createLedgerToolDefinitions(
6264 "Truncated at 50KB / 2000 lines." ,
6365 } ) ,
6466 } ) ,
65- async execute ( _toolCallId , params , _signal , _onUpdate , _ctx ) {
67+ renderCall ( args , theme , _context ) {
68+ const preview = formatEntryPreview ( args . content ) . trim ( ) ;
69+
70+ let text = theme . fg ( "toolTitle" , theme . bold ( "ledger_add " ) ) +
71+ theme . fg ( "accent" , `"${ args . name } "` ) ;
72+ if ( preview ) {
73+ text += ": " + theme . fg ( "dim" , preview ) ;
74+ }
75+ return new Text ( text , 0 , 0 ) ;
76+ } ,
77+
78+ renderResult ( result , { expanded } , theme , context ) {
79+ const details = result . details as { entries : string [ ] ; preview : string } ;
80+
81+ let text = theme . fg ( "success" , "\u2713 Saved " ) + theme . fg ( "accent" , `"${ context . args . name } "` ) ;
82+ if ( details . preview ) {
83+ text += ": " + theme . fg ( "dim" , details . preview ) ;
84+ }
85+ if ( expanded ) {
86+ text += "\n" + theme . fg ( "dim" , details . entries . join ( "\n" ) ) ;
87+ }
88+ return new Text ( text , 0 , 0 ) ;
89+ } ,
90+
91+ async execute ( _toolCallId , params , _signal , onUpdate , ctx ) {
6692 assertFresh ( ) ;
67- const names = await saveLedgerEntry ( pi , state , params . name , params . content , assertFresh ) ;
93+ const saved = await saveLedgerEntry ( pi , state , params . name , params . content , assertFresh ) ;
94+ updateIndicators ( ctx , state ) ;
95+
96+ onUpdate ?.( {
97+ content : [ {
98+ type : "text" ,
99+ text : `Saved "${ params . name } "` + ( saved . preview ? `: ${ saved . preview } ` : "" ) ,
100+ } ] ,
101+ details : { entries : saved . entries , preview : saved . preview } ,
102+ } ) ;
68103 return {
69104 content : [
70105 {
71106 type : "text" ,
72107 text : `Saved ledger entry "${ params . name } ".` +
108+ ( saved . preview ? `\n${ saved . preview } ` : "" ) +
73109 `\n\nEntries:\n${ formatEntryList ( state ) || "(empty)" } ` ,
74110 } ,
75111 ] ,
76- details : { entries : names } ,
112+ details : { entries : saved . entries , preview : saved . preview } ,
77113 } ;
78114 } ,
79115 } ;
@@ -92,6 +128,22 @@ export function createLedgerToolDefinitions(
92128 description : "Entry name to retrieve." ,
93129 } ) ,
94130 } ) ,
131+ renderResult ( result , { expanded } , theme , context ) {
132+ const details = result . details as { entries : string [ ] ; found : boolean ; body ?: string } ;
133+ if ( ! details . found ) {
134+ return new Text (
135+ theme . fg ( "error" , "\u2717 " ) + theme . fg ( "muted" , `"${ context . args . name } " not found` ) ,
136+ 0 ,
137+ 0 ,
138+ ) ;
139+ }
140+ let text = theme . fg ( "success" , "\u2713 " ) + theme . fg ( "accent" , `"${ context . args . name } "` ) ;
141+ if ( expanded && details . body ) {
142+ text += "\n" + theme . fg ( "toolOutput" , details . body . trim ( ) ) ;
143+ }
144+ return new Text ( text , 0 , 0 ) ;
145+ } ,
146+
95147 async execute ( _toolCallId , params , _signal , _onUpdate , _ctx ) {
96148 assertFresh ( ) ;
97149 const content = state . ledger . get ( params . name ) ;
@@ -120,7 +172,7 @@ export function createLedgerToolDefinitions(
120172 `---\nEntries:\n${ formatEntryList ( state ) || "(empty)" } ` ,
121173 } ,
122174 ] ,
123- details : { entries : names , found : true } ,
175+ details : { entries : names , found : true , body : content } ,
124176 } ;
125177 } ,
126178 } ;
@@ -135,6 +187,18 @@ export function createLedgerToolDefinitions(
135187 ? { promptSnippet : "List all ledger entries" }
136188 : { } ) ,
137189 parameters : Type . Object ( { } ) ,
190+ renderResult ( result , { expanded } , theme , _context ) {
191+ const entries = ( result . details as { entries : string [ ] } ) . entries ;
192+ if ( entries . length === 0 ) {
193+ return new Text ( theme . fg ( "dim" , "\u{1F4D2} (empty)" ) , 0 , 0 ) ;
194+ }
195+ let text = theme . fg ( "muted" , `\u{1F4D2} ${ entries . length } entr${ entries . length === 1 ? "y" : "ies" } ` ) ;
196+ if ( expanded ) {
197+ text += "\n" + theme . fg ( "dim" , entries . join ( "\n" ) ) ;
198+ }
199+ return new Text ( text , 0 , 0 ) ;
200+ } ,
201+
138202 async execute ( ) {
139203 assertFresh ( ) ;
140204 const names = getEntryNames ( state ) ;
0 commit comments