@guildai/cli 0.6.0 → 0.6.2
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/README.md +17 -0
- package/dist/commands/agent/chat.js +31 -31
- package/dist/commands/agent/fork.js +1 -1
- package/dist/commands/agent/init.js +1 -1
- package/dist/commands/agent/publish.js +13 -53
- package/dist/commands/agent/pull.js +36 -21
- package/dist/commands/agent/save.js +16 -52
- package/dist/commands/agent/test.js +8 -12
- package/dist/commands/auth/login.js +3 -3
- package/dist/commands/chat.js +68 -106
- package/dist/commands/credentials/endpoint-list.js +1 -1
- package/dist/commands/integration/connect.d.ts +3 -0
- package/dist/commands/integration/connect.js +76 -0
- package/dist/commands/integration/create.d.ts +3 -0
- package/dist/commands/integration/create.js +298 -0
- package/dist/commands/integration/get.d.ts +3 -0
- package/dist/commands/integration/get.js +95 -0
- package/dist/commands/integration/list.d.ts +3 -0
- package/dist/commands/integration/list.js +61 -0
- package/dist/commands/integration/operation/create.d.ts +3 -0
- package/dist/commands/integration/operation/create.js +163 -0
- package/dist/commands/integration/operation/list.d.ts +3 -0
- package/dist/commands/integration/operation/list.js +83 -0
- package/dist/commands/integration/update.d.ts +3 -0
- package/dist/commands/integration/update.js +139 -0
- package/dist/commands/integration/version/build.d.ts +3 -0
- package/dist/commands/integration/version/build.js +86 -0
- package/dist/commands/integration/version/create.d.ts +3 -0
- package/dist/commands/integration/version/create.js +45 -0
- package/dist/commands/integration/version/get.d.ts +3 -0
- package/dist/commands/integration/version/get.js +72 -0
- package/dist/commands/integration/version/list.d.ts +3 -0
- package/dist/commands/integration/version/list.js +44 -0
- package/dist/commands/integration/version/publish.d.ts +3 -0
- package/dist/commands/integration/version/publish.js +79 -0
- package/dist/commands/integration/version/test.d.ts +3 -0
- package/dist/commands/integration/version/test.js +104 -0
- package/dist/commands/workspace/create.js +10 -4
- package/dist/index.js +38 -0
- package/dist/lib/api-types.d.ts +69 -12
- package/dist/lib/auth.d.ts +1 -1
- package/dist/lib/auth.js +3 -2
- package/dist/lib/integration-helpers.d.ts +15 -0
- package/dist/lib/integration-helpers.js +38 -0
- package/dist/lib/output.d.ts +11 -1
- package/dist/lib/output.js +94 -0
- package/dist/lib/session-events-fetch.d.ts +27 -0
- package/dist/lib/session-events-fetch.js +25 -0
- package/dist/lib/session-polling.d.ts +7 -2
- package/dist/lib/session-polling.js +19 -12
- package/dist/lib/session-resume.js +2 -5
- package/dist/lib/table.d.ts +0 -1
- package/dist/lib/table.js +0 -1
- package/dist/lib/version-helpers.d.ts +15 -0
- package/dist/lib/version-helpers.js +83 -0
- package/dist/mcp/tools.js +6 -12
- package/docs/CLI_WORKFLOW.md +15 -0
- package/docs/skills/agent-dev.md +15 -0
- package/package.json +4 -3
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { GuildAPIClient } from '../../../lib/api-client.js';
|
|
6
|
+
import { getAuthToken } from '../../../lib/auth.js';
|
|
7
|
+
import { handleAxiosError } from '../../../lib/errors.js';
|
|
8
|
+
import { getOutputMode } from '../../../lib/output-mode.js';
|
|
9
|
+
import { createOutputWriter } from '../../../lib/output.js';
|
|
10
|
+
import { resolveVersionId } from '../../../lib/integration-helpers.js';
|
|
11
|
+
function parseJsonFlag(value, flagName) {
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(value);
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
17
|
+
throw new Error(`Invalid JSON for ${flagName}: ${msg}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function createIntegrationVersionTestCommand() {
|
|
21
|
+
const cmd = new Command('test');
|
|
22
|
+
cmd
|
|
23
|
+
.description('Test an endpoint invocation')
|
|
24
|
+
.argument('<id_or_name>', 'Integration ID or name (owner~name)')
|
|
25
|
+
.option('--version <semver>', 'Specific version, e.g. 1.0.0')
|
|
26
|
+
.requiredOption('--operation <name>', 'Operation to test, e.g. list_users')
|
|
27
|
+
.option('--account <name>', 'Account name to resolve credential from')
|
|
28
|
+
.option('--input-path <json>', 'JSON object of path parameters')
|
|
29
|
+
.option('--input-query <json>', 'JSON object of query parameters')
|
|
30
|
+
.option('--input-body <json>', 'JSON object for request body')
|
|
31
|
+
.action(async (identifier, options) => {
|
|
32
|
+
const output = createOutputWriter();
|
|
33
|
+
try {
|
|
34
|
+
const token = await getAuthToken();
|
|
35
|
+
if (!token) {
|
|
36
|
+
output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
// Validate JSON inputs before any API calls
|
|
40
|
+
const body = {
|
|
41
|
+
operation: options.operation,
|
|
42
|
+
};
|
|
43
|
+
if (options.inputPath) {
|
|
44
|
+
body.input_path = parseJsonFlag(options.inputPath, '--input-path');
|
|
45
|
+
}
|
|
46
|
+
if (options.inputQuery) {
|
|
47
|
+
body.input_query = parseJsonFlag(options.inputQuery, '--input-query');
|
|
48
|
+
}
|
|
49
|
+
if (options.inputBody) {
|
|
50
|
+
body.input_body = parseJsonFlag(options.inputBody, '--input-body');
|
|
51
|
+
}
|
|
52
|
+
const client = new GuildAPIClient();
|
|
53
|
+
const versionId = await resolveVersionId(client, identifier, options.version);
|
|
54
|
+
if (options.account) {
|
|
55
|
+
const creds = await client.get(`/accounts/${options.account}/credentials?integration=${encodeURIComponent(identifier)}`);
|
|
56
|
+
if (creds.items.length === 0) {
|
|
57
|
+
output.error(`Error: No credentials found for account '${options.account}' on integration '${identifier}'`);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
body.credential_id = creds.items[0].id;
|
|
61
|
+
}
|
|
62
|
+
const response = await client.post(`/integration_versions/${versionId}/test`, body);
|
|
63
|
+
if (getOutputMode() === 'json') {
|
|
64
|
+
output.data(response);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
console.log(`Testing operation: ${options.operation}`);
|
|
68
|
+
console.log();
|
|
69
|
+
console.log(chalk.bold('Request'));
|
|
70
|
+
console.log(` ${'URL'.padEnd(9)}${response.request_url}`);
|
|
71
|
+
console.log();
|
|
72
|
+
console.log(chalk.bold('Response'));
|
|
73
|
+
console.log(` ${'Status'.padEnd(9)}${response.status_code}`);
|
|
74
|
+
console.log(` ${'Type'.padEnd(9)}${response.content_type || chalk.dim('—')}`);
|
|
75
|
+
console.log();
|
|
76
|
+
console.log(chalk.bold('Body'));
|
|
77
|
+
if (response.body !== null && response.body !== undefined) {
|
|
78
|
+
const bodyStr = typeof response.body === 'string'
|
|
79
|
+
? response.body
|
|
80
|
+
: JSON.stringify(response.body, null, 2);
|
|
81
|
+
const indented = bodyStr
|
|
82
|
+
.split('\n')
|
|
83
|
+
.map((line) => ` ${line}`)
|
|
84
|
+
.join('\n');
|
|
85
|
+
console.log(indented);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.log(chalk.dim(' (empty)'));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
if (error instanceof Error && error.message.startsWith('Invalid JSON')) {
|
|
94
|
+
output.error(`Error: ${error.message}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
const formattedError = handleAxiosError(error);
|
|
98
|
+
output.error(`Failed to test endpoint: ${formattedError.details}`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return cmd;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=test.js.map
|
|
@@ -4,21 +4,27 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
5
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
6
6
|
import { createOutputWriter } from '../../lib/output.js';
|
|
7
|
+
import { resolveOwnerId } from '../../lib/owner-helpers.js';
|
|
8
|
+
import { isInteractive } from '../../lib/stdin.js';
|
|
7
9
|
export function createWorkspaceCreateCommand() {
|
|
8
10
|
const cmd = new Command('create');
|
|
9
11
|
cmd
|
|
10
12
|
.description('Create a new workspace')
|
|
11
13
|
.argument('<name>', 'Workspace name')
|
|
12
|
-
.
|
|
14
|
+
.option('--owner <owner>', 'Owner (name or ID)')
|
|
15
|
+
.action(async (name, options) => {
|
|
13
16
|
const output = createOutputWriter();
|
|
14
17
|
try {
|
|
15
18
|
const client = new GuildAPIClient();
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
const owner = await resolveOwnerId({
|
|
20
|
+
ownerFlag: options.owner,
|
|
21
|
+
client,
|
|
22
|
+
interactive: isInteractive(),
|
|
23
|
+
});
|
|
18
24
|
// Create workspace
|
|
19
25
|
const workspace = await client.post('/workspaces', {
|
|
20
26
|
name,
|
|
21
|
-
owner_id:
|
|
27
|
+
owner_id: owner.id,
|
|
22
28
|
});
|
|
23
29
|
output.data(workspace);
|
|
24
30
|
}
|
package/dist/index.js
CHANGED
|
@@ -74,6 +74,19 @@ import { createCredentialsPolicyUpdateCommand } from './commands/credentials/pol
|
|
|
74
74
|
import { createDoctorCommand } from './commands/doctor.js';
|
|
75
75
|
import { createSetupCommand } from './commands/setup.js';
|
|
76
76
|
import { createMcpCommand } from './commands/mcp.js';
|
|
77
|
+
import { createIntegrationListCommand } from './commands/integration/list.js';
|
|
78
|
+
import { createIntegrationGetCommand } from './commands/integration/get.js';
|
|
79
|
+
import { createIntegrationCreateCommand } from './commands/integration/create.js';
|
|
80
|
+
import { createIntegrationUpdateCommand } from './commands/integration/update.js';
|
|
81
|
+
import { createIntegrationConnectCommand } from './commands/integration/connect.js';
|
|
82
|
+
import { createIntegrationVersionListCommand } from './commands/integration/version/list.js';
|
|
83
|
+
import { createIntegrationVersionCreateCommand } from './commands/integration/version/create.js';
|
|
84
|
+
import { createIntegrationVersionGetCommand } from './commands/integration/version/get.js';
|
|
85
|
+
import { createIntegrationVersionBuildCommand } from './commands/integration/version/build.js';
|
|
86
|
+
import { createIntegrationVersionPublishCommand } from './commands/integration/version/publish.js';
|
|
87
|
+
import { createIntegrationVersionTestCommand } from './commands/integration/version/test.js';
|
|
88
|
+
import { createIntegrationOperationListCommand } from './commands/integration/operation/list.js';
|
|
89
|
+
import { createIntegrationOperationCreateCommand } from './commands/integration/operation/create.js';
|
|
77
90
|
import { showSplashScreen, shouldShowSplash } from './lib/splash.js';
|
|
78
91
|
import { checkForUpdate } from './lib/update-check.js';
|
|
79
92
|
import { setupUnknownCommandSuggestions } from './lib/did-you-mean.js';
|
|
@@ -153,6 +166,31 @@ tagsCmd.addCommand(createAgentTagsListCommand());
|
|
|
153
166
|
tagsCmd.addCommand(createAgentTagsAddCommand());
|
|
154
167
|
tagsCmd.addCommand(createAgentTagsRemoveCommand());
|
|
155
168
|
tagsCmd.addCommand(createAgentTagsSetCommand());
|
|
169
|
+
// Integration command group
|
|
170
|
+
const integrationCmd = program
|
|
171
|
+
.command('integration')
|
|
172
|
+
.description('Manage integrations');
|
|
173
|
+
integrationCmd.addCommand(createIntegrationListCommand());
|
|
174
|
+
integrationCmd.addCommand(createIntegrationGetCommand());
|
|
175
|
+
integrationCmd.addCommand(createIntegrationCreateCommand());
|
|
176
|
+
integrationCmd.addCommand(createIntegrationUpdateCommand());
|
|
177
|
+
integrationCmd.addCommand(createIntegrationConnectCommand());
|
|
178
|
+
// Integration version subcommand group
|
|
179
|
+
const integrationVersionCmd = integrationCmd
|
|
180
|
+
.command('version')
|
|
181
|
+
.description('Manage integration versions');
|
|
182
|
+
integrationVersionCmd.addCommand(createIntegrationVersionListCommand());
|
|
183
|
+
integrationVersionCmd.addCommand(createIntegrationVersionCreateCommand());
|
|
184
|
+
integrationVersionCmd.addCommand(createIntegrationVersionGetCommand());
|
|
185
|
+
integrationVersionCmd.addCommand(createIntegrationVersionBuildCommand());
|
|
186
|
+
integrationVersionCmd.addCommand(createIntegrationVersionPublishCommand());
|
|
187
|
+
integrationVersionCmd.addCommand(createIntegrationVersionTestCommand());
|
|
188
|
+
// Integration operation subcommand group
|
|
189
|
+
const integrationOperationCmd = integrationCmd
|
|
190
|
+
.command('operation')
|
|
191
|
+
.description('Manage version operations');
|
|
192
|
+
integrationOperationCmd.addCommand(createIntegrationOperationListCommand());
|
|
193
|
+
integrationOperationCmd.addCommand(createIntegrationOperationCreateCommand());
|
|
156
194
|
// Workspace command group
|
|
157
195
|
const workspaceCmd = program.command('workspace').description('Workspace management');
|
|
158
196
|
workspaceCmd.addCommand(createWorkspaceListCommand());
|
package/dist/lib/api-types.d.ts
CHANGED
|
@@ -204,25 +204,17 @@ 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 {
|
|
207
|
+
export interface TriggerIntegrationWebhookConfig {
|
|
212
208
|
id: string;
|
|
213
209
|
enabled: boolean;
|
|
214
210
|
events: Record<string, string[]>;
|
|
215
211
|
}
|
|
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 {
|
|
212
|
+
export interface TriggerIntegration {
|
|
221
213
|
id: string;
|
|
222
214
|
name: string;
|
|
223
215
|
full_name: string;
|
|
224
216
|
service?: string | null;
|
|
225
|
-
webhook_config:
|
|
217
|
+
webhook_config: TriggerIntegrationWebhookConfig | null;
|
|
226
218
|
}
|
|
227
219
|
export type TriggerType = 'webhook' | 'time';
|
|
228
220
|
import { WEBHOOK_SERVICES, type WebhookService, TIME_TRIGGER_FREQUENCIES, type TimeTriggerFrequency } from './generated-types.js';
|
|
@@ -267,7 +259,7 @@ export interface TriggerWebhook {
|
|
|
267
259
|
project?: string;
|
|
268
260
|
jql_filter?: string;
|
|
269
261
|
} | Record<string, unknown>;
|
|
270
|
-
integration:
|
|
262
|
+
integration: TriggerIntegration;
|
|
271
263
|
created_at: string;
|
|
272
264
|
deactivated_at: string | null;
|
|
273
265
|
disabled_reason: TriggerDisabledReason | null;
|
|
@@ -424,6 +416,71 @@ export interface JobStepsResponse {
|
|
|
424
416
|
job_id: string;
|
|
425
417
|
steps: JobStep[];
|
|
426
418
|
}
|
|
419
|
+
export interface IntegrationOwner {
|
|
420
|
+
id: string;
|
|
421
|
+
name: string;
|
|
422
|
+
}
|
|
423
|
+
export interface IntegrationAuthConfig {
|
|
424
|
+
id: string;
|
|
425
|
+
entity_type: string;
|
|
426
|
+
auth_scheme: 'API_KEY' | 'OAUTH';
|
|
427
|
+
token_header_template?: string;
|
|
428
|
+
install_url?: string;
|
|
429
|
+
token_url?: string;
|
|
430
|
+
client_id?: string;
|
|
431
|
+
scopes?: string[];
|
|
432
|
+
}
|
|
433
|
+
export interface IntegrationProtocolConfig {
|
|
434
|
+
protocol: 'REST';
|
|
435
|
+
base_url: string;
|
|
436
|
+
}
|
|
437
|
+
export interface IntegrationWebhookConfig {
|
|
438
|
+
enabled: boolean;
|
|
439
|
+
events?: string[];
|
|
440
|
+
}
|
|
441
|
+
export interface IntegrationPublishedVersion {
|
|
442
|
+
id: string;
|
|
443
|
+
version_number: string;
|
|
444
|
+
published_at: string;
|
|
445
|
+
}
|
|
446
|
+
export interface Integration {
|
|
447
|
+
id: string;
|
|
448
|
+
entity_type: string;
|
|
449
|
+
created_at: string;
|
|
450
|
+
updated_at: string;
|
|
451
|
+
name: string;
|
|
452
|
+
description: string | null;
|
|
453
|
+
is_public: boolean;
|
|
454
|
+
avatar_url: string | null;
|
|
455
|
+
owner: IntegrationOwner;
|
|
456
|
+
auth_config: IntegrationAuthConfig;
|
|
457
|
+
protocol_config: IntegrationProtocolConfig;
|
|
458
|
+
webhook_config: IntegrationWebhookConfig | null;
|
|
459
|
+
params: unknown[];
|
|
460
|
+
viewer_can_edit: boolean;
|
|
461
|
+
latest_published_version?: IntegrationPublishedVersion | null;
|
|
462
|
+
}
|
|
463
|
+
export type IntegrationListResponse = PaginatedResponse<Integration>;
|
|
464
|
+
export interface IntegrationVersion {
|
|
465
|
+
id: string;
|
|
466
|
+
entity_type: string;
|
|
467
|
+
created_at: string;
|
|
468
|
+
updated_at: string;
|
|
469
|
+
author: {
|
|
470
|
+
id: string;
|
|
471
|
+
name: string;
|
|
472
|
+
};
|
|
473
|
+
validation_status: string;
|
|
474
|
+
published_at: string | null;
|
|
475
|
+
publishing_started_at: string | null;
|
|
476
|
+
version_number: string | null;
|
|
477
|
+
integration?: {
|
|
478
|
+
id: string;
|
|
479
|
+
name: string;
|
|
480
|
+
description: string;
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
export type IntegrationVersionListResponse = PaginatedResponse<IntegrationVersion>;
|
|
427
484
|
/**
|
|
428
485
|
* Contents of guild.json file in agent directories.
|
|
429
486
|
*/
|
package/dist/lib/auth.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ export declare function showBetaGuidance(): void;
|
|
|
50
50
|
* @param returnLabel - Optional friendly label for return button (e.g., "VSCode")
|
|
51
51
|
* @returns true if successful, false otherwise
|
|
52
52
|
*/
|
|
53
|
-
export declare function login(returnUrl?: string, returnLabel?: string,
|
|
53
|
+
export declare function login(returnUrl?: string, returnLabel?: string, nonInteractive?: boolean): Promise<boolean>;
|
|
54
54
|
/**
|
|
55
55
|
* Perform logout
|
|
56
56
|
*/
|
package/dist/lib/auth.js
CHANGED
|
@@ -10,6 +10,7 @@ import { createSpinner } from './progress.js';
|
|
|
10
10
|
import { getGuildcoreUrl } from './config.js';
|
|
11
11
|
import { getIapHeaders } from './iap.js';
|
|
12
12
|
import { brand, warn } from './colors.js';
|
|
13
|
+
import { isInteractive } from './stdin.js';
|
|
13
14
|
const SERVICE_NAME = 'guild-cli';
|
|
14
15
|
/**
|
|
15
16
|
* Get account name for keyring, keyed by host to support multiple backends
|
|
@@ -199,12 +200,12 @@ export function showBetaGuidance() {
|
|
|
199
200
|
* @param returnLabel - Optional friendly label for return button (e.g., "VSCode")
|
|
200
201
|
* @returns true if successful, false otherwise
|
|
201
202
|
*/
|
|
202
|
-
export async function login(returnUrl, returnLabel,
|
|
203
|
+
export async function login(returnUrl, returnLabel, nonInteractive) {
|
|
203
204
|
const authUrl = getGuildcoreUrl();
|
|
204
205
|
try {
|
|
205
206
|
console.log(chalk.bold('\nGuild.ai Authentication'));
|
|
206
207
|
const deviceCode = await startDeviceFlow(authUrl, returnUrl, returnLabel);
|
|
207
|
-
const skipBrowser =
|
|
208
|
+
const skipBrowser = nonInteractive || !isInteractive();
|
|
208
209
|
if (skipBrowser) {
|
|
209
210
|
console.log(`\nVerification code: ${deviceCode.user_code}`);
|
|
210
211
|
console.log(`Open to authenticate: ${deviceCode.verification_uri_complete}\n`);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { GuildAPIClient } from './api-client.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve a version ID from an integration identifier and optional semver.
|
|
4
|
+
*
|
|
5
|
+
* 1. GET /integrations/<identifier> to resolve the integration
|
|
6
|
+
* 2. GET /integrations/<id>/versions to list versions
|
|
7
|
+
* 3. If semver provided, find matching version_number; otherwise use latest (first)
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveVersionId(client: GuildAPIClient, identifier: string, versionNumber?: string): Promise<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the latest draft version ID for an integration.
|
|
12
|
+
* Used by the build command where --version is not applicable (drafts have no semver).
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveLatestDraftId(client: GuildAPIClient, identifier: string): Promise<string>;
|
|
15
|
+
//# sourceMappingURL=integration-helpers.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a version ID from an integration identifier and optional semver.
|
|
5
|
+
*
|
|
6
|
+
* 1. GET /integrations/<identifier> to resolve the integration
|
|
7
|
+
* 2. GET /integrations/<id>/versions to list versions
|
|
8
|
+
* 3. If semver provided, find matching version_number; otherwise use latest (first)
|
|
9
|
+
*/
|
|
10
|
+
export async function resolveVersionId(client, identifier, versionNumber) {
|
|
11
|
+
const integration = await client.get(`/integrations/${identifier}`);
|
|
12
|
+
const versions = await client.get(`/integrations/${integration.id}/versions?limit=100`);
|
|
13
|
+
if (versions.items.length === 0) {
|
|
14
|
+
throw new Error('No versions found for this integration');
|
|
15
|
+
}
|
|
16
|
+
if (versionNumber) {
|
|
17
|
+
const match = versions.items.find((v) => v.version_number === versionNumber);
|
|
18
|
+
if (!match) {
|
|
19
|
+
throw new Error(`Version ${versionNumber} not found`);
|
|
20
|
+
}
|
|
21
|
+
return match.id;
|
|
22
|
+
}
|
|
23
|
+
return versions.items[0].id;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolve the latest draft version ID for an integration.
|
|
27
|
+
* Used by the build command where --version is not applicable (drafts have no semver).
|
|
28
|
+
*/
|
|
29
|
+
export async function resolveLatestDraftId(client, identifier) {
|
|
30
|
+
const integration = await client.get(`/integrations/${identifier}`);
|
|
31
|
+
const versions = await client.get(`/integrations/${integration.id}/versions?limit=100`);
|
|
32
|
+
const draft = versions.items.find((v) => v.version_number === null);
|
|
33
|
+
if (!draft) {
|
|
34
|
+
throw new Error('No draft version found for this integration');
|
|
35
|
+
}
|
|
36
|
+
return draft.id;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=integration-helpers.js.map
|
package/dist/lib/output.d.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { type Spinner } from './progress.js';
|
|
2
|
-
import type { Agent, AgentVersion, Credentials, CredentialsPolicy, Context, JobStep, Pagination, Session, Workspace, WorkspaceAgent, Trigger } from './api-types.js';
|
|
2
|
+
import type { Agent, AgentVersion, Credentials, CredentialsPolicy, Context, Integration, IntegrationVersion, 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.
|
|
6
6
|
*/
|
|
7
7
|
export declare function formatAgentTable(agents: Agent[], pagination: Pagination): void;
|
|
8
|
+
/**
|
|
9
|
+
* Format an integration list as a human-readable table.
|
|
10
|
+
* Used by integration list command.
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatIntegrationTable(integrations: Integration[], pagination: Pagination): void;
|
|
13
|
+
/**
|
|
14
|
+
* Format an integration version list as a human-readable table.
|
|
15
|
+
* Used by integration version list command.
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatIntegrationVersionTable(versions: IntegrationVersion[], pagination: Pagination, integrationName: string): void;
|
|
8
18
|
/**
|
|
9
19
|
* Format an agent version list as a human-readable table.
|
|
10
20
|
* Used by agent versions command.
|
package/dist/lib/output.js
CHANGED
|
@@ -81,6 +81,100 @@ export function formatAgentTable(agents, pagination) {
|
|
|
81
81
|
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} agents`));
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Format an integration list as a human-readable table.
|
|
86
|
+
* Used by integration list command.
|
|
87
|
+
*/
|
|
88
|
+
export function formatIntegrationTable(integrations, pagination) {
|
|
89
|
+
if (integrations.length === 0) {
|
|
90
|
+
console.log(chalk.dim('No integrations found'));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const table = new Table({
|
|
94
|
+
columns: [
|
|
95
|
+
{ name: 'name', title: 'NAME', alignment: 'left' },
|
|
96
|
+
{ name: 'description', title: 'DESCRIPTION', alignment: 'left' },
|
|
97
|
+
{ name: 'visibility', title: 'VISIBILITY', alignment: 'left' },
|
|
98
|
+
{ name: 'owner', title: 'OWNER', alignment: 'left', color: 'cyan' },
|
|
99
|
+
{ name: 'updated', title: 'UPDATED', alignment: 'left' },
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
integrations.forEach((integration) => {
|
|
103
|
+
table.addRow({
|
|
104
|
+
name: integration.name,
|
|
105
|
+
description: truncate(integration.description || '', 40),
|
|
106
|
+
visibility: integration.is_public ? 'public' : 'internal',
|
|
107
|
+
owner: integration.owner?.name || '',
|
|
108
|
+
updated: integration.updated_at ? formatRelativeTime(integration.updated_at) : '',
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
table.printTable();
|
|
112
|
+
const showing = Math.min(pagination.limit, integrations.length);
|
|
113
|
+
if (pagination.has_more) {
|
|
114
|
+
const nextOffset = pagination.offset + pagination.limit;
|
|
115
|
+
console.log(`\nShowing ${showing} of ${pagination.total_count} integrations. ` +
|
|
116
|
+
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
117
|
+
}
|
|
118
|
+
else if (pagination.total_count > showing) {
|
|
119
|
+
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} integrations`));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Format an integration version list as a human-readable table.
|
|
124
|
+
* Used by integration version list command.
|
|
125
|
+
*/
|
|
126
|
+
export function formatIntegrationVersionTable(versions, pagination, integrationName) {
|
|
127
|
+
if (versions.length === 0) {
|
|
128
|
+
console.log(chalk.dim('No versions found'));
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
console.log(chalk.bold(`Versions for ${integrationName}`));
|
|
132
|
+
console.log();
|
|
133
|
+
const table = new Table({
|
|
134
|
+
columns: [
|
|
135
|
+
{ name: 'id', title: 'ID', alignment: 'left' },
|
|
136
|
+
{ name: 'version', title: 'VERSION', alignment: 'left' },
|
|
137
|
+
{ name: 'author', title: 'AUTHOR', alignment: 'left', color: 'cyan' },
|
|
138
|
+
{ name: 'status', title: 'STATUS', alignment: 'left' },
|
|
139
|
+
{ name: 'published', title: 'PUBLISHED', alignment: 'left' },
|
|
140
|
+
{ name: 'created', title: 'CREATED', alignment: 'left' },
|
|
141
|
+
],
|
|
142
|
+
});
|
|
143
|
+
versions.forEach((v) => {
|
|
144
|
+
let statusLabel;
|
|
145
|
+
switch (v.validation_status) {
|
|
146
|
+
case 'PASSED':
|
|
147
|
+
statusLabel = chalk.green('Valid');
|
|
148
|
+
break;
|
|
149
|
+
case 'FAILED':
|
|
150
|
+
statusLabel = chalk.red('Failed');
|
|
151
|
+
break;
|
|
152
|
+
case 'RUNNING':
|
|
153
|
+
statusLabel = chalk.yellow('Building');
|
|
154
|
+
break;
|
|
155
|
+
default:
|
|
156
|
+
statusLabel = chalk.dim('—');
|
|
157
|
+
}
|
|
158
|
+
table.addRow({
|
|
159
|
+
id: v.id,
|
|
160
|
+
version: v.version_number || 'Draft',
|
|
161
|
+
author: v.author?.name || '',
|
|
162
|
+
status: statusLabel,
|
|
163
|
+
published: v.published_at ? formatRelativeTime(v.published_at) : chalk.dim('—'),
|
|
164
|
+
created: v.created_at ? formatRelativeTime(v.created_at) : '',
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
table.printTable();
|
|
168
|
+
const showing = Math.min(pagination.limit, versions.length);
|
|
169
|
+
if (pagination.has_more) {
|
|
170
|
+
const nextOffset = pagination.offset + pagination.limit;
|
|
171
|
+
console.log(`\nShowing ${showing} of ${pagination.total_count} versions. ` +
|
|
172
|
+
chalk.dim(`Use --offset ${nextOffset} to see more.`));
|
|
173
|
+
}
|
|
174
|
+
else if (pagination.total_count > showing) {
|
|
175
|
+
console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} versions`));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
84
178
|
/**
|
|
85
179
|
* Format an agent version list as a human-readable table.
|
|
86
180
|
* Used by agent versions command.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared event/task fetching for session polling.
|
|
3
|
+
*
|
|
4
|
+
* Consolidates the duplicate response parsing that was scattered across
|
|
5
|
+
* chat.tsx, session-polling.ts, and session-resume.ts.
|
|
6
|
+
*/
|
|
7
|
+
import { GuildAPIClient } from './api-client.js';
|
|
8
|
+
import { SessionEvent, SessionTask } from './session-events.js';
|
|
9
|
+
interface FetchOptions {
|
|
10
|
+
/** Only return events after this event ID (server-side cursor). */
|
|
11
|
+
fromId?: string;
|
|
12
|
+
/** Maximum number of events to return. Default 1000. */
|
|
13
|
+
limit?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Fetch session events from the API.
|
|
17
|
+
*
|
|
18
|
+
* Uses from_id cursor so callers only fetch new events
|
|
19
|
+
* instead of re-fetching everything on every poll cycle.
|
|
20
|
+
*/
|
|
21
|
+
export declare function fetchEvents(client: GuildAPIClient, sessionId: string, options?: FetchOptions): Promise<SessionEvent[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Fetch session tasks from the API.
|
|
24
|
+
*/
|
|
25
|
+
export declare function fetchTasks(client: GuildAPIClient, sessionId: string): Promise<SessionTask[]>;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=session-events-fetch.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Fetch session events from the API.
|
|
5
|
+
*
|
|
6
|
+
* Uses from_id cursor so callers only fetch new events
|
|
7
|
+
* instead of re-fetching everything on every poll cycle.
|
|
8
|
+
*/
|
|
9
|
+
export async function fetchEvents(client, sessionId, options = {}) {
|
|
10
|
+
const { fromId, limit = 1000 } = options;
|
|
11
|
+
let url = `/sessions/${sessionId}/events?limit=${limit}`;
|
|
12
|
+
if (fromId) {
|
|
13
|
+
url += `&from_id=${fromId}`;
|
|
14
|
+
}
|
|
15
|
+
const response = await client.get(url);
|
|
16
|
+
return response?.items || [];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Fetch session tasks from the API.
|
|
20
|
+
*/
|
|
21
|
+
export async function fetchTasks(client, sessionId) {
|
|
22
|
+
const response = await client.get(`/sessions/${sessionId}/tasks?limit=1000`);
|
|
23
|
+
return response?.items || [];
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=session-events-fetch.js.map
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { GuildAPIClient } from './api-client.js';
|
|
2
|
+
export interface PollResult {
|
|
3
|
+
response: string | null;
|
|
4
|
+
/** Last event ID seen — pass as `afterEventId` on next call. */
|
|
5
|
+
lastEventId: string | undefined;
|
|
6
|
+
}
|
|
2
7
|
/**
|
|
3
|
-
* Poll for agent response
|
|
8
|
+
* Poll for agent response using from_id cursor.
|
|
4
9
|
*
|
|
5
10
|
* Handles both multi-turn agents (which emit agent_notification_message)
|
|
6
11
|
* and one-shot agents (which may only emit runtime_done with output content).
|
|
@@ -10,5 +15,5 @@ import { GuildAPIClient } from './api-client.js';
|
|
|
10
15
|
* 2. runtime_done from agent tasks — fallback for one-shot agents
|
|
11
16
|
* 3. runtime_error from agent tasks — fail fast
|
|
12
17
|
*/
|
|
13
|
-
export declare function pollForResponse(client: GuildAPIClient, sessionId: string,
|
|
18
|
+
export declare function pollForResponse(client: GuildAPIClient, sessionId: string, afterEventId: string | undefined, maxWaitTime?: number): Promise<PollResult>;
|
|
14
19
|
//# sourceMappingURL=session-polling.d.ts.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Copyright 2026 Guild.ai
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { isDebugMode } from './errors.js';
|
|
3
|
+
import { debug, isDebugMode } from './errors.js';
|
|
4
|
+
import { fetchEvents } from './session-events-fetch.js';
|
|
4
5
|
/**
|
|
5
|
-
* Poll for agent response
|
|
6
|
+
* Poll for agent response using from_id cursor.
|
|
6
7
|
*
|
|
7
8
|
* Handles both multi-turn agents (which emit agent_notification_message)
|
|
8
9
|
* and one-shot agents (which may only emit runtime_done with output content).
|
|
@@ -12,16 +13,16 @@ import { isDebugMode } from './errors.js';
|
|
|
12
13
|
* 2. runtime_done from agent tasks — fallback for one-shot agents
|
|
13
14
|
* 3. runtime_error from agent tasks — fail fast
|
|
14
15
|
*/
|
|
15
|
-
export async function pollForResponse(client, sessionId,
|
|
16
|
+
export async function pollForResponse(client, sessionId, afterEventId, maxWaitTime = 60000) {
|
|
16
17
|
const startTime = Date.now();
|
|
18
|
+
let fromId = afterEventId;
|
|
17
19
|
while (Date.now() - startTime < maxWaitTime) {
|
|
18
|
-
const
|
|
19
|
-
const events = response?.items || [];
|
|
20
|
+
const events = await fetchEvents(client, sessionId, { fromId });
|
|
20
21
|
let lastAgentRuntimeDone = null;
|
|
21
|
-
for (
|
|
22
|
-
|
|
22
|
+
for (const event of events) {
|
|
23
|
+
debug(`pollForResponse event: ${event.type}`);
|
|
23
24
|
if (event.type === 'agent_notification_message') {
|
|
24
|
-
return event.content.data;
|
|
25
|
+
return { response: event.content.data, lastEventId: event.id };
|
|
25
26
|
}
|
|
26
27
|
if (event.type === 'runtime_done' &&
|
|
27
28
|
event.content !== undefined &&
|
|
@@ -30,17 +31,23 @@ export async function pollForResponse(client, sessionId, afterEventCount, maxWai
|
|
|
30
31
|
lastAgentRuntimeDone = JSON.stringify(event.content);
|
|
31
32
|
}
|
|
32
33
|
if (event.type === 'runtime_error' && event.task && 'agent' in event.task) {
|
|
33
|
-
return
|
|
34
|
+
return {
|
|
35
|
+
response: JSON.stringify({ error: event.content }),
|
|
36
|
+
lastEventId: event.id,
|
|
37
|
+
};
|
|
34
38
|
}
|
|
35
39
|
if (event.type === 'agent_console' && isDebugMode()) {
|
|
36
40
|
process.stderr.write(`[console.${event.level}] ${event.content}\n`);
|
|
37
41
|
}
|
|
38
42
|
}
|
|
43
|
+
if (events.length > 0) {
|
|
44
|
+
fromId = events[events.length - 1].id;
|
|
45
|
+
}
|
|
39
46
|
if (lastAgentRuntimeDone !== null) {
|
|
40
|
-
return lastAgentRuntimeDone;
|
|
47
|
+
return { response: lastAgentRuntimeDone, lastEventId: fromId };
|
|
41
48
|
}
|
|
42
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
49
|
+
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
43
50
|
}
|
|
44
|
-
return null;
|
|
51
|
+
return { response: null, lastEventId: fromId };
|
|
45
52
|
}
|
|
46
53
|
//# sourceMappingURL=session-polling.js.map
|