@guildai/cli 0.5.13 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/commands/agent/clone.js +3 -1
  2. package/dist/commands/agent/code.js +3 -2
  3. package/dist/commands/agent/fork.js +40 -14
  4. package/dist/commands/agent/get.js +3 -2
  5. package/dist/commands/agent/grep.js +61 -31
  6. package/dist/commands/agent/publish.js +3 -2
  7. package/dist/commands/agent/revalidate.js +4 -3
  8. package/dist/commands/agent/search.js +3 -3
  9. package/dist/commands/agent/tags/add.js +4 -3
  10. package/dist/commands/agent/tags/list.js +3 -2
  11. package/dist/commands/agent/tags/remove.js +4 -3
  12. package/dist/commands/agent/tags/set.js +3 -2
  13. package/dist/commands/agent/unpublish.js +3 -2
  14. package/dist/commands/agent/update.js +9 -8
  15. package/dist/commands/agent/versions.js +3 -2
  16. package/dist/commands/agent/workspaces.js +3 -2
  17. package/dist/commands/credentials/endpoint-list.d.ts +3 -0
  18. package/dist/commands/credentials/endpoint-list.js +87 -0
  19. package/dist/commands/credentials/list.d.ts +3 -0
  20. package/dist/commands/{container → credentials}/list.js +11 -10
  21. package/dist/commands/credentials/policy-create.d.ts +3 -0
  22. package/dist/commands/credentials/policy-create.js +66 -0
  23. package/dist/commands/credentials/policy-delete.d.ts +3 -0
  24. package/dist/commands/{container/get.js → credentials/policy-delete.js} +9 -9
  25. package/dist/commands/credentials/policy-list.d.ts +3 -0
  26. package/dist/commands/{container-image/list.js → credentials/policy-list.js} +9 -9
  27. package/dist/commands/credentials/policy-update.d.ts +3 -0
  28. package/dist/commands/credentials/policy-update.js +66 -0
  29. package/dist/commands/trigger/create.js +35 -19
  30. package/dist/commands/workspace/select.js +0 -1
  31. package/dist/index.js +22 -27
  32. package/dist/lib/agent-helpers.d.ts +8 -0
  33. package/dist/lib/agent-helpers.js +15 -0
  34. package/dist/lib/api-types.d.ts +52 -78
  35. package/dist/lib/auth.js +7 -4
  36. package/dist/lib/output.d.ts +3 -16
  37. package/dist/lib/output.js +43 -109
  38. package/dist/mcp/tools.js +1 -1
  39. package/docs/CLI_WORKFLOW.md +4 -2
  40. package/docs/skills/agent-dev.md +2 -2
  41. package/package.json +3 -3
  42. package/dist/commands/container/destroy.d.ts +0 -3
  43. package/dist/commands/container/destroy.js +0 -48
  44. package/dist/commands/container/events.d.ts +0 -3
  45. package/dist/commands/container/events.js +0 -44
  46. package/dist/commands/container/exec.d.ts +0 -3
  47. package/dist/commands/container/exec.js +0 -64
  48. package/dist/commands/container/get.d.ts +0 -3
  49. package/dist/commands/container/list.d.ts +0 -3
  50. package/dist/commands/container-image/create.d.ts +0 -3
  51. package/dist/commands/container-image/create.js +0 -41
  52. package/dist/commands/container-image/get.d.ts +0 -3
  53. package/dist/commands/container-image/get.js +0 -33
  54. package/dist/commands/container-image/list.d.ts +0 -3
@@ -204,6 +204,26 @@ export interface AgentVersionDetail {
204
204
  description: string;
205
205
  };
206
206
  }
207
+ /**
208
+ * Webhook config nested in integration responses.
209
+ * Used by: trigger create (to resolve webhook_config_id)
210
+ */
211
+ export interface IntegrationWebhookConfig {
212
+ id: string;
213
+ enabled: boolean;
214
+ events: Record<string, string[]>;
215
+ }
216
+ /**
217
+ * Integration entity from the API.
218
+ * Used by: trigger create (to resolve webhook_config_id from integration name)
219
+ */
220
+ export interface Integration {
221
+ id: string;
222
+ name: string;
223
+ full_name: string;
224
+ service?: string | null;
225
+ webhook_config: IntegrationWebhookConfig | null;
226
+ }
207
227
  export type TriggerType = 'webhook' | 'time';
