agent-orchestrator-mcp-server 0.2.4 → 0.3.0

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 (32) hide show
  1. package/README.md +125 -30
  2. package/build/index.js +4 -4
  3. package/package.json +1 -1
  4. package/shared/orchestrator-client/orchestrator-client.d.ts +128 -3
  5. package/shared/orchestrator-client/orchestrator-client.integration-mock.js +313 -1
  6. package/shared/orchestrator-client/orchestrator-client.js +205 -0
  7. package/shared/resources.js +9 -4
  8. package/shared/tools/action-health.d.ts +58 -0
  9. package/shared/tools/action-health.js +101 -0
  10. package/shared/tools/action-notification.d.ts +46 -0
  11. package/shared/tools/action-notification.js +99 -0
  12. package/shared/tools/action-session.d.ts +33 -9
  13. package/shared/tools/action-session.js +177 -15
  14. package/shared/tools/action-trigger.d.ts +114 -0
  15. package/shared/tools/action-trigger.js +177 -0
  16. package/shared/tools/get-notifications.d.ts +70 -0
  17. package/shared/tools/get-notifications.js +113 -0
  18. package/shared/tools/get-session.d.ts +8 -0
  19. package/shared/tools/get-session.js +21 -2
  20. package/shared/tools/get-system-health.d.ts +38 -0
  21. package/shared/tools/get-system-health.js +69 -0
  22. package/shared/tools/get-transcript-archive.d.ts +27 -0
  23. package/shared/tools/get-transcript-archive.js +64 -0
  24. package/shared/tools/manage-enqueued-messages.d.ts +94 -0
  25. package/shared/tools/manage-enqueued-messages.js +259 -0
  26. package/shared/tools/search-sessions.d.ts +3 -10
  27. package/shared/tools/search-sessions.js +10 -15
  28. package/shared/tools/search-triggers.d.ts +78 -0
  29. package/shared/tools/search-triggers.js +145 -0
  30. package/shared/tools.d.ts +7 -9
  31. package/shared/tools.js +105 -32
  32. package/shared/types.d.ts +162 -1
