@agentuity/coder-tui 2.0.11 → 2.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/agentuity-cli.d.ts +12 -0
  2. package/dist/agentuity-cli.d.ts.map +1 -0
  3. package/dist/agentuity-cli.js +178 -0
  4. package/dist/agentuity-cli.js.map +1 -0
  5. package/dist/auth.d.ts +5 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +62 -0
  8. package/dist/auth.js.map +1 -0
  9. package/dist/client.d.ts +1 -1
  10. package/dist/client.d.ts.map +1 -1
  11. package/dist/client.js +5 -6
  12. package/dist/client.js.map +1 -1
  13. package/dist/hub-overlay-state.d.ts.map +1 -1
  14. package/dist/hub-overlay-state.js +3 -1
  15. package/dist/hub-overlay-state.js.map +1 -1
  16. package/dist/hub-overlay.d.ts.map +1 -1
  17. package/dist/hub-overlay.js +18 -12
  18. package/dist/hub-overlay.js.map +1 -1
  19. package/dist/index.d.ts +1 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +50 -39
  22. package/dist/index.js.map +1 -1
  23. package/dist/local-init-filter.d.ts +5 -0
  24. package/dist/local-init-filter.d.ts.map +1 -0
  25. package/dist/local-init-filter.js +40 -0
  26. package/dist/local-init-filter.js.map +1 -0
  27. package/dist/protocol.d.ts +4 -2
  28. package/dist/protocol.d.ts.map +1 -1
  29. package/dist/remote-session.d.ts.map +1 -1
  30. package/dist/remote-session.js +17 -9
  31. package/dist/remote-session.js.map +1 -1
  32. package/dist/renderers.d.ts.map +1 -1
  33. package/dist/renderers.js +53 -1
  34. package/dist/renderers.js.map +1 -1
  35. package/dist/subagent-tool-selection.d.ts +3 -0
  36. package/dist/subagent-tool-selection.d.ts.map +1 -0
  37. package/dist/subagent-tool-selection.js +22 -0
  38. package/dist/subagent-tool-selection.js.map +1 -0
  39. package/package.json +5 -5
  40. package/src/agentuity-cli.ts +225 -0
  41. package/src/auth.ts +75 -0
  42. package/src/client.ts +6 -6
  43. package/src/hub-overlay-state.ts +4 -1
  44. package/src/hub-overlay.ts +28 -14
  45. package/src/index.ts +53 -39
  46. package/src/local-init-filter.ts +54 -0
  47. package/src/protocol.ts +4 -2
  48. package/src/remote-session.ts +17 -9
  49. package/src/renderers.ts +61 -1
  50. package/src/subagent-tool-selection.ts +33 -0