208
228
  import { WEBHOOK_SERVICES, type WebhookService, TIME_TRIGGER_FREQUENCIES, type TimeTriggerFrequency } from './generated-types.js';
209
229
  export { WEBHOOK_SERVICES, type WebhookService, TIME_TRIGGER_FREQUENCIES, type TimeTriggerFrequency, };
@@ -239,7 +259,6 @@ export interface TriggerWorkspaceAgent {
239
259
  export interface TriggerWebhook {
240
260
  id: string;
241
261
  type: 'webhook';
242
- service: WebhookService;
243
262
  event_type: string | null;
244
263
  action: string | null;
245
264
  service_config?: {
@@ -248,6 +267,7 @@ export interface TriggerWebhook {
248
267
  project?: string;
249
268
  jql_filter?: string;
250
269
  } | Record<string, unknown>;
270
+ integration: Integration;
251
271
  created_at: string;
252
272
  deactivated_at: string | null;
253
273
  disabled_reason: TriggerDisabledReason | null;
@@ -315,101 +335,55 @@ export interface Organization {
315
335
  viewer_role: 'ADMIN' | 'MEMBER' | null;
316
336
  }
317
337
  export type OrganizationListResponse = PaginatedResponse<Organization>;
318
- /**
319
- * Session entity from API responses.
320
- * Used by: session list, container list (as owner)
321
- */
322
- export interface Session {
338
+ export interface Credentials {
323
339
  id: string;
324
- session_type: 'chat' | 'agent_test' | 'time' | 'webhook';
325
- name?: string;
326
- workspace?: {
340
+ integration: {
341
+ id: string;
342
+ name: string;
343
+ full_name: string;
344
+ };
345
+ creator: {
327
346
  id: string;
328
347
  name: string;
329
348
  };
330
349
  created_at: string;
331
350
  updated_at: string;
332
351
  }
333
- export type ContainerStatus = 'STARTING' | 'RUNNING' | 'ERRORED' | 'DESTROYED';
334
- /**
335
- * Container image entity from the API.
336
- */
337
- export interface ContainerImage {
352
+ export type CredentialsListResponse = PaginatedResponse<Credentials>;
353
+ export interface CredentialsPolicy {
338
354
  id: string;
339
- name: string;
340
- image_name: string;
341
- tag: string;
342
- is_public: boolean;
355
+ decision: 'ALLOW' | 'DENY';
356
+ operations: string[] | null;
357
+ resources: Record<string, string[]> | null;
358
+ workspaces: {
359
+ id: string;
360
+ name: string;
361
+ full_name?: string;
362
+ }[];
363
+ agents: {
364
+ id: string;
365
+ name: string;
366
+ full_name?: string;
367
+ }[];
343
368
  created_at: string;
344
369
  updated_at: string;
345
370
  }
371
+ export type CredentialsPolicyListResponse = PaginatedResponse<CredentialsPolicy>;
346
372
  /**
347
- * The actor that created the container (user or task agent).
373
+ * Session entity from API responses.
374
+ * Used by: session list
348
375
  */
349
- export interface ContainerActor {
376
+ export interface Session {
350
377
  id: string;
351
- entity_type: string;
378
+ session_type: 'chat' | 'agent_test' | 'time' | 'webhook';
352
379
  name?: string;
353
- full_name?: string;
354
- }
355
- /**
356
- * Container entity from the API.
357
- * Used by: container list
358
- */
359
- export interface Container {
360
- id: string;
361
- status: ContainerStatus;
362
- owner: Session;
363
- created_by: ContainerActor;
364
- image: ContainerImage;
365
- created_at: string;
366
- updated_at: string;
367
- }
368
- export type ContainerListResponse = PaginatedResponse<Container>;
369
- /**
370
- * Container image as returned in list responses.
371
- */
372
- export interface ContainerImageListItem {
373
- id: string;
374
- name: string;
375
- image_name: string;
376
- tag: string;
377
- is_public: boolean;
378
- created_at: string;
379
- updated_at: string;
380
- }
381
- export type ContainerImageListResponse = PaginatedResponse<ContainerImageListItem>;
382
- export type ContainerEventStatus = 'PENDING' | 'ERROR' | 'SUCCESS';
383
- /**
384
- * Base fields shared by all container events.
385
- */
386
- export interface ContainerEventBase {
387
- id: string;
388
- entity_type: string;
389
- actor: ContainerActor;
390
- status: ContainerEventStatus;
391
- completed_at: string | null;
392
- error: string | null;
380
+ workspace?: {
381
+ id: string;
382
+ name: string;
383
+ };
393
384
  created_at: string;
394
385
  updated_at: string;
395
386
  }
396
- export interface ContainerEventCreate extends ContainerEventBase {
397
- entity_type: 'EntContainerEventCreate';
398
- is_local: boolean;
399
- }
400
- export interface ContainerEventDestroy extends ContainerEventBase {
401
- entity_type: 'EntContainerEventDestroy';
402
- found: boolean | null;
403
- }
404
- export interface ContainerEventCommand extends ContainerEventBase {
405
- entity_type: 'EntContainerEventCommand';
406
- command: string;
407
- return_code: number | null;
408
- stdout: string | null;
409
- stderr: string | null;
410
- }
411
- export type ContainerEvent = ContainerEventCreate | ContainerEventDestroy | ContainerEventCommand;
412
- export type ContainerEventListResponse = PaginatedResponse<ContainerEvent>;
413
387
  export type JobType = 'VALIDATION' | 'PUBLISH' | 'PUBLISH_PRE_CHECK';
414
388
  export type JobStatus = 'PENDING' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'ERRORED' | 'CANCELLED';
415
389
  export type JobStepStatus = 'PENDING' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'SKIPPED' | 'ERRORED';
package/dist/lib/auth.js CHANGED
@@ -137,6 +137,7 @@ export async function startDeviceFlow(authUrl = getGuildcoreUrl(), returnUrl, re
137
137
  * @returns Access token if successful, null if failed/expired
138
138
  */
139
139
  export async function pollForToken(authUrl, code, interval) {
140
+ const isTTY = process.stderr.isTTY || false;
140
141
  const spinner = createSpinner('Waiting for authorization...');
141
142
  spinner.start();
142
143
  const maxAttempts = 90; // 3 minutes (90 * 2 seconds)
@@ -167,7 +168,9 @@ export async function pollForToken(authUrl, code, interval) {
167
168
  }
168
169
  if (error.response?.data?.error === 'authorization_pending' ||
169
170
  error.response?.data?.error === 'slow_down') {
170
- spinner.text = `Waiting for authorization... (${attempts}/${maxAttempts})`;
171
+ if (isTTY) {
172
+ spinner.text = `Waiting for authorization... (${attempts}/${maxAttempts})`;
173
+ }
171
174
  continue;
172
175
  }
173
176
  }
@@ -201,13 +204,13 @@ export async function login(returnUrl, returnLabel, noBrowser) {
201
204
  try {
202
205
  console.log(chalk.bold('\nGuild.ai Authentication'));
203
206
  const deviceCode = await startDeviceFlow(authUrl, returnUrl, returnLabel);
204
- // Display styled verification code box
205
- displayVerificationCode(deviceCode.user_code, deviceCode.verification_uri_complete);
206
207
  const skipBrowser = noBrowser || process.stdin.isTTY !== true;
207
208
  if (skipBrowser) {
208
- console.log(chalk.dim('Open the URL above in your browser to complete authentication.'));
209
+ console.log(`\nVerification code: ${deviceCode.user_code}`);
210
+ console.log(`Open to authenticate: ${deviceCode.verification_uri_complete}\n`);
209
211
  }
210
212
  else {
213
+ displayVerificationCode(deviceCode.user_code, deviceCode.verification_uri_complete);
211
214
  // Wait for user to press Enter before opening browser
212
215
  // This gives them time to see and copy the code before browser opens
213
216
  // Critical for VSCode integration where browser may open full screen
@@ -1,5 +1,5 @@
1
1
  import { type Spinner } from './progress.js';
2
- import type { Agent, AgentVersion, Container, ContainerEvent, ContainerImageListItem, Context, JobStep, Pagination, Session, Workspace, WorkspaceAgent, Trigger } from './api-types.js';
2
+ import type { Agent, AgentVersion, Credentials, CredentialsPolicy, Context, JobStep, Pagination, Session, Workspace, WorkspaceAgent, Trigger } from './api-types.js';
3
3
  /**
4
4
  * Format an agent list as a human-readable table.
5
5
  * Shared by agent list and agent search commands.
@@ -35,21 +35,8 @@ export declare function formatSessionTable(sessions: Session[], pagination: Pagi
35
35
  * Used by trigger list command.
36
36
  */
37
37
  export declare function formatTriggerTable(triggers: Trigger[], pagination: Pagination): void;
38
- /**
39
- * Format a container list as a human-readable table.
40
- * Used by container list command.
41
- */
42
- export declare function formatContainerTable(containers: Container[], pagination: Pagination): void;
43
- /**
44
- * Format a container image list as a human-readable table.
45
- * Used by container-image list command.
46
- */
47
- export declare function formatContainerImageTable(images: ContainerImageListItem[], pagination: Pagination): void;
48
- /**
49
- * Format a container event list as a human-readable table.
50
- * Used by container events command.
51
- */
52
- export declare function formatContainerEventTable(events: ContainerEvent[], pagination: Pagination): void;
38
+ export declare function formatCredentialsTable(credentials: Credentials[], pagination: Pagination): void;
39
+ export declare function formatPoliciesTable(policies: CredentialsPolicy[], pagination: Pagination): void;
53
40
  /**
54
41
  * Format job steps as a human-readable table.
55
42
  * Used by job get command.
@@ -313,151 +313,85 @@ export function formatTriggerTable(triggers, pagination) {
313
313
  console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} triggers`));
314
314
  }
315
315
  }
316
- /**
317
- * Format a container list as a human-readable table.
318
- * Used by container list command.
319
- */
320
- export function formatContainerTable(containers, pagination) {
321
- if (containers.length === 0) {
322
- console.log(chalk.dim('No containers found'));
316
+ export function formatCredentialsTable(credentials, pagination) {
317
+ if (credentials.length === 0) {
318
+ console.log(chalk.dim('No credentials found'));
323
319
  return;
324
320
  }
325
321
  const table = new Table({
326
322
  columns: [
327
323
  { name: 'id', title: 'ID', alignment: 'left' },
328
- { name: 'status', title: 'STATUS', alignment: 'left' },
329
- { name: 'image', title: 'IMAGE', alignment: 'left' },
330
- { name: 'tag', title: 'TAG', alignment: 'left' },
324
+ { name: 'integration', title: 'INTEGRATION', alignment: 'left' },
325
+ { name: 'creator', title: 'CREATOR', alignment: 'left', color: 'cyan' },
331
326
  { name: 'created', title: 'CREATED', alignment: 'left' },
332
327
  ],
333
328
  });
334
- containers.forEach((container) => {
335
- const statusColor = container.status === 'RUNNING'
336
- ? chalk.green
337
- : container.status === 'ERRORED'
338
- ? chalk.red
339
- : container.status === 'DESTROYED'
340
- ? chalk.dim
341
- : chalk.yellow;
329
+ credentials.forEach((cred) => {
342
330
  table.addRow({
343
- id: container.id,
344
- status: statusColor(container.status),
345
- image: container.image?.name || '-',
346
- tag: container.image?.tag || '-',
347
- created: container.created_at ? formatRelativeTime(container.created_at) : '',
331
+ id: cred.id,
332
+ integration: cred.integration.full_name,
333
+ creator: cred.creator.name,
334
+ created: formatRelativeTime(cred.created_at),
348
335
  });
349
336
  });
350
337
  table.printTable();
351
- const showing = Math.min(pagination.limit, containers.length);
338
+ const showing = Math.min(pagination.limit, credentials.length);
352
339
  if (pagination.has_more) {
353
340
  const nextOffset = pagination.offset + pagination.limit;
354
- console.log(`\nShowing ${showing} of ${pagination.total_count} containers. ` +
341
+ console.log(`\nShowing ${showing} of ${pagination.total_count} credentials. ` +
355
342
  chalk.dim(`Use --offset ${nextOffset} to see more.`));
356
343
  }
357
344
  else if (pagination.total_count > showing) {
358
- console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} containers`));
345
+ console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} credentials`));
359
346
  }
360
347
  }
361
- /**
362
- * Format a container image list as a human-readable table.
363
- * Used by container-image list command.
364
- */
365
- export function formatContainerImageTable(images, pagination) {
366
- if (images.length === 0) {
367
- console.log(chalk.dim('No container images found'));
348
+ export function formatPoliciesTable(policies, pagination) {
349
+ if (policies.length === 0) {
350
+ console.log(chalk.dim('No policies found'));
368
351
  return;
369
352
  }
370
353
  const table = new Table({
371
354
  columns: [
372
355
  { name: 'id', title: 'ID', alignment: 'left' },
373
- { name: 'name', title: 'NAME', alignment: 'left' },
374
- { name: 'image', title: 'IMAGE', alignment: 'left' },
375
- { name: 'tag', title: 'TAG', alignment: 'left' },
376
- { name: 'public', title: 'PUBLIC', alignment: 'left' },
377
- ],
378
- });
379
- images.forEach((image) => {
380
- table.addRow({
381
- id: image.id,
382
- name: image.name,
383
- image: image.image_name,
384
- tag: image.tag,
385
- public: image.is_public ? chalk.green('yes') : chalk.dim('no'),
386
- });
387
- });
388
- table.printTable();
389
- const showing = Math.min(pagination.limit, images.length);
390
- if (pagination.has_more) {
391
- const nextOffset = pagination.offset + pagination.limit;
392
- console.log(`\nShowing ${showing} of ${pagination.total_count} images. ` +
393
- chalk.dim(`Use --offset ${nextOffset} to see more.`));
394
- }
395
- else if (pagination.total_count > showing) {
396
- console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} images`));
397
- }
398
- }
399
- /**
400
- * Derive a human-readable event type label from entity_type.
401
- */
402
- function formatEventType(entityType) {
403
- if (entityType === 'EntContainerEventCreate')
404
- return 'create';
405
- if (entityType === 'EntContainerEventDestroy')
406
- return 'destroy';
407
- if (entityType === 'EntContainerEventCommand')
408
- return 'command';
409
- return entityType;
410
- }
411
- /**
412
- * Format a container event list as a human-readable table.
413
- * Used by container events command.
414
- */
415
- export function formatContainerEventTable(events, pagination) {
416
- if (events.length === 0) {
417
- console.log(chalk.dim('No events found'));
418
- return;
419
- }
420
- const table = new Table({
421
- columns: [
422
- { name: 'id', title: 'ID', alignment: 'left' },
423
- { name: 'type', title: 'TYPE', alignment: 'left', color: 'cyan' },
424
- { name: 'status', title: 'STATUS', alignment: 'left' },
425
- { name: 'actor', title: 'ACTOR', alignment: 'left' },
426
- { name: 'detail', title: 'DETAIL', alignment: 'left' },
356
+ { name: 'decision', title: 'DECISION', alignment: 'left' },
357
+ { name: 'operations', title: 'OPERATIONS', alignment: 'left' },
358
+ { name: 'workspaces', title: 'WORKSPACES', alignment: 'left' },
359
+ { name: 'agents', title: 'AGENTS', alignment: 'left' },
360
+ { name: 'resources', title: 'RESOURCES', alignment: 'left' },
427
361
  { name: 'created', title: 'CREATED', alignment: 'left' },
428
362
  ],
429
363
  });
430
- events.forEach((event) => {
431
- const statusColor = event.status === 'SUCCESS'
432
- ? chalk.green
433
- : event.status === 'ERROR'
434
- ? chalk.red
435
- : chalk.yellow;
436
- let detail = '';
437
- if (event.entity_type === 'EntContainerEventCommand') {
438
- detail = truncate(event.command, 30);
439
- }
440
- else if (event.status === 'ERROR' && event.error) {
441
- detail = truncate(event.error, 30);
442
- }
364
+ policies.forEach((policy) => {
365
+ const decisionColor = policy.decision === 'ALLOW' ? chalk.green : chalk.red;
443
366
  table.addRow({
444
- id: event.id,
445
- type: formatEventType(event.entity_type),
446
- status: statusColor(event.status),
447
- actor: event.actor?.name || event.actor?.full_name || '-',
448
- detail,
449
- created: event.created_at ? formatRelativeTime(event.created_at) : '',
367
+ id: policy.id,
368
+ decision: decisionColor(policy.decision),
369
+ operations: policy.operations
370
+ ? truncate(policy.operations.join(', '), 30)
371
+ : chalk.dim('all'),
372
+ workspaces: policy.workspaces.length > 0
373
+ ? truncate(policy.workspaces.map((w) => w.full_name || w.name).join(', '), 20)
374
+ : chalk.dim('all'),
375
+ agents: policy.agents.length > 0
376
+ ? truncate(policy.agents.map((a) => a.full_name || a.name).join(', '), 20)
377
+ : chalk.dim('all'),
378
+ resources: policy.resources
379
+ ? truncate(Object.entries(policy.resources)
380
+ .map(([k, v]) => `${k}: ${v.join(', ')}`)
381
+ .join('; '), 30)
382
+ : chalk.dim('none'),
383
+ created: formatRelativeTime(policy.created_at),
450
384
  });
451
385
  });
452
386
  table.printTable();
453
- const showing = Math.min(pagination.limit, events.length);
387
+ const showing = Math.min(pagination.limit, policies.length);
454
388
  if (pagination.has_more) {
455
389
  const nextOffset = pagination.offset + pagination.limit;
456
- console.log(`\nShowing ${showing} of ${pagination.total_count} events. ` +
390
+ console.log(`\nShowing ${showing} of ${pagination.total_count} policies. ` +
457
391
  chalk.dim(`Use --offset ${nextOffset} to see more.`));
458
392
  }
459
393
  else if (pagination.total_count > showing) {
460
- console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} events`));
394
+ console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} policies`));
461
395
  }
462
396
  }
463
397
  /**
package/dist/mcp/tools.js CHANGED
@@ -694,7 +694,7 @@ export function registerTools(server, apiClient, defaultWorkspaceId, debug) {
694
694
  const agent = t.agent.full_name || t.agent.name;
695
695
  const disabled = t.deactivated_at ? ' [DISABLED]' : '';
696
696
  if (t.type === 'webhook') {
697
- return `• ${t.id} [webhook] ${t.service}/${t.event_type || '*'} → ${agent}${disabled}`;
697
+ return `• ${t.id} [webhook] ${t.integration.name}/${t.event_type || '*'} → ${agent}${disabled}`;
698
698
  }
699
699
  return `• ${t.id} [time] ${t.frequency} → ${agent}${disabled}`;
700
700
  })
@@ -21,8 +21,9 @@ Use the **CLI** (via Bash) for **local development operations**: `guild agent in
21
21
  # Create a new agent
22
22
  guild agent init --name my-agent --template LLM
23
23
 
24
- # Clone an existing agent
24
+ # Clone an existing agent (full name or short name)
25
25
  guild agent clone guildai/dev-assistant
26
+ guild agent clone dev-assistant # resolves to your-username/dev-assistant
26
27
  cd dev-assistant
27
28
 
28
29
  # Save changes (pushes commits to Guild server)
@@ -75,8 +76,9 @@ guild agent init --name my-agent --template BLANK
75
76
  # Fork an existing agent
76
77
  guild agent init --fork owner/agent-name
77
78
 
78
- # Clone to work on an existing agent
79
+ # Clone to work on an existing agent (full name, short name, or UUID)
79
80
  guild agent clone owner/agent-name
81
+ guild agent clone agent-name # auto-resolves owner
80
82
  ```
81
83
 
82
84
  ### Working with Existing Agents
@@ -1740,10 +1740,10 @@ guild agent list --search "github" --published # Search published agents
1740
1740
  guild agent search <query> # Search published agents
1741
1741
  guild agent versions [agent-id] # Version history
1742
1742
  guild agent clone <agent-id> # Clone existing agent
1743
- guild agent fork <agent-id>:<version-id> # Fork a specific version as a new agent
1743
+ guild agent fork [identifier] # Fork an agent (latest published version, or identifier:version)
1744
1744
  guild agent publish # Publish a version
1745
1745
  guild agent unpublish # Remove from catalog
1746
- guild agent update # Update agent metadata
1746
+ guild agent update [identifier] # Update agent metadata
1747
1747
  guild agent workspaces [agent-id] # List workspaces using an agent
1748
1748
  guild agent tags list|add|remove|set # Manage agent tags
1749
1749
  guild agent revalidate # Re-run validation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guildai/cli",
3
- "version": "0.5.13",
3
+ "version": "0.6.0",
4
4
  "description": "Guild.ai CLI - Build, test, and deploy AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -35,12 +35,12 @@
35
35
  "format:fix": "prettier --write .",
36
36
  "format:check": "prettier --check .",
37
37
  "test": "vitest run",
38
- "test:unit": "vitest run test/unit",
38
+ "test:unit": "vitest run test/unit --config vitest.unit.config.ts",
39
39
  "test:e2e": "vitest run test/e2e --exclude='**/**.slow.test.ts'",
40
40
  "test:e2e:slow": "vitest run 'test/e2e/**/*.slow.test.ts'",
41
41
  "test:e2e:all": "vitest run test/e2e",
42
42
  "test:watch": "vitest",
43
- "prepublishOnly": "npm run build && npm run lint && npm run test"
43
+ "prepublishOnly": "npm run build && npm run lint && npm run test:unit"
44
44
  },
45
45
  "keywords": [
46
46
  "guild",
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createContainerDestroyCommand(): Command;
3
- //# sourceMappingURL=destroy.d.ts.map
@@ -1,48 +0,0 @@
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 { getOutputMode } from '../../lib/output-mode.js';
8
- import { createOutputWriter } from '../../lib/output.js';
9
- export function createContainerDestroyCommand() {
10
- const cmd = new Command('destroy');
11
- cmd
12
- .description('Destroy a running container')
13
- .argument('<container-id>', 'Container ID')
14
- .action(async (containerId) => {
15
- const output = createOutputWriter();
16
- try {
17
- const token = await getAuthToken();
18
- if (!token) {
19
- output.error('Not authenticated. Run: guild auth login');
20
- process.exit(1);
21
- }
22
- const client = new GuildAPIClient();
23
- const response = await client.post(`/containers/${containerId}/destroy`, {});
24
- if (getOutputMode() === 'json') {
25
- console.log(JSON.stringify(response, null, 2));
26
- }
27
- else {
28
- if (response.status === 'SUCCESS') {
29
- output.success(`Container ${containerId} destroyed`);
30
- }
31
- else if (response.status === 'ERROR') {
32
- output.error(`Failed to destroy container: ${response.error || 'unknown error'}`);
33
- process.exit(1);
34
- }
35
- else {
36
- output.progress(`Container destruction ${response.status.toLowerCase()}...`);
37
- }
38
- }
39
- }
40
- catch (error) {
41
- const formattedError = handleAxiosError(error);
42
- output.error(`Failed to destroy container: ${formattedError.details}`);
43
- process.exit(1);
44
- }
45
- });
46
- return cmd;
47
- }
48
- //# sourceMappingURL=destroy.js.map
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createContainerEventsCommand(): Command;
3
- //# sourceMappingURL=events.d.ts.map
@@ -1,44 +0,0 @@
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 { getOutputMode } from '../../lib/output-mode.js';
8
- import { createOutputWriter, formatContainerEventTable } from '../../lib/output.js';
9
- export function createContainerEventsCommand() {
10
- const cmd = new Command('events');
11
- cmd
12
- .description('List events for a container')
13
- .argument('<container-id>', 'Container ID')
14
- .option('--limit <number>', 'Number of results to return', '20')
15
- .option('--offset <number>', 'Offset for pagination', '0')
16
- .action(async (containerId, options) => {
17
- const output = createOutputWriter();
18
- try {
19
- const token = await getAuthToken();
20
- if (!token) {
21
- output.error('Not authenticated. Run: guild auth login');
22
- process.exit(1);
23
- }
24
- const client = new GuildAPIClient();
25
- const params = new URLSearchParams();
26
- params.append('limit', options.limit);
27
- params.append('offset', options.offset);
28
- const response = await client.get(`/containers/${containerId}/events?${params.toString()}`);
29
- if (getOutputMode() === 'json') {
30
- console.log(JSON.stringify(response, null, 2));
31
- }
32
- else {
33
- formatContainerEventTable(response.items, response.pagination);
34
- }
35
- }
36
- catch (error) {
37
- const formattedError = handleAxiosError(error);
38
- output.error(`Failed to list container events: ${formattedError.details}`);
39
- process.exit(1);
40
- }
41
- });
42
- return cmd;
43
- }
44
- //# sourceMappingURL=events.js.map
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createContainerExecCommand(): Command;
3
- //# sourceMappingURL=exec.d.ts.map