@@ -0,0 +1,101 @@
1
+ import { z } from 'zod';
2
+ const ACTION_ENUM = [
3
+ 'cleanup_processes',
4
+ 'retry_sessions',
5
+ 'archive_old',
6
+ 'cli_refresh',
7
+ 'cli_clear_cache',
8
+ ];
9
+ export const ActionHealthSchema = z.object({
10
+ action: z.enum(ACTION_ENUM),
11
+ session_ids: z.array(z.number()).optional(),
12
+ days: z.number().min(1).max(365).optional(),
13
+ });
14
+ const TOOL_DESCRIPTION = `Perform system health and maintenance actions.
15
+
16
+ **Actions:**
17
+ - **cleanup_processes**: Terminate orphaned agent processes
18
+ - **retry_sessions**: Retry failed sessions (optionally specify session_ids)
19
+ - **archive_old**: Archive sessions older than N days (requires "days", default 7)
20
+ - **cli_refresh**: Trigger a background refresh of CLI tool installations
21
+ - **cli_clear_cache**: Clear npm/pip caches and reinstall MCP packages
22
+
23
+ Note: Health actions are rate-limited (30s cooldown between calls).`;
24
+ export function actionHealthTool(_server, clientFactory) {
25
+ return {
26
+ name: 'action_health',
27
+ description: TOOL_DESCRIPTION,
28
+ inputSchema: {
29
+ type: 'object',
30
+ properties: {
31
+ action: { type: 'string', enum: ACTION_ENUM, description: 'Health action to perform.' },
32
+ session_ids: {
33
+ type: 'array',
34
+ items: { type: 'number' },
35
+ description: 'Session IDs to retry. For retry_sessions action.',
36
+ },
37
+ days: {
38
+ type: 'number',
39
+ minimum: 1,
40
+ maximum: 365,
41
+ description: 'Archive sessions older than this many days. For archive_old action. Default: 7',
42
+ },
43
+ },
44
+ required: ['action'],
45
+ },
46
+ handler: async (args) => {
47
+ try {
48
+ const validated = ActionHealthSchema.parse(args);
49
+ const client = clientFactory();
50
+ const { action } = validated;
51
+ let result;
52
+ switch (action) {
53
+ case 'cleanup_processes': {
54
+ const response = await client.cleanupProcesses();
55
+ result = `## Processes Cleaned Up\n\n\`\`\`json\n${JSON.stringify(response, null, 2)}\n\`\`\``;
56
+ break;
57
+ }
58
+ case 'retry_sessions': {
59
+ const response = await client.retrySessions(validated.session_ids);
60
+ result = `## Sessions Retried\n\n\`\`\`json\n${JSON.stringify(response, null, 2)}\n\`\`\``;
61
+ break;
62
+ }
63
+ case 'archive_old': {
64
+ const response = await client.archiveOldSessions(validated.days);
65
+ result = `## Old Sessions Archived\n\n\`\`\`json\n${JSON.stringify(response, null, 2)}\n\`\`\``;
66
+ break;
67
+ }
68
+ case 'cli_refresh': {
69
+ const response = await client.refreshCli();
70
+ result = `## CLI Refresh Queued\n\n- **Message:** ${response.message}`;
71
+ break;
72
+ }
73
+ case 'cli_clear_cache': {
74
+ const response = await client.clearCliCache();
75
+ result = `## CLI Cache Clear Queued\n\n- **Message:** ${response.message}`;
76
+ break;
77
+ }
78
+ default: {
79
+ const _exhaustiveCheck = action;
80
+ return {
81
+ content: [{ type: 'text', text: `Error: Unknown action "${_exhaustiveCheck}"` }],
82
+ isError: true,
83
+ };
84
+ }
85
+ }
86
+ return { content: [{ type: 'text', text: result }] };
87
+ }
88
+ catch (error) {
89
+ return {
90
+ content: [
91
+ {
92
+ type: 'text',
93
+ text: `Error performing health action: ${error instanceof Error ? error.message : 'Unknown error'}`,
94
+ },
95
+ ],
96
+ isError: true,
97
+ };
98
+ }
99
+ },
100
+ };
101
+ }
@@ -0,0 +1,46 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { z } from 'zod';
3
+ import type { IAgentOrchestratorClient } from '../orchestrator-client/orchestrator-client.js';
4
+ export declare const ActionNotificationSchema: z.ZodObject<{
5
+ action: z.ZodEnum<["mark_read", "mark_all_read", "dismiss", "dismiss_all_read"]>;
6
+ id: z.ZodOptional<z.ZodNumber>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ action: "mark_read" | "mark_all_read" | "dismiss" | "dismiss_all_read";
9
+ id?: number | undefined;
10
+ }, {
11
+ action: "mark_read" | "mark_all_read" | "dismiss" | "dismiss_all_read";
12
+ id?: number | undefined;
13
+ }>;
14
+ export declare function actionNotificationTool(_server: Server, clientFactory: () => IAgentOrchestratorClient): {
15
+ name: string;
16
+ description: string;
17
+ inputSchema: {
18
+ type: "object";
19
+ properties: {
20
+ action: {
21
+ type: string;
22
+ enum: readonly ["mark_read", "mark_all_read", "dismiss", "dismiss_all_read"];
23
+ description: string;
24
+ };
25
+ id: {
26
+ type: string;
27
+ description: string;
28
+ };
29
+ };
30
+ required: string[];
31
+ };
32
+ handler: (args: unknown) => Promise<{
33
+ content: {
34
+ type: string;
35
+ text: string;
36
+ }[];
37
+ isError: boolean;
38
+ } | {
39
+ content: {
40
+ type: string;
41
+ text: string;
42
+ }[];
43
+ isError?: undefined;
44
+ }>;
45
+ };
46
+ //# sourceMappingURL=action-notification.d.ts.map
@@ -0,0 +1,99 @@
1
+ import { z } from 'zod';
2
+ const ACTION_ENUM = ['mark_read', 'mark_all_read', 'dismiss', 'dismiss_all_read'];
3
+ export const ActionNotificationSchema = z.object({
4
+ action: z.enum(ACTION_ENUM),
5
+ id: z.number().optional(),
6
+ });
7
+ const TOOL_DESCRIPTION = `Manage notifications in the Agent Orchestrator.
8
+
9
+ **Actions:**
10
+ - **mark_read**: Mark a specific notification as read (requires "id")
11
+ - **mark_all_read**: Mark all notifications as read
12
+ - **dismiss**: Delete a notification (requires "id", must be read first)
13
+ - **dismiss_all_read**: Delete all read notifications`;
14
+ export function actionNotificationTool(_server, clientFactory) {
15
+ return {
16
+ name: 'action_notification',
17
+ description: TOOL_DESCRIPTION,
18
+ inputSchema: {
19
+ type: 'object',
20
+ properties: {
21
+ action: {
22
+ type: 'string',
23
+ enum: ACTION_ENUM,
24
+ description: 'Action to perform.',
25
+ },
26
+ id: {
27
+ type: 'number',
28
+ description: 'Notification ID. Required for mark_read and dismiss.',
29
+ },
30
+ },
31
+ required: ['action'],
32
+ },
33
+ handler: async (args) => {
34
+ try {
35
+ const validated = ActionNotificationSchema.parse(args);
36
+ const client = clientFactory();
37
+ const { action, id } = validated;
38
+ let result;
39
+ switch (action) {
40
+ case 'mark_read': {
41
+ if (!id) {
42
+ return {
43
+ content: [
44
+ { type: 'text', text: 'Error: "id" is required for the "mark_read" action.' },
45
+ ],
46
+ isError: true,
47
+ };
48
+ }
49
+ const notification = await client.markNotificationRead(id);
50
+ result = `## Notification Marked Read\n\n- **ID:** ${notification.id}\n- **Type:** ${notification.notification_type}`;
51
+ break;
52
+ }
53
+ case 'mark_all_read': {
54
+ const response = await client.markAllNotificationsRead();
55
+ result = `## All Notifications Marked Read\n\n- **Marked:** ${response.marked_count}\n- **Remaining Pending:** ${response.pending_count}`;
56
+ break;
57
+ }
58
+ case 'dismiss': {
59
+ if (!id) {
60
+ return {
61
+ content: [
62
+ { type: 'text', text: 'Error: "id" is required for the "dismiss" action.' },
63
+ ],
64
+ isError: true,
65
+ };
66
+ }
67
+ await client.dismissNotification(id);
68
+ result = `## Notification Dismissed\n\nNotification ${id} has been deleted.`;
69
+ break;
70
+ }
71
+ case 'dismiss_all_read': {
72
+ const response = await client.dismissAllReadNotifications();
73
+ result = `## Read Notifications Dismissed\n\n- **Dismissed:** ${response.dismissed_count}\n- **Remaining Pending:** ${response.pending_count}`;
74
+ break;
75
+ }
76
+ default: {
77
+ const _exhaustiveCheck = action;
78
+ return {
79
+ content: [{ type: 'text', text: `Error: Unknown action "${_exhaustiveCheck}"` }],
80
+ isError: true,
81
+ };
82
+ }
83
+ }
84
+ return { content: [{ type: 'text', text: result }] };
85
+ }
86
+ catch (error) {
87
+ return {
88
+ content: [
89
+ {
90
+ type: 'text',
91
+ text: `Error managing notification: ${error instanceof Error ? error.message : 'Unknown error'}`,
92
+ },
93
+ ],
94
+ isError: true,
95
+ };
96
+ }
97
+ },
98
+ };
99
+ }
@@ -2,20 +2,29 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { z } from 'zod';
3
3
  import type { IAgentOrchestratorClient } from '../orchestrator-client/orchestrator-client.js';
