@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.
- package/dist/commands/agent/clone.js +22 -67
- package/dist/commands/agent/code.js +12 -32
- package/dist/commands/agent/create.js +14 -30
- package/dist/commands/agent/fork.js +27 -73
- package/dist/commands/agent/get.js +5 -4
- package/dist/commands/agent/grep.js +7 -9
- package/dist/commands/agent/init.js +2 -0
- package/dist/commands/agent/list.js +5 -6
- package/dist/commands/agent/publish.js +27 -44
- package/dist/commands/agent/pull.js +8 -35
- package/dist/commands/agent/revalidate.js +8 -16
- package/dist/commands/agent/save.js +30 -76
- package/dist/commands/agent/search.js +5 -6
- package/dist/commands/agent/tags/add.js +14 -24
- package/dist/commands/agent/tags/list.js +12 -23
- package/dist/commands/agent/tags/remove.js +16 -27
- package/dist/commands/agent/tags/set.js +14 -19
- package/dist/commands/agent/unpublish.js +12 -17
- package/dist/commands/agent/update.js +12 -29
- package/dist/commands/agent/versions.js +13 -11
- package/dist/commands/agent/workspaces.d.ts +3 -0
- package/dist/commands/agent/workspaces.js +51 -0
- package/dist/commands/auth/login.js +4 -2
- package/dist/commands/auth/logout.js +3 -1
- package/dist/commands/auth/status.js +4 -3
- package/dist/commands/auth/token.js +3 -2
- package/dist/commands/config/get.js +7 -9
- package/dist/commands/config/list.js +13 -11
- package/dist/commands/config/path.js +6 -4
- package/dist/commands/config/set.js +17 -22
- package/dist/commands/doctor.js +9 -7
- package/dist/commands/session/create.js +7 -5
- package/dist/commands/session/events.js +5 -3
- package/dist/commands/session/get.js +5 -3
- package/dist/commands/session/list.js +5 -4
- package/dist/commands/session/send.js +7 -5
- package/dist/commands/session/tasks.js +5 -3
- package/dist/commands/setup.js +15 -14
- package/dist/commands/trigger/activate.js +7 -6
- package/dist/commands/trigger/create.js +16 -15
- package/dist/commands/trigger/deactivate.js +7 -6
- package/dist/commands/trigger/get.js +5 -4
- package/dist/commands/trigger/list.js +5 -5
- package/dist/commands/trigger/sessions.js +7 -6
- package/dist/commands/trigger/update.js +11 -10
- package/dist/commands/version.js +7 -5
- package/dist/commands/workspace/agent/add.js +16 -22
- package/dist/commands/workspace/agent/list.js +12 -32
- package/dist/commands/workspace/agent/remove.js +9 -15
- package/dist/commands/workspace/context/edit.js +13 -27
- package/dist/commands/workspace/context/get.js +8 -14
- package/dist/commands/workspace/context/list.js +12 -37
- package/dist/commands/workspace/context/publish.js +7 -11
- package/dist/commands/workspace/create.js +7 -11
- package/dist/commands/workspace/current.js +19 -31
- package/dist/commands/workspace/get.js +7 -11
- package/dist/commands/workspace/list.js +5 -8
- package/dist/commands/workspace/select.js +17 -22
- package/dist/index.js +2 -0
- package/dist/lib/agent-helpers.js +2 -2
- package/dist/lib/generated-types.d.ts +1 -1
- package/dist/lib/generated-types.js +1 -0
- package/dist/lib/npmrc.js +9 -1
- package/dist/lib/output.d.ts +18 -4
- package/dist/lib/output.js +112 -19
- package/docs/getting-started.md +1 -1
- package/docs/output-format.md +1 -1
- package/docs/skills/agent-dev.md +18 -17
- 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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
52
|
+
output.success(`Workspace set for this agent: ${formatWorkspaceDisplay(workspace)}`);
|
|
54
53
|
}
|
|
55
54
|
else {
|
|
56
|
-
|
|
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
|
-
|
|
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
|
-
|
|
93
|
+
output.success(`Workspace set for this agent: ${formatWorkspaceDisplay(selectedWorkspace)}`);
|
|
95
94
|
}
|
|
96
95
|
else {
|
|
97
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
70
|
-
const missing = REQUIRED_AGENT_FILES.filter((
|
|
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];
|
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', [
|
|
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
|
package/dist/lib/output.d.ts
CHANGED
|
@@ -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
|
-
* -
|
|
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
|
|
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;
|
package/dist/lib/output.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
313
|
+
process.stderr.write(chalk.green('✓') + ' ' + message + '\n');
|
|
221
314
|
if (details) {
|
|
222
315
|
Object.entries(details).forEach(([k, v]) => {
|
|
223
|
-
|
|
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
|
-
|
|
349
|
+
process.stderr.write(JSON.stringify({ success: true, message, ...details }) + '\n');
|
|
257
350
|
}
|
|
258
351
|
error(message, details) {
|
|
259
|
-
|
|
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
|
|
369
|
+
return mode === 'json' ? new JSONOutputWriter() : new InteractiveOutputWriter();
|
|
277
370
|
}
|
|
278
371
|
/**
|
|
279
372
|
* Create a no-op spinner (for quiet/JSON modes)
|
package/docs/getting-started.md
CHANGED
|
@@ -316,7 +316,7 @@ guild agent code # View source of latest version
|
|
|
316
316
|
|
|
317
317
|
## Key Rules
|
|
318
318
|
|
|
319
|
-
- Agent code lives
|
|
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.
|
package/docs/output-format.md
CHANGED
|
@@ -46,7 +46,7 @@ interface OutputWriter {
|
|
|
46
46
|
|
|
47
47
|
Two implementations:
|
|
48
48
|
|
|
49
|
-
- `
|
|
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.
|
package/docs/skills/agent-dev.md
CHANGED
|
@@ -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
|
-
|
|
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`)
|
|
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 (
|
|
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)
|