@guildai/cli 0.5.12 → 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.
- package/dist/commands/agent/clone.js +3 -1
- package/dist/commands/agent/code.js +3 -2
- package/dist/commands/agent/fork.js +41 -17
- package/dist/commands/agent/get.js +3 -2
- package/dist/commands/agent/grep.js +61 -31
- package/dist/commands/agent/init.js +1 -3
- package/dist/commands/agent/publish.js +3 -2
- package/dist/commands/agent/revalidate.js +4 -3
- 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/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/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/trigger/create.js +35 -19
- package/dist/commands/workspace/select.js +28 -33
- package/dist/index.js +22 -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 +52 -78
- package/dist/lib/auth.js +7 -4
- package/dist/lib/output.d.ts +3 -16
- package/dist/lib/output.js +43 -109
- package/dist/lib/stdin.d.ts +4 -0
- package/dist/lib/stdin.js +6 -0
- package/dist/mcp/tools.js +1 -1
- package/docs/CLI_WORKFLOW.md +4 -2
- package/docs/skills/agent-dev.md +61 -34
- package/package.json +4 -3
- 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
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { LocalConfig } from './guild-config.js';
|
|
2
|
+
import { GuildAPIClient } from './api-client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve an agent identifier to a fully-qualified form.
|
|
5
|
+
*
|
|
6
|
+
* If the identifier already contains `/` or is a UUID, return it verbatim.
|
|
7
|
+
* Otherwise, resolve the default owner and prepend `owner.name/`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveAgentRef(client: GuildAPIClient, identifier: string): Promise<string>;
|
|
2
10
|
/**
|
|
3
11
|
* Get agent ID from argument or guild.json in current directory
|
|
4
12
|
* @param agentIdArg - Optional agent ID from command argument
|
|
@@ -4,6 +4,21 @@ import * as fs from 'fs/promises';
|
|
|
4
4
|
import * as path from 'path';
|
|
5
5
|
import { loadLocalConfig } from './guild-config.js';
|
|
6
6
|
import { runGit } from './git.js';
|
|
7
|
+
import { resolveOwnerId } from './owner-helpers.js';
|
|
8
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve an agent identifier to a fully-qualified form.
|
|
11
|
+
*
|
|
12
|
+
* If the identifier already contains `/` or is a UUID, return it verbatim.
|
|
13
|
+
* Otherwise, resolve the default owner and prepend `owner.name/`.
|
|
14
|
+
*/
|
|
15
|
+
export async function resolveAgentRef(client, identifier) {
|
|
16
|
+
if (identifier.includes('/') || UUID_RE.test(identifier)) {
|
|
17
|
+
return identifier;
|
|
18
|
+
}
|
|
19
|
+
const owner = await resolveOwnerId({ client, interactive: false });
|
|
20
|
+
return `${owner.name}/${identifier}`;
|
|
21
|
+
}
|
|
7
22
|
/**
|
|
8
23
|
* Get agent ID from argument or guild.json in current directory
|
|
9
24
|
* @param agentIdArg - Optional agent ID from command argument
|
package/dist/lib/api-types.d.ts
CHANGED
|
@@ -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
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
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
|
-
*
|
|
373
|
+
* Session entity from API responses.
|
|
374
|
+
* Used by: session list
|
|
348
375
|
*/
|
|
349
|
-
export interface
|
|
376
|
+
export interface Session {
|
|
350
377
|
id: string;
|
|
351
|
-
|
|
378
|
+
session_type: 'chat' | 'agent_test' | 'time' | 'webhook';
|
|
352
379
|
name?: string;
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
package/dist/lib/output.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Spinner } from './progress.js';
|
|
2
|
-
import type { Agent, AgentVersion,
|
|
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
|
-
|
|
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.
|
package/dist/lib/output.js
CHANGED
|
@@ -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
|
-
|
|
318
|
-
|
|
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: '
|
|
329
|
-
{ name: '
|
|
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
|
-
|
|
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:
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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,
|
|
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}
|
|
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}
|
|
345
|
+
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} credentials`));
|
|
359
346
|
}
|
|
360
347
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
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: '
|
|
374
|
-
{ name: '
|
|
375
|
-
{ name: '
|
|
376
|
-
{ name: '
|
|
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
|
-
|
|
431
|
-
const
|
|
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:
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
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,
|
|
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}
|
|
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}
|
|
394
|
+
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} policies`));
|
|
461
395
|
}
|
|
462
396
|
}
|
|
463
397
|
/**
|
package/dist/lib/stdin.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if stdin is connected to an interactive terminal (TTY).
|
|
3
|
+
*/
|
|
4
|
+
export declare function isInteractive(): boolean;
|
|
1
5
|
/**
|
|
2
6
|
* Exit with a helpful error when stdin is piped but no --mode flag was given.
|
|
3
7
|
* Call this before rendering an interactive UI (Ink render()) so users who
|
package/dist/lib/stdin.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// Copyright 2026 Guild.ai
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Check if stdin is connected to an interactive terminal (TTY).
|
|
5
|
+
*/
|
|
6
|
+
export function isInteractive() {
|
|
7
|
+
return process.stdin.isTTY === true;
|
|
8
|
+
}
|
|
3
9
|
/**
|
|
4
10
|
* Exit with a helpful error when stdin is piped but no --mode flag was given.
|
|
5
11
|
* Call this before rendering an interactive UI (Ink render()) so users who
|
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.
|
|
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
|
})
|
package/docs/CLI_WORKFLOW.md
CHANGED
|
@@ -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
|