@guildai/cli 0.3.16 → 0.3.18

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 (69) hide show
  1. package/dist/commands/agent/clone.js +22 -67
  2. package/dist/commands/agent/code.js +12 -32
  3. package/dist/commands/agent/create.js +14 -30
  4. package/dist/commands/agent/fork.js +27 -73
  5. package/dist/commands/agent/get.js +5 -4
  6. package/dist/commands/agent/grep.js +7 -9
  7. package/dist/commands/agent/init.js +2 -0
  8. package/dist/commands/agent/list.js +5 -6
  9. package/dist/commands/agent/publish.js +27 -44
  10. package/dist/commands/agent/pull.js +8 -35
  11. package/dist/commands/agent/revalidate.js +8 -16
  12. package/dist/commands/agent/save.js +30 -76
  13. package/dist/commands/agent/search.js +5 -6
  14. package/dist/commands/agent/tags/add.js +14 -24
  15. package/dist/commands/agent/tags/list.js +12 -23
  16. package/dist/commands/agent/tags/remove.js +16 -27
  17. package/dist/commands/agent/tags/set.js +14 -19
  18. package/dist/commands/agent/unpublish.js +12 -17
  19. package/dist/commands/agent/update.js +12 -29
  20. package/dist/commands/agent/versions.js +13 -11
  21. package/dist/commands/agent/workspaces.d.ts +3 -0
  22. package/dist/commands/agent/workspaces.js +51 -0
  23. package/dist/commands/auth/login.js +4 -2
  24. package/dist/commands/auth/logout.js +3 -1
  25. package/dist/commands/auth/status.js +4 -3
  26. package/dist/commands/auth/token.js +3 -2
  27. package/dist/commands/config/get.js +7 -9
  28. package/dist/commands/config/list.js +13 -11
  29. package/dist/commands/config/path.js +6 -4
  30. package/dist/commands/config/set.js +17 -22
  31. package/dist/commands/doctor.js +9 -7
  32. package/dist/commands/session/create.js +7 -5
  33. package/dist/commands/session/events.js +5 -3
  34. package/dist/commands/session/get.js +5 -3
  35. package/dist/commands/session/list.js +5 -4
  36. package/dist/commands/session/send.js +7 -5
  37. package/dist/commands/session/tasks.js +5 -3
  38. package/dist/commands/setup.js +15 -14
  39. package/dist/commands/trigger/activate.js +7 -6
  40. package/dist/commands/trigger/create.js +16 -15
  41. package/dist/commands/trigger/deactivate.js +7 -6
  42. package/dist/commands/trigger/get.js +5 -4
  43. package/dist/commands/trigger/list.js +5 -5
  44. package/dist/commands/trigger/sessions.js +7 -6
  45. package/dist/commands/trigger/update.js +11 -10
  46. package/dist/commands/version.js +7 -5
  47. package/dist/commands/workspace/agent/add.js +16 -22
  48. package/dist/commands/workspace/agent/list.js +12 -32
  49. package/dist/commands/workspace/agent/remove.js +9 -15
  50. package/dist/commands/workspace/context/edit.js +13 -27
  51. package/dist/commands/workspace/context/get.js +8 -14
  52. package/dist/commands/workspace/context/list.js +12 -37
  53. package/dist/commands/workspace/context/publish.js +7 -11
  54. package/dist/commands/workspace/create.js +7 -11
  55. package/dist/commands/workspace/current.js +19 -31
  56. package/dist/commands/workspace/get.js +7 -11
  57. package/dist/commands/workspace/list.js +5 -8
  58. package/dist/commands/workspace/select.js +17 -22
  59. package/dist/index.js +2 -0
  60. package/dist/lib/agent-helpers.js +2 -2
  61. package/dist/lib/generated-types.d.ts +1 -1
  62. package/dist/lib/generated-types.js +1 -0
  63. package/dist/lib/npmrc.js +9 -1
  64. package/dist/lib/output.d.ts +18 -4
  65. package/dist/lib/output.js +112 -19
  66. package/docs/getting-started.md +1 -1
  67. package/docs/output-format.md +1 -1
  68. package/docs/skills/agent-dev.md +18 -17
  69. package/package.json +1 -1