4
4
  export declare const ActionSessionSchema: z.ZodObject<{
5
- session_id: z.ZodUnion<[z.ZodString, z.ZodNumber]>;
6
- action: z.ZodEnum<["follow_up", "pause", "restart", "archive", "unarchive", "change_mcp_servers"]>;
5
+ session_id: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodNumber]>>;
6
+ action: z.ZodEnum<["follow_up", "pause", "restart", "archive", "unarchive", "change_mcp_servers", "fork", "refresh", "refresh_all", "update_notes", "toggle_favorite", "bulk_archive"]>;
7
7
  prompt: z.ZodOptional<z.ZodString>;
8
8
  mcp_servers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
9
+ message_index: z.ZodOptional<z.ZodNumber>;
10
+ session_notes: z.ZodOptional<z.ZodString>;
11
+ session_ids: z.ZodOptional<z.ZodArray<z.ZodNumber, "many">>;
9
12
  }, "strip", z.ZodTypeAny, {
10
- session_id: string | number;
11
- action: "follow_up" | "pause" | "restart" | "archive" | "unarchive" | "change_mcp_servers";
13
+ action: "follow_up" | "pause" | "restart" | "archive" | "unarchive" | "change_mcp_servers" | "fork" | "refresh" | "refresh_all" | "update_notes" | "toggle_favorite" | "bulk_archive";
12
14
  mcp_servers?: string[] | undefined;
13
15
  prompt?: string | undefined;
16
+ session_id?: string | number | undefined;
17
+ message_index?: number | undefined;
18
+ session_notes?: string | undefined;
19
+ session_ids?: number[] | undefined;
14
20
  }, {
15
- session_id: string | number;
16
- action: "follow_up" | "pause" | "restart" | "archive" | "unarchive" | "change_mcp_servers";
21
+ action: "follow_up" | "pause" | "restart" | "archive" | "unarchive" | "change_mcp_servers" | "fork" | "refresh" | "refresh_all" | "update_notes" | "toggle_favorite" | "bulk_archive";
17
22
  mcp_servers?: string[] | undefined;
18
23
  prompt?: string | undefined;
24
+ session_id?: string | number | undefined;
25
+ message_index?: number | undefined;
26
+ session_notes?: string | undefined;
27
+ session_ids?: number[] | undefined;
19
28
  }>;
