@guildai/cli 0.8.0 → 0.8.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.
@@ -82,14 +82,6 @@ export function formatError(error, details, code, stack, suggestions) {
82
82
  }
83
83
  return result;
84
84
  }
85
- /**
86
- * Print error to stdout and exit
87
- */
88
- export function exitWithError(error, details, code, exitCode = 1) {
89
- const formattedError = formatError(error, details, code);
90
- console.log(JSON.stringify(formattedError, null, 2));
91
- process.exit(exitCode);
92
- }
93
85
  /**
94
86
  * Get user-friendly error message for common error codes
95
87
  */
@@ -280,9 +272,15 @@ const IAP_ERROR_PATTERNS = [
280
272
  'gcloud returned empty token',
281
273
  ];
282
274
  /**
283
- * Patterns that indicate Guild auth errors (not IAP)
275
+ * Messages from Guildcore that indicate a real Guild auth failure.
276
+ * Source: python/guildcore/core/session.py and routing.py
284
277
  */
285
- const AUTH_ERROR_PATTERNS = ['Not authenticated', 'Authentication required'];
278
+ const GUILD_AUTH_FAILURE_MESSAGES = [
279
+ 'Access token expired',
280
+ 'Access token invalid',
281
+ 'Session expired',
282
+ 'Not authenticated',
283
+ ];
286
284
  /**
287
285
  * Check if an error is an IAP (Google Identity-Aware Proxy) error
288
286
  */