@@ -0,0 +1,54 @@
1
+ import type { AgentDefinition, HubToolDefinition, InitMessage } from './protocol.ts';
2
+
3
+ const LOCAL_TUI_HIDDEN_HUB_TOOL_NAMES = new Set(['sandbox_exec']);
4
+
5
+ function filterHubToolsForLocalTui(tools?: HubToolDefinition[]): HubToolDefinition[] | undefined {
6
+ if (!tools) return tools;
7
+
8
+ const filtered = tools.filter((tool) => !LOCAL_TUI_HIDDEN_HUB_TOOL_NAMES.has(tool.name));
9
+ return filtered.length === tools.length ? tools : filtered;
10
+ }
11
+
12
+ function filterAgentHubToolsForLocalTui(agents?: AgentDefinition[]): AgentDefinition[] | undefined {
13
+ if (!agents) return agents;
14
+
15
+ let changed = false;
16
+ const filteredAgents = agents.map((agent) => {
17
+ const filteredHubTools = filterHubToolsForLocalTui(agent.hubTools);
18
+ if (filteredHubTools === agent.hubTools) {
19
+ return agent;
20
+ }
21
+
22
+ changed = true;
23
+ return {
24
+ ...agent,
25
+ hubTools: filteredHubTools && filteredHubTools.length > 0 ? filteredHubTools : undefined,
26
+ };
27
+ });
28
+
29
+ return changed ? filteredAgents : agents;
30
+ }
31
+
32
+ export function adaptInitMessageForLocalTui(
33
+ init: InitMessage,
34
+ options: {
35
+ isRemoteSession: boolean;
36
+ }
37
+ ): InitMessage {
38
+ if (options.isRemoteSession) {
39
+ return init;
40
+ }
41
+
42
+ const tools = filterHubToolsForLocalTui(init.tools);
43
+ const agents = filterAgentHubToolsForLocalTui(init.agents);
44
+
45
+ if (tools === init.tools && agents === init.agents) {
46
+ return init;
47
+ }
48
+
49
+ return {
50
+ ...init,
51
+ tools,
52
+ agents,
53
+ };
54
+ }
package/src/protocol.ts CHANGED
@@ -75,6 +75,7 @@ export type HubAction =
75
75
  export interface AgentDefinition {
76
76
  name: string;
77
77
  displayName?: string;
78
+ source?: 'builtin' | 'custom';
78
79
  description: string;
79
80
  systemPrompt: string;
80
81
  model?: string;
@@ -84,6 +85,7 @@ export interface AgentDefinition {
84
85
  readOnly?: boolean;
85
86
  hubTools?: HubToolDefinition[];
86
87
  capabilities?: string[];
88
+ strictToolSelection?: boolean;
87
89
  status?: 'available' | 'busy' | 'offline';
88
90
  }
89
91
 
@@ -381,7 +383,7 @@ export interface SessionListItem {
381
383
  participantCount: number;
382
384
  tags: string[];
383
385
  skills: SessionSkillRef[];
384
- agentSlugs: string[];
386
+ enabledAgents: string[];
385
387
  defaultAgent?: string;
386
388
  bucket: SessionBucket;
387
389
  runtimeAvailable: boolean;
@@ -530,7 +532,7 @@ export interface SessionSnapshotMetadataExtensions {
530
532
  product?: SessionProductProjection;
531
533
  tags: string[];
532
534
  skills: SessionSkillRef[];
533
- agentSlugs: string[];
535
+ enabledAgents: string[];
534
536
  defaultAgent?: string;
535
537
  workers?: SessionListItem[];
536
538
  }
@@ -22,6 +22,8 @@ import {
22
22
  syncRemoteLifecycleWorkingMessage,
23
23
  type RemoteLifecycleState,
24
24
  } from './remote-lifecycle.ts';
25
+ import { resolveCoderOrgId } from './auth.ts';
26
+ import { formatToolDisplay } from './agentuity-cli.ts';
25
27
 
26
28
  const DEBUG = !!process.env['AGENTUITY_DEBUG'];
27
29
 
@@ -267,9 +269,10 @@ export class RemoteSession {
267
269
  wsHeaders['Authorization'] = `Bearer ${this.apiKey}`;
268
270
  }
269
271
  }
270
- if (this.orgId) {
271
- url.searchParams.set('orgId', this.orgId);
272
- wsHeaders['x-agentuity-orgid'] = this.orgId;
272
+ const orgId = resolveCoderOrgId(this.orgId);
273
+ if (orgId) {
274
+ url.searchParams.set('orgId', orgId);
275
+ wsHeaders['x-agentuity-orgid'] = orgId;
273
276
  }
274
277
 
275
278
  log(`${isReconnect ? 'Reconnecting' : 'Connecting'} to ${url.toString()}`);
@@ -999,18 +1002,23 @@ export async function setupRemoteMode(
999
1002
  break;
1000
1003
 
1001
1004
  case 'tool_execution_start': {
1002
- const tool = (event as { toolName?: string }).toolName ?? 'tool';
1003
- currentTool = tool;
1005
+ const rawTool = (event as { toolName?: string }).toolName ?? 'tool';
1006
+ const rawArgs = (event as { args?: string | Record<string, unknown> }).args;
1007
+ const display = formatToolDisplay(rawTool, rawArgs);
1008
+ currentTool = display.toolName;
1004
1009
  if (extensionCtxRef?.hasUI) {
1005
- setNonLifecycleWorkingMessage(`Running ${tool}...`);
1006
- extensionCtxRef.ui.setStatus('remote_activity', `Running ${tool}...`);
1010
+ setNonLifecycleWorkingMessage(`Running ${display.fullLabel}...`);
1011
+ extensionCtxRef.ui.setStatus('remote_activity', `Running ${display.fullLabel}...`);
1007
1012
  }
1008
- log(`Tool: ${tool}`);
1013
+ log(`Tool: ${display.fullLabel}`);
1009
1014
  break;
1010
1015
  }
1011
1016
 
1012
1017
  case 'tool_execution_end': {
1013
- const tool = (event as { toolName?: string }).toolName ?? currentTool ?? 'tool';
1018
+ const rawTool = (event as { toolName?: string }).toolName ?? currentTool ?? 'tool';
1019
+ const rawArgs = (event as { args?: string | Record<string, unknown> }).args;
1020
+ const display = rawArgs ? formatToolDisplay(rawTool, rawArgs) : null;
1021
+ const tool = display?.fullLabel ?? currentTool ?? rawTool;
1014
1022
  currentTool = null;
1015
1023
  if (extensionCtxRef?.hasUI) {
1016
1024
  clearWorkingMessage();
package/src/renderers.ts CHANGED
@@ -12,6 +12,7 @@ import type {
12
12
  AgentToolResult,
13
13
  } from '@mariozechner/pi-coding-agent';
14
14
  import { Box, Text, Container, type Component } from '@mariozechner/pi-tui';
15
+ import { formatToolDisplay } from './agentuity-cli.ts';
15
16
 
16
17
  // ──────────────────────────────────────────────
17
18
  // Line-safety helper — must be declared before SimpleText so
@@ -125,6 +126,32 @@ function truncate(str: string, max: number): string {
125
126
  return str.slice(0, max - 1) + '\u2026';
126
127
  }
127
128
 
129
+ function toSingleLinePreview(value: string): string {
130
+ return value.replace(/\s+/g, ' ').trim();
131
+ }
132
+
133
+ function isCommandToolName(toolName: string): boolean {
134
+ const normalized = toolName.trim().toLowerCase();
135
+ return normalized === 'bash' || normalized === 'execute_command' || normalized.includes('shell');
136
+ }
137
+
138
+ function getCommandArg(args: Record<string, unknown>): string | undefined {
139
+ const value = args['command'] ?? args['cmd'];
140
+ return typeof value === 'string' && value.trim() ? value.trim() : undefined;
141
+ }
142
+
143
+ function getCommandTimeoutLabel(args: Record<string, unknown>): string | undefined {
144
+ const timeout = args['timeout'];
145
+ if (typeof timeout === 'number' && Number.isFinite(timeout) && timeout > 0) {
146
+ return `${timeout}s`;
147
+ }
148
+ if (typeof timeout === 'string' && timeout.trim()) {
149
+ const value = timeout.trim();
150
+ return /s$/i.test(value) ? value : `${value}s`;
151
+ }
152
+ return undefined;
153
+ }
154
+
128
155
  // ──────────────────────────────────────────────
129
156
  // Individual tool renderers
130
157
  // ──────────────────────────────────────────────
@@ -709,6 +736,37 @@ function parallelTasksRenderers(): ToolRenderers {
709
736
  };
710
737
  }
711
738
 
739
+ function commandToolRenderers(toolName: string): ToolRenderers {
740
+ return {
741
+ renderCall(args, theme) {
742
+ const display = formatToolDisplay(toolName, args);
743
+ const timeout = getCommandTimeoutLabel(args);
744
+
745
+ if (display.branded) {
746
+ let text = theme.fg('toolTitle', theme.bold(display.toolName));
747
+ if (display.toolArgs) {
748
+ text += theme.fg('accent', ` ${display.toolArgs}`);
749
+ }
750
+ if (timeout) {
751
+ text += theme.fg('dim', ` (timeout ${timeout})`);
752
+ }
753
+ return new SimpleText(text);
754
+ }
755
+
756
+ let text = theme.fg('toolTitle', theme.bold('$ '));
757
+ const commandPreview = getCommandArg(args);
758
+ text += theme.fg(
759
+ 'accent',
760
+ truncate(commandPreview ? toSingleLinePreview(commandPreview) : display.toolName, 80)
761
+ );
762
+ if (timeout) {
763
+ text += theme.fg('dim', ` (timeout ${timeout})`);
764
+ }
765
+ return new SimpleText(text);
766
+ },
767
+ };
768
+ }
769
+
712
770
  // ──────────────────────────────────────────────
713
771
 
714
772
  const RENDERERS: Record<string, () => ToolRenderers> = {
@@ -736,5 +794,7 @@ const RENDERERS: Record<string, () => ToolRenderers> = {
736
794
  */
737
795
  export function getToolRenderers(toolName: string): ToolRenderers | undefined {
738
796
  const factory = RENDERERS[toolName];
739
- return factory?.();
797
+ if (factory) return factory();
798
+ if (isCommandToolName(toolName)) return commandToolRenderers(toolName);
799
+ return undefined;
740
800
  }
@@ -0,0 +1,33 @@
1
+ import type { AgentDefinition } from './protocol.ts';
2
+
3
+ const READ_ONLY_TOOL_NAMES = ['read', 'grep', 'find', 'ls'] as const;
4
+ const CODING_TOOL_NAMES = ['read', 'bash', 'edit', 'write'] as const;
5
+
6
+ function normalizeToolName(name: string): string {
7
+ return name.trim().toLowerCase();
8
+ }
9
+
10
+ export function selectSubAgentToolNames(agentConfig: AgentDefinition): string[] {
11
+ const declared = new Set(
12
+ (agentConfig.tools ?? [])
13
+ .filter((name): name is string => typeof name === 'string' && name.trim().length > 0)
14
+ .map(normalizeToolName)
15
+ );
16
+ const needsBash = declared.has('bash');
17
+ const baseToolNames =
18
+ agentConfig.readOnly && !needsBash ? READ_ONLY_TOOL_NAMES : CODING_TOOL_NAMES;
19
+ const allowLegacyFallback =
20
+ agentConfig.strictToolSelection !== true && agentConfig.source === 'builtin';
21
+
22
+ if (declared.size === 0) {
23
+ return allowLegacyFallback ? [...baseToolNames] : [];
24
+ }
25
+
26
+ const filtered = baseToolNames.filter((toolName) => declared.has(toolName));
27
+
28
+ if (filtered.length > 0) {
29
+ return filtered;
30
+ }
31
+
32
+ return allowLegacyFallback ? [...baseToolNames] : [];
33
+ }