@@ -4,6 +4,7 @@ import * as fs from 'fs/promises';
4
4
  import * as readline from 'readline';
5
5
  import { GuildAPIClient } from '../../lib/api-client.js';
6
6
  import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
7
+ import { createOutputWriter } from '../../lib/output.js';
7
8
  import { isAgentDirectory, loadLocalConfig, getLocalConfigPath, getWorkspaceId, saveGlobalConfig, } from '../../lib/guild-config.js';
8
9
  /**
9
10
  * Format workspace for display with owner name.
@@ -23,37 +24,35 @@ export function createWorkspaceSelectCommand() {
23
24
  .description('Select default workspace for agent testing')
24
25
  .argument('[workspace]', 'Workspace name or ID to select directly')
25
26
  .action(async (workspaceArg) => {
27
+ const output = createOutputWriter();
26
28
  try {
27
29
  const client = new GuildAPIClient();
28
30
  // Use filter=all to get workspaces from all orgs user is a member of
29
31
  const workspaces = await client.get('/me/workspaces?filter=all');
30
32
  if (workspaces.items.length === 0) {
31
- console.error('No workspaces found.');
32
- console.error('');
33
- console.error('Create a workspace first:');
34
- console.error(' guild workspace create <name>');
33
+ output.error('No workspaces found.', 'Create a workspace first:\n guild workspace create <name>');
35
34
  process.exit(1);
36
35
  }
37
36
  // If a workspace argument was provided, find and select it directly
38
37
  if (workspaceArg) {
39
38
  const workspace = workspaces.items.find((w) => w.name === workspaceArg ||
40
39
  w.name.toLowerCase() === workspaceArg.toLowerCase() ||
40
+ w.full_name === workspaceArg ||
41
+ w.full_name?.toLowerCase() === workspaceArg.toLowerCase() ||
41
42
  w.id === workspaceArg);
42
43
  if (!workspace) {
43
- console.error(`Workspace "${workspaceArg}" not found.`);
44
- console.error('');
45
- console.error('Available workspaces:');
46
- workspaces.items.forEach((w) => {
47
- console.error(` - ${formatWorkspaceDisplay(w)}`);
48
- });
44
+ const available = workspaces.items
45
+ .map((w) => ` - ${formatWorkspaceDisplay(w)}`)
46
+ .join('\n');
47
+ output.error(`Workspace "${workspaceArg}" not found.`, `Available workspaces:\n${available}`);
49
48
  process.exit(1);
50
49
  }
51
50
  const target = await saveWorkspaceConfig(workspace.id, workspace.name);
52
51
  if (target === 'local') {
53
- console.log(`✓ Workspace set for this agent: ${formatWorkspaceDisplay(workspace)}`);
52
+ output.success(`Workspace set for this agent: ${formatWorkspaceDisplay(workspace)}`);
54
53
  }
55
54
  else {
56
- console.log(`✓ Default workspace set to: ${formatWorkspaceDisplay(workspace)}`);
55
+ output.success(`Default workspace set to: ${formatWorkspaceDisplay(workspace)}`);
57
56
  }
58
57
  return;
59
58
  }
@@ -85,33 +84,29 @@ export function createWorkspaceSelectCommand() {
85
84
  }
86
85
  const selection = parseInt(answer.trim(), 10);
87
86
  if (isNaN(selection) || selection < 1 || selection > workspaces.items.length) {
88
- console.error('Invalid selection');
87
+ output.error('Invalid selection');
89
88
  process.exit(1);
90
89
  }
91
90
  const selectedWorkspace = workspaces.items[selection - 1];
92
91
  const target = await saveWorkspaceConfig(selectedWorkspace.id, selectedWorkspace.name);
93
92
  if (target === 'local') {
94
- console.log(`✓ Workspace set for this agent: ${formatWorkspaceDisplay(selectedWorkspace)}`);
93
+ output.success(`Workspace set for this agent: ${formatWorkspaceDisplay(selectedWorkspace)}`);
95
94
  }
96
95
  else {
97
- console.log(`✓ Default workspace set to: ${formatWorkspaceDisplay(selectedWorkspace)}`);
96
+ output.success(`Default workspace set to: ${formatWorkspaceDisplay(selectedWorkspace)}`);
98
97
  }
99
98
  }
100
99
  catch (error) {
101
100
  const formattedError = handleAxiosError(error);
102
101
  if (formattedError.code === ErrorCodes.AUTH_REQUIRED) {
103
- console.error('Not authenticated. Please log in first.');
104
- console.error('');
105
- console.error('Run: guild auth login');
102
+ output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
106
103
  process.exit(1);
107
104
  }
108
105
  if (formattedError.code === ErrorCodes.CONN_REFUSED) {
109
- console.error(`Failed to fetch workspaces: ${formattedError.details}`);
110
- console.error('');
111
- console.error('Run with --debug for more details');
106
+ output.error(`Failed to fetch workspaces: ${formattedError.details}`, 'Run with --debug for more details');
112
107
  process.exit(1);
113
108
  }
114
- console.error(`Failed to select workspace: ${formattedError.details}`);
109
+ output.error(`Failed to select workspace: ${formattedError.details}`);
115
110
  process.exit(1);
116
111
  }
117
112
  });
package/dist/index.js CHANGED
@@ -28,6 +28,7 @@ import { createAgentUnpublishCommand } from './commands/agent/unpublish.js';
28
28
  import { createAgentRevalidateCommand } from './commands/agent/revalidate.js';
29
29
  import { createAgentSearchCommand } from './commands/agent/search.js';
30
30
  import { createAgentOwnersCommand } from './commands/agent/owners.js';
31
+ import { createAgentWorkspacesCommand } from './commands/agent/workspaces.js';
31
32
  import { createAgentTagsListCommand } from './commands/agent/tags/list.js';
32
33
  import { createAgentTagsAddCommand } from './commands/agent/tags/add.js';
33
34
  import { createAgentTagsRemoveCommand } from './commands/agent/tags/remove.js';
@@ -131,6 +132,7 @@ agentCmd.addCommand(createAgentUnpublishCommand());
131
132
  agentCmd.addCommand(createAgentRevalidateCommand());
132
133
  agentCmd.addCommand(createAgentSearchCommand());
133
134
  agentCmd.addCommand(createAgentOwnersCommand());
135
+ agentCmd.addCommand(createAgentWorkspacesCommand());
134
136
  // Agent tags subcommand group
135
137
  const tagsCmd = agentCmd.command('tags').description('Manage agent tags');
136
138
  tagsCmd.addCommand(createAgentTagsListCommand());
@@ -66,8 +66,8 @@ export async function readAgentFiles(cwd) {
66
66
  const content = await fs.readFile(fullPath, 'utf-8');
67
67
  files.push({ path: filePath, content });
68
68
  }
69
- const fileNames = files.map((f) => f.path);
70
- const missing = REQUIRED_AGENT_FILES.filter((f) => !fileNames.includes(f));
69
+ const filePaths = files.map((f) => f.path);
70
+ const missing = REQUIRED_AGENT_FILES.filter((req) => !filePaths.some((fp) => fp === req || fp.endsWith(`/${req}`)));
71
71
  if (missing.length > 0) {
72
72
  throw new Error(`Missing required files: ${missing.join(', ')}`);
73
73
  }
@@ -1,4 +1,4 @@
1
- export declare const WEBHOOK_SERVICES: readonly ["AZURE_DEVOPS", "BITBUCKET", "CYPRESS", "GITHUB", "GOOGLE_DOCS", "JIRA", "LINEAR", "NEWRELIC", "NOTION", "SLACK", "TESTRAIL", "ZENDESK"];
1
+ export declare const WEBHOOK_SERVICES: readonly ["AZURE_DEVOPS", "BITBUCKET", "CYPRESS", "GITHUB", "GOOGLE_DOCS", "GOOGLE_LOGGING", "JIRA", "LINEAR", "NEWRELIC", "NOTION", "SLACK", "TESTRAIL", "ZENDESK"];
2
2
  export type WebhookService = (typeof WEBHOOK_SERVICES)[number];
3
3
  export declare const TIME_TRIGGER_FREQUENCIES: readonly ["HOURLY", "DAILY", "WEEKLY", "MONTHLY"];
4
4
  export type TimeTriggerFrequency = (typeof TIME_TRIGGER_FREQUENCIES)[number];
@@ -13,6 +13,7 @@ export const WEBHOOK_SERVICES = [
13
13
  'CYPRESS',
14
14
  'GITHUB',
15
15
  'GOOGLE_DOCS',
16
+ 'GOOGLE_LOGGING',
16
17
  'JIRA',
17
18
  'LINEAR',
18
19
  'NEWRELIC',
package/dist/lib/npmrc.js CHANGED
@@ -17,6 +17,7 @@ export async function configureNpmrc() {
17
17
  }
18
18
  try {
19
19
  await execa('npm', [
20
+ '--workspaces=false',
20
21
  'config',
21
22
  'set',
22
23
  '--location',
@@ -36,7 +37,14 @@ export async function cleanupNpmrc() {
36
37
  const keys = [...SCOPES.map((s) => `${s}:registry`), `${scope}:_authToken`];
37
38
  for (const key of keys) {
38
39
  try {
39
- await execa('npm', ['config', 'delete', '--location', 'user', key]);
40
+ await execa('npm', [
41
+ '--workspaces=false',
42
+ 'config',
43
+ 'delete',
44
+ '--location',
45
+ 'user',
46
+ key,
47
+ ]);
40
48
  }
41
49
  catch {
42
50
  // Key may not exist, that's fine
@@ -1,5 +1,5 @@
1
1
  import { type Spinner } from './progress.js';
2
- import type { Agent, Pagination, Workspace, Trigger } from './api-types.js';
2
+ import type { Agent, AgentVersion, Context, Pagination, Workspace, WorkspaceAgent, Trigger } from './api-types.js';
3
3
  /**
4
4
  * Session type from API responses
5
5
  */