@@ -295,7 +293,16 @@ export function isIapError(error) {
295
293
  */
296
294
  export function isAuthError(error) {
297
295
  const message = error instanceof Error ? error.message : String(error);
298
- return AUTH_ERROR_PATTERNS.some((pattern) => message.includes(pattern));
296
+ return GUILD_AUTH_FAILURE_MESSAGES.some((pattern) => message.includes(pattern));
297
+ }
298
+ /**
299
+ * Check if a 401 response message indicates the stored auth token should be cleared.
300
+ * Uses exact match — only clear for known Guild auth failures.
301
+ */
302
+ export function shouldClearAuthToken(responseMessage) {
303
+ if (!responseMessage)
304
+ return false;
305
+ return GUILD_AUTH_FAILURE_MESSAGES.some((msg) => msg === responseMessage);
299
306
  }
300
307
  /**
301
308
  * Check if an error is fatal (should not be retried)
@@ -4,7 +4,7 @@ import type { Agent, AgentVersion, Credentials, CredentialsPolicy, Context, Inte
4
4
  * Format an agent list as a human-readable table.
5
5
  * Shared by agent list and agent search commands.
6
6
  */
7
- export declare function formatAgentTable(agents: Agent[], pagination: Pagination): void;
7
+ export declare function formatAgentTable(agents: Agent[], pagination: Pagination, showArchived?: boolean): void;
8
8
  /**
9
9
  * Format an integration list as a human-readable table.
10
10
  * Used by integration list command.
@@ -42,7 +42,7 @@ function truncate(str, maxLen) {
42
42
  * Format an agent list as a human-readable table.
43
43
  * Shared by agent list and agent search commands.
44
44
  */
45
- export function formatAgentTable(agents, pagination) {
45
+ export function formatAgentTable(agents, pagination, showArchived = false) {
46
46
  if (agents.length === 0) {
47
47
  console.log(chalk.dim('No agents found'));
48
48
  return;
@@ -61,10 +61,14 @@ export function formatAgentTable(agents, pagination) {
61
61
  });
62
62
  const base = getDashboardUrl();
63
63
  agents.forEach((agent) => {
64
- const name = agent.full_name || agent.name;
64
+ const rawName = agent.full_name || agent.name;
65
65
  const agentUrl = agent.full_name ? `${base}/agents/${agent.full_name}` : '';
66
+ const linkedName = agentUrl ? hyperlink(rawName, agentUrl) : rawName;
67
+ const displayName = showArchived && agent.is_archived
68
+ ? linkedName + chalk.dim(' [archived]')
69
+ : linkedName;
66
70
  table.addRow({
67
- name: agentUrl ? hyperlink(name, agentUrl) : name,
71
+ name: displayName,
68
72
  owner: agent.owner?.name || '',
69
73
  description: truncate(agent.description || '', 40),
70
74
  updated: agent.updated_at ? formatRelativeTime(agent.updated_at) : '',
@@ -438,8 +442,10 @@ export function formatTriggerTable(triggers, pagination) {
438
442
  const agentUrl = trigger.agent?.full_name
439
443
  ? `${base}/agents/${trigger.agent.full_name}`
440
444
  : '';
445
+ const ownerSegment = trigger.workspace.owner.type === 'organization' ? 'organizations' : 'users';
446
+ const triggerUrl = `${base}/${ownerSegment}/${trigger.workspace.owner.name}/workspaces/${trigger.workspace.name}/triggers`;
441
447
  table.addRow({
442
- id: hyperlink(trigger.id, `${base}/triggers/${trigger.id}/sessions`),
448
+ id: hyperlink(trigger.id, triggerUrl),
443
449
  type: trigger.type,
444
450
  agent: agentUrl ? hyperlink(agentName, agentUrl) : agentName,
445
451
  status,
@@ -71,28 +71,4 @@ export interface PollResult<T = unknown> {
71
71
  * ```
72
72
  */
73
73
  export declare function pollUntilComplete<T = unknown>(options: PollOptions<T>): Promise<PollResult<T>>;
74
- /**
75
- * Agent response with status field
76
- */
77
- interface AgentStatusResponse {
78
- status: string;
79
- [key: string]: unknown;
80
- }
81
- /**
82
- * Poll an agent until it reaches a specific status
83
- *
84
- * @param agentId - Agent ID to poll
85
- * @param targetStatus - Status to wait for (e.g., 'READY')
86
- * @param options - Additional polling options
87
- *
88
- * @example
89
- * ```typescript
90
- * const result = await pollAgentStatus(agentId, 'READY');
91
- * if (result.success) {
92
- * console.log('Agent is ready');
93
- * }
94
- * ```
95
- */
96
- export declare function pollAgentStatus(agentId: string, targetStatus: string, options?: Partial<Omit<PollOptions<AgentStatusResponse>, 'resourceId' | 'endpoint' | 'isComplete'>>): Promise<PollResult<AgentStatusResponse>>;
97
- export {};
98
74
  //# sourceMappingURL=polling.d.ts.map
@@ -64,30 +64,4 @@ export async function pollUntilComplete(options) {
64
64
  attempts,
65
65
  };
66
66
  }
67
- /**
68
- * Poll an agent until it reaches a specific status
69
- *
70
- * @param agentId - Agent ID to poll
71
- * @param targetStatus - Status to wait for (e.g., 'READY')
72
- * @param options - Additional polling options
73
- *
74
- * @example
75
- * ```typescript
76
- * const result = await pollAgentStatus(agentId, 'READY');
77
- * if (result.success) {
78
- * console.log('Agent is ready');
79
- * }
80
- * ```
81
- */
82
- export async function pollAgentStatus(agentId, targetStatus, options = {}) {
83
- return pollUntilComplete({
84
- resourceId: agentId,
85
- endpoint: `/agents/${agentId}`,
86
- isComplete: (response) => response.status === targetStatus,
87
- message: options.message || 'Waiting for agent initialization...',
88
- successMessage: options.successMessage || 'Agent initialization complete',
89
- timeoutMessage: options.timeoutMessage || 'Agent initialization timed out after 60 seconds',
90
- ...options,
91
- });
92
- }
93
67
  //# sourceMappingURL=polling.js.map
package/dist/mcp/tools.js CHANGED
@@ -387,7 +387,7 @@ export function registerTools(server, apiClient, defaultWorkspaceId, debug) {
387
387
  server.tool('guild_get_agent', 'Get details for a specific Guild agent', {
388
388
  agent_id: z
389
389
  .string()
390
- .describe('The agent ID or full name (e.g. owner/agent-name)'),
390
+ .describe('The agent ID or full name (e.g. owner~agent-name)'),
391
391
  }, async ({ agent_id }) => {
392
392
  debugLog(debug, `guild_get_agent: ${agent_id}`);
393
393
  try {
@@ -489,7 +489,7 @@ export function registerTools(server, apiClient, defaultWorkspaceId, debug) {
489
489
  agent: z
490
490
  .string()
491
491
  .optional()
492
- .describe('Agent identifier (e.g. owner/agent-name). Uses workspace default if not specified'),
492
+ .describe('Agent identifier (e.g. owner~agent-name). Uses workspace default if not specified'),
493
493
  workspace_id: workspaceIdParam,
494
494
  }, async ({ message, agent, workspace_id }) => {
495
495
  const wsId = workspace_id || defaultWorkspaceId;