@guildai/cli 0.9.1 → 0.10.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.
@@ -143,6 +143,7 @@ export function createAgentForkCommand() {
143
143
  ownerFlag: options.owner,
144
144
  client,
145
145
  interactive: isInteractive(),
146
+ requireExplicitOwner: true,
146
147
  });
147
148
  // Create forked agent
148
149
  output.progress(`✓ Forking agent '${agentName}'...`);
@@ -192,6 +192,7 @@ export function createAgentInitCommand() {
192
192
  ownerFlag: options.owner,
193
193
  client,
194
194
  interactive: isInteractive(),
195
+ requireExplicitOwner: true,
195
196
  });
196
197
  const agent = await client.post('/agents', {
197
198
  name: agentName,
@@ -6,6 +6,7 @@ import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
7
7
  import { getOutputMode } from '../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatAgentTable } from '../../lib/output.js';
9
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
9
10
  const SORT_MAP = {
10
11
  updated: 'updated_at',
11
12
  newest: 'created_at',
@@ -23,8 +24,8 @@ export function createAgentListCommand() {
23
24
  .option('--all', 'Show all agents including archived')
24
25
  .option('--owner <name>', 'Filter by owner (user or org name). Without this flag, lists your own agents')
25
26
  .option('--workspace <id>', 'Filter agents by workspace ID or name')
26
- .option('--limit <number>', 'Number of results to return', '20')
27
- .option('--offset <number>', 'Offset for pagination', '0')
27
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
28
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
28
29
  .action(async (options) => {
29
30
  const output = createOutputWriter();
30
31
  if (options.archived && options.all) {
@@ -13,7 +13,7 @@ export function createAgentPullCommand() {
13
13
  const cmd = new Command('pull');
14
14
  cmd
15
15
  .description('Pull remote changes into local agent directory')
16
- .option('--json', 'Output JSON only (no progress messages)', false)
16
+ .option('--json', 'Output JSON only, no progress messages (default: off)', false)
17
17
  .action(async (_options) => {
18
18
  const cwd = process.cwd();
19
19
  const output = createOutputWriter();
@@ -16,11 +16,11 @@ export function createAgentSaveCommand() {
16
16
  .description('Commit, push, and create a new agent version')
17
17
  .option('-A, --all', 'Stage all changes and commit before pushing', false)
18
18
  .option('-m, --message <text>', 'Commit message (required with --all)')
19
- .option('--wait', 'Wait for validation to complete before returning', false)
20
- .option('--publish', 'Publish after validation passes (implies --wait)', false)
21
- .option('--bump [level]', 'Bump package.json version before saving (patch, or minor/major)', 'patch')
19
+ .option('--wait', 'Wait for validation to complete before returning (default: returns immediately)', false)
20
+ .option('--publish', 'Publish after validation passes (implies --wait) (default: does not publish)', false)
21
+ .option('--bump [level]', 'Bump package.json version before saving (patch, or minor/major) (default: patch)', 'patch')
22
22
  .option('--no-bump', 'Skip automatic version bump')
23
- .option('--json', 'Output JSON only (no progress messages)', false)
23
+ .option('--json', 'Output JSON only, no progress messages (default: off)', false)
24
24
  .action(async (options) => {
25
25
  const cwd = process.cwd();
26
26
  let guildConfig = null;
@@ -6,6 +6,7 @@ import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
7
  import { getOutputMode } from '../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatAgentTable } from '../../lib/output.js';
9
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
9
10
  const SORT_MAP = {
10
11
  updated: 'updated_at',
11
12
  newest: 'created_at',
@@ -19,8 +20,8 @@ export function createAgentSearchCommand() {
19
20
  .argument('<query>', 'Search query')
20
21
  .option('--sort <field>', 'Sort by: updated, newest, name, popular (default: updated)', 'updated')
21
22
  .option('--published', 'Only show published agents')
22
- .option('--limit <number>', 'Number of results to return', '20')
23
- .option('--offset <number>', 'Offset for pagination', '0')
23
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
24
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
24
25
  .action(async (query, options) => {
25
26
  const output = createOutputWriter();
26
27
  try {
@@ -7,13 +7,14 @@ import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
7
7
  import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
8
8
  import { getOutputMode } from '../../lib/output-mode.js';
9
9
  import { createOutputWriter, formatVersionTable } from '../../lib/output.js';
10
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
10
11
  export function createAgentVersionsCommand() {
11
12
  const cmd = new Command('versions');
12
13
  cmd
13
14
  .description('List all versions of an agent')
14
15
  .argument('[identifier]', 'Agent ID or full name (e.g., owner~agent-name)')
15
- .option('--limit <number>', 'Maximum number of versions to return', '20')
16
- .option('--offset <number>', 'Number of versions to skip', '0')
16
+ .option('--limit <number>', `Maximum number of versions to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
17
+ .option('--offset <number>', 'Number of versions to skip (default: 0)', '0')
17
18
  .action(async (agentIdArg, options) => {
18
19
  const output = createOutputWriter();
19
20
  // Get agent ID from argument or guild.json
@@ -7,13 +7,14 @@ import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
7
7
  import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
8
8
  import { createOutputWriter, formatWorkspaceTable } from '../../lib/output.js';
9
9
  import { getOutputMode } from '../../lib/output-mode.js';
10
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
10
11
  export function createAgentWorkspacesCommand() {
11
12
  const cmd = new Command('workspaces');
12
13
  cmd
13
14
  .description('List workspaces that use an agent')
14
15
  .argument('[identifier]', 'Agent ID or full name (e.g., owner~agent-name)')
15
- .option('--limit <number>', 'Maximum number of workspaces to return', '20')
16
- .option('--offset <number>', 'Number of workspaces to skip', '0')
16
+ .option('--limit <number>', `Maximum number of workspaces to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
17
+ .option('--offset <number>', 'Number of workspaces to skip (default: 0)', '0')
17
18
  .action(async (agentIdArg, options) => {
18
19
  const output = createOutputWriter();
19
20
  const { agentId } = await getAgentId(agentIdArg);
@@ -2,6 +2,15 @@ import React from 'react';
2
2
  import { Command } from 'commander';
3
3
  import { GuildAPIClient } from '../lib/api-client.js';
4
4
  import { SessionEvent, Session } from '../lib/session-events.js';
5
+ /** Thrown when no workspace is configured (no --workspace flag, no config). */
6
+ export declare class WorkspaceNotConfiguredError extends Error {
7
+ constructor();
8
+ }
9
+ /** Thrown when the specified workspace ID is not found in the backend. */
10
+ export declare class WorkspaceNotFoundError extends Error {
11
+ readonly workspaceId: string;
12
+ constructor(workspaceId: string);
13
+ }
5
14
  /**
6
15
  * ChatApp wrapper component that shows splash animation during connection
7
16
  * and then transitions to ChatUIWithConnection once connected.
@@ -31,6 +31,28 @@ import { getOutputMode, isQuietMode } from '../lib/output-mode.js';
31
31
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
32
32
  // Read version from package.json
33
33
  const packageJson = JSON.parse(readFileSync(path.join(__dirname, '../../package.json'), 'utf-8'));
34
+ // ---------------------------------------------------------------------------
35
+ // Workspace error types
36
+ // ---------------------------------------------------------------------------
37
+ /** Thrown when no workspace is configured (no --workspace flag, no config). */
38
+ export class WorkspaceNotConfiguredError extends Error {
39
+ constructor() {
40
+ super('No workspace configured.');
41
+ this.name = 'WorkspaceNotConfiguredError';
42
+ }
43
+ }
44
+ /** Thrown when the specified workspace ID is not found in the backend. */
45
+ export class WorkspaceNotFoundError extends Error {
46
+ workspaceId;
47
+ constructor(workspaceId) {
48
+ super(`Workspace ${workspaceId} not found.`);
49
+ this.name = 'WorkspaceNotFoundError';
50
+ this.workspaceId = workspaceId;
51
+ }
52
+ }
53
+ /** User-facing error messages for workspace resolution failures. */
54
+ const WORKSPACE_NOT_CONFIGURED_MSG = 'No workspace configured. Pass a --workspace <id_or_name> argument or run guild workspace select';
55
+ const WORKSPACE_NOT_FOUND_MSG = "The workspace doesn't exist.";
34
56
  // Configure marked for terminal
35
57
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
58
  marked.use(markedTerminal({}, { theme: {} }));
@@ -264,8 +286,11 @@ export function ChatApp({ initialPrompt, version, workspaceId, versionId, agentN
264
286
  formattedError.code === ErrorCodes.AUTH_TOKEN_INVALID) {
265
287
  format.error('Not authenticated. Run: guild auth login');
266
288
  }
267
- else if (details.includes('workspace')) {
268
- format.error('Workspace not found. Run: guild workspace select');
289
+ else if (error instanceof WorkspaceNotConfiguredError) {
290
+ format.error(WORKSPACE_NOT_CONFIGURED_MSG);
291
+ }
292
+ else if (error instanceof WorkspaceNotFoundError) {
293
+ format.error(WORKSPACE_NOT_FOUND_MSG);
269
294
  }
270
295
  else if (details.includes('agent')) {
271
296
  format.error('Agent not found in workspace.');
@@ -1108,7 +1133,7 @@ export async function createSession(client, workspaceId, initialPrompt, versionI
1108
1133
  }
1109
1134
  }
1110
1135
  if (!workspaceId) {
1111
- throw new Error('No workspace configured. Run: guild workspace select, or pass --workspace <id>');
1136
+ throw new WorkspaceNotConfiguredError();
1112
1137
  }
1113
1138
  progress('Creating session');
1114
1139
  const sessionData = {
@@ -1127,7 +1152,7 @@ export async function createSession(client, workspaceId, initialPrompt, versionI
1127
1152
  catch (error) {
1128
1153
  const err = handleAxiosError(error);
1129
1154
  if (err.code === ErrorCodes.NOT_FOUND) {
1130
- throw new Error(`Workspace ${workspaceId} not found. Run: guild workspace select`);
1155
+ throw new WorkspaceNotFoundError(workspaceId);
1131
1156
  }
1132
1157
  throw error;
1133
1158
  }
@@ -1256,6 +1281,14 @@ export function createChatCommand() {
1256
1281
  catch (error) {
1257
1282
  spinner.fail('Connection failed');
1258
1283
  console.error('');
1284
+ if (error instanceof WorkspaceNotConfiguredError) {
1285
+ format.error(WORKSPACE_NOT_CONFIGURED_MSG);
1286
+ process.exit(1);
1287
+ }
1288
+ if (error instanceof WorkspaceNotFoundError) {
1289
+ format.error(WORKSPACE_NOT_FOUND_MSG);
1290
+ process.exit(1);
1291
+ }
1259
1292
  const formattedError = handleAxiosError(error);
1260
1293
  console.error(`Error: ${formattedError.error}`);
1261
1294
  console.error(formattedError.details);
@@ -7,6 +7,7 @@ import { getAuthToken } from '../../lib/auth.js';
7
7
  import { handleAxiosError } from '../../lib/errors.js';
8
8
  import { getOutputMode } from '../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../lib/output.js';
10
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
10
11
  import { Table } from '../../lib/table.js';
11
12
  export function createCredentialsEndpointListCommand() {
12
13
  const cmd = new Command('list');
@@ -15,8 +16,8 @@ export function createCredentialsEndpointListCommand() {
15
16
  .argument('<credential-id>', 'Credential ID')
16
17
  .option('--include-previous-versions', 'Include endpoints from previous versions')
17
18
  .option('--search <query>', 'Search by operation name')
18
- .option('--limit <number>', 'Number of results to return', '20')
19
- .option('--offset <number>', 'Offset for pagination', '0')
19
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
20
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
20
21
  .action(async (credentialId, options) => {
21
22
  const output = createOutputWriter();
22
23
  try {
@@ -6,14 +6,15 @@ import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
7
  import { getOutputMode } from '../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatCredentialsTable } from '../../lib/output.js';
9
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
9
10
  export function createCredentialsListCommand() {
10
11
  const cmd = new Command('list');
11
12
  cmd
12
13
  .description('List credentials for an account')
13
14
  .requiredOption('--owner <account>', 'Account name or ID')
14
15
  .option('--search <query>', 'Filter by integration name')
15
- .option('--limit <number>', 'Number of results to return', '20')
16
- .option('--offset <number>', 'Offset for pagination', '0')
16
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
17
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
17
18
  .action(async (options) => {
18
19
  const output = createOutputWriter();
19
20
  try {
@@ -6,13 +6,14 @@ import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
7
  import { getOutputMode } from '../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatPoliciesTable } from '../../lib/output.js';
9
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
9
10
  export function createCredentialsPolicyListCommand() {
10
11
  const cmd = new Command('list');
11
12
  cmd
12
13
  .description('List policies for a credential')
13
14
  .argument('<credential-id>', 'Credential ID')
14
- .option('--limit <number>', 'Number of results to return', '20')
15
- .option('--offset <number>', 'Offset for pagination', '0')
15
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
16
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
16
17
  .action(async (credentialId, options) => {
17
18
  const output = createOutputWriter();
18
19
  try {
@@ -6,6 +6,7 @@ import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
7
  import { getOutputMode } from '../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatIntegrationTable } from '../../lib/output.js';
9
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
9
10
  const SORT_MAP = {
10
11
  updated: 'updated_at',
11
12
  newest: 'created_at',
@@ -18,8 +19,8 @@ export function createIntegrationListCommand() {
18
19
  .option('--search <query>', 'Search integrations by name or description')
19
20
  .option('--sort <field>', 'Sort by: updated, newest, name (default: updated)', 'updated')
20
21
  .option('--published', 'Only show integrations with at least one published version')
21
- .option('--limit <number>', 'Number of results to return', '20')
22
- .option('--offset <number>', 'Offset for pagination', '0')
22
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
23
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
23
24
  .action(async (options) => {
24
25
  const output = createOutputWriter();
25
26
  try {
@@ -9,14 +9,15 @@ import { getOutputMode } from '../../../lib/output-mode.js';
9
9
  import { createOutputWriter } from '../../../lib/output.js';
10
10
  import { resolveVersionId } from '../../../lib/integration-helpers.js';
11
11
  import { Table } from '../../../lib/table.js';
12
+ import { DEFAULT_PAGE_LIMIT_LARGE } from '../../../lib/api-types.js';
12
13
  export function createIntegrationOperationListCommand() {
13
14
  const cmd = new Command('list');
14
15
  cmd
15
16
  .description('List operations for an integration version')
16
17
  .argument('<id_or_name>', 'Integration ID or name (owner~name)')
17
18
  .option('--version-number <semver>', 'Specific version, e.g. 1.0.0')
18
- .option('--limit <number>', 'Number of results to return', '100')
19
- .option('--offset <number>', 'Offset for pagination', '0')
19
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT_LARGE})`, String(DEFAULT_PAGE_LIMIT_LARGE))
20
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
20
21
  .action(async (identifier, options) => {
21
22
  const output = createOutputWriter();
22
23
  try {
@@ -6,13 +6,14 @@ import { getAuthToken } from '../../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../../lib/errors.js';
7
7
  import { getOutputMode } from '../../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatIntegrationVersionTable, } from '../../../lib/output.js';
9
+ import { DEFAULT_PAGE_LIMIT } from '../../../lib/api-types.js';
9
10
  export function createIntegrationVersionListCommand() {
10
11
  const cmd = new Command('list');
11
12
  cmd
12
13
  .description('List integration versions')
13
14
  .argument('<id_or_name>', 'Integration ID or name')
14
- .option('--limit <number>', 'Number of results to return', '20')
15
- .option('--offset <number>', 'Offset for pagination', '0')
15
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
16
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
16
17
  .action(async (identifier, options) => {
17
18
  const output = createOutputWriter();
18
19
  try {
@@ -11,7 +11,7 @@ export function createSessionCreateCommand() {
11
11
  cmd
12
12
  .description('Create a new session')
13
13
  .option('--workspace <id>', 'Workspace ID or name (e.g., owner~workspace-name)')
14
- .option('--type <type>', 'Session type: chat or agent_test', 'chat')
14
+ .option('--type <type>', 'Session type: chat or agent_test (default: chat)', 'chat')
15
15
  .option('--prompt <text>', 'Initial prompt (required for chat sessions)')
16
16
  .option('--agent <identifier>', 'Agent identifier, e.g., owner~agent-name')
17
17
  .action(async (options) => {
@@ -4,6 +4,7 @@ import { Command } from 'commander';
4
4
  import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../lib/auth.js';
6
6
  import { parseEventFilter, DEFAULT_EVENT_TYPES, USER_EVENT_TYPES, SYSTEM_EVENT_TYPES, } from '../../lib/event-filter.js';
7
+ import { DEFAULT_PAGE_LIMIT_LARGE } from '../../lib/api-types.js';
7
8
  import { handleAxiosError } from '../../lib/errors.js';
8
9
  import { createOutputWriter } from '../../lib/output.js';
9
10
  export function createSessionEventsCommand() {
@@ -12,8 +13,8 @@ export function createSessionEventsCommand() {
12
13
  .description('List events in a session')
13
14
  .argument('<session-id>', 'Session ID')
14
15
  .option('--events <types>', 'Event types to show (default: user). Shorthands: none, user, system, all, or comma-separated type names')
15
- .option('--limit <number>', 'Number of results to return', '100')
16
- .option('--offset <number>', 'Offset for pagination', '0')
16
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT_LARGE})`, String(DEFAULT_PAGE_LIMIT_LARGE))
17
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
17
18
  .addHelpText('after', [
18
19
  '',
19
20
  'Available event types:',
@@ -7,14 +7,15 @@ import { getWorkspaceId } from '../../lib/guild-config.js';
7
7
  import { handleAxiosError } from '../../lib/errors.js';
8
8
  import { getOutputMode } from '../../lib/output-mode.js';
9
9
  import { createOutputWriter, formatSessionTable } from '../../lib/output.js';
10
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
10
11
  export function createSessionListCommand() {
11
12
  const cmd = new Command('list');
12
13
  cmd
13
14
  .description('List sessions in a workspace')
14
15
  .option('--workspace <id>', 'Workspace ID or name (e.g., owner~workspace-name)')
15
16
  .option('--type <type>', 'Filter by session type: chat, webhook, time, agent_test')
16
- .option('--limit <number>', 'Number of results to return', '20')
17
- .option('--offset <number>', 'Offset for pagination', '0')
17
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
18
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
18
19
  .action(async (options) => {
19
20
  const output = createOutputWriter();
20
21
  try {
@@ -6,13 +6,14 @@ import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError } from '../../lib/errors.js';
7
7
  import { getOutputMode } from '../../lib/output-mode.js';
8
8
  import { createOutputWriter, formatTaskTable } from '../../lib/output.js';
9
+ import { DEFAULT_PAGE_LIMIT_LARGE } from '../../lib/api-types.js';
9
10
  export function createSessionTasksCommand() {
10
11
  const cmd = new Command('tasks');
11
12
  cmd
12
13
  .description('List tasks in a session')
13
14
  .argument('<session-id>', 'Session ID')
14
- .option('--limit <number>', 'Number of results to return', '100')
15
- .option('--offset <number>', 'Offset for pagination', '0')
15
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT_LARGE})`, String(DEFAULT_PAGE_LIMIT_LARGE))
16
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
16
17
  .action(async (sessionId, options) => {
17
18
  const output = createOutputWriter();
18
19
  try {
@@ -7,13 +7,14 @@ import { getWorkspaceId } from '../../lib/guild-config.js';
7
7
  import { handleAxiosError } from '../../lib/errors.js';
8
8
  import { getOutputMode } from '../../lib/output-mode.js';
9
9
  import { createOutputWriter, formatTriggerTable } from '../../lib/output.js';
10
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
10
11
  export function createTriggerListCommand() {
11
12
  const cmd = new Command('list');
12
13
  cmd
13
14
  .description('List all triggers in a workspace')
14
15
  .option('--workspace <id>', 'Workspace ID or name')
15
- .option('--limit <number>', 'Number of results to return', '20')
16
- .option('--offset <number>', 'Offset for pagination', '0')
16
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
17
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
17
18
  .action(async (options) => {
18
19
  const output = createOutputWriter();
19
20
  try {
@@ -5,13 +5,14 @@ import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { getAuthToken } from '../../lib/auth.js';
6
6
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
7
7
  import { createOutputWriter } from '../../lib/output.js';
8
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
8
9
  export function createTriggerSessionsCommand() {
9
10
  const cmd = new Command('sessions');
10
11
  cmd
11
12
  .description('List sessions spawned by a trigger')
12
13
  .argument('<trigger-id>', 'Trigger ID')
13
- .option('--limit <number>', 'Number of results to return', '20')
14
- .option('--offset <number>', 'Offset for pagination', '0')
14
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
15
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
15
16
  .action(async (triggerId, options) => {
16
17
  const output = createOutputWriter();
17
18
  try {
@@ -8,13 +8,14 @@ import { handleAxiosError, ErrorCodes } from '../../../lib/errors.js';
8
8
  import { createOutputWriter, formatWorkspaceAgentTable } from '../../../lib/output.js';
9
9
  import { getOutputMode } from '../../../lib/output-mode.js';
10
10
  import { resolveWorkspaceId } from '../../../lib/workspace-helpers.js';
11
+ import { DEFAULT_PAGE_LIMIT } from '../../../lib/api-types.js';
11
12
  export function createWorkspaceAgentListCommand() {
12
13
  const cmd = new Command('list');
13
14
  cmd
14
15
  .description('List agents in a workspace')
15
16
  .option('--workspace <id>', 'Workspace ID or name')
16
- .option('--limit <number>', 'Number of results to return', '20')
17
- .option('--offset <number>', 'Offset for pagination', '0')
17
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
18
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
18
19
  .action(async (options) => {
19
20
  const output = createOutputWriter();
20
21
  try {
@@ -5,13 +5,14 @@ import { GuildAPIClient } from '../../../lib/api-client.js';
5
5
  import { handleAxiosError, ErrorCodes } from '../../../lib/errors.js';
6
6
  import { getOutputMode } from '../../../lib/output-mode.js';
7
7
  import { createOutputWriter, formatContextTable } from '../../../lib/output.js';
8
+ import { DEFAULT_PAGE_LIMIT } from '../../../lib/api-types.js';
8
9
  export function createWorkspaceContextListCommand() {
9
10
  const cmd = new Command('list');
10
11
  cmd
11
12
  .description('List context versions for a workspace')
12
13
  .argument('<workspace>', 'Workspace ID or full name (e.g., owner/workspace-name)')
13
- .option('--limit <number>', 'Number of results to return', '20')
14
- .option('--offset <number>', 'Offset for pagination', '0')
14
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
15
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
15
16
  .action(async (workspaceId, options) => {
16
17
  const output = createOutputWriter();
17
18
  try {
@@ -5,12 +5,13 @@ import { GuildAPIClient } from '../../lib/api-client.js';
5
5
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
6
6
  import { getOutputMode } from '../../lib/output-mode.js';
7
7
  import { createOutputWriter, formatWorkspaceTable } from '../../lib/output.js';
8
+ import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
8
9
  export function createWorkspaceListCommand() {
9
10
  const cmd = new Command('list');
10
11
  cmd
11
12
  .description('List workspaces')
12
- .option('--limit <number>', 'Number of results to return', '20')
13
- .option('--offset <number>', 'Offset for pagination', '0')
13
+ .option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
14
+ .option('--offset <number>', 'Offset for pagination (default: 0)', '0')
14
15
  .option('--owner <name>', 'Filter workspaces by owner name (case-insensitive)')
15
16
  .action(async (options) => {
16
17
  const output = createOutputWriter();
@@ -159,6 +159,10 @@ export interface Pagination {
159
159
  offset: number;
160
160
  has_more: boolean;
161
161
  }
162
+ /** Default page size for standard list endpoints (matches backend). */
163
+ export declare const DEFAULT_PAGE_LIMIT = 20;
164
+ /** Default page size for high-volume endpoints (events, tasks, operations). */
165
+ export declare const DEFAULT_PAGE_LIMIT_LARGE = 100;
162
166
  /**
163
167
  * Generic paginated response wrapper.
164
168
  * All list endpoints return { items: T[], pagination: Pagination }
@@ -1,5 +1,9 @@
1
1
  // Copyright 2026 Guild.ai
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ /** Default page size for standard list endpoints (matches backend). */
4
+ export const DEFAULT_PAGE_LIMIT = 20;
5
+ /** Default page size for high-volume endpoints (events, tasks, operations). */
6
+ export const DEFAULT_PAGE_LIMIT_LARGE = 100;
3
7
  // Import and re-export generated types (from cli/scripts/sync-types-from-python.py)
4
8
  import { WEBHOOK_SERVICES, TIME_TRIGGER_FREQUENCIES, } from './generated-types.js';
5
9
  export { WEBHOOK_SERVICES, TIME_TRIGGER_FREQUENCIES, };
@@ -195,7 +195,7 @@ export function formatVersionTable(versions, pagination) {
195
195
  ? chalk.red
196
196
  : chalk.dim;
197
197
  table.addRow({
198
- id: v.id.substring(0, 8),
198
+ id: v.id,
199
199
  version: v.version_number || '-',
200
200
  status: v.status,
201
201
  validation: validationColor(v.validation_status || '-'),
@@ -225,7 +225,7 @@ export function formatContextTable(contexts, pagination) {
225
225
  });
226
226
  contexts.forEach((ctx) => {
227
227
  table.addRow({
228
- id: truncate(ctx.id, 12),
228
+ id: ctx.id,
229
229
  status: ctx.status,
230
230
  type: ctx.type || '-',
231
231
  created: ctx.created_at ? formatRelativeTime(ctx.created_at) : '',
@@ -256,7 +256,7 @@ export function formatWorkspaceAgentTable(agents) {
256
256
  const agentUrl = wa.agent.full_name ? `${base}/agents/${wa.agent.full_name}` : '';
257
257
  table.addRow({
258
258
  name: agentUrl ? hyperlink(name, agentUrl) : name,
259
- version: wa.agent_version.version_number || wa.agent_version.id.substring(0, 8),
259
+ version: wa.agent_version.version_number || wa.agent_version.id,
260
260
  auto_update: wa.should_autoupdate ? chalk.green('yes') : chalk.dim('no'),
261
261
  });
262
262
  });
@@ -353,7 +353,7 @@ export function formatTaskTable(tasks, pagination) {
353
353
  ? chalk.yellow
354
354
  : chalk.dim;
355
355
  table.addRow({
356
- id: truncate(task.id, 13),
356
+ id: task.id,
357
357
  name,
358
358
  status: statusColor(task.status),
359
359
  tokens: task.token_usage ? task.token_usage.total_tokens.toLocaleString() : '-',
@@ -13,6 +13,9 @@ export interface ResolveOwnerOptions {
13
13
  ownerFlag?: string;
14
14
  client: GuildAPIClient;
15
15
  interactive: boolean;
16
+ /** When true, error if multiple accounts and no explicit owner in non-interactive mode.
17
+ * When false (default), fall back to current user. */
18
+ requireExplicitOwner?: boolean;
16
19
  }
17
20
  export declare function resolveOwnerId(options: ResolveOwnerOptions): Promise<OwnerChoice>;
18
21
  //# sourceMappingURL=owner-helpers.d.ts.map
@@ -11,9 +11,10 @@
11
11
  * 2. GUILD_OWNER_ID environment variable
12
12
  * 3. default_owner from ~/.guild/config.json
13
13
  * 4. Fetch user + orgs from API:
14
- * - No orgs → use current user
15
- * - Has orgs + interactive → prompt
16
- * - Has orgs + non-interactive → use current user
14
+ * - No orgs + non-interactive → use current user (single-account, stated explicitly)
15
+ * - No orgs + interactive → prompt with personal account as only choice
16
+ * - Has orgs + interactive → prompt to select from all accounts
17
+ * - Has orgs + non-interactive → error: require --owner flag
17
18
  */
18
19
  import inquirer from 'inquirer';
19
20
  import { loadGlobalConfig } from './guild-config.js';
@@ -35,7 +36,7 @@ export async function lookupOwner(client, val) {
35
36
  return undefined;
36
37
  }
37
38
  export async function resolveOwnerId(options) {
38
- const { ownerFlag, client, interactive } = options;
39
+ const { ownerFlag, client, interactive, requireExplicitOwner = false } = options;
39
40
  // Priority 1: --owner flag
40
41
  if (ownerFlag) {
41
42
  debug('Using owner from --owner flag: %s', ownerFlag);
@@ -71,17 +72,23 @@ export async function resolveOwnerId(options) {
71
72
  // Priority 4: Fetch user + orgs
72
73
  const me = await client.get('/me');
73
74
  const orgs = await client.fetchAll('/me/organizations');
74
- // No orgs → use current user
75
- if (orgs.length === 0) {
75
+ // No orgs + non-interactive → use current user (single account, stated explicitly by caller)
76
+ if (orgs.length === 0 && !interactive) {
76
77
  debug('No organizations found, using current user as owner');
77
78
  return { id: me.id, name: me.name, type: 'user' };
78
79
  }
79
- // Has orgs + non-interactive → use current user
80
- if (!interactive) {
81
- debug('Non-interactive mode with orgs available, using current user as owner');
80
+ // Has orgs + non-interactive
81
+ if (orgs.length > 0 && !interactive) {
82
+ if (requireExplicitOwner) {
83
+ debug('Non-interactive mode with multiple accounts available, requiring --owner');
84
+ throw new Error('Owner is required in non-interactive mode when multiple accounts are available.\n\n' +
85
+ 'Use --owner <name-or-id> to specify an owner, or set a default:\n' +
86
+ ' guild config set default_owner <name-or-id>');
87
+ }
88
+ debug('Multiple accounts available, defaulting to current user');
82
89
  return { id: me.id, name: me.name, type: 'user' };
83
90
  }
84
- // Has orgs + interactive prompt
91
+ // Interactive prompt (always, even with single account)
85
92
  const choices = [
86
93
  {
87
94
  name: `${me.name} (personal)`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guildai/cli",
3
- "version": "0.9.1",
3
+ "version": "0.10.0",
4
4
  "description": "Guild.ai CLI - Build, test, and deploy AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",