@guildai/cli 0.6.2 → 0.7.1

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 (55) hide show
  1. package/README.md +3 -1
  2. package/dist/commands/agent/chat.js +41 -99
  3. package/dist/commands/agent/clone.js +1 -1
  4. package/dist/commands/agent/code.js +1 -1
  5. package/dist/commands/agent/fork.js +2 -2
  6. package/dist/commands/agent/get.js +1 -1
  7. package/dist/commands/agent/grep.js +2 -2
  8. package/dist/commands/agent/init.js +10 -3
  9. package/dist/commands/agent/list.js +9 -1
  10. package/dist/commands/agent/publish.js +1 -1
  11. package/dist/commands/agent/revalidate.js +1 -1
  12. package/dist/commands/agent/save.js +23 -2
  13. package/dist/commands/agent/test.js +70 -130
  14. package/dist/commands/agent/unpublish.js +1 -1
  15. package/dist/commands/agent/update.js +1 -1
  16. package/dist/commands/agent/versions.js +1 -1
  17. package/dist/commands/agent/workspaces.js +1 -1
  18. package/dist/commands/chat.d.ts +2 -1
  19. package/dist/commands/chat.js +189 -88
  20. package/dist/commands/config/list.js +2 -2
  21. package/dist/commands/integration/operation/create.js +2 -2
  22. package/dist/commands/integration/operation/list.js +2 -2
  23. package/dist/commands/integration/update.js +1 -1
  24. package/dist/commands/integration/version/get.js +2 -2
  25. package/dist/commands/integration/version/publish.js +2 -2
  26. package/dist/commands/integration/version/test.js +2 -2
  27. package/dist/commands/session/events.js +7 -3
  28. package/dist/commands/session/interrupt.d.ts +3 -0
  29. package/dist/commands/session/interrupt.js +33 -0
  30. package/dist/commands/setup.js +70 -11
  31. package/dist/commands/workspace/get.js +1 -1
  32. package/dist/commands/workspace/list.js +28 -6
  33. package/dist/commands/workspace/select.js +40 -9
  34. package/dist/components/TaskView.js +2 -2
  35. package/dist/index.js +2 -0
  36. package/dist/lib/agent-helpers.d.ts +59 -2
  37. package/dist/lib/agent-helpers.js +153 -8
  38. package/dist/lib/alternate-screen.js +2 -0
  39. package/dist/lib/api-client.js +2 -1
  40. package/dist/lib/config.d.ts +3 -0
  41. package/dist/lib/config.js +33 -0
  42. package/dist/lib/event-filter.d.ts +50 -0
  43. package/dist/lib/event-filter.js +91 -0
  44. package/dist/lib/generated-types.d.ts +2 -0
  45. package/dist/lib/generated-types.js +20 -0
  46. package/dist/lib/session-events.d.ts +27 -2
  47. package/dist/lib/session-events.js +5 -3
  48. package/dist/lib/session-polling.d.ts +8 -0
  49. package/dist/lib/session-polling.js +49 -0
  50. package/dist/lib/spinners.js +4 -1
  51. package/docs/CLI_WORKFLOW.md +7 -1
  52. package/docs/DESIGN.md +1 -1
  53. package/docs/skills/codex-agent-dev.md +155 -0
  54. package/docs/skills/integrations.md +338 -0
  55. package/package.json +1 -1
@@ -13,8 +13,9 @@ import chalk from 'chalk';
13
13
  import { readFileSync } from 'fs';
14
14
  import path from 'path';
15
15
  import { fileURLToPath } from 'url';
16
- import { isUnfulfilledAgentInstallRequest, isFilteredTaskName, getTaskDisplayName, matchesAgent, getAgentName, } from '../lib/session-events.js';
16
+ import { isUnfulfilledAgentInstallRequest, isFilteredTaskName, getTaskDisplayName, getAgentName, } from '../lib/session-events.js';
17
17
  import { printResumeHint, fetchSession, fetchSessionEvents, eventsToDisplayMessages, } from '../lib/session-resume.js';
18
+ import { DEFAULT_EVENT_TYPES, parseEventFilter, shouldShowEvent, } from '../lib/event-filter.js';
18
19
  import { fetchEvents, fetchTasks } from '../lib/session-events-fetch.js';
