@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.
- package/README.md +3 -1
- package/dist/commands/agent/chat.js +41 -99
- package/dist/commands/agent/clone.js +1 -1
- package/dist/commands/agent/code.js +1 -1
- package/dist/commands/agent/fork.js +2 -2
- package/dist/commands/agent/get.js +1 -1
- package/dist/commands/agent/grep.js +2 -2
- package/dist/commands/agent/init.js +10 -3
- package/dist/commands/agent/list.js +9 -1
- package/dist/commands/agent/publish.js +1 -1
- package/dist/commands/agent/revalidate.js +1 -1
- package/dist/commands/agent/save.js +23 -2
- package/dist/commands/agent/test.js +70 -130
- package/dist/commands/agent/unpublish.js +1 -1
- package/dist/commands/agent/update.js +1 -1
- package/dist/commands/agent/versions.js +1 -1
- package/dist/commands/agent/workspaces.js +1 -1
- package/dist/commands/chat.d.ts +2 -1
- package/dist/commands/chat.js +189 -88
- package/dist/commands/config/list.js +2 -2
- package/dist/commands/integration/operation/create.js +2 -2
- package/dist/commands/integration/operation/list.js +2 -2
- package/dist/commands/integration/update.js +1 -1
- package/dist/commands/integration/version/get.js +2 -2
- package/dist/commands/integration/version/publish.js +2 -2
- package/dist/commands/integration/version/test.js +2 -2
- package/dist/commands/session/events.js +7 -3
- package/dist/commands/session/interrupt.d.ts +3 -0
- package/dist/commands/session/interrupt.js +33 -0
- package/dist/commands/setup.js +70 -11
- package/dist/commands/workspace/get.js +1 -1
- package/dist/commands/workspace/list.js +28 -6
- package/dist/commands/workspace/select.js +40 -9
- package/dist/components/TaskView.js +2 -2
- package/dist/index.js +2 -0
- package/dist/lib/agent-helpers.d.ts +59 -2
- package/dist/lib/agent-helpers.js +153 -8
- package/dist/lib/alternate-screen.js +2 -0
- package/dist/lib/api-client.js +2 -1
- package/dist/lib/config.d.ts +3 -0
- package/dist/lib/config.js +33 -0
- package/dist/lib/event-filter.d.ts +50 -0
- package/dist/lib/event-filter.js +91 -0
- package/dist/lib/generated-types.d.ts +2 -0
- package/dist/lib/generated-types.js +20 -0
- package/dist/lib/session-events.d.ts +27 -2
- package/dist/lib/session-events.js +5 -3
- package/dist/lib/session-polling.d.ts +8 -0
- package/dist/lib/session-polling.js +49 -0
- package/dist/lib/spinners.js +4 -1
- package/docs/CLI_WORKFLOW.md +7 -1
- package/docs/DESIGN.md +1 -1
- package/docs/skills/codex-agent-dev.md +155 -0
- package/docs/skills/integrations.md +338 -0
- package/package.json +1 -1
package/dist/commands/chat.js
CHANGED
|
@@ -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,
|
|
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
|
-
//
|
|
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'
|
|
613
|
-
// Show console logs when
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
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
|
-
|
|
626
|
-
|
|
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: `
|
|
643
|
-
content:
|
|
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
|
-
|
|
649
|
-
|
|
650
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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('--
|
|
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.
|
|
29
|
-
|
|
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,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
|