@guildai/cli 0.5.10 → 0.5.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/dist/commands/agent/init.js +24 -3
  2. package/dist/commands/auth/login.js +3 -1
  3. package/dist/commands/container/destroy.d.ts +3 -0
  4. package/dist/commands/container/destroy.js +48 -0
  5. package/dist/commands/container/events.d.ts +3 -0
  6. package/dist/commands/container/events.js +44 -0
  7. package/dist/commands/container/exec.d.ts +3 -0
  8. package/dist/commands/container/exec.js +64 -0
  9. package/dist/commands/container/get.d.ts +3 -0
  10. package/dist/commands/container/get.js +33 -0
  11. package/dist/commands/container/list.d.ts +3 -0
  12. package/dist/commands/container/list.js +48 -0
  13. package/dist/commands/container-image/create.d.ts +3 -0
  14. package/dist/commands/container-image/create.js +41 -0
  15. package/dist/commands/container-image/get.d.ts +3 -0
  16. package/dist/commands/container-image/get.js +33 -0
  17. package/dist/commands/container-image/list.d.ts +3 -0
  18. package/dist/commands/container-image/list.js +44 -0
  19. package/dist/commands/job/get.d.ts +3 -0
  20. package/dist/commands/job/get.js +44 -0
  21. package/dist/commands/job/step-get.d.ts +3 -0
  22. package/dist/commands/job/step-get.js +40 -0
  23. package/dist/commands/trigger/create.js +4 -0
  24. package/dist/commands/trigger/update.js +4 -0
  25. package/dist/index.js +33 -2
  26. package/dist/lib/api-types.d.ts +135 -0
  27. package/dist/lib/auth.d.ts +1 -1
  28. package/dist/lib/auth.js +29 -23
  29. package/dist/lib/config.js +0 -4
  30. package/dist/lib/generated-types.d.ts +2 -2
  31. package/dist/lib/generated-types.js +2 -0
  32. package/dist/lib/gk.d.ts +15 -0
  33. package/dist/lib/gk.js +91 -0
  34. package/dist/lib/output.d.ts +21 -16
  35. package/dist/lib/output.js +184 -1
  36. package/dist/lib/session-events.d.ts +1 -0
  37. package/dist/lib/table.d.ts +22 -0
  38. package/dist/lib/table.js +60 -0
  39. package/docs/CLI_WORKFLOW.md +9 -9
  40. package/docs/skills/agent-dev.md +11 -15
  41. package/package.json +2 -3
  42. package/dist/commands/agent/create.d.ts +0 -3
  43. package/dist/commands/agent/create.js +0 -132
@@ -34,18 +34,30 @@ function slugify(text) {
34
34
  .replace(/[^a-z0-9]+/g, '-')
35
35
  .replace(/^-+|-+$/g, '');
36
36
  }
