@guildai/cli 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/agent/test.js +6 -12
- package/dist/commands/job/get-step.d.ts +3 -0
- package/dist/commands/job/{step-get.js → get-step.js} +3 -3
- package/dist/commands/mcp.js +1 -1
- package/dist/commands/session/create.js +1 -1
- package/dist/commands/session/list.js +1 -1
- package/dist/index.js +5 -2
- package/dist/lib/api-types.d.ts +6 -0
- package/dist/lib/output.js +25 -99
- package/dist/lib/polling.d.ts +7 -0
- package/dist/lib/polling.js +12 -3
- package/dist/lib/version-helpers.js +38 -0
- package/docs/CLI_WORKFLOW.md +1 -1
- package/docs/skills/agent-dev.md +1 -1
- package/docs/skills/integrations.md +1 -1
- package/package.json +1 -1
- package/dist/commands/job/step-get.d.ts +0 -3
|
@@ -15,7 +15,7 @@ import { format } from '../../lib/progress.js';
|
|
|
15
15
|
import * as readline from 'readline';
|
|
16
16
|
import { parseEventFilter } from '../../lib/event-filter.js';
|
|
17
17
|
import { isQuietMode, getOutputMode } from '../../lib/output-mode.js';
|
|
18
|
-
import {
|
|
18
|
+
import { pollForResponseWithEvents } from '../../lib/session-polling.js';
|
|
19
19
|
import { readStdinAsJSON, ensureInteractiveStdin } from '../../lib/stdin.js';
|
|
20
20
|
import { loadLocalConfig, getWorkspaceId } from '../../lib/guild-config.js';
|
|
21
21
|
import { GitError, formatGitError } from '../../lib/git.js';
|
|
@@ -36,15 +36,13 @@ export function createAgentTestCommand() {
|
|
|
36
36
|
.option('--agent-version <id>', 'Test a specific version (UUID or version number)')
|
|
37
37
|
.option('--resume <session-id>', 'Resume an existing test session')
|
|
38
38
|
.option('--open', 'Open session in web dashboard')
|
|
39
|
-
.option('--events <types>', 'Event types to stream (default:
|
|
39
|
+
.option('--events <types>', 'Event types to stream (default: all). Shorthands: none, user, system, all, or comma-separated type names')
|
|
40
40
|
.option('--bundle <file>', 'Path to a pre-built gzip+base64 bundle file')
|
|
41
41
|
.option('--no-cache', 'Skip ephemeral build cache (force a fresh build)')
|
|
42
42
|
.action(async (options) => {
|
|
43
43
|
const cwd = process.cwd();
|
|
44
|
-
// Parse --events filter once, before any branching
|
|
45
|
-
const eventFilter = options.events
|
|
46
|
-
? parseEventFilter(options.events)
|
|
47
|
-
: undefined;
|
|
44
|
+
// Parse --events filter once, before any branching (default: all)
|
|
45
|
+
const eventFilter = parseEventFilter(options.events ?? 'all');
|
|
48
46
|
try {
|
|
49
47
|
// Handle --resume: skip build, fetch existing session, hand off to ChatApp
|
|
50
48
|
if (options.resume) {
|
|
@@ -272,9 +270,7 @@ export function createAgentTestCommand() {
|
|
|
272
270
|
});
|
|
273
271
|
// Poll for response (starting from beginning)
|
|
274
272
|
// 3 minutes - allow time for agents that use LLM calls for input parsing
|
|
275
|
-
const { response } = eventFilter
|
|
276
|
-
? await pollForResponseWithEvents(client, session.id, eventFilter, undefined, 180000)
|
|
277
|
-
: await pollForResponse(client, session.id, undefined, 180000);
|
|
273
|
+
const { response } = await pollForResponseWithEvents(client, session.id, eventFilter, undefined, 180000);
|
|
278
274
|
if (!response) {
|
|
279
275
|
console.error('Error: No response received from agent within timeout');
|
|
280
276
|
console.error('');
|
|
@@ -350,9 +346,7 @@ export function createAgentTestCommand() {
|
|
|
350
346
|
content: jsonInput,
|
|
351
347
|
});
|
|
352
348
|
// Wait for response (looking for events after last seen)
|
|
353
|
-
const result = eventFilter
|
|
354
|
-
? await pollForResponseWithEvents(client, session.id, eventFilter, lastEventId, 180000)
|
|
355
|
-
: await pollForResponse(client, session.id, lastEventId, 180000);
|
|
349
|
+
const result = await pollForResponseWithEvents(client, session.id, eventFilter, lastEventId, 180000);
|
|
356
350
|
lastEventId = result.lastEventId;
|
|
357
351
|
if (!result.response) {
|
|
358
352
|
console.error(`Timeout: No response for line ${lineNumber}`);
|
|
@@ -5,8 +5,8 @@ import { GuildAPIClient } from '../../lib/api-client.js';
|
|
|
5
5
|
import { getAuthToken } from '../../lib/auth.js';
|
|
6
6
|
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
7
|
import { createOutputWriter } from '../../lib/output.js';
|
|
8
|
-
export function
|
|
9
|
-
const cmd = new Command('step
|
|
8
|
+
export function createJobGetStepCommand() {
|
|
9
|
+
const cmd = new Command('get-step');
|
|
10
10
|
cmd
|
|
11
11
|
.description('Get details of a step in a job')
|
|
12
12
|
.argument('<job-id>', 'Job ID')
|
|
@@ -37,4 +37,4 @@ export function createJobStepGetCommand() {
|
|
|
37
37
|
});
|
|
38
38
|
return cmd;
|
|
39
39
|
}
|
|
40
|
-
//# sourceMappingURL=step
|
|
40
|
+
//# sourceMappingURL=get-step.js.map
|
package/dist/commands/mcp.js
CHANGED
|
@@ -6,7 +6,7 @@ export function createMcpCommand() {
|
|
|
6
6
|
const cmd = new Command('mcp');
|
|
7
7
|
cmd
|
|
8
8
|
.description('Start an MCP server over stdio for use with Claude Code, Cursor, and other MCP hosts')
|
|
9
|
-
.option('--workspace <id>', 'Workspace ID (defaults to configured workspace)')
|
|
9
|
+
.option('--workspace <id>', 'Workspace ID or name (defaults to configured workspace)')
|
|
10
10
|
.option('--debug', 'Enable debug logging to stderr')
|
|
11
11
|
.addHelpText('after', `
|
|
12
12
|
Configuration:
|
|
@@ -10,7 +10,7 @@ export function createSessionCreateCommand() {
|
|
|
10
10
|
const cmd = new Command('create');
|
|
11
11
|
cmd
|
|
12
12
|
.description('Create a new session')
|
|
13
|
-
.option('--workspace <id>', 'Workspace ID or name')
|
|
13
|
+
.option('--workspace <id>', 'Workspace ID or name (e.g., owner~workspace-name)')
|
|
14
14
|
.option('--type <type>', 'Session type: chat or agent_test', 'chat')
|
|
15
15
|
.option('--prompt <text>', 'Initial prompt (required for chat sessions)')
|
|
16
16
|
.option('--agent <identifier>', 'Agent identifier, e.g., owner~agent-name')
|
|
@@ -11,7 +11,7 @@ export function createSessionListCommand() {
|
|
|
11
11
|
const cmd = new Command('list');
|
|
12
12
|
cmd
|
|
13
13
|
.description('List sessions in a workspace')
|
|
14
|
-
.option('--workspace <id>', 'Workspace ID or name')
|
|
14
|
+
.option('--workspace <id>', 'Workspace ID or name (e.g., owner~workspace-name)')
|
|
15
15
|
.option('--type <type>', 'Filter by session type: chat, webhook, time, agent_test')
|
|
16
16
|
.option('--limit <number>', 'Number of results to return', '20')
|
|
17
17
|
.option('--offset <number>', 'Offset for pagination', '0')
|
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ import { createSessionCreateCommand } from './commands/session/create.js';
|
|
|
61
61
|
import { createSessionSendCommand } from './commands/session/send.js';
|
|
62
62
|
import { createSessionInterruptCommand } from './commands/session/interrupt.js';
|
|
63
63
|
import { createJobGetCommand } from './commands/job/get.js';
|
|
64
|
-
import {
|
|
64
|
+
import { createJobGetStepCommand } from './commands/job/get-step.js';
|
|
65
65
|
import { createConfigListCommand } from './commands/config/list.js';
|
|
66
66
|
import { createConfigGetCommand } from './commands/config/get.js';
|
|
67
67
|
import { createConfigSetCommand } from './commands/config/set.js';
|
|
@@ -281,7 +281,10 @@ sessionCmd.addCommand(createSessionInterruptCommand());
|
|
|
281
281
|
// Job command group
|
|
282
282
|
const jobCmd = program.command('job').description('Job management');
|
|
283
283
|
jobCmd.addCommand(createJobGetCommand());
|
|
284
|
-
jobCmd.addCommand(
|
|
284
|
+
jobCmd.addCommand(createJobGetStepCommand());
|
|
285
|
+
const stepGetAlias = createJobGetStepCommand();
|
|
286
|
+
stepGetAlias.name('step-get');
|
|
287
|
+
jobCmd.addCommand(stepGetAlias, { hidden: true });
|
|
285
288
|
// Config command group
|
|
286
289
|
const configCmd = program
|
|
287
290
|
.command('config')
|
package/dist/lib/api-types.d.ts
CHANGED
|
@@ -116,6 +116,12 @@ export interface ValidationStep {
|
|
|
116
116
|
export interface ValidationStepsResponse {
|
|
117
117
|
steps: ValidationStep[];
|
|
118
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Response from /versions/{id}/publish/steps
|
|
121
|
+
*/
|
|
122
|
+
export interface PublishStepsResponse {
|
|
123
|
+
steps: ValidationStep[];
|
|
124
|
+
}
|
|
119
125
|
/**
|
|
120
126
|
* Workspace context entity from the API.
|
|
121
127
|
* Used by: workspace context list, get, edit
|
package/dist/lib/output.js
CHANGED
|
@@ -38,6 +38,20 @@ function truncate(str, maxLen) {
|
|
|
38
38
|
return str;
|
|
39
39
|
return str.slice(0, maxLen - 1) + '…';
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Print the "Showing N of M <entity>" footer after a paginated table.
|
|
43
|
+
*/
|
|
44
|
+
function printPaginationFooter(pagination, count, entityName) {
|
|
45
|
+
const showing = Math.min(pagination.limit, count);
|
|
46
|
+
if (pagination.has_more) {
|
|
47
|
+
const nextOffset = pagination.offset + pagination.limit;
|
|
48
|
+
console.log(`\nShowing ${showing} of ${pagination.total_count} ${entityName}. ` +
|
|
49
|
+
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
50
|
+
}
|
|
51
|
+
else if (pagination.total_count > showing) {
|
|
52
|
+
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} ${entityName}`));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
41
55
|
/**
|
|
42
56
|
* Format an agent list as a human-readable table.
|
|
43
57
|
* Shared by agent list and agent search commands.
|
|
@@ -75,15 +89,7 @@ export function formatAgentTable(agents, pagination, showArchived = false) {
|
|
|
75
89
|
});
|
|
76
90
|
});
|
|
77
91
|
table.printTable();
|
|
78
|
-
|
|
79
|
-
if (pagination.has_more) {
|
|
80
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
81
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} agents. ` +
|
|
82
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
83
|
-
}
|
|
84
|
-
else if (pagination.total_count > showing) {
|
|
85
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} agents`));
|
|
86
|
-
}
|
|
92
|
+
printPaginationFooter(pagination, agents.length, 'agents');
|
|
87
93
|
}
|
|
88
94
|
/**
|
|
89
95
|
* Format an integration list as a human-readable table.
|
|
@@ -113,15 +119,7 @@ export function formatIntegrationTable(integrations, pagination) {
|
|
|
113
119
|
});
|
|
114
120
|
});
|
|
115
121
|
table.printTable();
|
|
116
|
-
|
|
117
|
-
if (pagination.has_more) {
|
|
118
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
119
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} integrations. ` +
|
|
120
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
121
|
-
}
|
|
122
|
-
else if (pagination.total_count > showing) {
|
|
123
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} integrations`));
|
|
124
|
-
}
|
|
122
|
+
printPaginationFooter(pagination, integrations.length, 'integrations');
|
|
125
123
|
}
|
|
126
124
|
/**
|
|
127
125
|
* Format an integration version list as a human-readable table.
|
|
@@ -169,15 +167,7 @@ export function formatIntegrationVersionTable(versions, pagination, integrationN
|
|
|
169
167
|
});
|
|
170
168
|
});
|
|
171
169
|
table.printTable();
|
|
172
|
-
|
|
173
|
-
if (pagination.has_more) {
|
|
174
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
175
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} versions. ` +
|
|
176
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
177
|
-
}
|
|
178
|
-
else if (pagination.total_count > showing) {
|
|
179
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} versions`));
|
|
180
|
-
}
|
|
170
|
+
printPaginationFooter(pagination, versions.length, 'versions');
|
|
181
171
|
}
|
|
182
172
|
/**
|
|
183
173
|
* Format an agent version list as a human-readable table.
|
|
@@ -214,15 +204,7 @@ export function formatVersionTable(versions, pagination) {
|
|
|
214
204
|
});
|
|
215
205
|
});
|
|
216
206
|
table.printTable();
|
|
217
|
-
|
|
218
|
-
if (pagination.has_more) {
|
|
219
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
220
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} versions. ` +
|
|
221
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
222
|
-
}
|
|
223
|
-
else if (pagination.total_count > showing) {
|
|
224
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} versions`));
|
|
225
|
-
}
|
|
207
|
+
printPaginationFooter(pagination, versions.length, 'versions');
|
|
226
208
|
}
|
|
227
209
|
/**
|
|
228
210
|
* Format a context list as a human-readable table.
|
|
@@ -250,15 +232,7 @@ export function formatContextTable(contexts, pagination) {
|
|
|
250
232
|
});
|
|
251
233
|
});
|
|
252
234
|
table.printTable();
|
|
253
|
-
|
|
254
|
-
if (pagination.has_more) {
|
|
255
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
256
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} contexts. ` +
|
|
257
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
258
|
-
}
|
|
259
|
-
else if (pagination.total_count > showing) {
|
|
260
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} contexts`));
|
|
261
|
-
}
|
|
235
|
+
printPaginationFooter(pagination, contexts.length, 'contexts');
|
|
262
236
|
}
|
|
263
237
|
/**
|
|
264
238
|
* Format a workspace agent list as a human-readable table.
|
|
@@ -314,15 +288,7 @@ export function formatWorkspaceTable(workspaces, pagination) {
|
|
|
314
288
|
});
|
|
315
289
|
});
|
|
316
290
|
table.printTable();
|
|
317
|
-
|
|
318
|
-
if (pagination.has_more) {
|
|
319
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
320
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} workspaces. ` +
|
|
321
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
322
|
-
}
|
|
323
|
-
else if (pagination.total_count > showing) {
|
|
324
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} workspaces`));
|
|
325
|
-
}
|
|
291
|
+
printPaginationFooter(pagination, workspaces.length, 'workspaces');
|
|
326
292
|
}
|
|
327
293
|
/**
|
|
328
294
|
* Format a session list as a human-readable table.
|
|
@@ -353,15 +319,7 @@ export function formatSessionTable(sessions, pagination) {
|
|
|
353
319
|
});
|
|
354
320
|
});
|
|
355
321
|
table.printTable();
|
|
356
|
-
|
|
357
|
-
if (pagination.has_more) {
|
|
358
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
359
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} sessions. ` +
|
|
360
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
361
|
-
}
|
|
362
|
-
else if (pagination.total_count > showing) {
|
|
363
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} sessions`));
|
|
364
|
-
}
|
|
322
|
+
printPaginationFooter(pagination, sessions.length, 'sessions');
|
|
365
323
|
}
|
|
366
324
|
/**
|
|
367
325
|
* Format a task list as a human-readable table.
|
|
@@ -403,15 +361,7 @@ export function formatTaskTable(tasks, pagination) {
|
|
|
403
361
|
});
|
|
404
362
|
});
|
|
405
363
|
table.printTable();
|
|
406
|
-
|
|
407
|
-
if (pagination.has_more) {
|
|
408
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
409
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} tasks. ` +
|
|
410
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
411
|
-
}
|
|
412
|
-
else if (pagination.total_count > showing) {
|
|
413
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} tasks`));
|
|
414
|
-
}
|
|
364
|
+
printPaginationFooter(pagination, tasks.length, 'tasks');
|
|
415
365
|
}
|
|
416
366
|
/**
|
|
417
367
|
* Format a trigger list as a human-readable table.
|
|
@@ -453,15 +403,7 @@ export function formatTriggerTable(triggers, pagination) {
|
|
|
453
403
|
});
|
|
454
404
|
});
|
|
455
405
|
table.printTable();
|
|
456
|
-
|
|
457
|
-
if (pagination.has_more) {
|
|
458
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
459
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} triggers. ` +
|
|
460
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
461
|
-
}
|
|
462
|
-
else if (pagination.total_count > showing) {
|
|
463
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} triggers`));
|
|
464
|
-
}
|
|
406
|
+
printPaginationFooter(pagination, triggers.length, 'triggers');
|
|
465
407
|
}
|
|
466
408
|
export function formatCredentialsTable(credentials, pagination) {
|
|
467
409
|
if (credentials.length === 0) {
|
|
@@ -485,15 +427,7 @@ export function formatCredentialsTable(credentials, pagination) {
|
|
|
485
427
|
});
|
|
486
428
|
});
|
|
487
429
|
table.printTable();
|
|
488
|
-
|
|
489
|
-
if (pagination.has_more) {
|
|
490
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
491
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} credentials. ` +
|
|
492
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
493
|
-
}
|
|
494
|
-
else if (pagination.total_count > showing) {
|
|
495
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} credentials`));
|
|
496
|
-
}
|
|
430
|
+
printPaginationFooter(pagination, credentials.length, 'credentials');
|
|
497
431
|
}
|
|
498
432
|
export function formatPoliciesTable(policies, pagination) {
|
|
499
433
|
if (policies.length === 0) {
|
|
@@ -534,15 +468,7 @@ export function formatPoliciesTable(policies, pagination) {
|
|
|
534
468
|
});
|
|
535
469
|
});
|
|
536
470
|
table.printTable();
|
|
537
|
-
|
|
538
|
-
if (pagination.has_more) {
|
|
539
|
-
const nextOffset = pagination.offset + pagination.limit;
|
|
540
|
-
console.log(`\nShowing ${showing} of ${pagination.total_count} policies. ` +
|
|
541
|
-
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
542
|
-
}
|
|
543
|
-
else if (pagination.total_count > showing) {
|
|
544
|
-
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} policies`));
|
|
545
|
-
}
|
|
471
|
+
printPaginationFooter(pagination, policies.length, 'policies');
|
|
546
472
|
}
|
|
547
473
|
/**
|
|
548
474
|
* Format job steps as a human-readable table.
|
package/dist/lib/polling.d.ts
CHANGED
|
@@ -37,6 +37,13 @@ export interface PollOptions<T = unknown> {
|
|
|
37
37
|
* @default "Operation timed out"
|
|
38
38
|
*/
|
|
39
39
|
timeoutMessage?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Optional callback invoked after each poll when the operation is not yet
|
|
42
|
+
* complete. Return a non-null string to override the default spinner text
|
|
43
|
+
* (`${message} (${attempts}/${maxAttempts})`). Return null to keep the
|
|
44
|
+
* default. Errors thrown by the callback are silently ignored.
|
|
45
|
+
*/
|
|
46
|
+
onPoll?: (response: T, attempts: number) => Promise<string | null>;
|
|
40
47
|
}
|
|
41
48
|
export interface PollResult<T = unknown> {
|
|
42
49
|
/**
|
package/dist/lib/polling.js
CHANGED
|
@@ -21,7 +21,7 @@ import { createSpinner } from './progress.js';
|
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
23
|
export async function pollUntilComplete(options) {
|
|
24
|
-
const { endpoint, isComplete, message = 'Waiting for operation to complete...', maxAttempts = 60, delayMs = 1000, successMessage = 'Operation complete', timeoutMessage = 'Operation timed out', } = options;
|
|
24
|
+
const { endpoint, isComplete, message = 'Waiting for operation to complete...', maxAttempts = 60, delayMs = 1000, successMessage = 'Operation complete', timeoutMessage = 'Operation timed out', onPoll, } = options;
|
|
25
25
|
const client = new GuildAPIClient();
|
|
26
26
|
const spinner = createSpinner(message);
|
|
27
27
|
spinner.start();
|
|
@@ -40,8 +40,17 @@ export async function pollUntilComplete(options) {
|
|
|
40
40
|
attempts,
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
// Update spinner with progress
|
|
44
|
-
|
|
43
|
+
// Update spinner with progress — prefer onPoll text when available
|
|
44
|
+
let spinnerText = null;
|
|
45
|
+
if (onPoll) {
|
|
46
|
+
try {
|
|
47
|
+
spinnerText = await onPoll(response, attempts);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Silently ignore step-fetch errors; fall back to default text
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
spinner.text = spinnerText ?? `${message} (${attempts}/${maxAttempts})`;
|
|
45
54
|
}
|
|
46
55
|
catch {
|
|
47
56
|
// If we can't fetch the resource, continue polling
|
|
@@ -2,12 +2,41 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { GuildAPIClient } from './api-client.js';
|
|
4
4
|
import { pollUntilComplete } from './polling.js';
|
|
5
|
+
/**
|
|
6
|
+
* Format a list of validation steps into a compact single-line status string
|
|
7
|
+
* suitable for spinner text, e.g. `✓ build ⟳ test ○ deploy`.
|
|
8
|
+
* Returns null when the steps array is empty so callers can fall back to the
|
|
9
|
+
* default attempt-counter text.
|
|
10
|
+
*/
|
|
11
|
+
function formatStepProgress(steps) {
|
|
12
|
+
if (steps.length === 0)
|
|
13
|
+
return null;
|
|
14
|
+
const tokens = steps.map((step) => {
|
|
15
|
+
let prefix;
|
|
16
|
+
switch (step.status) {
|
|
17
|
+
case 'SUCCEEDED':
|
|
18
|
+
prefix = '✓';
|
|
19
|
+
break;
|
|
20
|
+
case 'RUNNING':
|
|
21
|
+
prefix = '⟳';
|
|
22
|
+
break;
|
|
23
|
+
case 'FAILED':
|
|
24
|
+
prefix = '✗';
|
|
25
|
+
break;
|
|
26
|
+
default:
|
|
27
|
+
prefix = '○';
|
|
28
|
+
}
|
|
29
|
+
return `${prefix} ${step.name}`;
|
|
30
|
+
});
|
|
31
|
+
return tokens.join(' ');
|
|
32
|
+
}
|
|
5
33
|
/**
|
|
6
34
|
* Poll until a version's validation completes, then check the result.
|
|
7
35
|
* Exits the process on timeout or validation failure.
|
|
8
36
|
* Returns the updated version on success.
|
|
9
37
|
*/
|
|
10
38
|
export async function waitForValidation(versionId, output) {
|
|
39
|
+
const client = new GuildAPIClient();
|
|
11
40
|
const pollResult = await pollUntilComplete({
|
|
12
41
|
resourceId: versionId,
|
|
13
42
|
endpoint: `/versions/${versionId}`,
|
|
@@ -18,6 +47,10 @@ export async function waitForValidation(versionId, output) {
|
|
|
18
47
|
timeoutMessage: 'Validation timed out',
|
|
19
48
|
maxAttempts: 120,
|
|
20
49
|
delayMs: 1000,
|
|
50
|
+
onPoll: async () => {
|
|
51
|
+
const r = await client.get(`/versions/${versionId}/validation/steps`);
|
|
52
|
+
return formatStepProgress(r.steps);
|
|
53
|
+
},
|
|
21
54
|
});
|
|
22
55
|
if (!pollResult.success || !pollResult.response) {
|
|
23
56
|
output.error('Validation did not complete in time', 'Check status manually:\n guild agent versions');
|
|
@@ -64,6 +97,7 @@ async function fetchValidationFailureDetails(versionId) {
|
|
|
64
97
|
* Returns the updated version on success.
|
|
65
98
|
*/
|
|
66
99
|
export async function waitForPublish(versionId, output) {
|
|
100
|
+
const client = new GuildAPIClient();
|
|
67
101
|
const pollResult = await pollUntilComplete({
|
|
68
102
|
resourceId: versionId,
|
|
69
103
|
endpoint: `/versions/${versionId}`,
|
|
@@ -73,6 +107,10 @@ export async function waitForPublish(versionId, output) {
|
|
|
73
107
|
timeoutMessage: 'Publish timed out',
|
|
74
108
|
maxAttempts: 60,
|
|
75
109
|
delayMs: 1000,
|
|
110
|
+
onPoll: async () => {
|
|
111
|
+
const r = await client.get(`/versions/${versionId}/publish/steps`);
|
|
112
|
+
return formatStepProgress(r.steps);
|
|
113
|
+
},
|
|
76
114
|
});
|
|
77
115
|
if (!pollResult.success || pollResult.response?.status !== 'PUBLISHED') {
|
|
78
116
|
output.error('Publish did not complete in time', 'Check status manually:\n guild agent versions');
|
package/docs/CLI_WORKFLOW.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: guild-cli-workflow
|
|
3
3
|
description: Agent development using the Guild CLI. Activated when user mentions guild agent commands, saving/publishing agents, clone/pull workflow, or agent testing. Covers CLI commands and common workflows.
|
|
4
4
|
---
|
|
5
5
|
|
package/docs/skills/agent-dev.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: guild-agent-development
|
|
3
3
|
description: Local agent development using the Guild CLI. Activated when user mentions creating agents, guild agent commands, saving/publishing agents, or agent development workflow. Handles proper CLI workflow and prevents direct git operations.
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: guild-integrations
|
|
3
3
|
description: Build custom integrations that connect external APIs to Guild agents. Activated when user mentions custom integrations, OpenAPI specs, connecting APIs via CLI, guild integration commands, or building service tools for agents.
|
|
4
4
|
---
|
|
5
5
|
|
package/package.json
CHANGED