20
29
  export declare function actionSessionTool(_server: Server, clientFactory: () => IAgentOrchestratorClient): {
21
30
  name: string;
@@ -27,12 +36,12 @@ export declare function actionSessionTool(_server: Server, clientFactory: () =>
27
36
  oneOf: {
28
37
  type: string;
29
38
  }[];
30
- description: "Session ID (numeric) or slug (string) to perform the action on.";
39
+ description: "Session ID (numeric) or slug (string). Required for most actions. Not required for \"refresh_all\" and \"bulk_archive\".";
31
40
  };
32
41
  action: {
33
42
  type: string;
34
- enum: readonly ["follow_up", "pause", "restart", "archive", "unarchive", "change_mcp_servers"];
35
- description: "Action to perform: \"follow_up\" (send prompt to paused session), \"pause\" (pause running session), \"restart\" (restart paused/failed session), \"archive\" (archive session), \"unarchive\" (restore archived session), \"change_mcp_servers\" (update MCP servers for session)";
43
+ enum: readonly ["follow_up", "pause", "restart", "archive", "unarchive", "change_mcp_servers", "fork", "refresh", "refresh_all", "update_notes", "toggle_favorite", "bulk_archive"];
44
+ description: "Action to perform: \"follow_up\", \"pause\", \"restart\", \"archive\", \"unarchive\", \"change_mcp_servers\", \"fork\", \"refresh\", \"refresh_all\", \"update_notes\", \"toggle_favorite\", \"bulk_archive\"";
36
45
  };
37
46
  prompt: {
38
47
  type: string;
@@ -45,6 +54,21 @@ export declare function actionSessionTool(_server: Server, clientFactory: () =>
45
54
  };
46
55
  description: "Required for \"change_mcp_servers\" action. Array of MCP server names to set for the session.";
47
56
  };
57
+ message_index: {
58
+ type: string;
59
+ description: "Required for \"fork\" action. The transcript message index to fork from.";
60
+ };
61
+ session_notes: {
62
+ type: string;
63
+ description: "Required for \"update_notes\" action. The notes text to set on the session.";
64
+ };
65
+ session_ids: {
66
+ type: string;
67
+ items: {
68
+ type: string;
69
+ };
70
+ description: "Required for \"bulk_archive\" action. Array of session IDs to archive.";
71
+ };
48
72
  };
