@guildai/cli 0.5.13 → 0.6.1
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/README.md +17 -0
- package/dist/commands/agent/chat.js +31 -31
- package/dist/commands/agent/clone.js +3 -1
- package/dist/commands/agent/code.js +3 -2
- package/dist/commands/agent/fork.js +41 -15
- package/dist/commands/agent/get.js +3 -2
- package/dist/commands/agent/grep.js +61 -31
- package/dist/commands/agent/init.js +1 -1
- package/dist/commands/agent/publish.js +3 -2
- package/dist/commands/agent/pull.js +36 -21
- package/dist/commands/agent/revalidate.js +4 -3
- package/dist/commands/agent/save.js +2 -2
- package/dist/commands/agent/search.js +3 -3
- package/dist/commands/agent/tags/add.js +4 -3
- package/dist/commands/agent/tags/list.js +3 -2
- package/dist/commands/agent/tags/remove.js +4 -3
- package/dist/commands/agent/tags/set.js +3 -2
- package/dist/commands/agent/test.js +8 -12
- package/dist/commands/agent/unpublish.js +3 -2
- package/dist/commands/agent/update.js +9 -8
- package/dist/commands/agent/versions.js +3 -2
- package/dist/commands/agent/workspaces.js +3 -2
- package/dist/commands/auth/login.js +3 -3
- package/dist/commands/chat.js +64 -102
- package/dist/commands/credentials/endpoint-list.d.ts +3 -0
- package/dist/commands/credentials/endpoint-list.js +87 -0
- package/dist/commands/credentials/list.d.ts +3 -0
- package/dist/commands/{container → credentials}/list.js +11 -10
- package/dist/commands/credentials/policy-create.d.ts +3 -0
- package/dist/commands/credentials/policy-create.js +66 -0
- package/dist/commands/credentials/policy-delete.d.ts +3 -0
- package/dist/commands/{container/get.js → credentials/policy-delete.js} +9 -9
- package/dist/commands/credentials/policy-list.d.ts +3 -0
- package/dist/commands/{container-image/list.js → credentials/policy-list.js} +9 -9
- package/dist/commands/credentials/policy-update.d.ts +3 -0
- package/dist/commands/credentials/policy-update.js +66 -0
- package/dist/commands/integration/connect.d.ts +3 -0
- package/dist/commands/integration/connect.js +76 -0
- package/dist/commands/integration/create.d.ts +3 -0
- package/dist/commands/integration/create.js +298 -0
- package/dist/commands/integration/get.d.ts +3 -0
- package/dist/commands/integration/get.js +95 -0
- package/dist/commands/integration/list.d.ts +3 -0
- package/dist/commands/integration/list.js +61 -0
- package/dist/commands/integration/operation/create.d.ts +3 -0
- package/dist/commands/integration/operation/create.js +163 -0
- package/dist/commands/integration/operation/list.d.ts +3 -0
- package/dist/commands/integration/operation/list.js +83 -0
- package/dist/commands/integration/update.d.ts +3 -0
- package/dist/commands/integration/update.js +139 -0
- package/dist/commands/integration/version/build.d.ts +3 -0
- package/dist/commands/integration/version/build.js +86 -0
- package/dist/commands/integration/version/create.d.ts +3 -0
- package/dist/commands/integration/version/create.js +45 -0
- package/dist/commands/integration/version/get.d.ts +3 -0
- package/dist/commands/integration/version/get.js +72 -0
- package/dist/commands/integration/version/list.d.ts +3 -0
- package/dist/commands/integration/version/list.js +44 -0
- package/dist/commands/integration/version/publish.d.ts +3 -0
- package/dist/commands/integration/version/publish.js +79 -0
- package/dist/commands/integration/version/test.d.ts +3 -0
- package/dist/commands/integration/version/test.js +104 -0
- package/dist/commands/trigger/create.js +35 -19
- package/dist/commands/workspace/create.js +10 -4
- package/dist/commands/workspace/select.js +0 -1
- package/dist/index.js +60 -27
- package/dist/lib/agent-helpers.d.ts +8 -0
- package/dist/lib/agent-helpers.js +15 -0
- package/dist/lib/api-types.d.ts +109 -78
- package/dist/lib/auth.d.ts +1 -1
- package/dist/lib/auth.js +10 -6
- package/dist/lib/integration-helpers.d.ts +15 -0
- package/dist/lib/integration-helpers.js +38 -0
- package/dist/lib/output.d.ts +13 -16
- package/dist/lib/output.js +137 -109
- package/dist/lib/session-events-fetch.d.ts +27 -0
- package/dist/lib/session-events-fetch.js +25 -0
- package/dist/lib/session-polling.d.ts +7 -2
- package/dist/lib/session-polling.js +18 -11
- package/dist/lib/session-resume.js +2 -5
- package/dist/lib/table.d.ts +0 -1
- package/dist/lib/table.js +0 -1
- package/dist/mcp/tools.js +6 -12
- package/docs/CLI_WORKFLOW.md +19 -2
- package/docs/skills/agent-dev.md +17 -2
- package/package.json +6 -5
- package/dist/commands/container/destroy.d.ts +0 -3
- package/dist/commands/container/destroy.js +0 -48
- package/dist/commands/container/events.d.ts +0 -3
- package/dist/commands/container/events.js +0 -44
- package/dist/commands/container/exec.d.ts +0 -3
- package/dist/commands/container/exec.js +0 -64
- package/dist/commands/container/get.d.ts +0 -3
- package/dist/commands/container/list.d.ts +0 -3
- package/dist/commands/container-image/create.d.ts +0 -3
- package/dist/commands/container-image/create.js +0 -41
- package/dist/commands/container-image/get.d.ts +0 -3
- package/dist/commands/container-image/get.js +0 -33
- package/dist/commands/container-image/list.d.ts +0 -3
package/README.md
CHANGED
|
@@ -183,6 +183,23 @@ guild trigger deactivate <trigger-id> # Deactivate a trigger
|
|
|
183
183
|
guild trigger sessions <trigger-id> # List sessions spawned by a trigger
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
+
### Integrations
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
guild integration list # List integrations
|
|
190
|
+
guild integration get <id> # Get integration details
|
|
191
|
+
guild integration create <name> # Create a new integration
|
|
192
|
+
guild integration update <id> # Update an integration
|
|
193
|
+
guild integration version list <id> # List versions
|
|
194
|
+
guild integration version create <id> # Create a draft version
|
|
195
|
+
guild integration version get <id> # Get version details
|
|
196
|
+
guild integration version build <id> # Build (validate) a draft
|
|
197
|
+
guild integration version publish <id> # Publish a built version
|
|
198
|
+
guild integration version test <id> # Test an endpoint invocation
|
|
199
|
+
guild integration operation list <id> # List operations for a version
|
|
200
|
+
guild integration operation create <id> # Create operations (or import from OpenAPI)
|
|
201
|
+
```
|
|
202
|
+
|
|
186
203
|
### Chat
|
|
187
204
|
|
|
188
205
|
```bash
|
|
@@ -38,13 +38,29 @@ export function createAgentChatCommand() {
|
|
|
38
38
|
.option('--no-splash', 'Skip the splash screen animation')
|
|
39
39
|
.option('--resume <session-id>', 'Resume an existing session')
|
|
40
40
|
.option('--open', 'Open session in web dashboard')
|
|
41
|
-
.addHelpText('after', '\
|
|
41
|
+
.addHelpText('after', '\nTo chat with a published agent by name: guild chat --agent owner/agent-name')
|
|
42
42
|
.action(async (promptArgs, options) => {
|
|
43
43
|
try {
|
|
44
44
|
// Get agent ID from guild.json in the specified path
|
|
45
45
|
const agentPath = options.path || '.';
|
|
46
46
|
const { agentId, config } = await getAgentId(undefined, agentPath);
|
|
47
47
|
const initialPrompt = promptArgs.length > 0 ? promptArgs.join(' ') : 'Hello';
|
|
48
|
+
// If using JSON input, read it early (before auth) for fast failure on bad input
|
|
49
|
+
let inputData;
|
|
50
|
+
if (options.mode === 'json') {
|
|
51
|
+
try {
|
|
52
|
+
inputData = await readStdinAsJSON();
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const err = error;
|
|
56
|
+
console.error(`Error: ${err.message}`);
|
|
57
|
+
console.error('');
|
|
58
|
+
console.error('Example usage:');
|
|
59
|
+
console.error(' echo \'{"prompt": "test"}\' | guild agent chat --mode json');
|
|
60
|
+
console.error(' guild agent chat --mode json < input.json');
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
48
64
|
// Check authentication (uses shared function from chat.tsx)
|
|
49
65
|
await ensureAuthenticated();
|
|
50
66
|
const client = new GuildAPIClient();
|
|
@@ -152,25 +168,14 @@ export function createAgentChatCommand() {
|
|
|
152
168
|
console.error(` guild agent chat ${agentId}`);
|
|
153
169
|
process.exit(1);
|
|
154
170
|
}
|
|
155
|
-
// If using JSON input, read it early (before session creation)
|
|
156
|
-
let inputData;
|
|
157
|
-
if (options.mode === 'json') {
|
|
158
|
-
try {
|
|
159
|
-
inputData = await readStdinAsJSON();
|
|
160
|
-
}
|
|
161
|
-
catch (error) {
|
|
162
|
-
const err = error;
|
|
163
|
-
console.error(`Error: ${err.message}`);
|
|
164
|
-
console.error('');
|
|
165
|
-
console.error('Example usage:');
|
|
166
|
-
console.error(' echo \'{"prompt": "test"}\' | guild agent chat --mode json');
|
|
167
|
-
console.error(' guild agent chat --mode json < input.json');
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
171
|
// Branch: JSON/JSONL modes vs interactive
|
|
172
172
|
if (options.mode === 'json' || options.mode === 'jsonl') {
|
|
173
|
-
|
|
173
|
+
// For JSON mode with piped input, use the piped data as the initial prompt
|
|
174
|
+
// so the agent receives it as its input (not the default 'Hello')
|
|
175
|
+
const sessionPrompt = options.mode === 'json' && inputData
|
|
176
|
+
? JSON.stringify(inputData)
|
|
177
|
+
: initialPrompt;
|
|
178
|
+
const session = await createSession(client, options.workspace, sessionPrompt, version.id);
|
|
174
179
|
if (!quiet) {
|
|
175
180
|
console.log(`✓ Agent: ${config?.name || agentId}`);
|
|
176
181
|
const sessionLink = session.session_url
|
|
@@ -183,13 +188,10 @@ export function createAgentChatCommand() {
|
|
|
183
188
|
await open(session.session_url);
|
|
184
189
|
}
|
|
185
190
|
if (options.mode === 'json' && inputData) {
|
|
186
|
-
// JSON one-shot mode
|
|
191
|
+
// JSON one-shot mode — input was passed as initial_prompt during
|
|
192
|
+
// session creation, so the agent already has it. Just poll for the response.
|
|
187
193
|
try {
|
|
188
|
-
await client
|
|
189
|
-
mode: 'json',
|
|
190
|
-
content: inputData,
|
|
191
|
-
});
|
|
192
|
-
const response = await pollForResponse(client, session.id, 0);
|
|
194
|
+
const { response } = await pollForResponse(client, session.id, undefined);
|
|
193
195
|
if (!response) {
|
|
194
196
|
console.error('Timeout: No response received from agent');
|
|
195
197
|
process.exit(1);
|
|
@@ -219,7 +221,7 @@ export function createAgentChatCommand() {
|
|
|
219
221
|
});
|
|
220
222
|
let lineNumber = 0;
|
|
221
223
|
let processedCount = 0;
|
|
222
|
-
let
|
|
224
|
+
let lastEventId;
|
|
223
225
|
for await (const line of rl) {
|
|
224
226
|
lineNumber++;
|
|
225
227
|
if (!line.trim())
|
|
@@ -233,15 +235,13 @@ export function createAgentChatCommand() {
|
|
|
233
235
|
mode: 'json',
|
|
234
236
|
content: jsonInput,
|
|
235
237
|
});
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
+
const result = await pollForResponse(client, session.id, lastEventId);
|
|
239
|
+
lastEventId = result.lastEventId;
|
|
240
|
+
if (!result.response) {
|
|
238
241
|
console.error(`Timeout: No response for line ${lineNumber}`);
|
|
239
|
-
const eventsAfterResponse = await client.get(`/sessions/${session.id}/events`);
|
|
240
|
-
lastEventCount = eventsAfterResponse?.items?.length || 0;
|
|
241
242
|
continue;
|
|
242
243
|
}
|
|
243
|
-
const
|
|
244
|
-
lastEventCount = eventsAfterResponse?.items?.length || 0;
|
|
244
|
+
const response = result.response;
|
|
245
245
|
if (quiet) {
|
|
246
246
|
console.log(response);
|
|
247
247
|
}
|
|
@@ -8,6 +8,7 @@ import * as path from 'path';
|
|
|
8
8
|
import { getAuthenticatedUrl } from '../../lib/auth.js';
|
|
9
9
|
import { runGit, GitError, formatGitError, installPrePushHook } from '../../lib/git.js';
|
|
10
10
|
import { createOutputWriter } from '../../lib/output.js';
|
|
11
|
+
import { resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
11
12
|
async function isDirectoryEmpty(dirPath) {
|
|
12
13
|
try {
|
|
13
14
|
const files = await fs.readdir(dirPath);
|
|
@@ -30,7 +31,8 @@ export function createAgentCloneCommand() {
|
|
|
30
31
|
try {
|
|
31
32
|
// Fetch agent details
|
|
32
33
|
const client = new GuildAPIClient();
|
|
33
|
-
const
|
|
34
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
35
|
+
const agent = await client.get(`/agents/${resolvedId}`);
|
|
34
36
|
if (!agent.git_url) {
|
|
35
37
|
output.error('Error: Agent does not have a git repository', 'This agent may not have been initialized with git.');
|
|
36
38
|
process.exit(1);
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
5
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
6
|
-
import { getAgentId } from '../../lib/agent-helpers.js';
|
|
6
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
7
7
|
import { createOutputWriter } from '../../lib/output.js';
|
|
8
8
|
import * as fs from 'fs/promises';
|
|
9
9
|
import * as path from 'path';
|
|
@@ -22,7 +22,8 @@ export function createAgentCodeCommand() {
|
|
|
22
22
|
const includeDraft = options.draft ? '1' : '0';
|
|
23
23
|
let files;
|
|
24
24
|
try {
|
|
25
|
-
|
|
25
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
26
|
+
files = await client.get(`/agents/${resolvedId}/code?include_unpublished=${includeDraft}`);
|
|
26
27
|
}
|
|
27
28
|
catch (error) {
|
|
28
29
|
const formattedError = handleAxiosError(error);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
5
6
|
import { handleAxiosError, ErrorCodes, debug } from '../../lib/errors.js';
|
|
6
7
|
import * as fs from 'fs/promises';
|
|
7
8
|
import * as readline from 'readline';
|
|
@@ -47,21 +48,48 @@ export function createAgentForkCommand() {
|
|
|
47
48
|
const cmd = new Command('fork');
|
|
48
49
|
cmd
|
|
49
50
|
.description('Fork an existing agent version to create a new agent')
|
|
50
|
-
.argument('
|
|
51
|
+
.argument('[identifier]', 'Agent ID, full name, or agent:version (e.g., owner/agent-name:version_xyz)')
|
|
51
52
|
.option('--name <name>', 'Name for the forked agent')
|
|
52
53
|
.option('--description <desc>', 'Description for the forked agent')
|
|
53
54
|
.option('--directory <path>', 'Target directory for clone')
|
|
54
|
-
.option('--owner <owner
|
|
55
|
-
.action(async (
|
|
55
|
+
.option('--owner <owner>', 'Owner (name or ID)')
|
|
56
|
+
.action(async (identifierArg, options) => {
|
|
56
57
|
const output = createOutputWriter();
|
|
57
58
|
try {
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
// Resolve agent ID and optional version ID
|
|
60
|
+
let sourceAgentId;
|
|
61
|
+
let sourceVersionId;
|
|
62
|
+
if (identifierArg && identifierArg.includes(':')) {
|
|
63
|
+
// Explicit agent:version format
|
|
64
|
+
const colonIndex = identifierArg.lastIndexOf(':');
|
|
65
|
+
const agentPart = identifierArg.substring(0, colonIndex);
|
|
66
|
+
sourceVersionId = identifierArg.substring(colonIndex + 1);
|
|
67
|
+
if (!agentPart || !sourceVersionId) {
|
|
68
|
+
output.error('Error: Invalid argument format', 'Expected: [identifier] or [identifier]:[version-id]\nExample: guild agent fork owner/agent-name:version_xyz\n\nTo find versions:\n guild agent versions <agent-id>');
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
const resolved = await getAgentId(agentPart);
|
|
72
|
+
sourceAgentId = resolved.agentId;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// No version specified — resolve agent, then find latest published
|
|
76
|
+
const resolved = await getAgentId(identifierArg);
|
|
77
|
+
sourceAgentId = resolved.agentId;
|
|
78
|
+
}
|
|
79
|
+
// Auto-resolve version if not specified
|
|
80
|
+
const client = new GuildAPIClient();
|
|
81
|
+
sourceAgentId = await resolveAgentRef(client, sourceAgentId);
|
|
82
|
+
if (!sourceVersionId) {
|
|
83
|
+
const versions = await client.get(`/agents/${sourceAgentId}/versions`);
|
|
84
|
+
const published = versions.items
|
|
85
|
+
.filter((v) => v.status === 'PUBLISHED')
|
|
86
|
+
.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
87
|
+
if (published.length === 0) {
|
|
88
|
+
output.error('No published versions found', `Agent ${sourceAgentId} has no published versions to fork.\n\nTo see all versions:\n guild agent versions ${sourceAgentId}`);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
sourceVersionId = published[0].id;
|
|
63
92
|
}
|
|
64
|
-
const [sourceAgentId, sourceVersionId] = parts;
|
|
65
93
|
// Determine name (validate before API call for better UX)
|
|
66
94
|
let agentName = options.name;
|
|
67
95
|
if (!agentName) {
|
|
@@ -73,7 +101,7 @@ export function createAgentForkCommand() {
|
|
|
73
101
|
}
|
|
74
102
|
}
|
|
75
103
|
else {
|
|
76
|
-
output.error('Error: Agent name required in non-interactive mode', `Provide a name:\n guild agent fork ${
|
|
104
|
+
output.error('Error: Agent name required in non-interactive mode', `Provide a name:\n guild agent fork ${identifierArg || '<identifier>'} --name my-forked-agent\n\nOr run interactively to be prompted.`);
|
|
77
105
|
process.exit(1);
|
|
78
106
|
}
|
|
79
107
|
}
|
|
@@ -92,12 +120,11 @@ export function createAgentForkCommand() {
|
|
|
92
120
|
if (dirExists) {
|
|
93
121
|
const isEmpty = await isDirectoryEmpty(targetDir);
|
|
94
122
|
if (!isEmpty) {
|
|
95
|
-
output.error(`Error: Directory '${targetDir}' already exists and is not empty`, `Choose a different directory:\n guild agent fork ${
|
|
123
|
+
output.error(`Error: Directory '${targetDir}' already exists and is not empty`, `Choose a different directory:\n guild agent fork ${identifierArg || '<identifier>'} --directory ./different-path\n\nOr remove the existing directory first.`);
|
|
96
124
|
process.exit(1);
|
|
97
125
|
}
|
|
98
126
|
}
|
|
99
|
-
//
|
|
100
|
-
const client = new GuildAPIClient();
|
|
127
|
+
// Fetch source version from API (after local validations)
|
|
101
128
|
const sourceVersion = await client.get(`/agents/${sourceAgentId}/versions/${sourceVersionId}`);
|
|
102
129
|
output.progress(`✓ Fetched source version from '${sourceVersion.agent.name}' (${sourceVersionId.substring(0, 12)})`);
|
|
103
130
|
// Determine description
|
|
@@ -174,8 +201,7 @@ export function createAgentForkCommand() {
|
|
|
174
201
|
process.exit(1);
|
|
175
202
|
}
|
|
176
203
|
if (formattedError.code === ErrorCodes.NOT_FOUND) {
|
|
177
|
-
|
|
178
|
-
output.error(`Error: Version not found: ${sourceArg}`, `Check available versions:\n guild agent versions ${sourceAgentId}`);
|
|
204
|
+
output.error(`Error: Agent or version not found: ${identifierArg || '<identifier>'}`, `Check available versions:\n guild agent versions <agent-id>`);
|
|
179
205
|
process.exit(1);
|
|
180
206
|
}
|
|
181
207
|
if (formattedError.code === ErrorCodes.CONN_REFUSED) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
5
|
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
-
import { getAgentId } from '../../lib/agent-helpers.js';
|
|
6
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
7
7
|
import { handleAxiosError } from '../../lib/errors.js';
|
|
8
8
|
import { createOutputWriter } from '../../lib/output.js';
|
|
9
9
|
export function createAgentGetCommand() {
|
|
@@ -22,7 +22,8 @@ export function createAgentGetCommand() {
|
|
|
22
22
|
// Get agent ID from argument or guild.json
|
|
23
23
|
const { agentId } = await getAgentId(idArg);
|
|
24
24
|
const client = new GuildAPIClient();
|
|
25
|
-
const
|
|
25
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
26
|
+
const response = await client.get(`/agents/${resolvedId}`);
|
|
26
27
|
output.data(response);
|
|
27
28
|
}
|
|
28
29
|
catch (error) {
|
|
@@ -5,12 +5,14 @@ import { GuildAPIClient } from '../../lib/api-client.js';
|
|
|
5
5
|
import { getAuthToken } from '../../lib/auth.js';
|
|
6
6
|
import { createOutputWriter } from '../../lib/output.js';
|
|
7
7
|
import { handleAxiosError } from '../../lib/errors.js';
|
|
8
|
+
import { loadLocalConfig } from '../../lib/guild-config.js';
|
|
8
9
|
export function createAgentGrepCommand() {
|
|
9
10
|
const cmd = new Command('grep');
|
|
10
11
|
cmd
|
|
11
12
|
.description('Search agent files for a matching pattern')
|
|
12
13
|
.argument('[pattern]', 'JavaScript regex for which to search: all lines matching this pattern will be printed')
|
|
13
|
-
.option('--
|
|
14
|
+
.option('--all', 'Search all agents (default: current agent only)')
|
|
15
|
+
.option('--published', 'Only search published agents (requires --all)')
|
|
14
16
|
.action(grep);
|
|
15
17
|
return cmd;
|
|
16
18
|
}
|
|
@@ -36,36 +38,11 @@ async function grep(patternArg, options) {
|
|
|
36
38
|
process.exit(1);
|
|
37
39
|
}
|
|
38
40
|
const client = new GuildAPIClient();
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (options.published) {
|
|
45
|
-
params.append('published_only', 'true');
|
|
46
|
-
}
|
|
47
|
-
const response = await client.get(`/agents?${params.toString()}`);
|
|
48
|
-
await Promise.all(response.items.map(async (agent) => {
|
|
49
|
-
let files = [];
|
|
50
|
-
try {
|
|
51
|
-
files = await client.get(`/agents/${agent.id}/code`);
|
|
52
|
-
}
|
|
53
|
-
catch (ex) {
|
|
54
|
-
const formattedError = handleAxiosError(ex);
|
|
55
|
-
output.error(`${agent.owner?.name}/${agent.name}: ${formattedError.details}`);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
for (const { path, content } of files) {
|
|
59
|
-
content.split('\n').forEach((line, lineNumber) => {
|
|
60
|
-
if (patternRE.test(line)) {
|
|
61
|
-
output.progress(`${agent.owner?.name}/${agent.name}/${path}:${lineNumber + 1}:${line}`);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}));
|
|
66
|
-
offset += response.pagination.limit;
|
|
67
|
-
if (!response.pagination.has_more)
|
|
68
|
-
break;
|
|
41
|
+
if (options.all) {
|
|
42
|
+
await grepAllAgents(client, patternRE, options.published, output);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
await grepCurrentAgent(client, patternRE, output);
|
|
69
46
|
}
|
|
70
47
|
}
|
|
71
48
|
catch (error) {
|
|
@@ -74,4 +51,57 @@ async function grep(patternArg, options) {
|
|
|
74
51
|
process.exit(1);
|
|
75
52
|
}
|
|
76
53
|
}
|
|
54
|
+
function searchFiles(files, patternRE, prefix, output) {
|
|
55
|
+
for (const { path, content } of files) {
|
|
56
|
+
content.split('\n').forEach((line, lineNumber) => {
|
|
57
|
+
if (patternRE.test(line)) {
|
|
58
|
+
output.progress(`${prefix}${path}:${lineNumber + 1}:${line}`);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function grepCurrentAgent(client, patternRE, output) {
|
|
64
|
+
const config = await loadLocalConfig();
|
|
65
|
+
if (!config?.agent_id) {
|
|
66
|
+
output.error('Not in an agent directory.', 'Either run from an agent directory with guild.json:\n cd <agent-directory>\n guild agent grep <pattern>\n\nOr search all agents:\n guild agent grep <pattern> --all');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
let files = [];
|
|
70
|
+
try {
|
|
71
|
+
files = await client.get(`/agents/${config.agent_id}/code`);
|
|
72
|
+
}
|
|
73
|
+
catch (ex) {
|
|
74
|
+
const formattedError = handleAxiosError(ex);
|
|
75
|
+
output.error(`Failed to fetch agent code: ${formattedError.details}`);
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
searchFiles(files, patternRE, '', output);
|
|
79
|
+
}
|
|
80
|
+
async function grepAllAgents(client, patternRE, publishedOnly, output) {
|
|
81
|
+
let offset = 0;
|
|
82
|
+
while (true) {
|
|
83
|
+
const params = new URLSearchParams();
|
|
84
|
+
params.append('offset', `${offset}`);
|
|
85
|
+
params.append('limit', `${BATCH_SIZE}`);
|
|
86
|
+
if (publishedOnly) {
|
|
87
|
+
params.append('published_only', 'true');
|
|
88
|
+
}
|
|
89
|
+
const response = await client.get(`/agents?${params.toString()}`);
|
|
90
|
+
await Promise.all(response.items.map(async (agent) => {
|
|
91
|
+
let files = [];
|
|
92
|
+
try {
|
|
93
|
+
files = await client.get(`/agents/${agent.id}/code`);
|
|
94
|
+
}
|
|
95
|
+
catch (ex) {
|
|
96
|
+
const formattedError = handleAxiosError(ex);
|
|
97
|
+
output.error(`${agent.owner?.name}/${agent.name}: ${formattedError.details}`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
searchFiles(files, patternRE, `${agent.owner?.name}/${agent.name}/`, output);
|
|
101
|
+
}));
|
|
102
|
+
offset += response.pagination.limit;
|
|
103
|
+
if (!response.pagination.has_more)
|
|
104
|
+
break;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
77
107
|
//# sourceMappingURL=grep.js.map
|
|
@@ -79,7 +79,7 @@ export function createAgentInitCommand() {
|
|
|
79
79
|
.option('--name <name>', 'Agent name')
|
|
80
80
|
.option('--template <template>', 'Agent template (LLM, AUTO_MANAGED_STATE, BLANK)')
|
|
81
81
|
.option('--fork <agent-id>', 'Fork from existing agent')
|
|
82
|
-
.option('--owner <owner
|
|
82
|
+
.option('--owner <owner>', 'Owner (name or ID)')
|
|
83
83
|
.option('--directory <path>', 'Directory to initialize (created if needed)')
|
|
84
84
|
.option('--force', 'Overwrite existing guild.json', false)
|
|
85
85
|
.action(async (options) => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
-
import { getAgentId } from '../../lib/agent-helpers.js';
|
|
5
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
7
7
|
import { pollUntilComplete } from '../../lib/polling.js';
|
|
8
8
|
import { createOutputWriter } from '../../lib/output.js';
|
|
@@ -18,8 +18,9 @@ export function createAgentPublishCommand() {
|
|
|
18
18
|
const client = new GuildAPIClient();
|
|
19
19
|
// Resolve agent ID
|
|
20
20
|
const { agentId, config } = await getAgentId(agentIdArg);
|
|
21
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
21
22
|
// Fetch all versions
|
|
22
|
-
const response = await client.get(`/agents/${
|
|
23
|
+
const response = await client.get(`/agents/${resolvedId}/versions`);
|
|
23
24
|
// Find latest DRAFT version
|
|
24
25
|
const draftVersions = response.items
|
|
25
26
|
.filter((v) => v.status === 'DRAFT')
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
5
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
6
|
+
import { getOutputMode } from '../../lib/output-mode.js';
|
|
6
7
|
import { createOutputWriter } from '../../lib/output.js';
|
|
7
8
|
import * as fs from 'fs/promises';
|
|
8
9
|
import * as path from 'path';
|
|
@@ -90,10 +91,12 @@ export function createAgentPullCommand() {
|
|
|
90
91
|
if (errMessage.includes('no tracking information') ||
|
|
91
92
|
errMessage.includes("couldn't find remote ref")) {
|
|
92
93
|
output.progress('✓ Already up to date (no remote branch yet)');
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
if (getOutputMode() === 'json') {
|
|
95
|
+
output.data({
|
|
96
|
+
success: true,
|
|
97
|
+
message: 'Already up to date (no remote branch yet)',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
97
100
|
return;
|
|
98
101
|
}
|
|
99
102
|
// Unknown git error
|
|
@@ -109,22 +112,28 @@ export function createAgentPullCommand() {
|
|
|
109
112
|
// Truly up to date — git pull + version match
|
|
110
113
|
if (!gitPulledNewCommits) {
|
|
111
114
|
output.progress('✓ Already up to date');
|
|
112
|
-
output.data({ success: true, message: 'Already up to date' });
|
|
113
115
|
}
|
|
114
|
-
|
|
115
|
-
output.data({
|
|
116
|
+
if (getOutputMode() === 'json') {
|
|
117
|
+
output.data({
|
|
118
|
+
success: true,
|
|
119
|
+
message: gitPulledNewCommits
|
|
120
|
+
? 'Pulled remote changes'
|
|
121
|
+
: 'Already up to date',
|
|
122
|
+
});
|
|
116
123
|
}
|
|
117
124
|
}
|
|
118
125
|
else if (latest.sha && latest.sha !== localHead) {
|
|
119
126
|
// SHA mismatch — warn user
|
|
120
127
|
output.progress(`⚠ Remote has a newer version (${latest.sha.slice(0, 7)}) not on this branch`);
|
|
121
128
|
output.progress(' Try: git fetch origin && git log --oneline origin/main');
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
if (getOutputMode() === 'json') {
|
|
130
|
+
output.data({
|
|
131
|
+
success: true,
|
|
132
|
+
message: 'SHA mismatch with latest version',
|
|
133
|
+
latest_sha: latest.sha,
|
|
134
|
+
local_sha: localHead,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
128
137
|
}
|
|
129
138
|
else {
|
|
130
139
|
// Ephemeral version — download from API
|
|
@@ -142,21 +151,27 @@ export function createAgentPullCommand() {
|
|
|
142
151
|
await fs.writeFile(filePath, file.content, 'utf-8');
|
|
143
152
|
}
|
|
144
153
|
output.progress(`✓ Downloaded ${files.length} files from latest draft version`);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
154
|
+
if (getOutputMode() === 'json') {
|
|
155
|
+
output.data({
|
|
156
|
+
success: true,
|
|
157
|
+
message: `Downloaded ${files.length} files from draft version`,
|
|
158
|
+
files_updated: files.length,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
150
161
|
}
|
|
151
162
|
}
|
|
152
163
|
else {
|
|
153
164
|
// No versions exist yet — just report git pull result
|
|
154
165
|
if (!gitPulledNewCommits) {
|
|
155
166
|
output.progress('✓ Already up to date');
|
|
156
|
-
output.data({ success: true, message: 'Already up to date' });
|
|
157
167
|
}
|
|
158
|
-
|
|
159
|
-
output.data({
|
|
168
|
+
if (getOutputMode() === 'json') {
|
|
169
|
+
output.data({
|
|
170
|
+
success: true,
|
|
171
|
+
message: gitPulledNewCommits
|
|
172
|
+
? 'Pulled remote changes'
|
|
173
|
+
: 'Already up to date',
|
|
174
|
+
});
|
|
160
175
|
}
|
|
161
176
|
}
|
|
162
177
|
}
|
|
@@ -4,7 +4,7 @@ import { Command } from 'commander';
|
|
|
4
4
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
5
|
import { getGuildcoreUrl } from '../../lib/config.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
7
|
-
import { getAgentId } from '../../lib/agent-helpers.js';
|
|
7
|
+
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
8
8
|
import { createOutputWriter } from '../../lib/output.js';
|
|
9
9
|
export function createAgentRevalidateCommand() {
|
|
10
10
|
const cmd = new Command('revalidate');
|
|
@@ -19,10 +19,11 @@ export function createAgentRevalidateCommand() {
|
|
|
19
19
|
const baseUrl = getGuildcoreUrl();
|
|
20
20
|
const client = new GuildAPIClient({ baseUrl });
|
|
21
21
|
try {
|
|
22
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
22
23
|
let versionId = versionIdArg;
|
|
23
24
|
// If no version ID provided, get the latest version
|
|
24
25
|
if (!versionId) {
|
|
25
|
-
const versions = await client.get(`/agents/${
|
|
26
|
+
const versions = await client.get(`/agents/${resolvedId}/versions?limit=1&offset=0`);
|
|
26
27
|
if (!versions.items || versions.items.length === 0) {
|
|
27
28
|
output.error('No versions found for this agent.', `The agent may still be initializing. Check status:\n guild agent get ${agentId}`);
|
|
28
29
|
process.exit(1);
|
|
@@ -30,7 +31,7 @@ export function createAgentRevalidateCommand() {
|
|
|
30
31
|
versionId = versions.items[0].id;
|
|
31
32
|
}
|
|
32
33
|
// Revalidate the version
|
|
33
|
-
const result = await client.post(`/agents/${
|
|
34
|
+
const result = await client.post(`/agents/${resolvedId}/versions/${versionId}/revalidate`);
|
|
34
35
|
output.data(result);
|
|
35
36
|
}
|
|
36
37
|
catch (error) {
|
|
@@ -13,9 +13,9 @@ import { pollUntilComplete } from '../../lib/polling.js';
|
|
|
13
13
|
export function createAgentSaveCommand() {
|
|
14
14
|
const cmd = new Command('save');
|
|
15
15
|
cmd
|
|
16
|
-
.description('
|
|
16
|
+
.description('Commit, push, and create a new agent version')
|
|
17
17
|
.option('-A, --all', 'Stage all changes and commit before pushing', false)
|
|
18
|
-
.option('--message <text>', 'Commit message (required with --all)')
|
|
18
|
+
.option('-m, --message <text>', 'Commit message (required with --all)')
|
|
19
19
|
.option('--wait', 'Wait for validation to complete before returning', false)
|
|
20
20
|
.option('--publish', 'Publish after validation passes (implies --wait)', false)
|
|
21
21
|
.option('--bump [level]', 'Bump package.json version before saving (patch, or minor/major)', 'patch')
|
|
@@ -15,10 +15,10 @@ const SORT_MAP = {
|
|
|
15
15
|
export function createAgentSearchCommand() {
|
|
16
16
|
const cmd = new Command('search');
|
|
17
17
|
cmd
|
|
18
|
-
.description('Search
|
|
18
|
+
.description('Search agents')
|
|
19
19
|
.argument('<query>', 'Search query')
|
|
20
20
|
.option('--sort <field>', 'Sort by: updated, newest, name, popular (default: updated)', 'updated')
|
|
21
|
-
.option('--
|
|
21
|
+
.option('--published', 'Only show published agents')
|
|
22
22
|
.option('--limit <number>', 'Number of results to return', '20')
|
|
23
23
|
.option('--offset <number>', 'Offset for pagination', '0')
|
|
24
24
|
.action(async (query, options) => {
|
|
@@ -34,7 +34,7 @@ export function createAgentSearchCommand() {
|
|
|
34
34
|
params.append('search', query);
|
|
35
35
|
params.append('limit', options.limit);
|
|
36
36
|
params.append('offset', options.offset);
|
|
37
|
-
if (
|
|
37
|
+
if (options.published) {
|
|
38
38
|
params.append('published_only', 'true');
|
|
39
39
|
}
|
|
40
40
|
const sortField = SORT_MAP[options.sort];
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { GuildAPIClient } from '../../../lib/api-client.js';
|
|
5
|
-
import { getAgentId } from '../../../lib/agent-helpers.js';
|
|
5
|
+
import { getAgentId, resolveAgentRef } from '../../../lib/agent-helpers.js';
|
|
6
6
|
import { handleAxiosError, ErrorCodes } from '../../../lib/errors.js';
|
|
7
7
|
import { createOutputWriter } from '../../../lib/output.js';
|
|
8
8
|
export function createAgentTagsAddCommand() {
|
|
@@ -34,17 +34,18 @@ export function createAgentTagsAddCommand() {
|
|
|
34
34
|
}
|
|
35
35
|
// Now resolve agent ID properly
|
|
36
36
|
const { agentId, config } = await getAgentId(agentIdArg);
|
|
37
|
+
const resolvedId = await resolveAgentRef(client, agentId);
|
|
37
38
|
if (tagsToAdd.length === 0) {
|
|
38
39
|
output.error('At least one tag is required.', 'Usage: guild agent tags add [agent-id] <tag...>');
|
|
39
40
|
process.exit(1);
|
|
40
41
|
}
|
|
41
42
|
// Fetch current tags
|
|
42
|
-
const response = await client.get(`/agents/${
|
|
43
|
+
const response = await client.get(`/agents/${resolvedId}/tags`);
|
|
43
44
|
const currentTags = response.names;
|
|
44
45
|
// Add new tags (deduplicate)
|
|
45
46
|
const updatedTags = Array.from(new Set([...currentTags, ...tagsToAdd]));
|
|
46
47
|
// Update tags
|
|
47
|
-
await client.post(`/agents/${
|
|
48
|
+
await client.post(`/agents/${resolvedId}/tags`, { names: updatedTags });
|
|
48
49
|
const agentName = config?.name || `agent ${agentId}`;
|
|
49
50
|
const label = `${agentName}${config ? '' : ` (${agentId})`}`;
|
|
50
51
|
output.success(`Updated tags for agent: ${label}`);
|