19
20
  import { AgentInstallPrompt } from '../components/AgentInstallPrompt.js';
20
21
  import { getWorkspaceId } from '../lib/guild-config.js';
@@ -117,7 +118,7 @@ function InputWrapper({ isReady, isInterrupted, input, setInput, handleSubmit, t
117
118
  React.createElement(Text, { color: isReady ? BRAND_COLOR : 'gray' }, "> "),
118
119
  isReady && isActive ? (React.createElement(CustomInput, { value: input, onChange: setInput, onSubmit: handleSubmit, trackedTasksSize: trackedTasksSize, setShowTaskPanel: setShowTaskPanel, isActive: isActive })) : isReady ? (React.createElement(Text, null, input)) : (React.createElement(Text, null, chalk.dim('(connecting...)')))));
119
120
  }
120
- export function ChatApp({ initialPrompt, version, workspaceId, versionId, agentName, showSplash = true, resumeSession, resumeEvents, resumeCommand, openDashboard, }) {
121
+ export function ChatApp({ initialPrompt, version, workspaceId, versionId, agentName, showSplash = true, resumeSession, resumeEvents, resumeCommand, openDashboard, eventFilter, }) {
121
122
  const { exit } = useApp();
122
123
  const isResuming = !!resumeSession;
123
124
  const [phase, setPhase] = useState(isResuming || !showSplash ? 'chat' : 'splash');
@@ -241,13 +242,14 @@ export function ChatApp({ initialPrompt, version, workspaceId, versionId, agentN
241
242
  }
242
243
  // If not connected yet, ignore escape (let connection complete)
243
244
  } })),
244
- phase === 'chat' && (React.createElement(ChatUIWithConnection, { initialPrompt: initialPrompt, version: version, versionId: versionId, agentName: agentName, client: connectedClient, session: connectedSession, onFirstMessage: () => setFirstMessageReceived(true), resumeEvents: resumeEvents, resumeCommand: resumeCommand })),
245
+ phase === 'chat' && (React.createElement(ChatUIWithConnection, { initialPrompt: initialPrompt, version: version, versionId: versionId, agentName: agentName, client: connectedClient, session: connectedSession, onFirstMessage: () => setFirstMessageReceived(true), resumeEvents: resumeEvents, resumeCommand: resumeCommand, eventFilter: eventFilter })),
245
246
  (phase === 'splash' || phase === 'finalizing') &&
246
247
  connectedSession &&
247
248
  connectedClient && (React.createElement(Box, { display: "none" },
248
- React.createElement(ChatUIWithConnection, { initialPrompt: initialPrompt, version: version, versionId: versionId, agentName: agentName, client: connectedClient, session: connectedSession, onFirstMessage: () => setFirstMessageReceived(true), isActive: false })))));
249
+ React.createElement(ChatUIWithConnection, { initialPrompt: initialPrompt, version: version, versionId: versionId, agentName: agentName, client: connectedClient, session: connectedSession, onFirstMessage: () => setFirstMessageReceived(true), isActive: false, eventFilter: eventFilter })))));
249
250
  }
