@guildai/cli 0.5.6 → 0.5.8
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/chat.js +2 -1
- package/dist/commands/agent/clone.js +2 -1
- package/dist/commands/agent/code.js +2 -1
- package/dist/commands/agent/create.js +2 -1
- package/dist/commands/agent/fork.js +2 -1
- package/dist/commands/agent/get.js +2 -1
- package/dist/commands/agent/grep.js +2 -1
- package/dist/commands/agent/init.js +2 -1
- package/dist/commands/agent/list.js +2 -1
- package/dist/commands/agent/owners.js +2 -1
- package/dist/commands/agent/publish.js +2 -1
- package/dist/commands/agent/pull.js +2 -1
- package/dist/commands/agent/revalidate.js +2 -1
- package/dist/commands/agent/save.js +2 -1
- package/dist/commands/agent/search.js +2 -1
- package/dist/commands/agent/tags/add.js +2 -1
- package/dist/commands/agent/tags/list.js +2 -1
- package/dist/commands/agent/tags/remove.js +2 -1
- package/dist/commands/agent/tags/set.js +2 -1
- package/dist/commands/agent/test.js +2 -1
- package/dist/commands/agent/unpublish.js +2 -1
- package/dist/commands/agent/update.js +2 -1
- package/dist/commands/agent/versions.js +2 -1
- package/dist/commands/agent/workspaces.js +2 -1
- package/dist/commands/auth/login.js +2 -1
- package/dist/commands/auth/logout.js +2 -1
- package/dist/commands/auth/status.js +2 -1
- package/dist/commands/auth/token.js +2 -1
- package/dist/commands/chat.js +2 -1
- package/dist/commands/config/get.js +2 -1
- package/dist/commands/config/list.js +2 -1
- package/dist/commands/config/path.js +2 -1
- package/dist/commands/config/set.js +2 -1
- package/dist/commands/doctor.js +2 -1
- package/dist/commands/mcp.d.ts +3 -0
- package/dist/commands/mcp.js +34 -0
- package/dist/commands/session/create.js +2 -1
- package/dist/commands/session/events.js +2 -1
- package/dist/commands/session/get.js +2 -1
- package/dist/commands/session/list.js +2 -1
- package/dist/commands/session/send.js +2 -1
- package/dist/commands/session/tasks.js +2 -1
- package/dist/commands/setup.js +39 -1
- package/dist/commands/trigger/activate.js +2 -1
- package/dist/commands/trigger/create.js +2 -1
- package/dist/commands/trigger/deactivate.js +2 -1
- package/dist/commands/trigger/get.js +2 -1
- package/dist/commands/trigger/list.js +2 -1
- package/dist/commands/trigger/sessions.js +2 -1
- package/dist/commands/trigger/update.js +2 -1
- package/dist/commands/version.js +2 -1
- package/dist/commands/workspace/agent/add.js +2 -1
- package/dist/commands/workspace/agent/list.js +2 -1
- package/dist/commands/workspace/agent/remove.js +2 -1
- package/dist/commands/workspace/context/edit.js +2 -1
- package/dist/commands/workspace/context/get.js +2 -1
- package/dist/commands/workspace/context/list.js +2 -1
- package/dist/commands/workspace/context/publish.js +2 -1
- package/dist/commands/workspace/create.js +2 -1
- package/dist/commands/workspace/current.js +2 -1
- package/dist/commands/workspace/get.js +2 -1
- package/dist/commands/workspace/list.js +2 -1
- package/dist/commands/workspace/select.js +2 -1
- package/dist/components/AgentInstallPrompt.js +2 -1
- package/dist/components/SplashAnimation.js +2 -1
- package/dist/components/TaskView.js +2 -1
- package/dist/index.js +11 -4
- package/dist/lib/agent-helpers.js +2 -1
- package/dist/lib/alternate-screen.js +2 -1
- package/dist/lib/api-client.js +2 -1
- package/dist/lib/api-types.js +2 -1
- package/dist/lib/auth.js +2 -1
- package/dist/lib/braille-canvas.js +2 -1
- package/dist/lib/colors.js +2 -1
- package/dist/lib/config-cache.js +2 -1
- package/dist/lib/config.js +2 -1
- package/dist/lib/did-you-mean.js +2 -1
- package/dist/lib/errors.js +2 -1
- package/dist/lib/git.js +2 -1
- package/dist/lib/guild-config.js +2 -1
- package/dist/lib/iap.js +2 -1
- package/dist/lib/loading-messages.js +2 -1
- package/dist/lib/logo.js +2 -1
- package/dist/lib/lottie-renderer.js +2 -1
- package/dist/lib/lottie-serverside.js +2 -1
- package/dist/lib/markdown.js +2 -1
- package/dist/lib/npmrc.js +2 -1
- package/dist/lib/output-mode.js +2 -1
- package/dist/lib/output.js +2 -1
- package/dist/lib/owner-helpers.js +2 -1
- package/dist/lib/polling.js +2 -1
- package/dist/lib/progress.js +2 -1
- package/dist/lib/session-events.js +2 -1
- package/dist/lib/session-polling.js +2 -1
- package/dist/lib/session-resume.js +2 -1
- package/dist/lib/spinners.js +2 -1
- package/dist/lib/splash.js +2 -1
- package/dist/lib/stdin.js +2 -1
- package/dist/lib/svg-renderer.js +2 -1
- package/dist/lib/svg-to-braille.js +2 -1
- package/dist/lib/update-check.js +2 -1
- package/dist/mcp/resources.d.ts +4 -0
- package/dist/mcp/resources.js +67 -0
- package/dist/mcp/server.d.ts +6 -0
- package/dist/mcp/server.js +64 -0
- package/dist/mcp/tools.d.ts +4 -0
- package/dist/mcp/tools.js +783 -0
- package/docs/skills/agent-dev.md +993 -0
- package/package.json +6 -2
|
@@ -0,0 +1,783 @@
|
|
|
1
|
+
// Copyright 2026 Guild.ai
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
// Constants
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
const POLL_INTERVAL_MS = 500;
|
|
8
|
+
const POLL_TIMEOUT_MS = 120_000;
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
// Helpers
|
|
11
|
+
// ---------------------------------------------------------------------------
|
|
12
|
+
function debugLog(debug, message) {
|
|
13
|
+
if (debug) {
|
|
14
|
+
process.stderr.write(`[guild-mcp] ${message}\n`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Poll session events until runtime_done or runtime_error.
|
|
19
|
+
* Returns collected agent messages.
|
|
20
|
+
*/
|
|
21
|
+
async function pollForResponse(apiClient, sessionId, debug) {
|
|
22
|
+
const startTime = Date.now();
|
|
23
|
+
const messages = [];
|
|
24
|
+
let lastEventId;
|
|
25
|
+
while (Date.now() - startTime < POLL_TIMEOUT_MS) {
|
|
26
|
+
try {
|
|
27
|
+
const response = await apiClient.get(`/sessions/${sessionId}/events`);
|
|
28
|
+
const events = response.events || [];
|
|
29
|
+
// Find new events after last seen
|
|
30
|
+
let foundLast = !lastEventId;
|
|
31
|
+
for (const event of events) {
|
|
32
|
+
if (!foundLast) {
|
|
33
|
+
if (event.id === lastEventId) {
|
|
34
|
+
foundLast = true;
|
|
35
|
+
}
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
debugLog(debug, `Event: ${event.event_type}`);
|
|
39
|
+
if (event.event_type === 'agent_notification_message') {
|
|
40
|
+
const data = extractEventText(event);
|
|
41
|
+
if (data) {
|
|
42
|
+
messages.push(data);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (event.event_type === 'runtime_error') {
|
|
46
|
+
const errorText = extractEventText(event);
|
|
47
|
+
if (errorText) {
|
|
48
|
+
return `Error: ${errorText}`;
|
|
49
|
+
}
|
|
50
|
+
return 'Error: Agent encountered an error';
|
|
51
|
+
}
|
|
52
|
+
if (event.event_type === 'runtime_done') {
|
|
53
|
+
debugLog(debug, 'Runtime done');
|
|
54
|
+
return messages.join('\n\n') || 'Agent completed without output.';
|
|
55
|
+
}
|
|
56
|
+
lastEventId = event.id;
|
|
57
|
+
}
|
|
58
|
+
// Update lastEventId to latest
|
|
59
|
+
if (events.length > 0) {
|
|
60
|
+
lastEventId = events[events.length - 1].id;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
debugLog(debug, `Poll error: ${String(error)}`);
|
|
65
|
+
}
|
|
66
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
67
|
+
}
|
|
68
|
+
return messages.length > 0
|
|
69
|
+
? messages.join('\n\n') + '\n\n(Timed out waiting for completion)'
|
|
70
|
+
: 'Timed out waiting for agent response.';
|
|
71
|
+
}
|
|
72
|
+
function extractEventText(event) {
|
|
73
|
+
if (!event.content)
|
|
74
|
+
return undefined;
|
|
75
|
+
if (typeof event.content === 'string') {
|
|
76
|
+
return event.content;
|
|
77
|
+
}
|
|
78
|
+
if (typeof event.content === 'object' && event.content.data) {
|
|
79
|
+
return event.content.data;
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
function errText(action, error) {
|
|
84
|
+
return `Failed to ${action}: ${error instanceof Error ? error.message : String(error)}`;
|
|
85
|
+
}
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Tool registration
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
export function registerTools(server, apiClient, workspaceId, debug) {
|
|
90
|
+
// =========================================================================
|
|
91
|
+
// User
|
|
92
|
+
// =========================================================================
|
|
93
|
+
server.tool('guild_whoami', 'Get current user info', {}, async () => {
|
|
94
|
+
debugLog(debug, 'guild_whoami');
|
|
95
|
+
try {
|
|
96
|
+
const me = await apiClient.get('/me');
|
|
97
|
+
const text = [`Name: ${me.name}`, `ID: ${me.id}`, `Type: ${me.type}`].join('\n');
|
|
98
|
+
return { content: [{ type: 'text', text }] };
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
return {
|
|
102
|
+
content: [{ type: 'text', text: errText('get user info', error) }],
|
|
103
|
+
isError: true,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
// =========================================================================
|
|
108
|
+
// Workspaces
|
|
109
|
+
// =========================================================================
|
|
110
|
+
server.tool('guild_list_workspaces', 'List workspaces the current user has access to', {
|
|
111
|
+
search: z.string().optional().describe('Filter workspaces by name'),
|
|
112
|
+
limit: z
|
|
113
|
+
.number()
|
|
114
|
+
.int()
|
|
115
|
+
.min(1)
|
|
116
|
+
.max(100)
|
|
117
|
+
.optional()
|
|
118
|
+
.describe('Max results (default 20)'),
|
|
119
|
+
}, async ({ search, limit }) => {
|
|
120
|
+
debugLog(debug, `guild_list_workspaces: search=${search || ''}`);
|
|
121
|
+
try {
|
|
122
|
+
const params = new URLSearchParams();
|
|
123
|
+
if (search)
|
|
124
|
+
params.set('search', search);
|
|
125
|
+
params.set('limit', String(limit || 20));
|
|
126
|
+
const response = await apiClient.get(`/me/workspaces?${params.toString()}`);
|
|
127
|
+
const text = response.items
|
|
128
|
+
.map((w) => `• ${w.full_name || w.name} (${w.id})`)
|
|
129
|
+
.join('\n');
|
|
130
|
+
return {
|
|
131
|
+
content: [{ type: 'text', text: text || 'No workspaces found.' }],
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: 'text', text: errText('list workspaces', error) }],
|
|
137
|
+
isError: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
server.tool('guild_get_workspace', 'Get workspace details including context', {
|
|
142
|
+
workspace_id: z
|
|
143
|
+
.string()
|
|
144
|
+
.optional()
|
|
145
|
+
.describe('Workspace ID (defaults to current workspace)'),
|
|
146
|
+
}, async ({ workspace_id }) => {
|
|
147
|
+
const wsId = workspace_id || workspaceId;
|
|
148
|
+
debugLog(debug, `guild_get_workspace: ${wsId}`);
|
|
149
|
+
try {
|
|
150
|
+
const ws = await apiClient.get(`/workspaces/${wsId}`);
|
|
151
|
+
const ownerLine = ws.owner
|
|
152
|
+
? `Owner: ${ws.owner.name} (${ws.owner.type})`
|
|
153
|
+
: null;
|
|
154
|
+
const text = [`Name: ${ws.full_name || ws.name}`, `ID: ${ws.id}`, ownerLine]
|
|
155
|
+
.filter(Boolean)
|
|
156
|
+
.join('\n');
|
|
157
|
+
return { content: [{ type: 'text', text }] };
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
return {
|
|
161
|
+
content: [{ type: 'text', text: errText('get workspace', error) }],
|
|
162
|
+
isError: true,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
server.tool('guild_list_workspace_agents', 'List agents installed in the current workspace', {
|
|
167
|
+
search: z.string().optional().describe('Filter agents by name'),
|
|
168
|
+
}, async ({ search }) => {
|
|
169
|
+
debugLog(debug, `guild_list_workspace_agents: search=${search || ''}`);
|
|
170
|
+
try {
|
|
171
|
+
let endpoint = `/workspaces/${workspaceId}/workspace_agents`;
|
|
172
|
+
if (search)
|
|
173
|
+
endpoint += `?search=${encodeURIComponent(search)}`;
|
|
174
|
+
const agents = await apiClient.fetchAll(endpoint);
|
|
175
|
+
const text = agents
|
|
176
|
+
.map((wa) => {
|
|
177
|
+
const name = wa.agent.full_name || wa.agent.name;
|
|
178
|
+
const version = wa.agent_version.version_number ||
|
|
179
|
+
wa.agent_version.sha?.slice(0, 7) ||
|
|
180
|
+
'latest';
|
|
181
|
+
return `• ${name} (workspace_agent: ${wa.id}, agent: ${wa.agent.id}) — v${version}`;
|
|
182
|
+
})
|
|
183
|
+
.join('\n');
|
|
184
|
+
return {
|
|
185
|
+
content: [{ type: 'text', text: text || 'No agents in workspace.' }],
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
return {
|
|
190
|
+
content: [
|
|
191
|
+
{ type: 'text', text: errText('list workspace agents', error) },
|
|
192
|
+
],
|
|
193
|
+
isError: true,
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
server.tool('guild_add_workspace_agent', 'Install an agent in the current workspace', {
|
|
198
|
+
agent_id: z.string().describe('The agent ID to install'),
|
|
199
|
+
}, async ({ agent_id }) => {
|
|
200
|
+
debugLog(debug, `guild_add_workspace_agent: ${agent_id}`);
|
|
201
|
+
try {
|
|
202
|
+
const wa = await apiClient.post(`/workspaces/${workspaceId}/workspace_agents`, { agent_id });
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: 'text',
|
|
207
|
+
text: `Installed agent ${wa.agent.full_name || wa.agent.name} (workspace_agent: ${wa.id})`,
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
return {
|
|
214
|
+
content: [
|
|
215
|
+
{ type: 'text', text: errText('add workspace agent', error) },
|
|
216
|
+
],
|
|
217
|
+
isError: true,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
server.tool('guild_remove_workspace_agent', 'Remove an agent from the workspace', {
|
|
222
|
+
workspace_agent_id: z.string().describe('The workspace agent ID to remove'),
|
|
223
|
+
}, async ({ workspace_agent_id }) => {
|
|
224
|
+
debugLog(debug, `guild_remove_workspace_agent: ${workspace_agent_id}`);
|
|
225
|
+
try {
|
|
226
|
+
await apiClient.delete(`/workspace_agents/${workspace_agent_id}`);
|
|
227
|
+
return {
|
|
228
|
+
content: [
|
|
229
|
+
{
|
|
230
|
+
type: 'text',
|
|
231
|
+
text: `Removed workspace agent ${workspace_agent_id}.`,
|
|
232
|
+
},
|
|
233
|
+
],
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
return {
|
|
238
|
+
content: [
|
|
239
|
+
{ type: 'text', text: errText('remove workspace agent', error) },
|
|
240
|
+
],
|
|
241
|
+
isError: true,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
// =========================================================================
|
|
246
|
+
// Contexts
|
|
247
|
+
// =========================================================================
|
|
248
|
+
server.tool('guild_list_contexts', 'List context versions for the current workspace', {
|
|
249
|
+
limit: z
|
|
250
|
+
.number()
|
|
251
|
+
.int()
|
|
252
|
+
.min(1)
|
|
253
|
+
.max(100)
|
|
254
|
+
.optional()
|
|
255
|
+
.describe('Max results (default 20)'),
|
|
256
|
+
}, async ({ limit }) => {
|
|
257
|
+
debugLog(debug, 'guild_list_contexts');
|
|
258
|
+
try {
|
|
259
|
+
const response = await apiClient.get(`/workspaces/${workspaceId}/contexts?limit=${limit || 20}`);
|
|
260
|
+
const text = response.items
|
|
261
|
+
.map((c) => {
|
|
262
|
+
const summary = c.summary ? ` — ${c.summary}` : '';
|
|
263
|
+
return `• ${c.id} [${c.status}] ${c.created_at}${summary}`;
|
|
264
|
+
})
|
|
265
|
+
.join('\n');
|
|
266
|
+
return {
|
|
267
|
+
content: [{ type: 'text', text: text || 'No contexts found.' }],
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
return {
|
|
272
|
+
content: [{ type: 'text', text: errText('list contexts', error) }],
|
|
273
|
+
isError: true,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
server.tool('guild_get_context', 'Get the content of a specific context version', {
|
|
278
|
+
context_id: z.string().describe('The context ID'),
|
|
279
|
+
}, async ({ context_id }) => {
|
|
280
|
+
debugLog(debug, `guild_get_context: ${context_id}`);
|
|
281
|
+
try {
|
|
282
|
+
const ctx = await apiClient.get(`/contexts/${context_id}`);
|
|
283
|
+
const sections = [
|
|
284
|
+
`Context: ${ctx.id}`,
|
|
285
|
+
`Status: ${ctx.status}`,
|
|
286
|
+
`Created: ${ctx.created_at}`,
|
|
287
|
+
];
|
|
288
|
+
if (ctx.summary)
|
|
289
|
+
sections.push(`Summary: ${ctx.summary}`);
|
|
290
|
+
if (ctx.manual_context) {
|
|
291
|
+
sections.push('', '--- Manual Context ---', ctx.manual_context);
|
|
292
|
+
}
|
|
293
|
+
if (ctx.generated_context) {
|
|
294
|
+
sections.push('', '--- Generated Context ---', ctx.generated_context);
|
|
295
|
+
}
|
|
296
|
+
return { content: [{ type: 'text', text: sections.join('\n') }] };
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
return {
|
|
300
|
+
content: [{ type: 'text', text: errText('get context', error) }],
|
|
301
|
+
isError: true,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
server.tool('guild_publish_context', 'Create or publish a new context version for the workspace', {
|
|
306
|
+
content: z.string().describe('The context content to publish'),
|
|
307
|
+
status: z
|
|
308
|
+
.enum(['ACTIVE', 'ARCHIVED'])
|
|
309
|
+
.optional()
|
|
310
|
+
.describe('Context status (default ACTIVE)'),
|
|
311
|
+
summary: z.string().optional().describe('Short summary of the context'),
|
|
312
|
+
}, async ({ content, status, summary }) => {
|
|
313
|
+
debugLog(debug, 'guild_publish_context');
|
|
314
|
+
try {
|
|
315
|
+
const body = { manual_context: content };
|
|
316
|
+
if (status)
|
|
317
|
+
body.status = status;
|
|
318
|
+
if (summary)
|
|
319
|
+
body.summary = summary;
|
|
320
|
+
const ctx = await apiClient.post(`/workspaces/${workspaceId}/contexts`, body);
|
|
321
|
+
return {
|
|
322
|
+
content: [
|
|
323
|
+
{
|
|
324
|
+
type: 'text',
|
|
325
|
+
text: `Published context ${ctx.id} [${ctx.status}]`,
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
catch (error) {
|
|
331
|
+
return {
|
|
332
|
+
content: [{ type: 'text', text: errText('publish context', error) }],
|
|
333
|
+
isError: true,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
// =========================================================================
|
|
338
|
+
// Agents (catalog)
|
|
339
|
+
// =========================================================================
|
|
340
|
+
server.tool('guild_search_agents', 'Search or list agents in the Guild catalog', {
|
|
341
|
+
search: z.string().optional().describe('Search query to filter agents by name'),
|
|
342
|
+
published_only: z
|
|
343
|
+
.boolean()
|
|
344
|
+
.optional()
|
|
345
|
+
.describe('Only show published agents (default true)'),
|
|
346
|
+
limit: z
|
|
347
|
+
.number()
|
|
348
|
+
.int()
|
|
349
|
+
.min(1)
|
|
350
|
+
.max(100)
|
|
351
|
+
.optional()
|
|
352
|
+
.describe('Max results (default 20)'),
|
|
353
|
+
}, async ({ search, published_only, limit }) => {
|
|
354
|
+
debugLog(debug, `guild_search_agents: search=${search || ''}`);
|
|
355
|
+
try {
|
|
356
|
+
const params = new URLSearchParams();
|
|
357
|
+
if (search)
|
|
358
|
+
params.set('search', search);
|
|
359
|
+
if (published_only !== undefined)
|
|
360
|
+
params.set('published_only', String(published_only));
|
|
361
|
+
params.set('limit', String(limit || 20));
|
|
362
|
+
const response = await apiClient.get(`/agents?${params.toString()}`);
|
|
363
|
+
const text = response.items
|
|
364
|
+
.map((a) => {
|
|
365
|
+
const name = a.full_name || a.name;
|
|
366
|
+
const desc = a.description ? ` — ${a.description}` : '';
|
|
367
|
+
return `• ${name} (${a.id})${desc}`;
|
|
368
|
+
})
|
|
369
|
+
.join('\n');
|
|
370
|
+
return {
|
|
371
|
+
content: [{ type: 'text', text: text || 'No agents found.' }],
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
return {
|
|
376
|
+
content: [{ type: 'text', text: errText('search agents', error) }],
|
|
377
|
+
isError: true,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
server.tool('guild_get_agent', 'Get details for a specific Guild agent', {
|
|
382
|
+
agent_id: z
|
|
383
|
+
.string()
|
|
384
|
+
.describe('The agent ID or full name (e.g. owner/agent-name)'),
|
|
385
|
+
}, async ({ agent_id }) => {
|
|
386
|
+
debugLog(debug, `guild_get_agent: ${agent_id}`);
|
|
387
|
+
try {
|
|
388
|
+
const agent = await apiClient.get(`/agents/${agent_id}`);
|
|
389
|
+
const lines = [
|
|
390
|
+
`Name: ${agent.full_name || agent.name}`,
|
|
391
|
+
`ID: ${agent.id}`,
|
|
392
|
+
`Status: ${agent.status}`,
|
|
393
|
+
agent.description ? `Description: ${agent.description}` : null,
|
|
394
|
+
agent.owner ? `Owner: ${agent.owner.name}` : null,
|
|
395
|
+
agent.is_public !== undefined ? `Public: ${agent.is_public}` : null,
|
|
396
|
+
];
|
|
397
|
+
return {
|
|
398
|
+
content: [{ type: 'text', text: lines.filter(Boolean).join('\n') }],
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
return {
|
|
403
|
+
content: [{ type: 'text', text: errText('get agent', error) }],
|
|
404
|
+
isError: true,
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
server.tool('guild_get_agent_readme', 'Get the README for a Guild agent', {
|
|
409
|
+
agent_id: z.string().describe('The agent ID or full name'),
|
|
410
|
+
}, async ({ agent_id }) => {
|
|
411
|
+
debugLog(debug, `guild_get_agent_readme: ${agent_id}`);
|
|
412
|
+
try {
|
|
413
|
+
const readme = await apiClient.get(`/agents/${agent_id}/readme`);
|
|
414
|
+
return { content: [{ type: 'text', text: readme.content }] };
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
return {
|
|
418
|
+
content: [
|
|
419
|
+
{ type: 'text', text: errText('get agent readme', error) },
|
|
420
|
+
],
|
|
421
|
+
isError: true,
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
server.tool('guild_get_agent_code', 'Get the source code files for a Guild agent', {
|
|
426
|
+
agent_id: z.string().describe('The agent ID or full name'),
|
|
427
|
+
}, async ({ agent_id }) => {
|
|
428
|
+
debugLog(debug, `guild_get_agent_code: ${agent_id}`);
|
|
429
|
+
try {
|
|
430
|
+
const files = await apiClient.get(`/agents/${agent_id}/code`);
|
|
431
|
+
if (files.length === 0) {
|
|
432
|
+
return {
|
|
433
|
+
content: [{ type: 'text', text: 'No source files found.' }],
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
const text = files.map((f) => `--- ${f.path} ---\n${f.content}`).join('\n\n');
|
|
437
|
+
return { content: [{ type: 'text', text }] };
|
|
438
|
+
}
|
|
439
|
+
catch (error) {
|
|
440
|
+
return {
|
|
441
|
+
content: [{ type: 'text', text: errText('get agent code', error) }],
|
|
442
|
+
isError: true,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
server.tool('guild_list_agent_versions', 'List versions of a Guild agent', {
|
|
447
|
+
agent_id: z.string().describe('The agent ID or full name'),
|
|
448
|
+
limit: z
|
|
449
|
+
.number()
|
|
450
|
+
.int()
|
|
451
|
+
.min(1)
|
|
452
|
+
.max(100)
|
|
453
|
+
.optional()
|
|
454
|
+
.describe('Max results (default 20)'),
|
|
455
|
+
}, async ({ agent_id, limit }) => {
|
|
456
|
+
debugLog(debug, `guild_list_agent_versions: ${agent_id}`);
|
|
457
|
+
try {
|
|
458
|
+
const response = await apiClient.get(`/agents/${agent_id}/versions?limit=${limit || 20}`);
|
|
459
|
+
const text = response.items
|
|
460
|
+
.map((v) => {
|
|
461
|
+
const version = v.version_number || v.sha?.slice(0, 7) || 'ephemeral';
|
|
462
|
+
return `• ${version} (${v.id}) [${v.status}] — ${v.summary} — ${v.created_at}`;
|
|
463
|
+
})
|
|
464
|
+
.join('\n');
|
|
465
|
+
return {
|
|
466
|
+
content: [{ type: 'text', text: text || 'No versions found.' }],
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
return {
|
|
471
|
+
content: [
|
|
472
|
+
{ type: 'text', text: errText('list agent versions', error) },
|
|
473
|
+
],
|
|
474
|
+
isError: true,
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
// =========================================================================
|
|
479
|
+
// Sessions
|
|
480
|
+
// =========================================================================
|
|
481
|
+
server.tool('guild_chat', 'Start a new chat session with a Guild agent and get a response', {
|
|
482
|
+
message: z.string().describe('The message to send to the agent'),
|
|
483
|
+
agent: z
|
|
484
|
+
.string()
|
|
485
|
+
.optional()
|
|
486
|
+
.describe('Agent identifier (e.g. owner/agent-name). Uses workspace default if not specified'),
|
|
487
|
+
}, async ({ message, agent }) => {
|
|
488
|
+
debugLog(debug, `guild_chat: message="${message}", agent=${agent || 'default'}`);
|
|
489
|
+
try {
|
|
490
|
+
const body = {
|
|
491
|
+
session_type: 'chat',
|
|
492
|
+
initial_prompt: message,
|
|
493
|
+
};
|
|
494
|
+
if (agent) {
|
|
495
|
+
body.agent_id = agent;
|
|
496
|
+
}
|
|
497
|
+
const session = await apiClient.post(`/workspaces/${workspaceId}/sessions`, body);
|
|
498
|
+
debugLog(debug, `Session created: ${session.id}`);
|
|
499
|
+
const response = await pollForResponse(apiClient, session.id, debug);
|
|
500
|
+
return {
|
|
501
|
+
content: [{ type: 'text', text: response }],
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
catch (error) {
|
|
505
|
+
return {
|
|
506
|
+
content: [{ type: 'text', text: errText('chat', error) }],
|
|
507
|
+
isError: true,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
server.tool('guild_send_message', 'Send a follow-up message to an existing Guild session', {
|
|
512
|
+
session_id: z.string().describe('The session ID to send the message to'),
|
|
513
|
+
message: z.string().describe('The message to send'),
|
|
514
|
+
}, async ({ session_id, message }) => {
|
|
515
|
+
debugLog(debug, `guild_send_message: session=${session_id}`);
|
|
516
|
+
try {
|
|
517
|
+
await apiClient.post(`/sessions/${session_id}/events`, {
|
|
518
|
+
event_type: 'user_message',
|
|
519
|
+
content: { type: 'text', data: message },
|
|
520
|
+
});
|
|
521
|
+
const response = await pollForResponse(apiClient, session_id, debug);
|
|
522
|
+
return {
|
|
523
|
+
content: [{ type: 'text', text: response }],
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
catch (error) {
|
|
527
|
+
return {
|
|
528
|
+
content: [{ type: 'text', text: errText('send message', error) }],
|
|
529
|
+
isError: true,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
});
|
|
533
|
+
server.tool('guild_list_sessions', 'List recent sessions in the current Guild workspace', {
|
|
534
|
+
limit: z
|
|
535
|
+
.number()
|
|
536
|
+
.int()
|
|
537
|
+
.min(1)
|
|
538
|
+
.max(100)
|
|
539
|
+
.optional()
|
|
540
|
+
.describe('Number of sessions to return (default 20)'),
|
|
541
|
+
}, async ({ limit }) => {
|
|
542
|
+
debugLog(debug, 'guild_list_sessions');
|
|
543
|
+
try {
|
|
544
|
+
const queryLimit = limit || 20;
|
|
545
|
+
const response = await apiClient.get(`/workspaces/${workspaceId}/sessions?limit=${queryLimit}`);
|
|
546
|
+
const text = response.items
|
|
547
|
+
.map((s) => `• ${s.id} (${s.session_type}) — ${s.created_at}`)
|
|
548
|
+
.join('\n');
|
|
549
|
+
return {
|
|
550
|
+
content: [{ type: 'text', text: text || 'No sessions found.' }],
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
catch (error) {
|
|
554
|
+
return {
|
|
555
|
+
content: [{ type: 'text', text: errText('list sessions', error) }],
|
|
556
|
+
isError: true,
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
server.tool('guild_get_session', 'Get session details and recent events from a Guild session', {
|
|
561
|
+
session_id: z.string().describe('The session ID'),
|
|
562
|
+
}, async ({ session_id }) => {
|
|
563
|
+
debugLog(debug, `guild_get_session: ${session_id}`);
|
|
564
|
+
try {
|
|
565
|
+
const [session, eventsResponse] = await Promise.all([
|
|
566
|
+
apiClient.get(`/sessions/${session_id}`),
|
|
567
|
+
apiClient.get(`/sessions/${session_id}/events`),
|
|
568
|
+
]);
|
|
569
|
+
const events = eventsResponse.events || [];
|
|
570
|
+
const recentEvents = events.slice(-20);
|
|
571
|
+
const eventLines = recentEvents.map((e) => {
|
|
572
|
+
const text = extractEventText(e);
|
|
573
|
+
const preview = text
|
|
574
|
+
? `: ${text.slice(0, 100)}${text.length > 100 ? '...' : ''}`
|
|
575
|
+
: '';
|
|
576
|
+
return ` [${e.event_type}]${preview}`;
|
|
577
|
+
});
|
|
578
|
+
const text = [
|
|
579
|
+
`Session: ${session.id}`,
|
|
580
|
+
`Type: ${session.session_type}`,
|
|
581
|
+
`Created: ${session.created_at}`,
|
|
582
|
+
`Updated: ${session.updated_at}`,
|
|
583
|
+
'',
|
|
584
|
+
`Recent events (${recentEvents.length} of ${events.length}):`,
|
|
585
|
+
...eventLines,
|
|
586
|
+
].join('\n');
|
|
587
|
+
return {
|
|
588
|
+
content: [{ type: 'text', text }],
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
catch (error) {
|
|
592
|
+
return {
|
|
593
|
+
content: [{ type: 'text', text: errText('get session', error) }],
|
|
594
|
+
isError: true,
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
});
|
|
598
|
+
server.tool('guild_get_session_events', 'Get events from a Guild session with pagination', {
|
|
599
|
+
session_id: z.string().describe('The session ID'),
|
|
600
|
+
limit: z
|
|
601
|
+
.number()
|
|
602
|
+
.int()
|
|
603
|
+
.min(1)
|
|
604
|
+
.max(200)
|
|
605
|
+
.optional()
|
|
606
|
+
.describe('Max events to return (default 50)'),
|
|
607
|
+
}, async ({ session_id, limit }) => {
|
|
608
|
+
debugLog(debug, `guild_get_session_events: ${session_id}`);
|
|
609
|
+
try {
|
|
610
|
+
const response = await apiClient.get(`/sessions/${session_id}/events`);
|
|
611
|
+
const events = response.events || [];
|
|
612
|
+
const maxEvents = limit || 50;
|
|
613
|
+
const displayed = events.slice(-maxEvents);
|
|
614
|
+
const lines = displayed.map((e) => {
|
|
615
|
+
const text = extractEventText(e);
|
|
616
|
+
const preview = text
|
|
617
|
+
? `: ${text.slice(0, 200)}${text.length > 200 ? '...' : ''}`
|
|
618
|
+
: '';
|
|
619
|
+
return `[${e.created_at}] ${e.event_type}${preview}`;
|
|
620
|
+
});
|
|
621
|
+
const header = `Events (${displayed.length} of ${events.length}):`;
|
|
622
|
+
return {
|
|
623
|
+
content: [{ type: 'text', text: [header, ...lines].join('\n') }],
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
catch (error) {
|
|
627
|
+
return {
|
|
628
|
+
content: [
|
|
629
|
+
{ type: 'text', text: errText('get session events', error) },
|
|
630
|
+
],
|
|
631
|
+
isError: true,
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
});
|
|
635
|
+
server.tool('guild_interrupt_session', 'Interrupt a running Guild session', {
|
|
636
|
+
session_id: z.string().describe('The session ID to interrupt'),
|
|
637
|
+
}, async ({ session_id }) => {
|
|
638
|
+
debugLog(debug, `guild_interrupt_session: ${session_id}`);
|
|
639
|
+
try {
|
|
640
|
+
await apiClient.post(`/sessions/${session_id}/interrupt`);
|
|
641
|
+
return {
|
|
642
|
+
content: [
|
|
643
|
+
{
|
|
644
|
+
type: 'text',
|
|
645
|
+
text: `Interrupted session ${session_id}.`,
|
|
646
|
+
},
|
|
647
|
+
],
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
catch (error) {
|
|
651
|
+
return {
|
|
652
|
+
content: [
|
|
653
|
+
{ type: 'text', text: errText('interrupt session', error) },
|
|
654
|
+
],
|
|
655
|
+
isError: true,
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
// =========================================================================
|
|
660
|
+
// Triggers
|
|
661
|
+
// =========================================================================
|
|
662
|
+
server.tool('guild_list_triggers', 'List triggers configured in the current workspace', {
|
|
663
|
+
limit: z
|
|
664
|
+
.number()
|
|
665
|
+
.int()
|
|
666
|
+
.min(1)
|
|
667
|
+
.max(100)
|
|
668
|
+
.optional()
|
|
669
|
+
.describe('Max results (default 20)'),
|
|
670
|
+
}, async ({ limit }) => {
|
|
671
|
+
debugLog(debug, 'guild_list_triggers');
|
|
672
|
+
try {
|
|
673
|
+
const response = await apiClient.get(`/workspaces/${workspaceId}/triggers?limit=${limit || 20}`);
|
|
674
|
+
const text = response.items
|
|
675
|
+
.map((t) => {
|
|
676
|
+
const agent = t.agent.full_name || t.agent.name;
|
|
677
|
+
const disabled = t.deactivated_at ? ' [DISABLED]' : '';
|
|
678
|
+
if (t.type === 'webhook') {
|
|
679
|
+
return `• ${t.id} [webhook] ${t.service}/${t.event_type || '*'} → ${agent}${disabled}`;
|
|
680
|
+
}
|
|
681
|
+
return `• ${t.id} [time] ${t.frequency} → ${agent}${disabled}`;
|
|
682
|
+
})
|
|
683
|
+
.join('\n');
|
|
684
|
+
return {
|
|
685
|
+
content: [{ type: 'text', text: text || 'No triggers found.' }],
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
catch (error) {
|
|
689
|
+
return {
|
|
690
|
+
content: [{ type: 'text', text: errText('list triggers', error) }],
|
|
691
|
+
isError: true,
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
});
|
|
695
|
+
server.tool('guild_get_trigger_sessions', 'List sessions spawned by a specific trigger', {
|
|
696
|
+
trigger_id: z.string().describe('The trigger ID'),
|
|
697
|
+
limit: z
|
|
698
|
+
.number()
|
|
699
|
+
.int()
|
|
700
|
+
.min(1)
|
|
701
|
+
.max(100)
|
|
702
|
+
.optional()
|
|
703
|
+
.describe('Max results (default 20)'),
|
|
704
|
+
}, async ({ trigger_id, limit }) => {
|
|
705
|
+
debugLog(debug, `guild_get_trigger_sessions: ${trigger_id}`);
|
|
706
|
+
try {
|
|
707
|
+
const response = await apiClient.get(`/workspaces/${workspaceId}/sessions?trigger_id=${trigger_id}&limit=${limit || 20}`);
|
|
708
|
+
const text = response.items
|
|
709
|
+
.map((s) => `• ${s.id} (${s.session_type}) — ${s.created_at}`)
|
|
710
|
+
.join('\n');
|
|
711
|
+
return {
|
|
712
|
+
content: [
|
|
713
|
+
{ type: 'text', text: text || 'No trigger sessions found.' },
|
|
714
|
+
],
|
|
715
|
+
};
|
|
716
|
+
}
|
|
717
|
+
catch (error) {
|
|
718
|
+
return {
|
|
719
|
+
content: [
|
|
720
|
+
{ type: 'text', text: errText('get trigger sessions', error) },
|
|
721
|
+
],
|
|
722
|
+
isError: true,
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
// =========================================================================
|
|
727
|
+
// Credentials / Integrations
|
|
728
|
+
// =========================================================================
|
|
729
|
+
server.tool('guild_list_credentials', 'List connected integration credentials', {}, async () => {
|
|
730
|
+
debugLog(debug, 'guild_list_credentials');
|
|
731
|
+
try {
|
|
732
|
+
const me = await apiClient.get('/me');
|
|
733
|
+
const response = await apiClient.get(`/credentials?account_id=${me.id}`);
|
|
734
|
+
const text = response.items
|
|
735
|
+
.map((c) => {
|
|
736
|
+
const status = c.status ? ` [${c.status}]` : '';
|
|
737
|
+
return `• ${c.service} (${c.id})${status}`;
|
|
738
|
+
})
|
|
739
|
+
.join('\n');
|
|
740
|
+
return {
|
|
741
|
+
content: [{ type: 'text', text: text || 'No credentials found.' }],
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
catch (error) {
|
|
745
|
+
return {
|
|
746
|
+
content: [
|
|
747
|
+
{ type: 'text', text: errText('list credentials', error) },
|
|
748
|
+
],
|
|
749
|
+
isError: true,
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
server.tool('guild_list_available_integrations', 'List available integrations that can be connected', {}, async () => {
|
|
754
|
+
debugLog(debug, 'guild_list_available_integrations');
|
|
755
|
+
try {
|
|
756
|
+
const integrations = await apiClient.get('/credentials/available');
|
|
757
|
+
const items = Array.isArray(integrations) ? integrations : [];
|
|
758
|
+
const text = items
|
|
759
|
+
.map((i) => {
|
|
760
|
+
const desc = i.description ? ` — ${i.description}` : '';
|
|
761
|
+
return `• ${i.name || i.service} (${i.service})${desc}`;
|
|
762
|
+
})
|
|
763
|
+
.join('\n');
|
|
764
|
+
return {
|
|
765
|
+
content: [
|
|
766
|
+
{ type: 'text', text: text || 'No integrations available.' },
|
|
767
|
+
],
|
|
768
|
+
};
|
|
769
|
+
}
|
|
770
|
+
catch (error) {
|
|
771
|
+
return {
|
|
772
|
+
content: [
|
|
773
|
+
{
|
|
774
|
+
type: 'text',
|
|
775
|
+
text: errText('list available integrations', error),
|
|
776
|
+
},
|
|
777
|
+
],
|
|
778
|
+
isError: true,
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
//# sourceMappingURL=tools.js.map
|