@@ -6,6 +6,7 @@ package cmd
66import  (
77	"encoding/json" 
88	"fmt" 
9+ 	"sort" 
910	"strings" 
1011
1112	"github.com/spf13/cobra" 
2122	blocksTabId        string  // Tab ID to filter blocks by 
2223	blocksView         string  // View type to filter blocks by (term, web, etc.) 
2324	blocksJSON         bool    // Whether to output as JSON 
25+ 	blocksTimeout      int     // Timeout in seconds for RPC calls 
2426)
2527
2628// BlockDetails represents the information about a block returned by the list command 
@@ -55,6 +57,7 @@ Examples:
5557  wsh blocks list --json` ,
5658	RunE :    blocksListRun ,
5759	PreRunE : preRunSetupRpcClient ,
60+ 	SilenceUsage : true ,
5861}
5962
6063// init registers the blocks commands with the root command 
@@ -65,6 +68,7 @@ func init() {
6568	blocksListCmd .Flags ().StringVar (& blocksTabId , "tab" , "" , "restrict to tab id" )
6669	blocksListCmd .Flags ().StringVar (& blocksView , "view" , "" , "restrict to view type (term/terminal, web/browser, preview/edit, sysinfo, waveai)" )
6770	blocksListCmd .Flags ().BoolVar (& blocksJSON , "json" , false , "output as JSON" )
71+ 	blocksListCmd .Flags ().IntVar (& blocksTimeout , "timeout" , 5 , "timeout in seconds for RPC calls" )
6872
6973	for  _ , cmd  :=  range  rootCmd .Commands () {
7074		if  cmd .Use  ==  "blocks"  {
@@ -88,7 +92,7 @@ func init() {
8892func  blocksListRun (cmd  * cobra.Command , args  []string ) error  {
8993	var  allBlocks  []BlockDetails 
9094
91- 	workspaces , err  :=  wshclient .WorkspaceListCommand (RpcClient , & wshrpc.RpcOpts {Timeout : 5000 })
95+ 	workspaces , err  :=  wshclient .WorkspaceListCommand (RpcClient , & wshrpc.RpcOpts {Timeout : int64 ( blocksTimeout   *   1000 ) })
9296	if  err  !=  nil  {
9397		return  fmt .Errorf ("failed to list workspaces: %v" , err )
9498	}
@@ -100,6 +104,9 @@ func blocksListRun(cmd *cobra.Command, args []string) error {
100104	var  workspaceIdsToQuery  []string 
101105
102106	// Determine which workspaces to query 
107+ 	if  blocksWorkspaceId  !=  ""  &&  blocksWindowId  !=  ""  {
108+ 		return  fmt .Errorf ("--workspace and --window are mutually exclusive; specify only one" )
109+ 	}
103110	if  blocksWorkspaceId  !=  ""  {
104111		workspaceIdsToQuery  =  []string {blocksWorkspaceId }
105112	} else  if  blocksWindowId  !=  ""  {
@@ -124,11 +131,12 @@ func blocksListRun(cmd *cobra.Command, args []string) error {
124131
125132	// Query each selected workspace 
126133	for  _ , wsId  :=  range  workspaceIdsToQuery  {
127- 		req  :=  wshrpc.BlocksListRequest {
128- 			WorkspaceId : wsId ,
134+ 		req  :=  wshrpc.BlocksListRequest {WorkspaceId : wsId }
135+ 		if  blocksWindowId  !=  ""  {
136+ 			req .WindowId  =  blocksWindowId 
129137		}
130138
131- 		blocks , err  :=  wshclient .BlocksListCommand (RpcClient , req , & wshrpc.RpcOpts {Timeout : 5000 })
139+ 		blocks , err  :=  wshclient .BlocksListCommand (RpcClient , req , & wshrpc.RpcOpts {Timeout : int64 ( blocksTimeout   *   1000 ) })
132140		if  err  !=  nil  {
133141			WriteStderr ("Warning: couldn't list blocks for workspace %s: %v\n " , wsId , err )
134142			continue 
@@ -173,10 +181,24 @@ func blocksListRun(cmd *cobra.Command, args []string) error {
173181		return  nil 
174182	}
175183
184+ 	// Stable ordering 
185+ 	sort .Slice (allBlocks , func (i , j  int ) bool  {
186+ 		if  allBlocks [i ].WorkspaceId  !=  allBlocks [j ].WorkspaceId  {
187+ 			return  allBlocks [i ].WorkspaceId  <  allBlocks [j ].WorkspaceId 
188+ 		}
189+ 		if  allBlocks [i ].TabId  !=  allBlocks [j ].TabId  {
190+ 			return  allBlocks [i ].TabId  <  allBlocks [j ].TabId 
191+ 		}
192+ 		return  allBlocks [i ].BlockId  <  allBlocks [j ].BlockId 
193+ 	})
176194	format  :=  "%-36s  %-10s  %-36s  %-15s  %s\n " 
177195	WriteStdout (format , "BLOCK ID" , "WORKSPACE" , "TAB ID" , "VIEW" , "CONTENT" )
178196
179197	for  _ , b  :=  range  allBlocks  {
198+ 		blockID  :=  b .BlockId 
199+ 		if  len (blockID ) >  36  {
200+ 			blockID  =  blockID [:34 ] +  ".." 
201+ 		}
180202		view  :=  b .Meta .GetString (waveobj .MetaKey_View , "<unknown>" )
181203		var  content  string 
182204
@@ -201,15 +223,13 @@ func blocksListRun(cmd *cobra.Command, args []string) error {
201223			tabID  =  tabID [0 :34 ] +  ".." 
202224		}
203225
204- 		WriteStdout (format , b . BlockId , wsID , tabID , view , content )
226+ 		WriteStdout (format , blockID , wsID , tabID , view , content )
205227	}
206228
207229	return  nil 
208230}
209231
210232// matchesViewType checks if a view type matches a filter, supporting aliases 
211- // It handles different aliases for the same view type, allowing flexible filtering 
212- // Examples: "term" matches "terminal", "shell", "console"; "web" matches "browser", "url" 
213233func  matchesViewType (actual , filter  string ) bool  {
214234	// Direct match (case insensitive) 
215235	if  strings .EqualFold (actual , filter ) {
0 commit comments