49
73
  required: string[];
50
74
  };
@@ -1,9 +1,12 @@
1
1
  import { z } from 'zod';
2
2
  const PARAM_DESCRIPTIONS = {
3
- session_id: 'Session ID (numeric) or slug (string) to perform the action on.',
4
- action: 'Action to perform: "follow_up" (send prompt to paused session), "pause" (pause running session), "restart" (restart paused/failed session), "archive" (archive session), "unarchive" (restore archived session), "change_mcp_servers" (update MCP servers for session)',
3
+ session_id: 'Session ID (numeric) or slug (string). Required for most actions. Not required for "refresh_all" and "bulk_archive".',
4
+ action: 'Action to perform: "follow_up", "pause", "restart", "archive", "unarchive", "change_mcp_servers", "fork", "refresh", "refresh_all", "update_notes", "toggle_favorite", "bulk_archive"',
5
5
  prompt: 'Required for "follow_up" action. The prompt to send to the agent. Not used for other actions.',
6
6
  mcp_servers: 'Required for "change_mcp_servers" action. Array of MCP server names to set for the session.',
7
+ message_index: 'Required for "fork" action. The transcript message index to fork from.',
8
+ session_notes: 'Required for "update_notes" action. The notes text to set on the session.',
9
+ session_ids: 'Required for "bulk_archive" action. Array of session IDs to archive.',
7
10
  };
