@guildai/cli 0.5.13 → 0.6.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 +17 -0
- package/dist/commands/agent/chat.js +31 -31
- package/dist/commands/agent/clone.js +3 -1
- package/dist/commands/agent/code.js +3 -2
- package/dist/commands/agent/fork.js +41 -15
- package/dist/commands/agent/get.js +3 -2
- package/dist/commands/agent/grep.js +61 -31
- package/dist/commands/agent/init.js +1 -1
- package/dist/commands/agent/publish.js +3 -2
- package/dist/commands/agent/pull.js +36 -21
- package/dist/commands/agent/revalidate.js +4 -3
- package/dist/commands/agent/save.js +2 -2
- package/dist/commands/agent/search.js +3 -3
- package/dist/commands/agent/tags/add.js +4 -3
- package/dist/commands/agent/tags/list.js +3 -2
- package/dist/commands/agent/tags/remove.js +4 -3
- package/dist/commands/agent/tags/set.js +3 -2
- package/dist/commands/agent/test.js +8 -12
- package/dist/commands/agent/unpublish.js +3 -2
- package/dist/commands/agent/update.js +9 -8
- package/dist/commands/agent/versions.js +3 -2
- package/dist/commands/agent/workspaces.js +3 -2
- package/dist/commands/auth/login.js +3 -3
- package/dist/commands/chat.js +64 -102
- package/dist/commands/credentials/endpoint-list.d.ts +3 -0
- package/dist/commands/credentials/endpoint-list.js +87 -0
- package/dist/commands/credentials/list.d.ts +3 -0
- package/dist/commands/{container → credentials}/list.js +11 -10
- package/dist/commands/credentials/policy-create.d.ts +3 -0
- package/dist/commands/credentials/policy-create.js +66 -0
- package/dist/commands/credentials/policy-delete.d.ts +3 -0
- package/dist/commands/{container/get.js → credentials/policy-delete.js} +9 -9
- package/dist/commands/credentials/policy-list.d.ts +3 -0
- package/dist/commands/{container-image/list.js → credentials/policy-list.js} +9 -9
- package/dist/commands/credentials/policy-update.d.ts +3 -0
- package/dist/commands/credentials/policy-update.js +66 -0
- package/dist/commands/integration/connect.d.ts +3 -0
- package/dist/commands/integration/connect.js +76 -0
- package/dist/commands/integration/create.d.ts +3 -0
- package/dist/commands/integration/create.js +298 -0
- package/dist/commands/integration/get.d.ts +3 -0
- package/dist/commands/integration/get.js +95 -0
- package/dist/commands/integration/list.d.ts +3 -0
- package/dist/commands/integration/list.js +61 -0
- package/dist/commands/integration/operation/create.d.ts +3 -0
- package/dist/commands/integration/operation/create.js +163 -0
- package/dist/commands/integration/operation/list.d.ts +3 -0
- package/dist/commands/integration/operation/list.js +83 -0
- package/dist/commands/integration/update.d.ts +3 -0
- package/dist/commands/integration/update.js +139 -0
- package/dist/commands/integration/version/build.d.ts +3 -0
- package/dist/commands/integration/version/build.js +86 -0
- package/dist/commands/integration/version/create.d.ts +3 -0
- package/dist/commands/integration/version/create.js +45 -0
- package/dist/commands/integration/version/get.d.ts +3 -0
- package/dist/commands/integration/version/get.js +72 -0
- package/dist/commands/integration/version/list.d.ts +3 -0
- package/dist/commands/integration/version/list.js +44 -0
- package/dist/commands/integration/version/publish.d.ts +3 -0
- package/dist/commands/integration/version/publish.js +79 -0
- package/dist/commands/integration/version/test.d.ts +3 -0
- package/dist/commands/integration/version/test.js +104 -0
- package/dist/commands/trigger/create.js +35 -19
- package/dist/commands/workspace/create.js +10 -4
- package/dist/commands/workspace/select.js +0 -1
- package/dist/index.js +60 -27
- package/dist/lib/agent-helpers.d.ts +8 -0
- package/dist/lib/agent-helpers.js +15 -0
- package/dist/lib/api-types.d.ts +109 -78
- package/dist/lib/auth.d.ts +1 -1
- package/dist/lib/auth.js +10 -6
- package/dist/lib/integration-helpers.d.ts +15 -0
- package/dist/lib/integration-helpers.js +38 -0
- package/dist/lib/output.d.ts +13 -16
- package/dist/lib/output.js +137 -109
- package/dist/lib/session-events-fetch.d.ts +27 -0
- package/dist/lib/session-events-fetch.js +25 -0
- package/dist/lib/session-polling.d.ts +7 -2
- package/dist/lib/session-polling.js +18 -11
- package/dist/lib/session-resume.js +2 -5
- package/dist/lib/table.d.ts +0 -1
- package/dist/lib/table.js +0 -1
- package/dist/mcp/tools.js +6 -12
- package/docs/CLI_WORKFLOW.md +19 -2
- package/docs/skills/agent-dev.md +17 -2
- package/package.json +6 -5
- package/dist/commands/container/destroy.d.ts +0 -3
- package/dist/commands/container/destroy.js +0 -48
- package/dist/commands/container/events.d.ts +0 -3
- package/dist/commands/container/events.js +0 -44
- package/dist/commands/container/exec.d.ts +0 -3
- package/dist/commands/container/exec.js +0 -64
- package/dist/commands/container/get.d.ts +0 -3
- package/dist/commands/container/list.d.ts +0 -3
- package/dist/commands/container-image/create.d.ts +0 -3
- package/dist/commands/container-image/create.js +0 -41
- package/dist/commands/container-image/get.d.ts +0 -3
- package/dist/commands/container-image/get.js +0 -33
- package/dist/commands/container-image/list.d.ts +0 -3
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../../lib/api-client.js';
|
|
5
|
-
import { getAgentId } from '../../../lib/agent-helpers.js';
|
|
5
|
+
import { getAgentId, resolveAgentRef } from '../../../lib/agent-helpers.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../../lib/errors.js';
|
|
7
7
|
import { createOutputWriter } from '../../../lib/output.js';
|
|
8
8
|
export function createAgentTagsListCommand() {
|
|
@@ -16,8 +16,9 @@ export function createAgentTagsListCommand() {
|
|
|
16
16
|
const client = new GuildAPIClient();
|
|
17
17
|
// Resolve agent ID
|
|
18
18
|
const { agentId } = await getAgentId(agentIdArg);
|
|
19
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
19
20
|
// Fetch tags
|
|
20
|
-
const response = await client.get(`/agents/${
|
|
21
|
+
const response = await client.get(`/agents/${resolvedId}/tags`);
|
|
21
22
|
output.data(response);
|
|
22
23
|
}
|
|
23
24
|
catch (error) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../../lib/api-client.js';
|
|
5
|
-
import { getAgentId } from '../../../lib/agent-helpers.js';
|
|
5
|
+
import { getAgentId, resolveAgentRef } from '../../../lib/agent-helpers.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../../lib/errors.js';
|
|
7
7
|
import { createOutputWriter } from '../../../lib/output.js';
|
|
8
8
|
export function createAgentTagsRemoveCommand() {
|
|
@@ -34,19 +34,20 @@ export function createAgentTagsRemoveCommand() {
|
|
|
34
34
|
}
|
|
35
35
|
// Now resolve agent ID properly
|
|
36
36
|
const { agentId, config } = await getAgentId(agentIdArg);
|
|
37
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
37
38
|
if (tagsToRemove.length === 0) {
|
|
38
39
|
output.error('At least one tag is required.', 'Usage: guild agent tags remove [agent-id] <tag...>');
|
|
39
40
|
process.exit(1);
|
|
40
41
|
}
|
|
41
42
|
// Fetch current tags
|
|
42
|
-
const response = await client.get(`/agents/${
|
|
43
|
+
const response = await client.get(`/agents/${resolvedId}/tags`);
|
|
43
44
|
const currentTags = response.names;
|
|
44
45
|
// Remove specified tags
|
|
45
46
|
const updatedTags = currentTags.filter((tag) => !tagsToRemove.includes(tag));
|
|
46
47
|
// Track which tags were not present
|
|
47
48
|
const notPresentTags = tagsToRemove.filter((tag) => !currentTags.includes(tag));
|
|
48
49
|
// Update tags
|
|
49
|
-
await client.post(`/agents/${
|
|
50
|
+
await client.post(`/agents/${resolvedId}/tags`, { names: updatedTags });
|
|
50
51
|
const agentName = config?.name || `agent ${agentId}`;
|
|
51
52
|
const label = `${agentName}${config ? '' : ` (${agentId})`}`;
|
|
52
53
|
output.success(`Updated tags for agent: ${label}`);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../../lib/api-client.js';
|
|
5
|
-
import { getAgentId } from '../../../lib/agent-helpers.js';
|
|
5
|
+
import { getAgentId, resolveAgentRef } from '../../../lib/agent-helpers.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../../lib/errors.js';
|
|
7
7
|
import { createOutputWriter } from '../../../lib/output.js';
|
|
8
8
|
export function createAgentTagsSetCommand() {
|
|
@@ -36,8 +36,9 @@ export function createAgentTagsSetCommand() {
|
|
|
36
36
|
}
|
|
37
37
|
// Now resolve agent ID properly
|
|
38
38
|
const { agentId, config } = await getAgentId(agentIdArg);
|
|
39
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
39
40
|
// Update tags (direct replacement)
|
|
40
|
-
await client.post(`/agents/${
|
|
41
|
+
await client.post(`/agents/${resolvedId}/tags`, { names: tagsToSet });
|
|
41
42
|
const agentName = config?.name || `agent ${agentId}`;
|
|
42
43
|
const label = `${agentName}${config ? '' : ` (${agentId})`}`;
|
|
43
44
|
if (tagsToSet.length === 0) {
|
|
@@ -303,9 +303,9 @@ export function createAgentTestCommand() {
|
|
|
303
303
|
mode: 'json',
|
|
304
304
|
content: inputData,
|
|
305
305
|
});
|
|
306
|
-
// Poll for response (starting from
|
|
306
|
+
// Poll for response (starting from beginning)
|
|
307
307
|
// 3 minutes - allow time for agents that use LLM calls for input parsing
|
|
308
|
-
const response = await pollForResponse(client, session.id,
|
|
308
|
+
const { response } = await pollForResponse(client, session.id, undefined, 180000);
|
|
309
309
|
if (!response) {
|
|
310
310
|
console.error('Error: No response received from agent within timeout');
|
|
311
311
|
console.error('');
|
|
@@ -365,7 +365,7 @@ export function createAgentTestCommand() {
|
|
|
365
365
|
});
|
|
366
366
|
let lineNumber = 0;
|
|
367
367
|
let processedCount = 0;
|
|
368
|
-
let
|
|
368
|
+
let lastEventId;
|
|
369
369
|
for await (const line of rl) {
|
|
370
370
|
lineNumber++;
|
|
371
371
|
if (!line.trim())
|
|
@@ -380,18 +380,14 @@ export function createAgentTestCommand() {
|
|
|
380
380
|
mode: 'json',
|
|
381
381
|
content: jsonInput,
|
|
382
382
|
});
|
|
383
|
-
// Wait for response (looking for events after
|
|
384
|
-
const
|
|
385
|
-
|
|
383
|
+
// Wait for response (looking for events after last seen)
|
|
384
|
+
const result = await pollForResponse(client, session.id, lastEventId, 180000);
|
|
385
|
+
lastEventId = result.lastEventId;
|
|
386
|
+
if (!result.response) {
|
|
386
387
|
console.error(`Timeout: No response for line ${lineNumber}`);
|
|
387
|
-
// Update event count even if timeout
|
|
388
|
-
const eventsAfterResponse = await client.get(`/sessions/${session.id}/events`);
|
|
389
|
-
lastEventCount = eventsAfterResponse?.items?.length || 0;
|
|
390
388
|
continue;
|
|
391
389
|
}
|
|
392
|
-
|
|
393
|
-
const eventsAfterResponse = await client.get(`/sessions/${session.id}/events`);
|
|
394
|
-
lastEventCount = eventsAfterResponse?.items?.length || 0;
|
|
390
|
+
const response = result.response;
|
|
395
391
|
// Output response
|
|
396
392
|
if (quiet) {
|
|
397
393
|
// In quiet mode, output just the message content (or as JSON if --json is used)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
-
import { getAgentId } from '../../lib/agent-helpers.js';
|
|
5
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
7
7
|
import { createOutputWriter } from '../../lib/output.js';
|
|
8
8
|
export function createAgentUnpublishCommand() {
|
|
@@ -16,8 +16,9 @@ export function createAgentUnpublishCommand() {
|
|
|
16
16
|
const client = new GuildAPIClient();
|
|
17
17
|
// Resolve agent ID
|
|
18
18
|
const { agentId, config } = await getAgentId(agentIdArg);
|
|
19
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
19
20
|
// Fetch all versions
|
|
20
|
-
const response = await client.get(`/agents/${
|
|
21
|
+
const response = await client.get(`/agents/${resolvedId}/versions`);
|
|
21
22
|
// Find latest PUBLISHED version
|
|
22
23
|
const publishedVersions = response.items
|
|
23
24
|
.filter((v) => v.status === 'PUBLISHED')
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import * as readline from 'readline';
|
|
5
5
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
6
|
-
import {
|
|
6
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
7
7
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
8
8
|
import { createOutputWriter } from '../../lib/output.js';
|
|
9
9
|
async function confirmVisibilityChange(agentName, makePublic) {
|
|
@@ -26,15 +26,15 @@ export function createAgentUpdateCommand() {
|
|
|
26
26
|
const cmd = new Command('update');
|
|
27
27
|
cmd
|
|
28
28
|
.description('Update agent properties (visibility)')
|
|
29
|
-
.argument('
|
|
29
|
+
.argument('[identifier]', 'Agent ID or full name (e.g., owner/agent-name)')
|
|
30
30
|
.option('--public', 'Make the agent public (visible to everyone)')
|
|
31
31
|
.option('--private', 'Make the agent private (only visible to owner)')
|
|
32
32
|
.option('--yes', 'Skip confirmation prompt for visibility changes')
|
|
33
|
-
.action(async (
|
|
33
|
+
.action(async (identifierArg, options) => {
|
|
34
34
|
const output = createOutputWriter();
|
|
35
35
|
// Validate that at least one option is provided
|
|
36
36
|
if (!options.public && !options.private) {
|
|
37
|
-
output.error('No update options provided.', 'Usage: guild agent update
|
|
37
|
+
output.error('No update options provided.', 'Usage: guild agent update [identifier] [options]\n\nOptions:\n --public Make the agent public\n --private Make the agent private\n --yes Skip confirmation prompt\n\nExamples:\n guild agent update my-agent --public\n guild agent update my-agent --private --yes\n guild agent update --public (uses guild.json)\n\nNote: Agent descriptions are set from README.md when publishing.');
|
|
38
38
|
process.exit(1);
|
|
39
39
|
}
|
|
40
40
|
// Validate that --public and --private are not both specified
|
|
@@ -42,11 +42,12 @@ export function createAgentUpdateCommand() {
|
|
|
42
42
|
output.error('Cannot specify both --public and --private');
|
|
43
43
|
process.exit(1);
|
|
44
44
|
}
|
|
45
|
-
const
|
|
46
|
-
const client = new GuildAPIClient(
|
|
45
|
+
const { agentId } = await getAgentId(identifierArg);
|
|
46
|
+
const client = new GuildAPIClient();
|
|
47
47
|
try {
|
|
48
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
48
49
|
// Fetch current agent info for confirmation prompts
|
|
49
|
-
const agent = await client.get(`/agents/${
|
|
50
|
+
const agent = await client.get(`/agents/${resolvedId}`);
|
|
50
51
|
// Handle visibility change confirmation
|
|
51
52
|
const changingVisibility = options.public || options.private;
|
|
52
53
|
if (changingVisibility) {
|
|
@@ -73,7 +74,7 @@ export function createAgentUpdateCommand() {
|
|
|
73
74
|
if (options.private) {
|
|
74
75
|
updatePayload.is_public = false;
|
|
75
76
|
}
|
|
76
|
-
const result = await client.patch(`/agents/${
|
|
77
|
+
const result = await client.patch(`/agents/${resolvedId}`, updatePayload);
|
|
77
78
|
// Build success message
|
|
78
79
|
const changes = [];
|
|
79
80
|
if (changingVisibility) {
|
|
@@ -4,7 +4,7 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
5
|
import { getGuildcoreUrl } from '../../lib/config.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
7
|
-
import { getAgentId } from '../../lib/agent-helpers.js';
|
|
7
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
8
8
|
import { getOutputMode } from '../../lib/output-mode.js';
|
|
9
9
|
import { createOutputWriter, formatVersionTable } from '../../lib/output.js';
|
|
10
10
|
export function createAgentVersionsCommand() {
|
|
@@ -23,7 +23,8 @@ export function createAgentVersionsCommand() {
|
|
|
23
23
|
const limit = parseInt(options.limit, 10);
|
|
24
24
|
const offset = parseInt(options.offset, 10);
|
|
25
25
|
try {
|
|
26
|
-
const
|
|
26
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
27
|
+
const result = await client.get(`/agents/${resolvedId}/versions?limit=${limit}&offset=${offset}`);
|
|
27
28
|
if (getOutputMode() === 'json') {
|
|
28
29
|
output.data(result);
|
|
29
30
|
}
|
|
@@ -4,7 +4,7 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
5
|
import { getGuildcoreUrl } from '../../lib/config.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
7
|
-
import { getAgentId } from '../../lib/agent-helpers.js';
|
|
7
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
8
8
|
import { createOutputWriter, formatWorkspaceTable } from '../../lib/output.js';
|
|
9
9
|
import { getOutputMode } from '../../lib/output-mode.js';
|
|
10
10
|
export function createAgentWorkspacesCommand() {
|
|
@@ -22,7 +22,8 @@ export function createAgentWorkspacesCommand() {
|
|
|
22
22
|
const limit = parseInt(options.limit, 10);
|
|
23
23
|
const offset = parseInt(options.offset, 10);
|
|
24
24
|
try {
|
|
25
|
-
const
|
|
25
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
26
|
+
const result = await client.get(`/agents/${resolvedId}/workspaces?limit=${limit}&offset=${offset}`);
|
|
26
27
|
if (getOutputMode() === 'json') {
|
|
27
28
|
output.data(result);
|
|
28
29
|
}
|
|
@@ -11,11 +11,11 @@ export function createAuthLoginCommand() {
|
|
|
11
11
|
.description('Login to Guild.ai')
|
|
12
12
|
.option('--return-url <url>', 'Custom URL to redirect to after authentication')
|
|
13
13
|
.option('--return-label <text>', 'Friendly label for return button (e.g., "VSCode")')
|
|
14
|
-
.option('--
|
|
14
|
+
.option('--non-interactive', 'Skip interactive prompts (for use with coding agents)')
|
|
15
15
|
.action(async (options) => {
|
|
16
16
|
const output = createOutputWriter();
|
|
17
|
-
const
|
|
18
|
-
const success = await login(options.returnUrl, options.returnLabel,
|
|
17
|
+
const nonInteractive = options.nonInteractive || false;
|
|
18
|
+
const success = await login(options.returnUrl, options.returnLabel, nonInteractive);
|
|
19
19
|
if (success) {
|
|
20
20
|
try {
|
|
21
21
|
await configureNpmrc();
|
package/dist/commands/chat.js
CHANGED
|
@@ -15,6 +15,7 @@ import path from 'path';
|
|
|
15
15
|
import { fileURLToPath } from 'url';
|
|
16
16
|
import { isUnfulfilledAgentInstallRequest, isFilteredTaskName, getTaskDisplayName, matchesAgent, getAgentName, } from '../lib/session-events.js';
|
|
17
17
|
import { printResumeHint, fetchSession, fetchSessionEvents, eventsToDisplayMessages, } from '../lib/session-resume.js';
|
|
18
|
+
import { fetchEvents, fetchTasks } from '../lib/session-events-fetch.js';
|
|
18
19
|
import { AgentInstallPrompt } from '../components/AgentInstallPrompt.js';
|
|
19
20
|
import { getWorkspaceId } from '../lib/guild-config.js';
|
|
20
21
|
import { ensureInteractiveStdin } from '../lib/stdin.js';
|
|
@@ -46,6 +47,35 @@ function fixListItemMarkdown(text) {
|
|
|
46
47
|
text = text.replace(/(?<![\\w])_([^_]+)_(?![\\w])/g, (_, content) => chalk.italic(content));
|
|
47
48
|
return text;
|
|
48
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Output the result of a --once mode session.
|
|
52
|
+
* Handles both JSON and human-readable output formats.
|
|
53
|
+
*/
|
|
54
|
+
async function outputOnceResult(sessionId, events, mode) {
|
|
55
|
+
if (mode === 'json') {
|
|
56
|
+
console.log(JSON.stringify({ session_id: sessionId, events }, null, 2));
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const agentMessages = events.filter((e) => e.type === 'agent_notification_message');
|
|
60
|
+
if (agentMessages.length > 0) {
|
|
61
|
+
let messageContent = agentMessages[agentMessages.length - 1].content.data;
|
|
62
|
+
const trimmed = messageContent.trim();
|
|
63
|
+
if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse(trimmed);
|
|
66
|
+
if (typeof parsed === 'object' && parsed !== null && 'message' in parsed) {
|
|
67
|
+
messageContent = parsed.message;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// If parsing fails, use content as-is
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const rendered = fixListItemMarkdown(await marked(messageContent));
|
|
75
|
+
console.log(rendered.trim());
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
49
79
|
import { createSpinner as createAnimatedSpinner, createRandomSpinner, } from '../lib/spinners.js';
|
|
50
80
|
function CustomInput({ value, onChange, onSubmit, trackedTasksSize, setShowTaskPanel, isActive, }) {
|
|
51
81
|
useInput((input, key) => {
|
|
@@ -146,6 +176,16 @@ export function ChatApp({ initialPrompt, version, workspaceId, versionId, agentN
|
|
|
146
176
|
initialDelay: 500,
|
|
147
177
|
maxDelay: 5000,
|
|
148
178
|
backoffMultiplier: 1.5,
|
|
179
|
+
shouldRetry: (error) => {
|
|
180
|
+
if (typeof error === 'object' && error !== null) {
|
|
181
|
+
const err = error;
|
|
182
|
+
return (err.code === 'ECONNREFUSED' ||
|
|
183
|
+
err.code === 'ETIMEDOUT' ||
|
|
184
|
+
err.code === 'ENOTFOUND' ||
|
|
185
|
+
err.code === 'ECONNABORTED');
|
|
186
|
+
}
|
|
187
|
+
return false;
|
|
188
|
+
},
|
|
149
189
|
});
|
|
150
190
|
setConnectedClient(client);
|
|
151
191
|
setConnectedSession(session);
|
|
@@ -382,7 +422,7 @@ function ChatUIWithConnection({ initialPrompt, version: _version, versionId: _ve
|
|
|
382
422
|
const sentMessages = useRef(new Set());
|
|
383
423
|
const pollInterval = useRef(null);
|
|
384
424
|
const spinnerInterval = useRef(null);
|
|
385
|
-
const
|
|
425
|
+
const lastEventIdRef = useRef(resumeEvents?.length ? resumeEvents[resumeEvents.length - 1].id : undefined);
|
|
386
426
|
const isPolling = useRef(false);
|
|
387
427
|
const receivedResponseSinceLastInput = useRef(false);
|
|
388
428
|
const firstMessageNotified = useRef(!!resumeEvents);
|
|
@@ -435,10 +475,7 @@ function ChatUIWithConnection({ initialPrompt, version: _version, versionId: _ve
|
|
|
435
475
|
return;
|
|
436
476
|
isPollingTasks.current = true;
|
|
437
477
|
try {
|
|
438
|
-
const
|
|
439
|
-
const tasksList = (Array.isArray(response)
|
|
440
|
-
? response
|
|
441
|
-
: response?.items || []);
|
|
478
|
+
const tasksList = await fetchTasks(client, session.id);
|
|
442
479
|
setTasks(tasksList);
|
|
443
480
|
}
|
|
444
481
|
catch (error) {
|
|
@@ -463,20 +500,14 @@ function ChatUIWithConnection({ initialPrompt, version: _version, versionId: _ve
|
|
|
463
500
|
if (isPolling.current)
|
|
464
501
|
return;
|
|
465
502
|
isPolling.current = true;
|
|
466
|
-
debug(`poll() called, session=${session.id}`);
|
|
503
|
+
debug(`poll() called, session=${session.id}, fromId=${lastEventIdRef.current}`);
|
|
467
504
|
try {
|
|
468
|
-
const
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
debug(`
|
|
472
|
-
const allEvents = (Array.isArray(response)
|
|
473
|
-
? response
|
|
474
|
-
: response?.items || []);
|
|
475
|
-
const newEvents = allEvents.slice(lastMessageCountRef.current);
|
|
476
|
-
// Debug: log event counts
|
|
477
|
-
debug(`Events: total=${allEvents.length}, lastCount=${lastMessageCountRef.current}, new=${newEvents.length}`);
|
|
505
|
+
const newEvents = await fetchEvents(client, session.id, {
|
|
506
|
+
fromId: lastEventIdRef.current,
|
|
507
|
+
});
|
|
508
|
+
debug(`Events: fromId=${lastEventIdRef.current}, new=${newEvents.length}`);
|
|
478
509
|
if (newEvents.length > 0) {
|
|
479
|
-
|
|
510
|
+
lastEventIdRef.current = newEvents[newEvents.length - 1].id;
|
|
480
511
|
for (const event of newEvents) {
|
|
481
512
|
// Track task from event if present
|
|
482
513
|
const taskInfo = event.task;
|
|
@@ -919,7 +950,7 @@ export function createChatCommand() {
|
|
|
919
950
|
.option('--workspace <identifier>', 'Workspace ID or full name (e.g., owner/workspace-name)')
|
|
920
951
|
.option('--no-splash', 'Skip the splash screen animation')
|
|
921
952
|
.option('--resume <session-id>', 'Resume an existing session')
|
|
922
|
-
.addHelpText('after', '\nTo chat with
|
|
953
|
+
.addHelpText('after', '\nTo chat with a local agent under development: guild agent chat')
|
|
923
954
|
.action(async (promptArgs, options) => {
|
|
924
955
|
const initialPrompt = promptArgs.length > 0 ? promptArgs.join(' ') : 'Hello';
|
|
925
956
|
if (options.once) {
|
|
@@ -943,19 +974,15 @@ export function createChatCommand() {
|
|
|
943
974
|
const inactivityTimeoutMs = 300000; // 5 minutes
|
|
944
975
|
const pollIntervalMs = 500;
|
|
945
976
|
const maxInactivityAttempts = inactivityTimeoutMs / pollIntervalMs;
|
|
946
|
-
let
|
|
977
|
+
let lastSeenEventId;
|
|
978
|
+
const allEvents = [];
|
|
947
979
|
let inactivityCounter = 0;
|
|
948
980
|
while (true) {
|
|
949
981
|
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
950
|
-
const
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
: response?.items || []);
|
|
955
|
-
// Check if we got new events (reset inactivity counter)
|
|
956
|
-
if (events.length > lastMessageCount) {
|
|
957
|
-
// Debug: log all new events
|
|
958
|
-
const newEvents = events.slice(lastMessageCount);
|
|
982
|
+
const newEvents = await fetchEvents(client, session.id, {
|
|
983
|
+
fromId: lastSeenEventId,
|
|
984
|
+
});
|
|
985
|
+
if (newEvents.length > 0) {
|
|
959
986
|
for (const evt of newEvents) {
|
|
960
987
|
const taskInfo = evt.task;
|
|
961
988
|
if (taskInfo) {
|
|
@@ -965,8 +992,9 @@ export function createChatCommand() {
|
|
|
965
992
|
debug(`Event: ${evt.type} (no task info)`);
|
|
966
993
|
}
|
|
967
994
|
}
|
|
968
|
-
|
|
969
|
-
|
|
995
|
+
allEvents.push(...newEvents);
|
|
996
|
+
lastSeenEventId = newEvents[newEvents.length - 1].id;
|
|
997
|
+
inactivityCounter = 0;
|
|
970
998
|
}
|
|
971
999
|
else {
|
|
972
1000
|
inactivityCounter++;
|
|
@@ -976,93 +1004,27 @@ export function createChatCommand() {
|
|
|
976
1004
|
// For orchestrating agents like agent-builder that spawn child tasks, we need to
|
|
977
1005
|
// wait for the root agent's completion, not just any runtime_done event.
|
|
978
1006
|
const targetAgent = options.agent || 'assistant';
|
|
979
|
-
const hasRootTaskDone =
|
|
1007
|
+
const hasRootTaskDone = allEvents.some((e) => e.type === 'runtime_done' &&
|
|
980
1008
|
matchesAgent(e.task?.agent, targetAgent) &&
|
|
981
1009
|
!e.task?.parent_task_id // Root task has no parent
|
|
982
1010
|
);
|
|
983
1011
|
// Also check for agent_notification_message events from the root agent
|
|
984
|
-
const hasAgentMessage =
|
|
1012
|
+
const hasAgentMessage = allEvents.some((e) => e.type === 'agent_notification_message' &&
|
|
985
1013
|
matchesAgent(e.task?.agent, targetAgent) &&
|
|
986
1014
|
!e.task?.parent_task_id);
|
|
987
1015
|
// Check for a ui_prompt request... that ends the game.
|
|
988
|
-
const hasUIPromptMessage =
|
|
1016
|
+
const hasUIPromptMessage = allEvents.some((e) => e.type === 'agent_notification_message' &&
|
|
989
1017
|
e.task?.tool_name === 'ui_prompt');
|
|
990
1018
|
if (hasRootTaskDone || hasAgentMessage || hasUIPromptMessage) {
|
|
991
1019
|
debug(`Found completion event from root agent (${targetAgent}), exiting --once mode`);
|
|
992
|
-
|
|
993
|
-
if (options.mode === 'json') {
|
|
994
|
-
// JSON mode: output structured events
|
|
995
|
-
console.log(JSON.stringify({
|
|
996
|
-
session_id: session.id,
|
|
997
|
-
events: events,
|
|
998
|
-
}, null, 2));
|
|
999
|
-
}
|
|
1000
|
-
else {
|
|
1001
|
-
// Human-readable mode (default): extract and render message content
|
|
1002
|
-
const agentMessages = events.filter((e) => e.type === 'agent_notification_message');
|
|
1003
|
-
if (agentMessages.length > 0) {
|
|
1004
|
-
// Get the last message content
|
|
1005
|
-
let messageContent = agentMessages[agentMessages.length - 1].content.data;
|
|
1006
|
-
// Handle JSON {"message": "..."} wrapper
|
|
1007
|
-
const trimmed = messageContent.trim();
|
|
1008
|
-
if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
|
1009
|
-
try {
|
|
1010
|
-
const parsed = JSON.parse(trimmed);
|
|
1011
|
-
if (typeof parsed === 'object' &&
|
|
1012
|
-
parsed !== null &&
|
|
1013
|
-
'message' in parsed) {
|
|
1014
|
-
messageContent = parsed.message;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
catch {
|
|
1018
|
-
// If parsing fails, use content as-is
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
// Render markdown and output
|
|
1022
|
-
const rendered = fixListItemMarkdown(await marked(messageContent));
|
|
1023
|
-
console.log(rendered.trim());
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1020
|
+
await outputOnceResult(session.id, allEvents, options.mode);
|
|
1026
1021
|
process.exit(0);
|
|
1027
1022
|
}
|
|
1028
1023
|
// Timeout if no activity for too long
|
|
1029
1024
|
if (inactivityCounter >= maxInactivityAttempts) {
|
|
1030
1025
|
debug(`Inactivity timeout reached (${maxInactivityAttempts} attempts with no new events)`);
|
|
1031
|
-
debug(`Exiting with ${
|
|
1032
|
-
|
|
1033
|
-
if (options.mode === 'json') {
|
|
1034
|
-
// JSON mode: output structured events
|
|
1035
|
-
console.log(JSON.stringify({
|
|
1036
|
-
session_id: session.id,
|
|
1037
|
-
events: events,
|
|
1038
|
-
}, null, 2));
|
|
1039
|
-
}
|
|
1040
|
-
else {
|
|
1041
|
-
// Human-readable mode (default): extract and render message content
|
|
1042
|
-
const agentMessages = events.filter((e) => e.type === 'agent_notification_message');
|
|
1043
|
-
if (agentMessages.length > 0) {
|
|
1044
|
-
// Get the last message content
|
|
1045
|
-
let messageContent = agentMessages[agentMessages.length - 1].content.data;
|
|
1046
|
-
// Handle JSON {"message": "..."} wrapper
|
|
1047
|
-
const trimmed = messageContent.trim();
|
|
1048
|
-
if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
|
1049
|
-
try {
|
|
1050
|
-
const parsed = JSON.parse(trimmed);
|
|
1051
|
-
if (typeof parsed === 'object' &&
|
|
1052
|
-
parsed !== null &&
|
|
1053
|
-
'message' in parsed) {
|
|
1054
|
-
messageContent = parsed.message;
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
catch {
|
|
1058
|
-
// If parsing fails, use content as-is
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
// Render markdown and output
|
|
1062
|
-
const rendered = fixListItemMarkdown(await marked(messageContent));
|
|
1063
|
-
console.log(rendered.trim());
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1026
|
+
debug(`Exiting with ${allEvents.length} events total`);
|
|
1027
|
+
await outputOnceResult(session.id, allEvents, options.mode);
|
|
1066
1028
|
process.exit(0);
|
|
1067
1029
|
}
|
|
1068
1030
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
6
|
+
import { getAuthToken } from '../../lib/auth.js';
|
|
7
|
+
import { handleAxiosError } from '../../lib/errors.js';
|
|
8
|
+
import { getOutputMode } from '../../lib/output-mode.js';
|
|
9
|
+
import { createOutputWriter } from '../../lib/output.js';
|
|
10
|
+
import { Table } from '../../lib/table.js';
|
|
11
|
+
export function createCredentialsEndpointListCommand() {
|
|
12
|
+
const cmd = new Command('list');
|
|
13
|
+
cmd
|
|
14
|
+
.description('List endpoints for a credential')
|
|
15
|
+
.argument('<credential-id>', 'Credential ID')
|
|
16
|
+
.option('--include-previous-versions', 'Include endpoints from previous versions')
|
|
17
|
+
.option('--search <query>', 'Search by operation name')
|
|
18
|
+
.option('--limit <number>', 'Number of results to return', '20')
|
|
19
|
+
.option('--offset <number>', 'Offset for pagination', '0')
|
|
20
|
+
.action(async (credentialId, options) => {
|
|
21
|
+
const output = createOutputWriter();
|
|
22
|
+
try {
|
|
23
|
+
const token = await getAuthToken();
|
|
24
|
+
if (!token) {
|
|
25
|
+
output.error('Not authenticated. Run: guild auth login');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const client = new GuildAPIClient();
|
|
29
|
+
const params = new URLSearchParams();
|
|
30
|
+
params.append('limit', options.limit);
|
|
31
|
+
params.append('offset', options.offset);
|
|
32
|
+
if (options.includePreviousVersions) {
|
|
33
|
+
params.append('include_previous_versions', 'true');
|
|
34
|
+
}
|
|
35
|
+
if (options.search) {
|
|
36
|
+
params.append('search', options.search);
|
|
37
|
+
}
|
|
38
|
+
const response = await client.get(`/credentials/${credentialId}/endpoints?${params.toString()}`);
|
|
39
|
+
if (getOutputMode() === 'json') {
|
|
40
|
+
console.log(JSON.stringify(response, null, 2));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
formatEndpointsTable(response.items, response.pagination);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const formattedError = handleAxiosError(error);
|
|
48
|
+
output.error(formattedError.details);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
return cmd;
|
|
53
|
+
}
|
|
54
|
+
function formatEndpointsTable(endpoints, pagination) {
|
|
55
|
+
if (endpoints.length === 0) {
|
|
56
|
+
console.log(chalk.dim('No endpoints found'));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const table = new Table({
|
|
60
|
+
columns: [
|
|
61
|
+
{ name: 'operation', title: 'OPERATION', alignment: 'left' },
|
|
62
|
+
{ name: 'method', title: 'METHOD', alignment: 'left' },
|
|
63
|
+
{ name: 'path', title: 'PATH', alignment: 'left' },
|
|
64
|
+
{ name: 'tags', title: 'TAGS', alignment: 'left' },
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
endpoints.forEach((ep) => {
|
|
68
|
+
const methodColor = ep.method === 'DELETE' ? chalk.red : chalk.green;
|
|
69
|
+
table.addRow({
|
|
70
|
+
operation: ep.operation,
|
|
71
|
+
method: methodColor(ep.method),
|
|
72
|
+
path: ep.path,
|
|
73
|
+
tags: ep.tags?.join(', ') || '',
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
table.printTable();
|
|
77
|
+
const showing = Math.min(pagination.limit, endpoints.length);
|
|
78
|
+
if (pagination.has_more) {
|
|
79
|
+
const nextOffset = pagination.offset + pagination.limit;
|
|
80
|
+
console.log(`\nShowing ${showing} of ${pagination.total_count} endpoints. ` +
|
|
81
|
+
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
82
|
+
}
|
|
83
|
+
else if (pagination.total_count > showing) {
|
|
84
|
+
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} endpoints`));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=endpoint-list.js.map
|