250
- function ChatUIWithConnection({ initialPrompt, version: _version, versionId: _versionId, agentName, client: preConnectedClient, session: preConnectedSession, onFirstMessage, isActive = true, resumeEvents, resumeCommand, }) {
251
+ function ChatUIWithConnection({ initialPrompt, version: _version, versionId: _versionId, agentName, client: preConnectedClient, session: preConnectedSession, onFirstMessage, isActive = true, resumeEvents, resumeCommand, eventFilter, }) {
252
+ const activeFilter = eventFilter ?? DEFAULT_EVENT_TYPES;
251
253
  // Note: We handle SIGINT directly via process.on, not using useApp().exit
252
254
  // Task panel state - managed at this level to handle keyboard input before TextInput
253
255
  // Default to showing task panel (Ctrl-T to toggle)
@@ -525,18 +527,107 @@ function ChatUIWithConnection({ initialPrompt, version: _version, versionId: _ve
525
527
  }
526
528
  // Process events that affect the chat UI (task state comes from tasks poll)
527
529
  if (event.type === 'runtime_error') {
528
- // Show runtime errors in the chat
529
- const errorText = typeof event.content === 'string' ? event.content : 'Unknown error';
530
- const taskName = agentName || 'assistant';
531
- setMessages((prev) => [
532
- ...prev,
533
- {
534
- key: `error-${Date.now()}`,
535
- content: `${chalk.red('●')} ${chalk.bold(taskName)}\n${chalk.red(`Error: ${errorText}`)}`,
536
- type: 'assistant',
537
- },
538
- ]);
530
+ // Always clear the spinner on runtime errors so the UI doesn't get stuck
539
531
  setCurrentOperation('');
532
+ // Show runtime errors in the chat (gated on --events filter)
533
+ if (shouldShowEvent('runtime_error', activeFilter)) {
534
+ const errorText = typeof event.content === 'string' ? event.content : 'Unknown error';
535
+ const taskName = agentName || 'assistant';
536
+ setMessages((prev) => [
537
+ ...prev,
538
+ {
539
+ key: `error-${Date.now()}`,
540
+ content: `${chalk.red('●')} ${chalk.bold(taskName)}\n${chalk.red(`Error: ${errorText}`)}`,
541
+ type: 'assistant',
542
+ },
543
+ ]);
544
+ }
545
+ }
546
+ else if (event.type === 'runtime_start') {
547
+ if (shouldShowEvent('runtime_start', activeFilter)) {
548
+ setMessages((prev) => [
549
+ ...prev,
550
+ {
551
+ key: `runtime-start-${Date.now()}`,
552
+ content: chalk.dim('[runtime/start]'),
553
+ type: 'assistant',
554
+ },
555
+ ]);
556
+ }
557
+ }
558
+ else if (event.type === 'runtime_running') {
559
+ if (shouldShowEvent('runtime_running', activeFilter)) {
560
+ setMessages((prev) => [
561
+ ...prev,
562
+ {
563
+ key: `runtime-running-${Date.now()}`,
564
+ content: chalk.dim('[runtime/running]'),
565
+ type: 'assistant',
566
+ },
567
+ ]);
568
+ }
569
+ }
570
+ else if (event.type === 'runtime_waiting') {
571
+ if (shouldShowEvent('runtime_waiting', activeFilter)) {
572
+ setMessages((prev) => [
573
+ ...prev,
574
+ {
575
+ key: `runtime-waiting-${Date.now()}`,
576
+ content: chalk.dim('[runtime/waiting]'),
577
+ type: 'assistant',
578
+ },
579
+ ]);
580
+ }
581
+ }
582
+ else if (event.type === 'trigger_message') {
583
+ if (shouldShowEvent('trigger_message', activeFilter)) {
584
+ const triggerText = typeof event.content === 'object' ? event.content?.data || '' : '';
585
+ setMessages((prev) => [
586
+ ...prev,
587
+ {
588
+ key: `trigger-${Date.now()}`,
589
+ content: `${chalk.cyan('[trigger]')} ${triggerText}`,
590
+ type: 'assistant',
591
+ },
592
+ ]);
593
+ }
594
+ }
595
+ else if (event.type === 'system_error') {
596
+ if (shouldShowEvent('system_error', activeFilter)) {
597
+ const errText = typeof event.content === 'object' ? event.content?.data || '' : '';
598
+ setMessages((prev) => [
599
+ ...prev,
600
+ {
601
+ key: `system-error-${Date.now()}`,
602
+ content: `${chalk.red('[system_error]')} ${errText}`,
603
+ type: 'assistant',
604
+ },
605
+ ]);
606
+ }
607
+ }
608
+ else if (event.type === 'llm_start') {
609
+ if (shouldShowEvent('llm_start', activeFilter)) {
610
+ setMessages((prev) => [
611
+ ...prev,
612
+ {
613
+ key: `llm-start-${Date.now()}`,
614
+ content: chalk.dim(`[llm_start] provider:${event.provider}`),
615
+ type: 'assistant',
616
+ },
617
+ ]);
618
+ }
619
+ }
620
+ else if (event.type === 'llm_done') {
621
+ if (shouldShowEvent('llm_done', activeFilter)) {
622
+ setMessages((prev) => [
623
+ ...prev,
624
+ {
625
+ key: `llm-done-${Date.now()}`,
626
+ content: chalk.dim(`[llm_done] HTTP ${event.status_code}`),
627
+ type: 'assistant',
628
+ },
629
+ ]);
630
+ }
540
631
  }
541
632
  else if (event.type === 'agent_notification_progress') {
542
633
  // Update status line with progress text (task tracking is done by tasks poll)
@@ -609,48 +700,63 @@ function ChatUIWithConnection({ initialPrompt, version: _version, versionId: _ve
609
700
  ]);
610
701
  setCurrentOperation('');
611
702
  }
612
- else if (event.type === 'agent_console' && isDebugMode()) {
613
- // Show console logs when debug mode is enabled (matches www debug checkbox behavior)
614
- const content = typeof event.content === 'string' ? event.content : '';
615
- setMessages((prev) => [
616
- ...prev,
617
- {
618
- key: `console-${Date.now()}-${Math.random()}`,
619
- content: chalk.dim(`[console.${event.level}] ${content}`),
620
- type: 'assistant',
621
- },
622
- ]);
703
+ else if (event.type === 'agent_console') {
704
+ // Show console logs when enabled via --events or --debug
705
+ // --debug continues to show console logs for backwards compatibility
706
+ if (shouldShowEvent('agent_console', activeFilter) || isDebugMode()) {
707
+ const content = typeof event.content === 'string' ? event.content : '';
708
+ setMessages((prev) => [
709
+ ...prev,
710
+ {
711
+ key: `console-${Date.now()}-${Math.random()}`,
712
+ content: chalk.dim(`[console.${event.level}] ${content}`),
713
+ type: 'assistant',
714
+ },
715
+ ]);
716
+ }
623
717
  }
624
- else if (event.type === 'runtime_done' &&
625
- !receivedResponseSinceLastInput.current &&
626
- event.content !== undefined &&
627
- taskInfo &&
628
- 'agent' in taskInfo) {
629
- // One-shot agents may complete with runtime_done without sending
630
- // agent_notification_message. Display the output if we haven't
631
- // already shown a response for this input cycle.
632
- const contentStr = typeof event.content === 'string'
633
- ? event.content
634
- : JSON.stringify(event.content);
635
- if (contentStr && contentStr !== '{}' && contentStr !== 'null') {
636
- const rendered = fixListItemMarkdown(marked.parse(contentStr));
637
- const taskName = agentName || 'assistant';
638
- const messageContent = `${chalk.green('●')} ${chalk.bold(taskName)}\n${rendered.trim()}`;
718
+ else if (event.type === 'runtime_done') {
719
+ if (shouldShowEvent('runtime_done', activeFilter)) {
720
+ // Show runtime_done as a system event when enabled via --events
639
721
  setMessages((prev) => [
640
722
  ...prev,
641
723
  {
642
- key: `msg-${Date.now()}-${Math.random()}`,
643
- content: messageContent,
724
+ key: `runtime-done-${Date.now()}`,
725
+ content: chalk.dim('[runtime/done]'),
644
726
  type: 'assistant',
645
- timestamp: new Date().toLocaleTimeString(),
646
727
  },
647
728
  ]);
648
- if (!firstMessageNotified.current && onFirstMessage) {
649
- firstMessageNotified.current = true;
650
- onFirstMessage();
729
+ }
730
+ if (!receivedResponseSinceLastInput.current &&
731
+ event.content !== undefined &&
732
+ taskInfo &&
733
+ 'agent' in taskInfo) {
734
+ // One-shot agents may complete with runtime_done without sending
735
+ // agent_notification_message. Display the output if we haven't
736
+ // already shown a response for this input cycle.
737
+ const contentStr = typeof event.content === 'string'
738
+ ? event.content
739
+ : JSON.stringify(event.content);
740
+ if (contentStr && contentStr !== '{}' && contentStr !== 'null') {
741
+ const rendered = fixListItemMarkdown(marked.parse(contentStr));
742
+ const taskName = agentName || 'assistant';
743
+ const messageContent = `${chalk.green('●')} ${chalk.bold(taskName)}\n${rendered.trim()}`;
744
+ setMessages((prev) => [
745
+ ...prev,
746
+ {
747
+ key: `msg-${Date.now()}-${Math.random()}`,
748
+ content: messageContent,
749
+ type: 'assistant',
750
+ timestamp: new Date().toLocaleTimeString(),
751
+ },
752
+ ]);
753
+ if (!firstMessageNotified.current && onFirstMessage) {
754
+ firstMessageNotified.current = true;
755
+ onFirstMessage();
756
+ }
757
+ receivedResponseSinceLastInput.current = true;
758
+ setCurrentOperation('');
651
759
  }
652
- receivedResponseSinceLastInput.current = true;
653
- setCurrentOperation('');
654
760
  }
655
761
  }
656
762
  else if (event.type === 'interrupted') {
@@ -887,29 +993,7 @@ export async function createSession(client, workspaceId, initialPrompt, versionI
887
993
  }
888
994
  }
889
995
  if (!workspaceId) {
890
- // Fall back to fetching workspaces from API
891
- progress('Fetching workspaces');
892
- const response = await client.get('/me/workspaces');
893
- if (!response) {
894
- throw new Error('Failed to fetch workspaces');
895
- }
896
- // Handle both array and paginated object responses
897
- const workspaces = (Array.isArray(response)
898
- ? response
899
- : response?.items || []);
900
- if (workspaces.length === 0) {
901
- // Get current user to use as workspace owner
902
- progress('Creating workspace');
903
- const me = (await client.get('/me'));
904
- const newWorkspace = (await client.post('/workspaces', {
905
- name: 'My Workspace',
906
- owner_id: me.id,
907
- }));
908
- workspaceId = newWorkspace.id;
909
- }
910
- else {
911
- workspaceId = workspaces[0].id;
912
- }
996
+ throw new Error('No workspace configured. Run: guild workspace select, or pass --workspace <id>');
913
997
  }
914
998
  progress('Creating session');
915
999
  const sessionData = {
@@ -950,9 +1034,13 @@ export function createChatCommand() {
950
1034
  .option('--workspace <identifier>', 'Workspace ID or full name (e.g., owner/workspace-name)')
951
1035
  .option('--no-splash', 'Skip the splash screen animation')
952
1036
  .option('--resume <session-id>', 'Resume an existing session')
1037
+ .option('--events <types>', 'Event types to show (default: user). Shorthands: none, user, system, all, or comma-separated type names (e.g. agent_console,llm_start)')
953
1038
  .addHelpText('after', '\nTo chat with a local agent under development: guild agent chat')
954
1039
  .action(async (promptArgs, options) => {
955
1040
  const initialPrompt = promptArgs.length > 0 ? promptArgs.join(' ') : 'Hello';
1041
+ const eventFilter = options.events
1042
+ ? parseEventFilter(options.events)
1043
+ : DEFAULT_EVENT_TYPES;
956
1044
  if (options.once) {
957
1045
  // --once mode: use old spinner-based approach
958
1046
  const spinner = createSpinner('Connecting to Guild servers...');
@@ -999,24 +1087,37 @@ export function createChatCommand() {
999
1087
  else {
1000
1088
  inactivityCounter++;
1001
1089
  }
1002
- // Check if we got a completion response
1003
- // Look for runtime_done events from the ROOT task (the agent we're chatting with)
1004
- // For orchestrating agents like agent-builder that spawn child tasks, we need to
1005
- // wait for the root agent's completion, not just any runtime_done event.
1006
- const targetAgent = options.agent || 'assistant';
1007
- const hasRootTaskDone = allEvents.some((e) => e.type === 'runtime_done' &&
1008
- matchesAgent(e.task?.agent, targetAgent) &&
1009
- !e.task?.parent_task_id // Root task has no parent
1010
- );
1011
- // Also check for agent_notification_message events from the root agent
1012
- const hasAgentMessage = allEvents.some((e) => e.type === 'agent_notification_message' &&
1013
- matchesAgent(e.task?.agent, targetAgent) &&
1014
- !e.task?.parent_task_id);
1090
+ const isRootTask = (e) => !e.task?.parent_task;
1091
+ const hasRootTaskDone = allEvents.some((e) => e.type === 'runtime_done' && isRootTask(e));
1092
+ const hasAgentMessage = allEvents.some((e) => e.type === 'agent_notification_message' && isRootTask(e));
1093
+ const hasRootTaskError = allEvents.some((e) => e.type === 'runtime_error' && isRootTask(e));
1015
1094
  // Check for a ui_prompt request... that ends the game.
1016
1095
  const hasUIPromptMessage = allEvents.some((e) => e.type === 'agent_notification_message' &&
1017
1096
  e.task?.tool_name === 'ui_prompt');
1097
+ if (hasRootTaskError) {
1098
+ debug('Found error event from root agent, exiting --once mode');
1099
+ const errorEvents = allEvents.filter((e) => e.type === 'runtime_error' || e.type === 'agent_notification_error');
1100
+ if (errorEvents.length > 0 && !options.mode) {
1101
+ const lastError = errorEvents[errorEvents.length - 1];
1102
+ const content = lastError.content;
1103
+ if (content?.data) {
1104
+ console.error(chalk.red(`Error: ${content.data}`));
1105
+ }
1106
+ else {
1107
+ console.error(chalk.red('Agent failed to start'));
1108
+ }
1109
+ }
1110
+ else if (options.mode === 'json') {
1111
+ console.log(JSON.stringify({
1112
+ session_id: session.id,
1113
+ events: allEvents,
1114
+ error: true,
1115
+ }, null, 2));
1116
+ }
1117
+ process.exit(1);
1118
+ }
1018
1119
  if (hasRootTaskDone || hasAgentMessage || hasUIPromptMessage) {
1019
- debug(`Found completion event from root agent (${targetAgent}), exiting --once mode`);
1120
+ debug('Found completion event from root agent, exiting --once mode');
1020
1121
  await outputOnceResult(session.id, allEvents, options.mode);
1021
1122
  process.exit(0);
1022
1123
  }
@@ -1075,7 +1176,7 @@ export function createChatCommand() {
1075
1176
  if (shouldShowSplash) {
1076
1177
  suppressScrollbackClear();
1077
1178
  }
1078
- const { waitUntilExit } = render(React.createElement(ChatApp, { initialPrompt: initialPrompt, version: packageJson.version, workspaceId: options.workspace, versionId: options.agent, showSplash: shouldShowSplash, resumeSession: resumeSession, resumeEvents: resumeSessionEvents, resumeCommand: resumeCommand }), {
1179
+ const { waitUntilExit } = render(React.createElement(ChatApp, { initialPrompt: initialPrompt, version: packageJson.version, workspaceId: options.workspace, versionId: options.agent, showSplash: shouldShowSplash, resumeSession: resumeSession, resumeEvents: resumeSessionEvents, resumeCommand: resumeCommand, eventFilter: eventFilter }), {
1079
1180
  exitOnCtrlC: false, // We handle Ctrl-C in useInput (raw mode)
1080
1181
  });
1081
1182
  await waitUntilExit();
@@ -27,13 +27,13 @@ export function createConfigListCommand() {
27
27
  output.progress(chalk.dim(' guild workspace select'));
28
28
  return;
29
29
  }
30
- if (hasGlobal) {
30
+ if (config.global && hasGlobal) {
31
31
  output.progress(chalk.bold('Global config') + chalk.dim(' (~/.guild/config.json):'));
32
32
  for (const [key, value] of Object.entries(config.global)) {
33
33
  output.progress(` ${key}: ${chalk.cyan(String(value))}`);
34
34
  }
35
35
  }
36
- if (hasLocal) {
36
+ if (config.local && hasLocal) {
37
37
  if (hasGlobal)
38
38
  output.progress('');
39
39
  output.progress(chalk.bold('Local config') + chalk.dim(' (guild.json):'));
@@ -17,7 +17,7 @@ export function createIntegrationOperationCreateCommand() {
17
17
  cmd
18
18
  .description('Create operation(s) for an integration version')
19
19
  .argument('<id_or_name>', 'Integration ID or name (owner~name)')
20
- .option('--version <semver>', 'Specific version, e.g. 1.0.0')
20
+ .option('--version-number <semver>', 'Specific version, e.g. 1.0.0')
21
21
  .option('--operation <name>', 'Operation identifier, e.g. list_users')
22
22
  .option('--method <method>', 'HTTP method: GET, POST, PUT, PATCH, DELETE')
23
23
  .option('--path <path>', 'REST path, e.g. /{owner}/{repo}/issues')
@@ -35,7 +35,7 @@ export function createIntegrationOperationCreateCommand() {
35
35
  process.exit(1);
36
36
  }
37
37
  const client = new GuildAPIClient();
38
- const versionId = await resolveVersionId(client, identifier, options.version);
38
+ const versionId = await resolveVersionId(client, identifier, options.versionNumber);
39
39
  if (options.openapi) {
40
40
  // OpenAPI mode
41
41
  if (!existsSync(options.openapi)) {
@@ -14,7 +14,7 @@ export function createIntegrationOperationListCommand() {
14
14
  cmd
15
15
  .description('List operations for an integration version')
16
16
  .argument('<id_or_name>', 'Integration ID or name (owner~name)')
17
- .option('--version <semver>', 'Specific version, e.g. 1.0.0')
17
+ .option('--version-number <semver>', 'Specific version, e.g. 1.0.0')
18
18
  .option('--limit <number>', 'Number of results to return', '100')
19
19
  .option('--offset <number>', 'Offset for pagination', '0')
20
20
  .action(async (identifier, options) => {
@@ -26,7 +26,7 @@ export function createIntegrationOperationListCommand() {
26
26
  process.exit(1);
27
27
  }
28
28
  const client = new GuildAPIClient();
29
- const versionId = await resolveVersionId(client, identifier, options.version);
29
+ const versionId = await resolveVersionId(client, identifier, options.versionNumber);
30
30
  const params = new URLSearchParams();
31
31
  params.append('limit', options.limit);
32
32
  params.append('offset', options.offset);
@@ -63,7 +63,7 @@ export function createIntegrationUpdateCommand() {
63
63
  hasUpdates = true;
64
64
  }
65
65
  if (options.baseUrl !== undefined) {
66
- body.protocol_config = { base_url: options.baseUrl };
66
+ body.protocol_config = { protocol: 'REST', base_url: options.baseUrl };
67
67
  hasUpdates = true;
68
68
  }
69
69
  // Auth config updates need the discriminator
@@ -34,7 +34,7 @@ export function createIntegrationVersionGetCommand() {
34
34
  cmd
35
35
  .description('Get version details')
36
36
  .argument('<id_or_name>', 'Integration ID or name (owner~name)')
37
- .option('--version <semver>', 'Specific version, e.g. 1.0.0')
37
+ .option('--version-number <semver>', 'Specific version, e.g. 1.0.0')
38
38
  .action(async (identifier, options) => {
39
39
  const output = createOutputWriter();
40
40
  try {
@@ -44,7 +44,7 @@ export function createIntegrationVersionGetCommand() {
44
44
  process.exit(1);
45
45
  }
46
46
  const client = new GuildAPIClient();
47
- const versionId = await resolveVersionId(client, identifier, options.version);
47
+ const versionId = await resolveVersionId(client, identifier, options.versionNumber);
48
48
  const response = await client.get(`/integration_versions/${versionId}`);
49
49
  if (getOutputMode() === 'json') {
50
50
  output.data(response);
@@ -23,7 +23,7 @@ export function createIntegrationVersionPublishCommand() {
23
23
  cmd
24
24
  .description('Publish a built version')
25
25
  .argument('<id_or_name>', 'Integration ID or name (owner~name)')
26
- .option('--version <semver>', 'Specific version to publish, e.g. 1.0.0')
26
+ .option('--version-number <semver>', 'Specific version to publish, e.g. 1.0.0')
27
27
  .action(async (identifier, options) => {
28
28
  const output = createOutputWriter();
29
29
  try {
@@ -33,7 +33,7 @@ export function createIntegrationVersionPublishCommand() {
33
33
  process.exit(1);
34
34
  }
35
35
  const client = new GuildAPIClient();
36
- const versionId = await resolveVersionId(client, identifier, options.version);
36
+ const versionId = await resolveVersionId(client, identifier, options.versionNumber);
37
37
  // Get current version info for display
38
38
  const currentVersion = await client.get(`/integration_versions/${versionId}`);
39
39
  const versionDisplay = currentVersion.version_number || versionId;
@@ -22,7 +22,7 @@ export function createIntegrationVersionTestCommand() {
22
22
  cmd
23
23
  .description('Test an endpoint invocation')
24
24
  .argument('<id_or_name>', 'Integration ID or name (owner~name)')
25
- .option('--version <semver>', 'Specific version, e.g. 1.0.0')
25
+ .option('--version-number <semver>', 'Specific version, e.g. 1.0.0')
26
26
  .requiredOption('--operation <name>', 'Operation to test, e.g. list_users')
27
27
  .option('--account <name>', 'Account name to resolve credential from')
28
28
  .option('--input-path <json>', 'JSON object of path parameters')
@@ -50,7 +50,7 @@ export function createIntegrationVersionTestCommand() {
50
50
  body.input_body = parseJsonFlag(options.inputBody, '--input-body');
51
51
  }
52
52
  const client = new GuildAPIClient();
53
- const versionId = await resolveVersionId(client, identifier, options.version);
53
+ const versionId = await resolveVersionId(client, identifier, options.versionNumber);
54
54
  if (options.account) {
55
55
  const creds = await client.get(`/accounts/${options.account}/credentials?integration=${encodeURIComponent(identifier)}`);
56
56
  if (creds.items.length === 0) {
@@ -3,6 +3,7 @@
3
3
  import { Command } from 'commander';
4
4
  import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../lib/auth.js';
6
+ import { parseEventFilter } from '../../lib/event-filter.js';
6
7
  import { handleAxiosError } from '../../lib/errors.js';
7
8
  import { createOutputWriter } from '../../lib/output.js';
8
9
  export function createSessionEventsCommand() {
@@ -10,7 +11,7 @@ export function createSessionEventsCommand() {
10
11
  cmd
11
12
  .description('List events in a session')
12
13
  .argument('<session-id>', 'Session ID')
13
- .option('--types <types>', 'Comma-separated event types to filter (e.g., user_message,agent_notification_message)')
14
+ .option('--events <types>', 'Event types to show. Shorthands: none, user, system, all, or comma-separated type names')
14
15
  .option('--limit <number>', 'Number of results to return', '100')
15
16
  .option('--offset <number>', 'Offset for pagination', '0')
16
17
  .action(async (sessionId, options) => {
@@ -25,8 +26,11 @@ export function createSessionEventsCommand() {
25
26
  const params = new URLSearchParams();
26
27
  params.append('limit', options.limit);
27
28
  params.append('offset', options.offset);
28
- if (options.types) {
29
- params.append('types', options.types);
29
+ if (options.events) {
30
+ const filter = parseEventFilter(options.events);
31
+ if (filter.size > 0) {
32
+ params.append('types', [...filter].join(','));
33
+ }
30
34
  }
31
35
  const response = await client.get(`/sessions/${sessionId}/events?${params.toString()}`);
32
36
  output.data(response);
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createSessionInterruptCommand(): Command;
3
+ //# sourceMappingURL=interrupt.d.ts.map
@@ -0,0 +1,33 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
8
+ export function createSessionInterruptCommand() {
9
+ const cmd = new Command('interrupt');
10
+ cmd
11
+ .description('Interrupt a running session')
12
+ .argument('<session-id>', 'Session ID')
13
+ .action(async (sessionId) => {
14
+ const output = createOutputWriter();
15
+ try {
16
+ const token = await getAuthToken();
17
+ if (!token) {
18
+ output.error('Not authenticated. Run: guild auth login');
19
+ process.exit(1);
20
+ }
21
+ const client = new GuildAPIClient();
22
+ const response = await client.post(`/sessions/${sessionId}/interrupt`, {});
23
+ output.data(response);
24
+ }
25
+ catch (error) {
26
+ const formattedError = handleAxiosError(error);
27
+ output.error(`Failed to interrupt session: ${formattedError.details}`);
28
+ process.exit(1);
29
+ }
30
+ });
31
+ return cmd;
32
+ }
33
+ //# sourceMappingURL=interrupt.js.map