@@ -19,6 +19,21 @@ interface Session {
19
19
  * Shared by agent list and agent search commands.
20
20
  */
21
21
  export declare function formatAgentTable(agents: Agent[], pagination: Pagination): void;
22
+ /**
23
+ * Format an agent version list as a human-readable table.
24
+ * Used by agent versions command.
25
+ */
26
+ export declare function formatVersionTable(versions: AgentVersion[], pagination: Pagination): void;
27
+ /**
28
+ * Format a context list as a human-readable table.
29
+ * Used by workspace context list command.
30
+ */
31
+ export declare function formatContextTable(contexts: Context[], pagination: Pagination): void;
32
+ /**
33
+ * Format a workspace agent list as a human-readable table.
34
+ * Used by workspace agent list command.
35
+ */
36
+ export declare function formatWorkspaceAgentTable(agents: WorkspaceAgent[]): void;
22
37
  /**
23
38
  * Format a workspace list as a human-readable table.
24
39
  * Used by workspace list command.
@@ -38,7 +53,7 @@ export declare function formatTriggerTable(triggers: Trigger[], pagination: Pagi
38
53
  * Output writer interface for consistent CLI output
39
54
  *
40
55
  * Implementations:
41
- * - HumanOutputWriter: Colors, tables, spinners for interactive use
56
+ * - InteractiveOutputWriter: Colors, tables, spinners for interactive use
42
57
  * - JSONOutputWriter: Pure JSON for scripting and automation
43
58
  */
44
59
  export interface OutputWriter {
@@ -69,9 +84,8 @@ export interface OutputWriter {
69
84
  * Uses colors, symbols, and formatting for readability.
70
85
  * Progress goes to stderr.
71
86
  */
72
- export declare class HumanOutputWriter implements OutputWriter {
87
+ export declare class InteractiveOutputWriter implements OutputWriter {
73
88
  data(value: unknown): void;
74
- private isAgentListResponse;
75
89
  success(message: string, details?: Record<string, unknown>): void;
76
90
  error(message: string, details?: string): void;
77
91
  progress(message: string): void;
@@ -76,6 +76,112 @@ export function formatAgentTable(agents, pagination) {
76
76
  console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} agents`));
77
77
  }
78
78
  }
79
+ /**
80
+ * Format an agent version list as a human-readable table.
81
+ * Used by agent versions command.
82
+ */
83
+ export function formatVersionTable(versions, pagination) {
84
+ if (versions.length === 0) {
85
+ console.log(chalk.dim('No versions found'));
86
+ return;
87
+ }
88
+ const table = new Table({
89
+ columns: [
90
+ { name: 'sha', title: 'SHA', alignment: 'left' },
91
+ { name: 'version', title: 'VERSION', alignment: 'left', color: 'cyan' },
92
+ { name: 'status', title: 'STATUS', alignment: 'left' },
93
+ { name: 'validation', title: 'VALIDATION', alignment: 'left' },
94
+ { name: 'summary', title: 'SUMMARY', alignment: 'left' },
95
+ { name: 'created', title: 'CREATED', alignment: 'left' },
96
+ ],
97
+ });
98
+ versions.forEach((v) => {
99
+ const validationColor = v.validation_status === 'PASSED'
100
+ ? chalk.green
101
+ : v.validation_status === 'FAILED'
102
+ ? chalk.red
103
+ : chalk.dim;
104
+ table.addRow({
105
+ sha: v.sha.slice(0, 7),
106
+ version: v.version_number || '-',
107
+ status: v.status,
108
+ validation: validationColor(v.validation_status || '-'),
109
+ summary: truncate(v.summary || '', 30),
110
+ created: v.created_at ? formatRelativeTime(v.created_at) : '',
111
+ });
112
+ });
113
+ table.printTable();
114
+ const showing = Math.min(pagination.limit, versions.length);
115
+ if (pagination.has_more) {
116
+ const nextOffset = pagination.offset + pagination.limit;
117
+ console.log(`\nShowing ${showing} of ${pagination.total_count} versions. ` +
118
+ chalk.dim(`Use --offset ${nextOffset} to see more.`));
119
+ }
120
+ else if (pagination.total_count > showing) {
121
+ console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} versions`));
122
+ }
123
+ }
124
+ /**
125
+ * Format a context list as a human-readable table.
126
+ * Used by workspace context list command.
127
+ */
128
+ export function formatContextTable(contexts, pagination) {
129
+ if (contexts.length === 0) {
130
+ console.log(chalk.dim('No contexts found'));
131
+ return;
132
+ }
133
+ const table = new Table({
134
+ columns: [
135
+ { name: 'id', title: 'ID', alignment: 'left' },
136
+ { name: 'status', title: 'STATUS', alignment: 'left', color: 'cyan' },
137
+ { name: 'type', title: 'TYPE', alignment: 'left' },
138
+ { name: 'created', title: 'CREATED', alignment: 'left' },
139
+ ],
140
+ });
141
+ contexts.forEach((ctx) => {
142
+ table.addRow({
143
+ id: truncate(ctx.id, 12),
144
+ status: ctx.status,
145
+ type: ctx.type || '-',
146
+ created: ctx.created_at ? formatRelativeTime(ctx.created_at) : '',
147
+ });
148
+ });
149
+ table.printTable();
150
+ const showing = Math.min(pagination.limit, contexts.length);
151
+ if (pagination.has_more) {
152
+ const nextOffset = pagination.offset + pagination.limit;
153
+ console.log(`\nShowing ${showing} of ${pagination.total_count} contexts. ` +
154
+ chalk.dim(`Use --offset ${nextOffset} to see more.`));
155
+ }
156
+ else if (pagination.total_count > showing) {
157
+ console.log(chalk.dim(`\nShowing ${showing} of ${pagination.total_count} contexts`));
158
+ }
159
+ }
160
+ /**
161
+ * Format a workspace agent list as a human-readable table.
162
+ * Used by workspace agent list command.
163
+ */
164
+ export function formatWorkspaceAgentTable(agents) {
165
+ if (agents.length === 0) {
166
+ console.log(chalk.dim('No agents installed in this workspace'));
167
+ return;
168
+ }
169
+ const table = new Table({
170
+ columns: [
171
+ { name: 'name', title: 'NAME', alignment: 'left' },
172
+ { name: 'version', title: 'VERSION', alignment: 'left', color: 'cyan' },
173
+ { name: 'auto_update', title: 'AUTO-UPDATE', alignment: 'left' },
174
+ ],
175
+ });
176
+ agents.forEach((wa) => {
177
+ table.addRow({
178
+ name: wa.agent.full_name || wa.agent.name,
179
+ version: wa.agent_version.version_number || wa.agent_version.sha.slice(0, 7),
180
+ auto_update: wa.should_autoupdate ? chalk.green('yes') : chalk.dim('no'),
181
+ });
182
+ });
183
+ table.printTable();
184
+ }
79
185
  /**
80
186
  * Format a workspace list as a human-readable table.
81
187
  * Used by workspace list command.
@@ -199,28 +305,15 @@ export function formatTriggerTable(triggers, pagination) {
199
305
  * Uses colors, symbols, and formatting for readability.
200
306
  * Progress goes to stderr.
201
307
  */
202
- export class HumanOutputWriter {
308
+ export class InteractiveOutputWriter {
203
309
  data(value) {
204
- // Special handling for agent list responses
205
- if (this.isAgentListResponse(value)) {
206
- formatAgentTable(value.items, value.pagination);
207
- return;
208
- }
209
- // Fallback to pretty JSON for other data
210
310
  console.log(JSON.stringify(value, null, 2));
211
311
  }
212
- isAgentListResponse(value) {
213
- return (typeof value === 'object' &&
214
- value !== null &&
215
- 'items' in value &&
216
- 'pagination' in value &&
217
- Array.isArray(value.items));
218
- }
219
312
  success(message, details) {
220
- console.log(chalk.green('✓'), message);
313
+ process.stderr.write(chalk.green('✓') + ' ' + message + '\n');
221
314
  if (details) {
222
315
  Object.entries(details).forEach(([k, v]) => {
223
- console.log(` ${k}: ${brand(String(v))}`);
316
+ process.stderr.write(` ${k}: ${brand(String(v))}\n`);
224
317
  });
225
318
  }
226
319
  }
@@ -253,10 +346,10 @@ export class JSONOutputWriter {
253
346
  console.log(JSON.stringify(value, null, 2));
254
347
  }
255
348
  success(message, details) {
256
- this.data({ success: true, message, ...details });
349
+ process.stderr.write(JSON.stringify({ success: true, message, ...details }) + '\n');
257
350
  }
258
351
  error(message, details) {
259
- this.data({ success: false, error: message, details });
352
+ process.stderr.write(JSON.stringify({ success: false, error: message, details }) + '\n');
260
353
  }
261
354
  progress(message) {
262
355
  if (!isQuietMode()) {
@@ -273,7 +366,7 @@ export class JSONOutputWriter {
273
366
  */
274
367
  export function createOutputWriter() {
275
368
  const mode = getOutputMode();
276
- return mode === 'json' ? new JSONOutputWriter() : new HumanOutputWriter();
369
+ return mode === 'json' ? new JSONOutputWriter() : new InteractiveOutputWriter();
277
370
  }
278
371
  /**
279
372
  * Create a no-op spinner (for quiet/JSON modes)
@@ -316,7 +316,7 @@ guild agent code # View source of latest version
316
316
 
317
317
  ## Key Rules
318
318
 
319
- - Agent code lives at `agent.ts` in the project root.
319
+ - Agent code lives in `agent.ts` (typically at the project root, but can be in a subdirectory like `src/`).
320
320
  - Don't add `@guildai/agents-sdk`, `zod`, or `@guildai-services/*` to `package.json`. The runtime provides them. Only add third-party packages you actually use.
321
321
  - Always call tools through `task.tools.<name>(args)`. Never access services directly.
322
322
  - Always use `guild agent save` to commit and `guild agent pull` to sync. Don't use raw git commands.
@@ -46,7 +46,7 @@ interface OutputWriter {
46
46
 
47
47
  Two implementations:
48
48
 
49
- - `HumanOutputWriter` - Colors, symbols, formatted output
49
+ - `InteractiveOutputWriter` - Colors, symbols, formatted output
50
50
  - `JSONOutputWriter` - Pure JSON
51
51
 
52
52
  Commands use `createOutputWriter()` to get the right implementation based on flags.
@@ -489,10 +489,23 @@ async function onToolResults(
489
489
 
490
490
  ### Slack-Specific Patterns
491
491
 
492
- When posting to Slack, convert markdown to Slack's mrkdwn format:
492
+ When posting to Slack, convert markdown to Slack's mrkdwn format. Use an inline converter
493
+ (`slackify-markdown` is CJS and breaks in the ESM agent runtime):
493
494
 
494
495
  ```typescript
495
- import slackifyMarkdown from 'slackify-markdown';
496
+ // Simple markdown-to-Slack-mrkdwn converter (inline — do NOT use slackify-markdown)
497
+ function slackifyMarkdown(md: string): string {
498
+ return md
499
+ .replace(/\*\*(.+?)\*\*/g, '*$1*') // bold: **text** → *text*
500
+ .replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, '_$1_') // italic: *text* → _text_
501
+ .replace(/~~(.+?)~~/g, '~$1~') // strikethrough
502
+ .replace(/^### (.+)$/gm, '*$1*') // h3 → bold
503
+ .replace(/^## (.+)$/gm, '*$1*') // h2 → bold
504
+ .replace(/^# (.+)$/gm, '*$1*') // h1 → bold
505
+ .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<$2|$1>') // links
506
+ .replace(/^> (.+)$/gm, '> $1') // blockquotes (same syntax)
507
+ .replace(/`([^`]+)`/g, '`$1`'); // inline code (same syntax)
508
+ }
496
509
 
497
510
  // In your agent:
498
511
  const responseText = '## Summary\n- Item 1\n- Item 2';
@@ -504,16 +517,6 @@ await task.tools.slack_chat_post_message({
504
517
  });
505
518
  ```
506
519
 
507
- Add `slackify-markdown` to `package.json` dependencies:
508
-
509
- ```json
510
- {
511
- "dependencies": {
512
- "slackify-markdown": "^4.5.0"
513
- }
514
- }
515
- ```
516
-
517
520
  ---
518
521
 
519
522
  ## Anti-Hallucination Guide
@@ -620,9 +623,7 @@ export default agent({ run: async (input, task) => { ... } })
620
623
  "version": "1.0.0",
621
624
  "author": "Guild.ai",
622
625
  "type": "module",
623
- "dependencies": {
624
- "slackify-markdown": "^4.5.0"
625
- },
626
+ "dependencies": {},
626
627
  "devDependencies": {
627
628
  "typescript": "^5.0.0"
628
629
  }
@@ -632,7 +633,7 @@ export default agent({ run: async (input, task) => { ... } })
632
633
  **Important:**
633
634
 
634
635
  - Do NOT add `@guildai/agents-sdk`, `@guildai-services/*`, or `zod` to dependencies. The runtime provides them.
635
- - DO add third-party packages your agent uses (e.g., `slackify-markdown`) to `dependencies`.
636
+ - DO add third-party ESM-compatible packages your agent uses to `dependencies`. Note: CJS-only packages (e.g., `slackify-markdown`) will break in the ESM agent runtime — use inline alternatives instead.
636
637
  - `devDependencies` is for build tools only.
637
638
 
638
639
  ## Versioning
@@ -649,7 +650,7 @@ After `guild agent create` + `guild agent init`:
649
650
  my-agent/
650
651
  ├── .git/ # Git repo (remote is Guild server)
651
652
  ├── .gitignore # Includes guild.json
652
- ├── agent.ts # Your agent code (at project root, NOT in src/)
653
+ ├── agent.ts # Your agent code (default location; can also be in src/)
653
654
  ├── package.json # Dependencies
654
655
  ├── tsconfig.json # TypeScript config
655
656
  └── guild.json # Agent ID (gitignored, local only)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guildai/cli",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
4
4
  "description": "Guild.ai CLI - Build, test, and deploy AI agents",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",