@@ -70,6 +70,10 @@ export function formatTasksList(
7070 title : task . title || "Untitled" ,
7171 status : task . status || "Unknown" ,
7272 type : task . task_type || "Unknown" ,
73+ sourceLanguage : task . source_language_iso || "Unknown" ,
74+ progress : typeof task . progress === "number" ? `${ task . progress } %` : "N/A" ,
75+ keys : typeof task . keys_count === "number" ? task . keys_count : "N/A" ,
76+ words : typeof task . words_count === "number" ? task . words_count : "N/A" ,
7377 dueDate : formatDueDate ( task . due_date ) ,
7478 created : formatCreatedDate ( task . created_at ) ,
7579 } ) ) ;
@@ -79,13 +83,27 @@ export function formatTasksList(
7983 { key : "title" , header : "Title" , maxWidth : 30 } ,
8084 { key : "status" , header : "Status" } ,
8185 { key : "type" , header : "Type" } ,
86+ { key : "progress" , header : "Progress" } ,
87+ { key : "keys" , header : "Keys" } ,
88+ { key : "words" , header : "Words" } ,
8289 { key : "dueDate" , header : "Due Date" } ,
8390 { key : "created" , header : "Created" } ,
8491 ] ) ;
8592
8693 lines . push ( table ) ;
8794 lines . push ( "" ) ;
8895
96+ // Detailed snapshots per task covering all fields
97+ lines . push ( formatHeading ( "Detailed Task Snapshots" , 2 ) ) ;
98+ lines . push ( "" ) ;
99+ for ( const task of tasks ) {
100+ lines . push (
101+ formatHeading ( `Task #${ task . task_id } – ${ task . title || "Untitled" } ` , 3 ) ,
102+ ) ;
103+ lines . push ( formatTaskSnapshot ( task ) ) ;
104+ lines . push ( "" ) ;
105+ }
106+
89107 // Summary
90108 lines . push ( formatHeading ( "Summary" , 2 ) ) ;
91109 lines . push ( "" ) ;
@@ -135,6 +153,11 @@ export function formatTaskDetails(task: Task, projectId: string): string {
135153 Description : task . description || "*No description provided*" ,
136154 Type : task . task_type || "Unknown" ,
137155 Status : task . status || "Unknown" ,
156+ "Can Be Parent" : boolToYesNo ( task . can_be_parent ) ,
157+ "Parent Task ID" : task . parent_task_id ?? "None" ,
158+ "Closing Tags" : formatArray ( task . closing_tags ) ,
159+ "Lock Translations" : boolToYesNo ( task . do_lock_translations ) ,
160+ "Custom Status IDs" : formatArray ( task . custom_translation_status_ids ) ,
138161 } ;
139162 lines . push ( formatBulletList ( coreInfo ) ) ;
140163 lines . push ( "" ) ;
@@ -153,59 +176,53 @@ export function formatTaskDetails(task: Task, projectId: string): string {
153176 lines . push ( "" ) ;
154177 }
155178
156- // Language assignments
179+ // Language assignments (detailed)
157180 lines . push ( formatHeading ( "Language Assignments" , 2 ) ) ;
158181 if ( task . languages && task . languages . length > 0 ) {
159182 lines . push ( `**Target Languages:** ${ task . languages . length } ` ) ;
160183 lines . push ( "" ) ;
161-
162184 for ( const language of task . languages ) {
163- lines . push ( formatHeading ( language . language_iso . toUpperCase ( ) , 3 ) ) ;
164- lines . push ( "" ) ;
165-
166- if ( language . users && language . users . length > 0 ) {
167- lines . push ( `**Assigned Users (${ language . users . length } ):**` ) ;
168- for ( const user of language . users ) {
169- lines . push (
170- `- ${ user . fullname || user . email || `ID: ${ user . user_id } ` } ` ,
171- ) ;
172- }
173- lines . push ( "" ) ;
174- }
175-
176- if ( language . groups && language . groups . length > 0 ) {
177- lines . push ( `**Assigned Groups (${ language . groups . length } ):**` ) ;
178- for ( const group of language . groups ) {
179- lines . push ( `- ${ group . name || `ID: ${ group . id } ` } ` ) ;
180- }
181- lines . push ( "" ) ;
182- }
183-
184- if (
185- ( ! language . users || language . users . length === 0 ) &&
186- ( ! language . groups || language . groups . length === 0 )
187- ) {
188- lines . push ( "*No specific users or groups assigned to this language*" ) ;
189- lines . push ( "" ) ;
190- }
185+ lines . push ( formatLanguageDetails ( language ) ) ;
191186 }
192187 } else {
193188 lines . push ( "*No languages assigned to this task*" ) ;
194189 lines . push ( "" ) ;
195190 }
196191
197- // Task configuration
198- lines . push ( formatHeading ( "Task Configuration" , 2 ) ) ;
192+ // Task configuration & metrics
193+ lines . push ( formatHeading ( "Configuration & Metrics " , 2 ) ) ;
199194 const configInfo : Record < string , unknown > = {
200195 "Source Language" : task . source_language_iso || "Not specified" ,
201- "Auto-close Languages" : task . auto_close_languages ? "Yes" : "No" ,
202- "Auto-close Task" : task . auto_close_task ? "Yes" : "No" ,
203- "Auto-close Items" : task . auto_close_items ? "Yes" : "No" ,
204- "Lock Translations" : task . do_lock_translations ? "Yes" : "No" ,
196+ "Auto-close Languages" : boolToYesNo ( task . auto_close_languages ) ,
197+ "Auto-close Task" : boolToYesNo ( task . auto_close_task ) ,
198+ "Auto-close Items" : boolToYesNo ( task . auto_close_items ) ,
199+ "Total Keys" : task . keys_count ?? 0 ,
200+ "Total Words" : task . words_count ?? 0 ,
201+ "Overall Progress" :
202+ typeof task . progress === "number" ? `${ task . progress } %` : "N/A" ,
205203 } ;
206204 lines . push ( formatBulletList ( configInfo ) ) ;
207205 lines . push ( "" ) ;
208206
207+ // Audit & completion
208+ lines . push ( formatHeading ( "Audit" , 2 ) ) ;
209+ const auditInfo : Record < string , unknown > = {
210+ "Created By" : task . created_by ?? "Unknown" ,
211+ "Created By Email" : task . created_by_email ?? "Unknown" ,
212+ "Created At" : task . created_at
213+ ? formatCreatedDateWithTime ( task . created_at )
214+ : "Unknown" ,
215+ "Created At (ts)" : task . created_at_timestamp ?? "N/A" ,
216+ "Completed By" : task . completed_by ?? "N/A" ,
217+ "Completed By Email" : task . completed_by_email ?? "N/A" ,
218+ "Completed At" : task . completed_at
219+ ? formatCreatedDateWithTime ( task . completed_at )
220+ : "N/A" ,
221+ "Completed At (ts)" : task . completed_at_timestamp ?? "N/A" ,
222+ } ;
223+ lines . push ( formatBulletList ( auditInfo ) ) ;
224+ lines . push ( "" ) ;
225+
209226 // Summary for LLM reasoning
210227 lines . push ( formatHeading ( "Task Summary" , 2 ) ) ;
211228 lines . push ( "**Task Characteristics:**" ) ;
@@ -586,3 +603,144 @@ function formatScheduleInfo(task: Task): string {
586603 lines . push ( "" ) ;
587604 return lines . join ( "\n" ) ;
588605}
606+
607+ // --- Additional rich formatters ---
608+
609+ function boolToYesNo ( value ?: boolean ) : string {
610+ return value ? "Yes" : "No" ;
611+ }
612+
613+ function formatArray ( arr ?: Array < string | number > | null ) : string {
614+ if ( ! arr || arr . length === 0 ) return "None" ;
615+ return arr . join ( ", " ) ;
616+ }
617+
618+ function formatTaskSnapshot ( task : Task ) : string {
619+ const lines : string [ ] = [ ] ;
620+
621+ const meta : Record < string , unknown > = {
622+ Status : task . status || "Unknown" ,
623+ Type : task . task_type || "Unknown" ,
624+ Progress : typeof task . progress === "number" ? `${ task . progress } %` : "N/A" ,
625+ "Due Date" : task . due_date
626+ ? formatDueDateWithTime ( task . due_date )
627+ : "No deadline" ,
628+ "Due Date (ts)" : task . due_date_timestamp ?? "N/A" ,
629+ "Created At" : task . created_at
630+ ? formatCreatedDateWithTime ( task . created_at )
631+ : "Unknown" ,
632+ "Created At (ts)" : task . created_at_timestamp ?? "N/A" ,
633+ "Created By" : task . created_by ?? "Unknown" ,
634+ "Created By Email" : task . created_by_email ?? "Unknown" ,
635+ "Completed At" : task . completed_at
636+ ? formatCreatedDateWithTime ( task . completed_at )
637+ : "N/A" ,
638+ "Completed At (ts)" : task . completed_at_timestamp ?? "N/A" ,
639+ "Completed By" : task . completed_by ?? "N/A" ,
640+ "Completed By Email" : task . completed_by_email ?? "N/A" ,
641+ "Can Be Parent" : boolToYesNo ( task . can_be_parent ) ,
642+ "Parent Task ID" : task . parent_task_id ?? "None" ,
643+ "Closing Tags" : formatArray ( task . closing_tags ) ,
644+ "Lock Translations" : boolToYesNo ( task . do_lock_translations ) ,
645+ "Custom Status IDs" : formatArray ( task . custom_translation_status_ids ) ,
646+ "Source Language" : task . source_language_iso || "Not specified" ,
647+ "Auto-close Languages" : boolToYesNo ( task . auto_close_languages ) ,
648+ "Auto-close Task" : boolToYesNo ( task . auto_close_task ) ,
649+ "Auto-close Items" : boolToYesNo ( task . auto_close_items ) ,
650+ "Total Keys" : task . keys_count ?? 0 ,
651+ "Total Words" : task . words_count ?? 0 ,
652+ "Target Languages" : task . languages ?. length ?? 0 ,
653+ } ;
654+
655+ lines . push ( formatBulletList ( meta ) ) ;
656+ lines . push ( "" ) ;
657+
658+ if ( task . languages && task . languages . length > 0 ) {
659+ lines . push ( "**Languages:**" ) ;
660+ for ( const language of task . languages ) {
661+ lines . push (
662+ `- ${ language . language_iso . toUpperCase ( ) } • status: ${ language . status || "Unknown" } • progress: ${ typeof language . progress === "number" ? `${ language . progress } %` : "N/A" } • keys: ${ language . keys_count ?? 0 } • words: ${ language . words_count ?? 0 } ` ,
663+ ) ;
664+ }
665+ lines . push ( "" ) ;
666+ }
667+
668+ return lines . join ( "\n" ) ;
669+ }
670+
671+ function formatLanguageDetails ( language : Task [ "languages" ] [ number ] ) : string {
672+ const lines : string [ ] = [ ] ;
673+ lines . push ( formatHeading ( language . language_iso . toUpperCase ( ) , 3 ) ) ;
674+ lines . push ( "" ) ;
675+
676+ const langInfo : Record < string , unknown > = {
677+ Status : language . status || "Unknown" ,
678+ Progress :
679+ typeof language . progress === "number" ? `${ language . progress } %` : "N/A" ,
680+ "Keys Count" : language . keys_count ?? 0 ,
681+ "Words Count" : language . words_count ?? 0 ,
682+ "Completed At" : language . completed_at || "N/A" ,
683+ "Completed At (ts)" : language . completed_at_timestamp ?? "N/A" ,
684+ "Completed By" : language . completed_by ?? "N/A" ,
685+ "Completed By Email" : language . completed_by_email ?? "N/A" ,
686+ } ;
687+ lines . push ( formatBulletList ( langInfo ) ) ;
688+ lines . push ( "" ) ;
689+
690+ if ( Array . isArray ( language . keys ) && language . keys . length > 0 ) {
691+ lines . push ( `Keys scope: ${ language . keys . length } key(s)` ) ;
692+ }
693+
694+ if ( language . users && language . users . length > 0 ) {
695+ lines . push ( `Assigned Users (${ language . users . length } ):` ) ;
696+ for ( const user of language . users ) {
697+ lines . push ( `- ${ user . fullname || user . email || `ID: ${ user . user_id } ` } ` ) ;
698+ }
699+ lines . push ( "" ) ;
700+ }
701+
702+ if ( language . groups && language . groups . length > 0 ) {
703+ lines . push ( `Assigned Groups (${ language . groups . length } ):` ) ;
704+ for ( const group of language . groups ) {
705+ lines . push ( `- ${ group . name || `ID: ${ group . id } ` } ` ) ;
706+ }
707+ lines . push ( "" ) ;
708+ }
709+
710+ // Leverage
711+ if ( language . initial_tm_leverage ) {
712+ lines . push ( "Initial TM Leverage:" ) ;
713+ lines . push ( formatLeverageBuckets ( language . initial_tm_leverage ) ) ;
714+ lines . push ( "" ) ;
715+ }
716+ if ( language . tm_leverage ) {
717+ lines . push (
718+ `TM Leverage Status: ${ language . tm_leverage . status || "Unknown" } ` ,
719+ ) ;
720+ if ( language . tm_leverage . value ) {
721+ lines . push ( formatLeverageBuckets ( language . tm_leverage . value ) ) ;
722+ }
723+ lines . push ( "" ) ;
724+ }
725+
726+ if (
727+ ( ! language . users || language . users . length === 0 ) &&
728+ ( ! language . groups || language . groups . length === 0 )
729+ ) {
730+ lines . push ( "*No specific users or groups assigned to this language*" ) ;
731+ lines . push ( "" ) ;
732+ }
733+
734+ return lines . join ( "\n" ) ;
735+ }
736+
737+ function formatLeverageBuckets ( value : Record < string , number > ) : string {
738+ const orderedKeys = [ "0%+" , "50%+" , "60%+" , "75%+" , "85%+" , "95%+" , "100%" ] ;
739+ const present = orderedKeys . filter ( ( k ) => k in value ) ;
740+ if ( present . length === 0 ) return "- No leverage data" ;
741+ const lines : string [ ] = [ ] ;
742+ for ( const k of present ) {
743+ lines . push ( `- ${ k } : ${ value [ k ] } %` ) ;
744+ }
745+ return lines . join ( "\n" ) ;
746+ }
0 commit comments