37
+ const NAME_RULES = 'Lowercase letters, digits, hyphens, and underscores only (1-100 characters)';
38
+ function isValidAgentName(name) {
39
+ return name.length >= 1 && name.length <= 100 && /^[a-z0-9\-_.]+$/.test(name);
40
+ }
37
41
  async function promptForName(defaultName) {
38
42
  const rl = readline.createInterface({
39
43
  input: process.stdin,
40
44
  output: process.stdout,
41
45
  });
42
- return new Promise((resolve) => {
46
+ const ask = () => new Promise((resolve) => {
43
47
  rl.question(`Agent name [${defaultName}]: `, (answer) => {
44
- rl.close();
45
48
  const trimmed = answer.trim();
46
- resolve(trimmed || defaultName);
49
+ const name = trimmed || defaultName;
50
+ if (!isValidAgentName(name)) {
51
+ console.error(`Invalid name "${name}": ${NAME_RULES}`);
52
+ resolve(ask());
53
+ }
54
+ else {
55
+ rl.close();
56
+ resolve(name);
57
+ }
47
58
  });
48
59
  });
60
+ return ask();
49
61
  }
50
62
  async function promptForTemplate() {
51
63
  const { template } = await inquirer.prompt([
@@ -120,6 +132,15 @@ export function createAgentInitCommand() {
120
132
  process.exit(1);
121
133
  }
122
134
  }
135
+ // Validate name (catches --name flag and non-interactive paths)
136
+ if (!isValidAgentName(agentName)) {
137
+ console.error(`Error: Invalid agent name "${agentName}"`);
138
+ console.error('');
139
+ console.error(`Agent names must use ${NAME_RULES}`);
140
+ console.error('');
141
+ console.error('Examples: my-agent, my_agent');
142
+ process.exit(1);
143
+ }
123
144
  // Determine template: use --template option, prompt if interactive, or error
124
145
  let template = options.template;
125
146
  if (!template) {
@@ -11,9 +11,11 @@ export function createAuthLoginCommand() {
11
11
  .description('Login to Guild.ai')
12
12
  .option('--return-url <url>', 'Custom URL to redirect to after authentication')
13
13
  .option('--return-label <text>', 'Friendly label for return button (e.g., "VSCode")')
14
+ .option('--no-browser', 'Skip opening the browser (print URL only)')
14
15
  .action(async (options) => {
15
16
  const output = createOutputWriter();
16
- const success = await login(options.returnUrl, options.returnLabel);
17
+ const noBrowser = options.browser === false;
18
+ const success = await login(options.returnUrl, options.returnLabel, noBrowser);
17
19
  if (success) {
18
20
  try {
19
21
  await configureNpmrc();
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createContainerDestroyCommand(): Command;
3
+ //# sourceMappingURL=destroy.d.ts.map
@@ -0,0 +1,48 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { getOutputMode } from '../../lib/output-mode.js';
8
+ import { createOutputWriter } from '../../lib/output.js';
9
+ export function createContainerDestroyCommand() {
10
+ const cmd = new Command('destroy');
11
+ cmd
12
+ .description('Destroy a running container')
13
+ .argument('<container-id>', 'Container ID')
14
+ .action(async (containerId) => {
15
+ const output = createOutputWriter();
16
+ try {
17
+ const token = await getAuthToken();
18
+ if (!token) {
19
+ output.error('Not authenticated. Run: guild auth login');
20
+ process.exit(1);
21
+ }
22
+ const client = new GuildAPIClient();
23
+ const response = await client.post(`/containers/${containerId}/destroy`, {});
24
+ if (getOutputMode() === 'json') {
25
+ console.log(JSON.stringify(response, null, 2));
26
+ }
27
+ else {
28
+ if (response.status === 'SUCCESS') {
29
+ output.success(`Container ${containerId} destroyed`);
30
+ }
31
+ else if (response.status === 'ERROR') {
32
+ output.error(`Failed to destroy container: ${response.error || 'unknown error'}`);
33
+ process.exit(1);
34
+ }
35
+ else {
36
+ output.progress(`Container destruction ${response.status.toLowerCase()}...`);
37
+ }
38
+ }
39
+ }
40
+ catch (error) {
41
+ const formattedError = handleAxiosError(error);
42
+ output.error(`Failed to destroy container: ${formattedError.details}`);
43
+ process.exit(1);
44
+ }
45
+ });
46
+ return cmd;
47
+ }
48
+ //# sourceMappingURL=destroy.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createContainerEventsCommand(): Command;
3
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1,44 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { getOutputMode } from '../../lib/output-mode.js';
8
+ import { createOutputWriter, formatContainerEventTable } from '../../lib/output.js';
9
+ export function createContainerEventsCommand() {
10
+ const cmd = new Command('events');
11
+ cmd
12
+ .description('List events for a container')
13
+ .argument('<container-id>', 'Container ID')
14
+ .option('--limit <number>', 'Number of results to return', '20')
15
+ .option('--offset <number>', 'Offset for pagination', '0')
16
+ .action(async (containerId, options) => {
17
+ const output = createOutputWriter();
18
+ try {
19
+ const token = await getAuthToken();
20
+ if (!token) {
21
+ output.error('Not authenticated. Run: guild auth login');
22
+ process.exit(1);
23
+ }
24
+ const client = new GuildAPIClient();
25
+ const params = new URLSearchParams();
26
+ params.append('limit', options.limit);
27
+ params.append('offset', options.offset);
28
+ const response = await client.get(`/containers/${containerId}/events?${params.toString()}`);
29
+ if (getOutputMode() === 'json') {
30
+ console.log(JSON.stringify(response, null, 2));
31
+ }
32
+ else {
33
+ formatContainerEventTable(response.items, response.pagination);
34
+ }
35
+ }
36
+ catch (error) {
37
+ const formattedError = handleAxiosError(error);
38
+ output.error(`Failed to list container events: ${formattedError.details}`);
39
+ process.exit(1);
40
+ }
41
+ });
42
+ return cmd;
43
+ }
44
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createContainerExecCommand(): Command;
3
+ //# sourceMappingURL=exec.d.ts.map
@@ -0,0 +1,64 @@
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
+ export function createContainerExecCommand() {
11
+ const cmd = new Command('exec');
12
+ cmd
13
+ .description('Execute a command in a running container')
14
+ .argument('<container-id>', 'Container ID')
15
+ .argument('<command>', 'Command to execute')
16
+ .action(async (containerId, command) => {
17
+ const output = createOutputWriter();
18
+ try {
19
+ const token = await getAuthToken();
20
+ if (!token) {
21
+ output.error('Not authenticated. Run: guild auth login');
22
+ process.exit(1);
23
+ }
24
+ const client = new GuildAPIClient();
25
+ const response = await client.post(`/containers/${containerId}/command`, { command });
26
+ if (getOutputMode() === 'json') {
27
+ console.log(JSON.stringify(response, null, 2));
28
+ }
29
+ else {
30
+ // Display return code
31
+ if (response.return_code !== null) {
32
+ const codeColor = response.return_code === 0 ? chalk.green : chalk.red;
33
+ console.error(chalk.dim('Return code:'), codeColor(String(response.return_code)));
34
+ }
35
+ // Display stdout
36
+ if (response.stdout) {
37
+ console.log(response.stdout);
38
+ }
39
+ // Display stderr
40
+ if (response.stderr) {
41
+ console.error(chalk.red(response.stderr));
42
+ }
43
+ // Display error from event
44
+ if (response.status === 'ERROR' && response.error) {
45
+ console.error(chalk.red(`Error: ${response.error}`));
46
+ }
47
+ }
48
+ // Exit with the command's return code if available
49
+ if (response.return_code !== null && response.return_code !== 0) {
50
+ process.exit(response.return_code);
51
+ }
52
+ if (response.status === 'ERROR') {
53
+ process.exit(1);
54
+ }
55
+ }
56
+ catch (error) {
57
+ const formattedError = handleAxiosError(error);
58
+ output.error(`Failed to execute command: ${formattedError.details}`);
59
+ process.exit(1);
60
+ }
61
+ });
62
+ return cmd;
63
+ }
64
+ //# sourceMappingURL=exec.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createContainerGetCommand(): Command;
3
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1,33 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
8
+ export function createContainerGetCommand() {
9
+ const cmd = new Command('get');
10
+ cmd
11
+ .description('Get container details')
12
+ .argument('<container-id>', 'Container ID')
13
+ .action(async (containerId) => {
14
+ const output = createOutputWriter();
15
+ try {
16
+ const token = await getAuthToken();
17
+ if (!token) {
18
+ output.error('Not authenticated. Run: guild auth login');
19
+ process.exit(1);
20
+ }
21
+ const client = new GuildAPIClient();
22
+ const response = await client.get(`/containers/${containerId}`);
23
+ output.data(response);
24
+ }
25
+ catch (error) {
26
+ const formattedError = handleAxiosError(error);
27
+ output.error(`Failed to get container: ${formattedError.details}`);
28
+ process.exit(1);
29
+ }
30
+ });
31
+ return cmd;
32
+ }
33
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createContainerListCommand(): Command;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1,48 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { getOutputMode } from '../../lib/output-mode.js';
8
+ import { createOutputWriter, formatContainerTable } from '../../lib/output.js';
9
+ export function createContainerListCommand() {
10
+ const cmd = new Command('list');
11
+ cmd
12
+ .description('List containers for an account')
13
+ .requiredOption('--account <id-or-name>', 'Account ID or name')
14
+ .option('--status <status>', 'Filter by status: STARTING, RUNNING, ERRORED, DESTROYED')
15
+ .option('--limit <number>', 'Number of results to return', '20')
16
+ .option('--offset <number>', 'Offset for pagination', '0')
17
+ .action(async (options) => {
18
+ const output = createOutputWriter();
19
+ try {
20
+ const token = await getAuthToken();
21
+ if (!token) {
22
+ output.error('Not authenticated. Run: guild auth login');
23
+ process.exit(1);
24
+ }
25
+ const client = new GuildAPIClient();
26
+ const params = new URLSearchParams();
27
+ params.append('limit', options.limit);
28
+ params.append('offset', options.offset);
29
+ if (options.status) {
30
+ params.append('statuses', options.status.toUpperCase());
31
+ }
32
+ const response = await client.get(`/accounts/${options.account}/containers?${params.toString()}`);
33
+ if (getOutputMode() === 'json') {
34
+ console.log(JSON.stringify(response, null, 2));
35
+ }
36
+ else {
37
+ formatContainerTable(response.items, response.pagination);
38
+ }
39
+ }
40
+ catch (error) {
41
+ const formattedError = handleAxiosError(error);
42
+ output.error(`Failed to list containers: ${formattedError.details}`);
43
+ process.exit(1);
44
+ }
45
+ });
46
+ return cmd;
47
+ }
48
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createContainerImageCreateCommand(): Command;
3
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1,41 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
8
+ export function createContainerImageCreateCommand() {
9
+ const cmd = new Command('create');
10
+ cmd
11
+ .description('Create a container image')
12
+ .requiredOption('--account <id-or-name>', 'Account or organization ID or name')
13
+ .requiredOption('--name <name>', 'Image name (1-100 characters)')
14
+ .requiredOption('--image <image>', 'Container image path (e.g. registry.example.com/org/image)')
15
+ .requiredOption('--tag <tag>', 'Image tag (e.g. latest)')
16
+ .action(async (opts) => {
17
+ const output = createOutputWriter();
18
+ try {
19
+ const token = await getAuthToken();
20
+ if (!token) {
21
+ output.error('Not authenticated. Run: guild auth login');
22
+ process.exit(1);
23
+ }
24
+ const client = new GuildAPIClient();
25
+ const response = await client.post('/container-images', {
26
+ name: opts.name,
27
+ image_name: opts.image,
28
+ tag: opts.tag,
29
+ owner_id_or_name: opts.account,
30
+ });
31
+ output.data(response);
32
+ }
33
+ catch (error) {
34
+ const formattedError = handleAxiosError(error);
35
+ output.error(`Failed to create container image: ${formattedError.details}`);
36
+ process.exit(1);
37
+ }
38
+ });
39
+ return cmd;
40
+ }
41
+ //# sourceMappingURL=create.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createContainerImageGetCommand(): Command;
3
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1,33 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
8
+ export function createContainerImageGetCommand() {
9
+ const cmd = new Command('get');
10
+ cmd
11
+ .description('Get container image details')
12
+ .argument('<image-id-or-name>', 'Container image ID or name (owner~name)')
13
+ .action(async (imageIdOrName) => {
14
+ const output = createOutputWriter();
15
+ try {
16
+ const token = await getAuthToken();
17
+ if (!token) {
18
+ output.error('Not authenticated. Run: guild auth login');
19
+ process.exit(1);
20
+ }
21
+ const client = new GuildAPIClient();
22
+ const response = await client.get(`/container-images/${imageIdOrName}`);
23
+ output.data(response);
24
+ }
25
+ catch (error) {
26
+ const formattedError = handleAxiosError(error);
27
+ output.error(`Failed to get container image: ${formattedError.details}`);
28
+ process.exit(1);
29
+ }
30
+ });
31
+ return cmd;
32
+ }
33
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createContainerImageListCommand(): Command;
3
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1,44 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { getOutputMode } from '../../lib/output-mode.js';
8
+ import { createOutputWriter, formatContainerImageTable } from '../../lib/output.js';
9
+ export function createContainerImageListCommand() {
10
+ const cmd = new Command('list');
11
+ cmd
12
+ .description('List container images for an account')
13
+ .requiredOption('--account <id-or-name>', 'Account ID or name')
14
+ .option('--limit <number>', 'Number of results to return', '20')
15
+ .option('--offset <number>', 'Offset for pagination', '0')
16
+ .action(async (options) => {
17
+ const output = createOutputWriter();
18
+ try {
19
+ const token = await getAuthToken();
20
+ if (!token) {
21
+ output.error('Not authenticated. Run: guild auth login');
22
+ process.exit(1);
23
+ }
24
+ const client = new GuildAPIClient();
25
+ const params = new URLSearchParams();
26
+ params.append('limit', options.limit);
27
+ params.append('offset', options.offset);
28
+ const response = await client.get(`/accounts/${options.account}/container-images?${params.toString()}`);
29
+ if (getOutputMode() === 'json') {
30
+ console.log(JSON.stringify(response, null, 2));
31
+ }
32
+ else {
33
+ formatContainerImageTable(response.items, response.pagination);
34
+ }
35
+ }
36
+ catch (error) {
37
+ const formattedError = handleAxiosError(error);
38
+ output.error(`Failed to list container images: ${formattedError.details}`);
39
+ process.exit(1);
40
+ }
41
+ });
42
+ return cmd;
43
+ }
44
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createJobGetCommand(): Command;
3
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1,44 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { getOutputMode } from '../../lib/output-mode.js';
8
+ import { createOutputWriter, formatJobStepTable } from '../../lib/output.js';
9
+ export function createJobGetCommand() {
10
+ const cmd = new Command('get');
11
+ cmd
12
+ .description('Get job details and steps')
13
+ .argument('<job-id>', 'Job ID')
14
+ .action(async (jobId) => {
15
+ const output = createOutputWriter();
16
+ try {
17
+ const token = await getAuthToken();
18
+ if (!token) {
19
+ output.error('Not authenticated. Run: guild auth login');
20
+ process.exit(1);
21
+ }
22
+ const client = new GuildAPIClient();
23
+ const [job, stepsResponse] = await Promise.all([
24
+ client.get(`/jobs/${jobId}`),
25
+ client.get(`/jobs/${jobId}/steps`),
26
+ ]);
27
+ if (getOutputMode() === 'json') {
28
+ console.log(JSON.stringify({ ...job, steps: stepsResponse.steps }, null, 2));
29
+ }
30
+ else {
31
+ output.data(job);
32
+ console.log();
33
+ formatJobStepTable(stepsResponse.steps);
34
+ }
35
+ }
36
+ catch (error) {
37
+ const formattedError = handleAxiosError(error);
38
+ output.error(`Failed to get job: ${formattedError.details}`);
39
+ process.exit(1);
40
+ }
41
+ });
42
+ return cmd;
43
+ }
44
+ //# sourceMappingURL=get.js.map
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createJobStepGetCommand(): Command;
3
+ //# sourceMappingURL=step-get.d.ts.map
@@ -0,0 +1,40 @@
1
+ // Copyright 2026 Guild.ai
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { Command } from 'commander';
4
+ import { GuildAPIClient } from '../../lib/api-client.js';
5
+ import { getAuthToken } from '../../lib/auth.js';
6
+ import { handleAxiosError } from '../../lib/errors.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
8
+ export function createJobStepGetCommand() {
9
+ const cmd = new Command('step-get');
10
+ cmd
11
+ .description('Get details of a step in a job')
12
+ .argument('<job-id>', 'Job ID')
13
+ .argument('<step-name>', 'Step name')
14
+ .action(async (jobId, stepName) => {
15
+ const output = createOutputWriter();
16
+ try {
17
+ const token = await getAuthToken();
18
+ if (!token) {
19
+ output.error('Not authenticated. Run: guild auth login');
20
+ process.exit(1);
21
+ }
22
+ const client = new GuildAPIClient();
23
+ const stepsResponse = await client.get(`/jobs/${jobId}/steps`);
24
+ const step = stepsResponse.steps.find((s) => s.name === stepName);
25
+ if (!step) {
26
+ const available = stepsResponse.steps.map((s) => s.name).join(', ');
27
+ output.error(`Step "${stepName}" not found. Available steps: ${available || 'none'}`);
28
+ process.exit(1);
29
+ }
30
+ output.data(step);
31
+ }
32
+ catch (error) {
33
+ const formattedError = handleAxiosError(error);
34
+ output.error(`Failed to get job step: ${formattedError.details}`);
35
+ process.exit(1);
36
+ }
37
+ });
38
+ return cmd;
39
+ }
40
+ //# sourceMappingURL=step-get.js.map
@@ -24,6 +24,7 @@ export function createTriggerCreateCommand() {
24
24
  .option('--time <time>', 'Time of day in HH:MM format')
25
25
  .option('--days-of-week <days>', 'Days of week (comma-separated: MONDAY,TUESDAY,...)')
26
26
  .option('--days-of-month <days>', 'Days of month (comma-separated: 1,15,-1)')
27
+ .option('--minutes-of-hour <minutes>', 'Minutes of hour, comma-separated (0-59)')
27
28
  .option('--input <json>', 'Agent input as JSON object')
28
29
  .action(async (options) => {
29
30
  const output = createOutputWriter();
@@ -130,6 +131,9 @@ export function createTriggerCreateCommand() {
130
131
  if (options.daysOfMonth) {
131
132
  body.days_of_month = options.daysOfMonth;
132
133
  }
134
+ if (options.minutesOfHour) {
135
+ body.minutes_of_hour = options.minutesOfHour;
136
+ }
133
137
  }
134
138
  const response = await client.post(`/workspaces/${workspaceId}/triggers`, body);
135
139
  output.data(response);
@@ -20,6 +20,7 @@ export function createTriggerUpdateCommand() {
20
20
  .option('--time <time>', 'Time of day in HH:MM format (for time triggers)')
21
21
  .option('--days-of-week <days>', 'Days of week, comma-separated (for time triggers)')
22
22
  .option('--days-of-month <days>', 'Days of month, comma-separated (for time triggers)')
23
+ .option('--minutes-of-hour <minutes>', 'Minutes of hour, comma-separated (0-59, for HOURLY triggers)')
23
24
  .option('--input <json>', 'Agent input as JSON object (for time triggers)')
24
25
  .action(async (triggerId, options) => {
25
26
  const output = createOutputWriter();
@@ -66,6 +67,9 @@ export function createTriggerUpdateCommand() {
66
67
  if (options.daysOfMonth !== undefined) {
67
68
  body.days_of_month = options.daysOfMonth;
68
69
  }
70
+ if (options.minutesOfHour !== undefined) {
71
+ body.minutes_of_hour = options.minutesOfHour;
72
+ }
69
73
  if (options.input !== undefined) {
70
74
  try {
71
75
  body.agent_input = JSON.parse(options.input);