8
11
  const ACTION_ENUM = [
9
12
  'follow_up',
@@ -12,12 +15,21 @@ const ACTION_ENUM = [
12
15
  'archive',
13
16
  'unarchive',
14
17
  'change_mcp_servers',
18
+ 'fork',
19
+ 'refresh',
20
+ 'refresh_all',
21
+ 'update_notes',
22
+ 'toggle_favorite',
23
+ 'bulk_archive',
15
24
  ];
16
25
  export const ActionSessionSchema = z.object({
17
- session_id: z.union([z.string(), z.number()]).describe(PARAM_DESCRIPTIONS.session_id),
26
+ session_id: z.union([z.string(), z.number()]).optional().describe(PARAM_DESCRIPTIONS.session_id),
18
27
  action: z.enum(ACTION_ENUM).describe(PARAM_DESCRIPTIONS.action),
19
28
  prompt: z.string().optional().describe(PARAM_DESCRIPTIONS.prompt),
20
29
  mcp_servers: z.array(z.string()).optional().describe(PARAM_DESCRIPTIONS.mcp_servers),
30
+ message_index: z.number().optional().describe(PARAM_DESCRIPTIONS.message_index),
31
+ session_notes: z.string().optional().describe(PARAM_DESCRIPTIONS.session_notes),
32
+ session_ids: z.array(z.number()).optional().describe(PARAM_DESCRIPTIONS.session_ids),
21
33
  });
22
34
  const TOOL_DESCRIPTION = `Perform an action on an agent session.
23
35
 
@@ -28,19 +40,17 @@ const TOOL_DESCRIPTION = `Perform an action on an agent session.
28
40
  - **archive**: Archive a session (marks as completed)
29
41
  - **unarchive**: Restore an archived session to "needs_input" status
30
42
  - **change_mcp_servers**: Update the MCP servers for a session (requires "mcp_servers" parameter)
31
-
32
- **Status requirements:**
33
- - follow_up: Session must be "needs_input"
34
- - pause: Session must be "running"
35
- - restart: Session must be "needs_input" or "failed"
36
- - archive: Session can be in any status except "archived"
37
- - unarchive: Session must be "archived"
38
- - change_mcp_servers: Session can be in any status except "archived"
43
+ - **fork**: Fork a session from a specific transcript message (requires "message_index")
44
+ - **refresh**: Refresh a single session's status from the execution provider
45
+ - **refresh_all**: Refresh all active sessions (no session_id needed)
46
+ - **update_notes**: Update the notes on a session (requires "session_notes")
47
+ - **toggle_favorite**: Toggle favorite status on a session
48
+ - **bulk_archive**: Archive multiple sessions at once (requires "session_ids", no session_id needed)
39
49
 
40
50
  **Use cases:**
41
51
  - Provide additional instructions to an agent
42
- - Control session lifecycle (pause, restart)
43
- - Organize sessions (archive, unarchive)
52
+ - Control session lifecycle (pause, restart, fork, refresh)
53
+ - Organize sessions (archive, unarchive, bulk_archive, toggle_favorite, update_notes)
44
54
  - Reconfigure session MCP server access`;
45
55
  export function actionSessionTool(_server, clientFactory) {
46
56
  return {
@@ -67,14 +77,51 @@ export function actionSessionTool(_server, clientFactory) {
67
77
  items: { type: 'string' },
68
78
  description: PARAM_DESCRIPTIONS.mcp_servers,
69
79
  },
80
+ message_index: {
81
+ type: 'number',
82
+ description: PARAM_DESCRIPTIONS.message_index,
83
+ },
84
+ session_notes: {
85
+ type: 'string',
86
+ description: PARAM_DESCRIPTIONS.session_notes,
87
+ },
88
+ session_ids: {
89
+ type: 'array',
90
+ items: { type: 'number' },
91
+ description: PARAM_DESCRIPTIONS.session_ids,
92
+ },
70
93
  },
71
- required: ['session_id', 'action'],
94
+ required: ['action'],
72
95
  },
73
96
  handler: async (args) => {
74
97
  try {
75
98
  const validatedArgs = ActionSessionSchema.parse(args);
76
99
  const client = clientFactory();
77
- const { session_id, action, prompt, mcp_servers } = validatedArgs;
100
+ const { session_id, action, prompt, mcp_servers, message_index, session_notes, session_ids, } = validatedArgs;
101
+ // Actions that require session_id
102
+ const requiresSessionId = [
103
+ 'follow_up',
104
+ 'pause',
105
+ 'restart',
106
+ 'archive',
107
+ 'unarchive',
108
+ 'change_mcp_servers',
109
+ 'fork',
110
+ 'refresh',
111
+ 'update_notes',
112
+ 'toggle_favorite',
113
+ ];
114
+ if (requiresSessionId.includes(action) && !session_id) {
115
+ return {
116
+ content: [
117
+ {
118
+ type: 'text',
119
+ text: `Error: The "session_id" parameter is required for the "${action}" action.`,
120
+ },
121
+ ],
122
+ isError: true,
123
+ };
124
+ }
78
125
  // Validate that prompt is provided for follow_up action
79
126
  if (action === 'follow_up' && !prompt) {
80
127
  return {
@@ -99,6 +146,42 @@ export function actionSessionTool(_server, clientFactory) {
99
146
  isError: true,
100
147
  };
101
148
  }
149
+ // Validate fork requires message_index
150
+ if (action === 'fork' && message_index === undefined) {
151
+ return {
152
+ content: [
153
+ {
154
+ type: 'text',
155
+ text: 'Error: The "message_index" parameter is required for the "fork" action.',
156
+ },
157
+ ],
158
+ isError: true,
159
+ };
160
+ }
161
+ // Validate update_notes requires session_notes
162
+ if (action === 'update_notes' && session_notes === undefined) {
163
+ return {
164
+ content: [
165
+ {
166
+ type: 'text',
167
+ text: 'Error: The "session_notes" parameter is required for the "update_notes" action.',
168
+ },
169
+ ],
170
+ isError: true,
171
+ };
172
+ }
173
+ // Validate bulk_archive requires session_ids
174
+ if (action === 'bulk_archive' && (!session_ids || session_ids.length === 0)) {
175
+ return {
176
+ content: [
177
+ {
178
+ type: 'text',
179
+ text: 'Error: The "session_ids" parameter is required for the "bulk_archive" action.',
180
+ },
181
+ ],
182
+ isError: true,
183
+ };
184
+ }
102
185
  let result;
103
186
  switch (action) {
104
187
  case 'follow_up': {
@@ -189,6 +272,85 @@ export function actionSessionTool(_server, clientFactory) {
189
272
  result = lines.join('\n');
190
273
  break;
191
274
  }
275
+ case 'fork': {
276
+ const response = await client.forkSession(session_id, message_index);
277
+ const lines = [
278
+ `## Session Forked`,
279
+ '',
280
+ `- **New Session ID:** ${response.session.id}`,
281
+ `- **Title:** ${response.session.title}`,
282
+ `- **Status:** ${response.session.status}`,
283
+ `- **Message:** ${response.message}`,
284
+ ];
285
+ result = lines.join('\n');
286
+ break;
287
+ }
288
+ case 'refresh': {
289
+ const response = await client.refreshSession(session_id);
290
+ const lines = [
291
+ `## Session Refreshed`,
292
+ '',
293
+ `- **Session ID:** ${response.session.id}`,
294
+ `- **Title:** ${response.session.title}`,
295
+ `- **Status:** ${response.session.status}`,
296
+ `- **Message:** ${response.message}`,
297
+ ];
298
+ result = lines.join('\n');
299
+ break;
300
+ }
301
+ case 'refresh_all': {
302
+ const response = await client.refreshAllSessions();
303
+ const lines = [
304
+ `## All Sessions Refreshed`,
305
+ '',
306
+ `- **Message:** ${response.message}`,
307
+ `- **Refreshed:** ${response.refreshed}`,
308
+ `- **Restarted:** ${response.restarted}`,
309
+ `- **Continued:** ${response.continued}`,
310
+ `- **Errors:** ${response.errors}`,
311
+ ];
312
+ result = lines.join('\n');
313
+ break;
314
+ }
315
+ case 'update_notes': {
316
+ const session = await client.updateSessionNotes(session_id, session_notes);
317
+ const lines = [
318
+ `## Session Notes Updated`,
319
+ '',
320
+ `- **Session ID:** ${session.id}`,
321
+ `- **Title:** ${session.title}`,
322
+ ];
323
+ result = lines.join('\n');
324
+ break;
325
+ }
326
+ case 'toggle_favorite': {
327
+ const session = await client.toggleFavorite(session_id);
328
+ const lines = [
329
+ `## Favorite Toggled`,
330
+ '',
331
+ `- **Session ID:** ${session.id}`,
332
+ `- **Title:** ${session.title}`,
333
+ `- **Favorited:** ${session.favorited ? 'Yes' : 'No'}`,
334
+ ];
335
+ result = lines.join('\n');
336
+ break;
337
+ }
338
+ case 'bulk_archive': {
339
+ const response = await client.bulkArchiveSessions(session_ids);
340
+ const lines = [
341
+ `## Bulk Archive Complete`,
342
+ '',
343
+ `- **Archived:** ${response.archived_count}`,
344
+ ];
345
+ if (response.errors.length > 0) {
346
+ lines.push(`- **Errors:** ${response.errors.length}`);
347
+ response.errors.forEach((err) => {
348
+ lines.push(` - Session ${err.id}: ${err.error}`);
349
+ });
350
+ }
351
+ result = lines.join('\n');
352
+ break;
353
+ }
192
354
  default: {
193
355
  // This should never happen due to Zod validation
194
356
  const _exhaustiveCheck = action;