@guildai/cli 0.7.1 → 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.
- package/dist/commands/agent/chat.js +0 -2
- package/dist/commands/agent/init.js +10 -8
- package/dist/commands/agent/list.js +46 -7
- package/dist/commands/agent/owners.js +6 -8
- package/dist/commands/agent/test.js +36 -6
- package/dist/commands/chat.js +3 -10
- package/dist/commands/session/create.js +1 -1
- package/dist/commands/session/tasks.js +8 -2
- package/dist/commands/trigger/create.js +41 -17
- package/dist/commands/trigger/update.js +33 -10
- package/dist/commands/workspace/agent/add.js +3 -3
- package/dist/commands/workspace/agent/remove.js +1 -1
- package/dist/lib/agent-helpers.d.ts +15 -0
- package/dist/lib/agent-helpers.js +69 -0
- package/dist/lib/api-client.js +12 -5
- package/dist/lib/api-types.d.ts +56 -0
- package/dist/lib/auth.d.ts +0 -4
- package/dist/lib/auth.js +0 -11
- package/dist/lib/errors.d.ts +5 -4
- package/dist/lib/errors.js +18 -11
- package/dist/lib/output.d.ts +7 -2
- package/dist/lib/output.js +60 -4
- package/dist/lib/polling.d.ts +0 -24
- package/dist/lib/polling.js +0 -26
- package/dist/mcp/tools.js +2 -2
- package/docs/skills/agent-dev.md +301 -1006
- package/package.json +2 -2
- package/dist/lib/lottie-renderer.d.ts +0 -61
- package/dist/lib/lottie-renderer.js +0 -238
- package/dist/lib/svg-renderer.d.ts +0 -110
- package/dist/lib/svg-renderer.js +0 -858
|
@@ -234,4 +234,73 @@ export async function buildEphemeralVersion(client, agentId, files, cwd, summary
|
|
|
234
234
|
}
|
|
235
235
|
return { version, cached: false };
|
|
236
236
|
}
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
// Bundle version
|
|
239
|
+
// ---------------------------------------------------------------------------
|
|
240
|
+
/** Thrown when the specified bundle file cannot be found on disk. */
|
|
241
|
+
export class BundleNotFoundError extends Error {
|
|
242
|
+
constructor(filePath) {
|
|
243
|
+
super(`Bundle file not found: ${filePath}`);
|
|
244
|
+
this.name = 'BundleNotFoundError';
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Upload a pre-built bundle as an ephemeral version.
|
|
249
|
+
*
|
|
250
|
+
* The bundle file must be gzip+base64 encoded (the output of
|
|
251
|
+
* `esbuild ... | gzip | base64`). Source files are included for
|
|
252
|
+
* dashboard viewing, but the server skips its own build step because
|
|
253
|
+
* the ready-to-run artifact is already provided.
|
|
254
|
+
*/
|
|
255
|
+
export async function buildBundledVersion(client, agentId, bundlePath, cwd, summary) {
|
|
256
|
+
try {
|
|
257
|
+
await fs.access(bundlePath);
|
|
258
|
+
}
|
|
259
|
+
catch {
|
|
260
|
+
throw new BundleNotFoundError(bundlePath);
|
|
261
|
+
}
|
|
262
|
+
const bundle = (await fs.readFile(bundlePath, 'utf-8')).trim();
|
|
263
|
+
let files = [];
|
|
264
|
+
try {
|
|
265
|
+
files = await readAgentFiles(cwd);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
// No git or missing required files — proceed with bundle-only upload
|
|
269
|
+
}
|
|
270
|
+
const initial = (await client.post(`/agents/${agentId}/versions`, {
|
|
271
|
+
version_type: 'EPHEMERAL',
|
|
272
|
+
bundle,
|
|
273
|
+
encoding: 'gzip;base64',
|
|
274
|
+
files,
|
|
275
|
+
summary,
|
|
276
|
+
}));
|
|
277
|
+
const pollResult = await pollUntilComplete({
|
|
278
|
+
resourceId: initial.id,
|
|
279
|
+
endpoint: `/versions/${initial.id}`,
|
|
280
|
+
isComplete: (r) => r.validation_status !== 'PENDING' && r.validation_status !== 'RUNNING',
|
|
281
|
+
message: 'Validating bundle...',
|
|
282
|
+
successMessage: 'Bundle validated',
|
|
283
|
+
timeoutMessage: 'Bundle validation timed out',
|
|
284
|
+
maxAttempts: 120,
|
|
285
|
+
delayMs: 1000,
|
|
286
|
+
});
|
|
287
|
+
if (!pollResult.success || !pollResult.response) {
|
|
288
|
+
throw new BuildTimeoutError('Bundle validation timed out.');
|
|
289
|
+
}
|
|
290
|
+
const version = pollResult.response;
|
|
291
|
+
if (version.validation_status === 'FAILED') {
|
|
292
|
+
let failedSteps = [];
|
|
293
|
+
try {
|
|
294
|
+
const stepsResponse = await client.get(`/versions/${version.id}/validation/steps`);
|
|
295
|
+
failedSteps = stepsResponse.steps
|
|
296
|
+
.filter((step) => step.status === 'FAILED')
|
|
297
|
+
.map((step) => ({ name: step.name, content: step.content ?? undefined }));
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
// Could not fetch validation details — throw with empty steps
|
|
301
|
+
}
|
|
302
|
+
throw new BuildFailedError(failedSteps);
|
|
303
|
+
}
|
|
304
|
+
return { version };
|
|
305
|
+
}
|
|
237
306
|
//# sourceMappingURL=agent-helpers.js.map
|
package/dist/lib/api-client.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { getAuthToken, clearAuthToken } from './auth.js';
|
|
5
|
-
import { retry, debug, GuildCLIError, ErrorCodes } from './errors.js';
|
|
5
|
+
import { retry, debug, GuildCLIError, ErrorCodes, shouldClearAuthToken, } from './errors.js';
|
|
6
6
|
import { getUserAgent, getGuildcoreUrl } from './config.js';
|
|
7
7
|
import { getIapHeaders } from './iap.js';
|
|
8
8
|
/**
|
|
@@ -69,14 +69,21 @@ export class GuildAPIClient {
|
|
|
69
69
|
return response.data;
|
|
70
70
|
}
|
|
71
71
|
catch (error) {
|
|
72
|
-
// Handle invalid/expired token - clear it and give clear error
|
|
73
72
|
if (error &&
|
|
74
73
|
typeof error === 'object' &&
|
|
75
74
|
'response' in error &&
|
|
76
75
|
error.response?.status === 401) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
const resp = error.response;
|
|
77
|
+
const data = resp?.data;
|
|
78
|
+
const message = typeof data === 'object' && data && 'message' in data
|
|
79
|
+
? data.message
|
|
80
|
+
: undefined;
|
|
81
|
+
if (shouldClearAuthToken(message)) {
|
|
82
|
+
debug('Guild auth failure (401), clearing token');
|
|
83
|
+
await clearAuthToken();
|
|
84
|
+
throw new GuildCLIError(ErrorCodes.AUTH_TOKEN_INVALID, 'Your authentication token is invalid or expired. Please run: guild auth login');
|
|
85
|
+
}
|
|
86
|
+
debug(`Non-auth 401: ${message ?? 'no message'}`);
|
|
80
87
|
}
|
|
81
88
|
throw error;
|
|
82
89
|
}
|
package/dist/lib/api-types.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export interface Agent {
|
|
|
25
25
|
status: string;
|
|
26
26
|
description: string | null;
|
|
27
27
|
is_public?: boolean;
|
|
28
|
+
is_archived?: boolean;
|
|
28
29
|
git_url?: string;
|
|
29
30
|
cached_likes_count?: number;
|
|
30
31
|
created_at?: string;
|
|
@@ -244,6 +245,22 @@ export interface TriggerWorkspaceAgent {
|
|
|
244
245
|
version_number: string | null;
|
|
245
246
|
};
|
|
246
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* Workspace owner as embedded in trigger API responses.
|
|
250
|
+
*/
|
|
251
|
+
export interface TriggerWorkspaceOwner {
|
|
252
|
+
id: string;
|
|
253
|
+
type: 'user' | 'organization';
|
|
254
|
+
name: string;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Workspace as embedded in trigger API responses.
|
|
258
|
+
*/
|
|
259
|
+
export interface TriggerWorkspace {
|
|
260
|
+
id: string;
|
|
261
|
+
name: string;
|
|
262
|
+
owner: TriggerWorkspaceOwner;
|
|
263
|
+
}
|
|
247
264
|
/**
|
|
248
265
|
* Webhook trigger - fires when a third-party service sends an event.
|
|
249
266
|
* Used by: trigger list, trigger get, trigger create
|
|
@@ -265,6 +282,7 @@ export interface TriggerWebhook {
|
|
|
265
282
|
disabled_reason: TriggerDisabledReason | null;
|
|
266
283
|
agent: TriggerAgent;
|
|
267
284
|
workspace_agent: TriggerWorkspaceAgent | null;
|
|
285
|
+
workspace: TriggerWorkspace;
|
|
268
286
|
}
|
|
269
287
|
/**
|
|
270
288
|
* Time trigger - fires on a schedule.
|
|
@@ -284,6 +302,7 @@ export interface TriggerTime {
|
|
|
284
302
|
disabled_reason: TriggerDisabledReason | null;
|
|
285
303
|
agent: TriggerAgent;
|
|
286
304
|
workspace_agent: TriggerWorkspaceAgent | null;
|
|
305
|
+
workspace: TriggerWorkspace;
|
|
287
306
|
}
|
|
288
307
|
/**
|
|
289
308
|
* Discriminated union of trigger types.
|
|
@@ -361,6 +380,43 @@ export interface CredentialsPolicy {
|
|
|
361
380
|
updated_at: string;
|
|
362
381
|
}
|
|
363
382
|
export type CredentialsPolicyListResponse = PaginatedResponse<CredentialsPolicy>;
|
|
383
|
+
export type TaskStatus = 'CREATED' | 'DISPATCHED' | 'STARTED' | 'RUNNING' | 'WAITING' | 'ERROR' | 'DONE' | 'INTERRUPTED';
|
|
384
|
+
export interface TokenUsage {
|
|
385
|
+
input_tokens: number;
|
|
386
|
+
output_tokens: number;
|
|
387
|
+
cache_read_tokens: number;
|
|
388
|
+
cache_write_tokens: number;
|
|
389
|
+
total_tokens: number;
|
|
390
|
+
llm_call_count: number;
|
|
391
|
+
}
|
|
392
|
+
interface TaskBase {
|
|
393
|
+
id: string;
|
|
394
|
+
entity_type: string;
|
|
395
|
+
status: TaskStatus;
|
|
396
|
+
token_usage: TokenUsage | null;
|
|
397
|
+
created_at: string;
|
|
398
|
+
updated_at: string;
|
|
399
|
+
}
|
|
400
|
+
export interface TaskAgent extends TaskBase {
|
|
401
|
+
entity_type: 'EntTaskAgent';
|
|
402
|
+
agent: {
|
|
403
|
+
name: string;
|
|
404
|
+
full_name?: string;
|
|
405
|
+
} | null;
|
|
406
|
+
version: {
|
|
407
|
+
id: string;
|
|
408
|
+
version_number?: string;
|
|
409
|
+
} | null;
|
|
410
|
+
}
|
|
411
|
+
export interface TaskTool extends TaskBase {
|
|
412
|
+
entity_type: 'EntTaskTool';
|
|
413
|
+
tool_name: string;
|
|
414
|
+
tool_call_id: string;
|
|
415
|
+
request_bytes: number;
|
|
416
|
+
response_bytes: number;
|
|
417
|
+
http_status_code: number;
|
|
418
|
+
}
|
|
419
|
+
export type Task = TaskAgent | TaskTool;
|
|
364
420
|
/**
|
|
365
421
|
* Session entity from API responses.
|
|
366
422
|
* Used by: session list
|
package/dist/lib/auth.d.ts
CHANGED
|
@@ -40,10 +40,6 @@ export declare function startDeviceFlow(authUrl?: string, returnUrl?: string, re
|
|
|
40
40
|
* @returns Access token if successful, null if failed/expired
|
|
41
41
|
*/
|
|
42
42
|
export declare function pollForToken(authUrl: string, code: string, interval: number): Promise<string | null>;
|
|
43
|
-
/**
|
|
44
|
-
* Show beta invitation guidance for users who aren't authenticated.
|
|
45
|
-
*/
|
|
46
|
-
export declare function showBetaGuidance(): void;
|
|
47
43
|
/**
|
|
48
44
|
* Perform complete login flow
|
|
49
45
|
* @param returnUrl - Optional custom URL to redirect to after authentication
|
package/dist/lib/auth.js
CHANGED
|
@@ -185,15 +185,6 @@ export async function pollForToken(authUrl, code, interval) {
|
|
|
185
185
|
spinner.fail('Authorization timed out');
|
|
186
186
|
return null;
|
|
187
187
|
}
|
|
188
|
-
/**
|
|
189
|
-
* Show beta invitation guidance for users who aren't authenticated.
|
|
190
|
-
*/
|
|
191
|
-
export function showBetaGuidance() {
|
|
192
|
-
console.error('');
|
|
193
|
-
console.error(chalk.dim("Don't have an account? Guild.ai is in closed beta."));
|
|
194
|
-
console.error(chalk.dim('Request an invitation at hello@guild.ai'));
|
|
195
|
-
console.error('');
|
|
196
|
-
}
|
|
197
188
|
/**
|
|
198
189
|
* Perform complete login flow
|
|
199
190
|
* @param returnUrl - Optional custom URL to redirect to after authentication
|
|
@@ -242,7 +233,6 @@ export async function login(returnUrl, returnLabel, nonInteractive) {
|
|
|
242
233
|
await saveAuthToken(token);
|
|
243
234
|
return true;
|
|
244
235
|
}
|
|
245
|
-
showBetaGuidance();
|
|
246
236
|
return false;
|
|
247
237
|
}
|
|
248
238
|
catch (error) {
|
|
@@ -254,7 +244,6 @@ export async function login(returnUrl, returnLabel, nonInteractive) {
|
|
|
254
244
|
if (formattedError.code) {
|
|
255
245
|
console.error(chalk.dim(`\nError code: ${formattedError.code}`));
|
|
256
246
|
}
|
|
257
|
-
showBetaGuidance();
|
|
258
247
|
return false;
|
|
259
248
|
}
|
|
260
249
|
}
|
package/dist/lib/errors.d.ts
CHANGED
|
@@ -50,10 +50,6 @@ export declare function debug(message: string, ...args: unknown[]): void;
|
|
|
50
50
|
* Format error for output
|
|
51
51
|
*/
|
|
52
52
|
export declare function formatError(error: string, details: string, code?: string, stack?: string, suggestions?: string[]): CLIError;
|
|
53
|
-
/**
|
|
54
|
-
* Print error to stdout and exit
|
|
55
|
-
*/
|
|
56
|
-
export declare function exitWithError(error: string, details: string, code?: string, exitCode?: number): never;
|
|
57
53
|
/**
|
|
58
54
|
* Get user-friendly error message for common error codes
|
|
59
55
|
*/
|
|
@@ -74,6 +70,11 @@ export declare function isIapError(error: unknown): boolean;
|
|
|
74
70
|
* Check if an error is a Guild auth error
|
|
75
71
|
*/
|
|
76
72
|
export declare function isAuthError(error: unknown): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Check if a 401 response message indicates the stored auth token should be cleared.
|
|
75
|
+
* Uses exact match — only clear for known Guild auth failures.
|
|
76
|
+
*/
|
|
77
|
+
export declare function shouldClearAuthToken(responseMessage: string | undefined): boolean;
|
|
77
78
|
/**
|
|
78
79
|
* Check if an error is fatal (should not be retried)
|
|
79
80
|
*
|
package/dist/lib/errors.js
CHANGED
|
@@ -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
|
-
*
|
|
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
|
|
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
|
|
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)
|
package/dist/lib/output.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { type Spinner } from './progress.js';
|
|
2
|
-
import type { Agent, AgentVersion, Credentials, CredentialsPolicy, Context, Integration, IntegrationVersion, JobStep, Pagination, Session, Workspace, WorkspaceAgent, Trigger } from './api-types.js';
|
|
2
|
+
import type { Agent, AgentVersion, Credentials, CredentialsPolicy, Context, Integration, IntegrationVersion, JobStep, Pagination, Session, Task, 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.
|
|
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.
|
|
@@ -40,6 +40,11 @@ export declare function formatWorkspaceTable(workspaces: Workspace[], pagination
|
|
|
40
40
|
* Used by session list command.
|
|
41
41
|
*/
|
|
42
42
|
export declare function formatSessionTable(sessions: Session[], pagination: Pagination): void;
|
|
43
|
+
/**
|
|
44
|
+
* Format a task list as a human-readable table.
|
|
45
|
+
* Used by session tasks command.
|
|
46
|
+
*/
|
|
47
|
+
export declare function formatTaskTable(tasks: Task[], pagination: Pagination): void;
|
|
43
48
|
/**
|
|
44
49
|
* Format a trigger list as a human-readable table.
|
|
45
50
|
* Used by trigger list command.
|
package/dist/lib/output.js
CHANGED
|
@@ -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
|
|
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:
|
|
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) : '',
|
|
@@ -359,6 +363,56 @@ export function formatSessionTable(sessions, pagination) {
|
|
|
359
363
|
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} sessions`));
|
|
360
364
|
}
|
|
361
365
|
}
|
|
366
|
+
/**
|
|
367
|
+
* Format a task list as a human-readable table.
|
|
368
|
+
* Used by session tasks command.
|
|
369
|
+
*/
|
|
370
|
+
export function formatTaskTable(tasks, pagination) {
|
|
371
|
+
if (tasks.length === 0) {
|
|
372
|
+
console.log(chalk.dim('No tasks found'));
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
const table = new Table({
|
|
376
|
+
columns: [
|
|
377
|
+
{ name: 'id', title: 'ID', alignment: 'left' },
|
|
378
|
+
{ name: 'name', title: 'NAME', alignment: 'left' },
|
|
379
|
+
{ name: 'status', title: 'STATUS', alignment: 'left' },
|
|
380
|
+
{ name: 'tokens', title: 'TOKENS', alignment: 'left' },
|
|
381
|
+
{ name: 'created', title: 'CREATED', alignment: 'left' },
|
|
382
|
+
],
|
|
383
|
+
});
|
|
384
|
+
tasks.forEach((task) => {
|
|
385
|
+
const name = task.entity_type === 'EntTaskAgent'
|
|
386
|
+
? task.agent?.full_name || task.agent?.name || '-'
|
|
387
|
+
: task.tool_name;
|
|
388
|
+
const statusColor = task.status === 'DONE'
|
|
389
|
+
? chalk.green
|
|
390
|
+
: task.status === 'ERROR'
|
|
391
|
+
? chalk.red
|
|
392
|
+
: task.status === 'RUNNING' ||
|
|
393
|
+
task.status === 'STARTED' ||
|
|
394
|
+
task.status === 'WAITING'
|
|
395
|
+
? chalk.yellow
|
|
396
|
+
: chalk.dim;
|
|
397
|
+
table.addRow({
|
|
398
|
+
id: truncate(task.id, 13),
|
|
399
|
+
name,
|
|
400
|
+
status: statusColor(task.status),
|
|
401
|
+
tokens: task.token_usage ? task.token_usage.total_tokens.toLocaleString() : '-',
|
|
402
|
+
created: task.created_at ? formatRelativeTime(task.created_at) : '',
|
|
403
|
+
});
|
|
404
|
+
});
|
|
405
|
+
table.printTable();
|
|
406
|
+
const showing = Math.min(pagination.limit, tasks.length);
|
|
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
|
+
}
|
|
415
|
+
}
|
|
362
416
|
/**
|
|
363
417
|
* Format a trigger list as a human-readable table.
|
|
364
418
|
* Used by trigger list command.
|
|
@@ -388,8 +442,10 @@ export function formatTriggerTable(triggers, pagination) {
|
|
|
388
442
|
const agentUrl = trigger.agent?.full_name
|
|
389
443
|
? `${base}/agents/${trigger.agent.full_name}`
|
|
390
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`;
|
|
391
447
|
table.addRow({
|
|
392
|
-
id: hyperlink(trigger.id,
|
|
448
|
+
id: hyperlink(trigger.id, triggerUrl),
|
|
393
449
|
type: trigger.type,
|
|
394
450
|
agent: agentUrl ? hyperlink(agentName, agentUrl) : agentName,
|
|
395
451
|
status,
|
package/dist/lib/polling.d.ts
CHANGED
|
@@ -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
|
package/dist/lib/polling.js
CHANGED
|
@@ -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
|
|
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
|
|
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;
|