@guildai/cli 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth-CRMO5O3N.js +29 -0
- package/dist/auth-CRMO5O3N.js.map +7 -0
- package/dist/chat-5VX2WJH2.js +303 -0
- package/dist/chat-5VX2WJH2.js.map +7 -0
- package/dist/chat-SIKDYZQK.js +31 -0
- package/dist/chat-SIKDYZQK.js.map +7 -0
- package/dist/chunk-56YCMGL3.js +522 -0
- package/dist/chunk-56YCMGL3.js.map +7 -0
- package/dist/chunk-6EX6E7WP.js +7042 -0
- package/dist/chunk-6EX6E7WP.js.map +7 -0
- package/dist/chunk-B7VAF5UG.js +532 -0
- package/dist/chunk-B7VAF5UG.js.map +7 -0
- package/dist/chunk-DOIYVBNY.js +3057 -0
- package/dist/chunk-DOIYVBNY.js.map +7 -0
- package/dist/chunk-ENKEEJ45.js +17 -0
- package/dist/chunk-ENKEEJ45.js.map +7 -0
- package/dist/chunk-IBRKVGMZ.js +97041 -0
- package/dist/chunk-IBRKVGMZ.js.map +7 -0
- package/dist/chunk-LFMQJOKC.js +19778 -0
- package/dist/chunk-LFMQJOKC.js.map +7 -0
- package/dist/chunk-M347HP6M.js +22896 -0
- package/dist/chunk-M347HP6M.js.map +7 -0
- package/dist/chunk-OYQ476FQ.js +44 -0
- package/dist/chunk-OYQ476FQ.js.map +7 -0
- package/dist/chunk-PNCUR4OB.js +257 -0
- package/dist/chunk-PNCUR4OB.js.map +7 -0
- package/dist/chunk-RIG2HZWM.js +317 -0
- package/dist/chunk-RIG2HZWM.js.map +7 -0
- package/dist/chunk-SPZPZXUN.js +826 -0
- package/dist/chunk-SPZPZXUN.js.map +7 -0
- package/dist/chunk-VVSOU6ON.js +53 -0
- package/dist/chunk-VVSOU6ON.js.map +7 -0
- package/dist/chunk-X3ADGWOF.js +3643 -0
- package/dist/chunk-X3ADGWOF.js.map +7 -0
- package/dist/commands/agent/logs.d.ts +3 -0
- package/dist/commands/setup.d.ts +16 -0
- package/dist/commands/skill/create.d.ts +3 -0
- package/dist/commands/skill/get.d.ts +3 -0
- package/dist/commands/skill/list.d.ts +3 -0
- package/dist/commands/skill/update.d.ts +3 -0
- package/dist/commands/skill/version/create.d.ts +3 -0
- package/dist/commands/skill/version/get.d.ts +3 -0
- package/dist/commands/skill/version/list.d.ts +3 -0
- package/dist/devtools-AO7YSDOD.js +67 -0
- package/dist/devtools-AO7YSDOD.js.map +7 -0
- package/dist/dist-4CBK6X5H.js +1566 -0
- package/dist/dist-4CBK6X5H.js.map +7 -0
- package/dist/esm-FRAVZP4J.js +13 -0
- package/dist/esm-FRAVZP4J.js.map +7 -0
- package/dist/execa-XQMWSABC.js +35 -0
- package/dist/execa-XQMWSABC.js.map +7 -0
- package/dist/index.js +8231 -253
- package/dist/index.js.map +7 -0
- package/dist/lib/api-types.d.ts +44 -0
- package/dist/lib/auth.d.ts +1 -1
- package/dist/lib/config.d.ts +9 -0
- package/dist/lib/errors.d.ts +1 -1
- package/dist/lib/output-mode.d.ts +9 -2
- package/dist/lib/output.d.ts +17 -1
- package/dist/lib/session-events.d.ts +14 -3
- package/dist/lib/session-polling.d.ts +24 -1
- package/dist/lib/session-resume.d.ts +15 -1
- package/dist/lib/stdin.d.ts +5 -1
- package/dist/lib/websocket-client.d.ts +46 -0
- package/dist/open-RF4X5MOP.js +13 -0
- package/dist/open-RF4X5MOP.js.map +7 -0
- package/dist/server-JYVH64FD.js +27659 -0
- package/dist/server-JYVH64FD.js.map +7 -0
- package/dist/test-SNIYRJ32.js +692 -0
- package/dist/test-SNIYRJ32.js.map +7 -0
- package/docs/skills/codex-agent-dev.md +2 -2
- package/package.json +8 -12
- package/dist/commands/agent/chat.js +0 -278
- package/dist/commands/agent/clone.js +0 -116
- package/dist/commands/agent/code.js +0 -87
- package/dist/commands/agent/fork.js +0 -218
- package/dist/commands/agent/get.js +0 -37
- package/dist/commands/agent/grep.js +0 -107
- package/dist/commands/agent/init.js +0 -390
- package/dist/commands/agent/list.js +0 -110
- package/dist/commands/agent/owners.js +0 -74
- package/dist/commands/agent/publish.js +0 -91
- package/dist/commands/agent/pull.js +0 -198
- package/dist/commands/agent/revalidate.js +0 -56
- package/dist/commands/agent/save.js +0 -346
- package/dist/commands/agent/search.js +0 -61
- package/dist/commands/agent/tags/add.js +0 -73
- package/dist/commands/agent/tags/list.js +0 -43
- package/dist/commands/agent/tags/remove.js +0 -84
- package/dist/commands/agent/tags/set.js +0 -71
- package/dist/commands/agent/test.js +0 -486
- package/dist/commands/agent/unpublish.js +0 -64
- package/dist/commands/agent/update.js +0 -110
- package/dist/commands/agent/versions.js +0 -55
- package/dist/commands/agent/workspaces.js +0 -54
- package/dist/commands/auth/login.js +0 -33
- package/dist/commands/auth/logout.js +0 -24
- package/dist/commands/auth/status.js +0 -38
- package/dist/commands/auth/token.js +0 -19
- package/dist/commands/chat.js +0 -1345
- package/dist/commands/config/get.js +0 -64
- package/dist/commands/config/list.js +0 -47
- package/dist/commands/config/path.js +0 -38
- package/dist/commands/config/set.js +0 -132
- package/dist/commands/credentials/endpoint-list.js +0 -88
- package/dist/commands/credentials/list.js +0 -50
- package/dist/commands/credentials/policy-create.js +0 -66
- package/dist/commands/credentials/policy-delete.js +0 -33
- package/dist/commands/credentials/policy-list.js +0 -45
- package/dist/commands/credentials/policy-update.js +0 -66
- package/dist/commands/doctor.js +0 -233
- package/dist/commands/integration/connect.js +0 -76
- package/dist/commands/integration/create.js +0 -298
- package/dist/commands/integration/get.js +0 -95
- package/dist/commands/integration/list.js +0 -62
- package/dist/commands/integration/operation/create.js +0 -164
- package/dist/commands/integration/operation/list.js +0 -92
- package/dist/commands/integration/update.js +0 -139
- package/dist/commands/integration/version/build.js +0 -86
- package/dist/commands/integration/version/create.js +0 -45
- package/dist/commands/integration/version/get.js +0 -72
- package/dist/commands/integration/version/list.js +0 -45
- package/dist/commands/integration/version/publish.js +0 -79
- package/dist/commands/integration/version/test.js +0 -104
- package/dist/commands/job/get-step.js +0 -40
- package/dist/commands/job/get.js +0 -44
- package/dist/commands/mcp.js +0 -34
- package/dist/commands/session/create.js +0 -59
- package/dist/commands/session/events.js +0 -56
- package/dist/commands/session/get.js +0 -33
- package/dist/commands/session/interrupt.js +0 -33
- package/dist/commands/session/list.js +0 -59
- package/dist/commands/session/send.js +0 -54
- package/dist/commands/session/tasks.js +0 -45
- package/dist/commands/setup.js +0 -230
- package/dist/commands/trigger/activate.js +0 -41
- package/dist/commands/trigger/create.js +0 -197
- package/dist/commands/trigger/deactivate.js +0 -41
- package/dist/commands/trigger/get.js +0 -33
- package/dist/commands/trigger/list.js +0 -57
- package/dist/commands/trigger/sessions.js +0 -48
- package/dist/commands/trigger/update.js +0 -128
- package/dist/commands/version.js +0 -24
- package/dist/commands/workspace/agent/add.js +0 -114
- package/dist/commands/workspace/agent/list.js +0 -78
- package/dist/commands/workspace/agent/remove.js +0 -78
- package/dist/commands/workspace/clear.js +0 -45
- package/dist/commands/workspace/context/edit.js +0 -107
- package/dist/commands/workspace/context/get.js +0 -47
- package/dist/commands/workspace/context/list.js +0 -51
- package/dist/commands/workspace/context/publish.js +0 -42
- package/dist/commands/workspace/create.js +0 -51
- package/dist/commands/workspace/current.js +0 -63
- package/dist/commands/workspace/get.js +0 -39
- package/dist/commands/workspace/list.js +0 -70
- package/dist/commands/workspace/select.js +0 -184
- package/dist/components/AgentInstallPrompt.js +0 -97
- package/dist/components/SplashAnimation.js +0 -321
- package/dist/components/TaskView.js +0 -268
- package/dist/lib/agent-helpers.js +0 -306
- package/dist/lib/alternate-screen.js +0 -59
- package/dist/lib/api-client.js +0 -154
- package/dist/lib/api-types.js +0 -10
- package/dist/lib/auth.js +0 -284
- package/dist/lib/braille-canvas.js +0 -321
- package/dist/lib/colors.js +0 -46
- package/dist/lib/config-cache.js +0 -45
- package/dist/lib/config.js +0 -153
- package/dist/lib/did-you-mean.js +0 -144
- package/dist/lib/errors.js +0 -375
- package/dist/lib/event-filter.js +0 -91
- package/dist/lib/generated-types.js +0 -56
- package/dist/lib/git.js +0 -176
- package/dist/lib/gk.js +0 -91
- package/dist/lib/guild-config.js +0 -178
- package/dist/lib/iap.js +0 -117
- package/dist/lib/integration-helpers.js +0 -38
- package/dist/lib/loading-messages.js +0 -72
- package/dist/lib/logo.js +0 -141
- package/dist/lib/lottie-serverside.js +0 -181
- package/dist/lib/markdown.js +0 -38
- package/dist/lib/npmrc.js +0 -59
- package/dist/lib/output-mode.js +0 -33
- package/dist/lib/output.js +0 -591
- package/dist/lib/owner-helpers.js +0 -112
- package/dist/lib/polling.js +0 -76
- package/dist/lib/progress.js +0 -324
- package/dist/lib/session-events-fetch.js +0 -25
- package/dist/lib/session-events.js +0 -112
- package/dist/lib/session-polling.js +0 -160
- package/dist/lib/session-resume.js +0 -96
- package/dist/lib/spinners.js +0 -770
- package/dist/lib/splash.js +0 -41
- package/dist/lib/stdin.js +0 -84
- package/dist/lib/svg-to-braille.js +0 -76
- package/dist/lib/table.js +0 -59
- package/dist/lib/update-check.js +0 -65
- package/dist/lib/validate-input-schema.js +0 -208
- package/dist/lib/version-helpers.js +0 -121
- package/dist/lib/workspace-helpers.js +0 -49
- package/dist/mcp/resources.js +0 -67
- package/dist/mcp/server.js +0 -64
- package/dist/mcp/tools.js +0 -753
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 Guild.ai
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
-
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
6
|
-
import { getOutputMode } from '../../lib/output-mode.js';
|
|
7
|
-
import { createOutputWriter } from '../../lib/output.js';
|
|
8
|
-
import * as fs from 'fs/promises';
|
|
9
|
-
import * as path from 'path';
|
|
10
|
-
import { getAuthenticatedUrl } from '../../lib/auth.js';
|
|
11
|
-
import { runGit, GitError, formatGitError } from '../../lib/git.js';
|
|
12
|
-
export function createAgentPullCommand() {
|
|
13
|
-
const cmd = new Command('pull');
|
|
14
|
-
cmd
|
|
15
|
-
.description('Pull remote changes into local agent directory')
|
|
16
|
-
.option('--json', 'Output JSON only, no progress messages (default: off)', false)
|
|
17
|
-
.action(async (_options) => {
|
|
18
|
-
const cwd = process.cwd();
|
|
19
|
-
const output = createOutputWriter();
|
|
20
|
-
try {
|
|
21
|
-
// Check for guild.json
|
|
22
|
-
const guildJsonPath = path.join(cwd, 'guild.json');
|
|
23
|
-
const guildJsonExists = await fs
|
|
24
|
-
.access(guildJsonPath)
|
|
25
|
-
.then(() => true)
|
|
26
|
-
.catch(() => false);
|
|
27
|
-
if (!guildJsonExists) {
|
|
28
|
-
output.error('Not in an agent directory', 'guild.json not found in current directory.\n\nInitialize an agent directory:\n guild agent init --name my-agent\n\nOr clone an existing agent:\n guild agent clone <agent-id>');
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
// Read guild.json
|
|
32
|
-
const guildConfig = JSON.parse(await fs.readFile(guildJsonPath, 'utf-8'));
|
|
33
|
-
// Fetch agent to get git_url
|
|
34
|
-
const client = new GuildAPIClient();
|
|
35
|
-
const agent = await client.get(`/agents/${guildConfig.agent_id}`);
|
|
36
|
-
if (!agent.git_url) {
|
|
37
|
-
output.error('Agent does not have a git repository', 'This agent may not have been initialized with git.');
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
// Get authenticated URL
|
|
41
|
-
const authenticatedUrl = await getAuthenticatedUrl(agent.git_url);
|
|
42
|
-
if (!authenticatedUrl) {
|
|
43
|
-
output.error('Not authenticated.', 'Run: guild auth login');
|
|
44
|
-
process.exit(1);
|
|
45
|
-
}
|
|
46
|
-
// Get current branch name
|
|
47
|
-
const { stdout: branchName } = await runGit(['rev-parse', '--abbrev-ref', 'HEAD'], { cwd });
|
|
48
|
-
const currentBranch = branchName.trim();
|
|
49
|
-
// Pull remote changes with rebase
|
|
50
|
-
let gitPulledNewCommits = false;
|
|
51
|
-
try {
|
|
52
|
-
const { stdout: pullOutput } = await runGit(['pull', '--rebase', authenticatedUrl, currentBranch], { cwd });
|
|
53
|
-
// Update remote-tracking ref so git status stays consistent
|
|
54
|
-
try {
|
|
55
|
-
await runGit(['update-ref', `refs/remotes/origin/${currentBranch}`, 'FETCH_HEAD'], { cwd });
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
// Non-fatal: git status will be stale but pull still succeeded
|
|
59
|
-
}
|
|
60
|
-
if (pullOutput.includes('Already up to date') ||
|
|
61
|
-
pullOutput.includes('Current branch') // "Current branch X is up to date."
|
|
62
|
-
) {
|
|
63
|
-
// Don't report yet — version check below may have more to say
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
gitPulledNewCommits = true;
|
|
67
|
-
// Count commits pulled
|
|
68
|
-
const updateMatch = pullOutput.match(/Updating\s+[a-f0-9]+\.\.[a-f0-9]+/);
|
|
69
|
-
const fastForward = pullOutput.includes('Fast-forward');
|
|
70
|
-
let message = 'Pulled remote changes';
|
|
71
|
-
if (fastForward || updateMatch) {
|
|
72
|
-
const filesMatch = pullOutput.match(/(\d+)\s+files?\s+changed/);
|
|
73
|
-
if (filesMatch) {
|
|
74
|
-
message = `Pulled remote changes (${filesMatch[1]} files changed)`;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
output.progress(`✓ ${message}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
catch (pullError) {
|
|
81
|
-
const errMessage = pullError instanceof GitError
|
|
82
|
-
? pullError.stderr || pullError.stdout
|
|
83
|
-
: String(pullError);
|
|
84
|
-
// Check for rebase conflicts
|
|
85
|
-
if (errMessage.includes('CONFLICT') ||
|
|
86
|
-
errMessage.includes('could not apply')) {
|
|
87
|
-
output.error('Merge conflict detected', 'Your changes conflict with remote changes.\n\nTo resolve:\n 1. Fix conflicts in the listed files\n 2. git add <resolved-files>\n 3. git rebase --continue\n\nOr abort the rebase:\n git rebase --abort');
|
|
88
|
-
process.exit(1);
|
|
89
|
-
}
|
|
90
|
-
// No upstream branch — nothing to pull
|
|
91
|
-
if (errMessage.includes('no tracking information') ||
|
|
92
|
-
errMessage.includes("couldn't find remote ref")) {
|
|
93
|
-
output.progress('✓ Already up to date (no remote branch yet)');
|
|
94
|
-
if (getOutputMode() === 'json') {
|
|
95
|
-
output.data({
|
|
96
|
-
success: true,
|
|
97
|
-
message: 'Already up to date (no remote branch yet)',
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
// Unknown git error
|
|
103
|
-
throw pullError;
|
|
104
|
-
}
|
|
105
|
-
// Version check: compare local state against backend
|
|
106
|
-
const versions = await client.get(`/agents/${guildConfig.agent_id}/versions?limit=1`);
|
|
107
|
-
if (versions.items.length > 0) {
|
|
108
|
-
const latest = versions.items[0];
|
|
109
|
-
const { stdout: headSha } = await runGit(['rev-parse', 'HEAD'], { cwd });
|
|
110
|
-
const localHead = headSha.trim();
|
|
111
|
-
if (latest.sha && latest.sha === localHead) {
|
|
112
|
-
// Truly up to date — git pull + version match
|
|
113
|
-
if (!gitPulledNewCommits) {
|
|
114
|
-
output.progress('✓ Already up to date');
|
|
115
|
-
}
|
|
116
|
-
if (getOutputMode() === 'json') {
|
|
117
|
-
output.data({
|
|
118
|
-
success: true,
|
|
119
|
-
message: gitPulledNewCommits
|
|
120
|
-
? 'Pulled remote changes'
|
|
121
|
-
: 'Already up to date',
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else if (latest.sha && latest.sha !== localHead) {
|
|
126
|
-
// SHA mismatch — warn user
|
|
127
|
-
output.progress(`⚠ Remote has a newer version (${latest.sha.slice(0, 7)}) not on this branch`);
|
|
128
|
-
output.progress(' Try: git fetch origin && git log --oneline origin/main');
|
|
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
|
-
}
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
// Ephemeral version — download from API
|
|
140
|
-
output.progress('Remote has unpublished changes from the web editor');
|
|
141
|
-
// Check for local uncommitted changes
|
|
142
|
-
const { stdout: status } = await runGit(['status', '--porcelain'], { cwd });
|
|
143
|
-
if (status.trim()) {
|
|
144
|
-
output.error('Cannot download remote changes — you have uncommitted local changes', 'Commit or stash your changes first, then run guild agent pull again.');
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
|
-
const files = await client.get(`/agents/${guildConfig.agent_id}/code?include_unpublished=1`);
|
|
148
|
-
for (const file of files) {
|
|
149
|
-
const filePath = path.join(cwd, file.path);
|
|
150
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
151
|
-
await fs.writeFile(filePath, file.content, 'utf-8');
|
|
152
|
-
}
|
|
153
|
-
output.progress(`✓ Downloaded ${files.length} files from latest draft version`);
|
|
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
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
// No versions exist yet — just report git pull result
|
|
165
|
-
if (!gitPulledNewCommits) {
|
|
166
|
-
output.progress('✓ Already up to date');
|
|
167
|
-
}
|
|
168
|
-
if (getOutputMode() === 'json') {
|
|
169
|
-
output.data({
|
|
170
|
-
success: true,
|
|
171
|
-
message: gitPulledNewCommits
|
|
172
|
-
? 'Pulled remote changes'
|
|
173
|
-
: 'Already up to date',
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
catch (error) {
|
|
179
|
-
if (error instanceof GitError) {
|
|
180
|
-
output.error('Git operation failed', formatGitError(error));
|
|
181
|
-
process.exit(1);
|
|
182
|
-
}
|
|
183
|
-
const formattedError = handleAxiosError(error);
|
|
184
|
-
if (formattedError.code === ErrorCodes.AUTH_REQUIRED) {
|
|
185
|
-
output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
|
|
186
|
-
process.exit(1);
|
|
187
|
-
}
|
|
188
|
-
if (formattedError.code === ErrorCodes.NOT_FOUND) {
|
|
189
|
-
output.error('Agent not found', 'The agent may have been deleted.\nCheck your guild.json agent_id.');
|
|
190
|
-
process.exit(1);
|
|
191
|
-
}
|
|
192
|
-
output.error(`Failed to pull: ${formattedError.details}`);
|
|
193
|
-
process.exit(1);
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
return cmd;
|
|
197
|
-
}
|
|
198
|
-
//# sourceMappingURL=pull.js.map
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 Guild.ai
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
-
import { getGuildcoreUrl } from '../../lib/config.js';
|
|
6
|
-
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
7
|
-
import { getAgentId, resolveAgentRef } from '../../lib/agent-helpers.js';
|
|
8
|
-
import { createOutputWriter } from '../../lib/output.js';
|
|
9
|
-
export function createAgentRevalidateCommand() {
|
|
10
|
-
const cmd = new Command('revalidate');
|
|
11
|
-
cmd
|
|
12
|
-
.description('Revalidate an agent version')
|
|
13
|
-
.argument('[identifier]', 'Agent ID or full name (e.g., owner~agent-name)')
|
|
14
|
-
.argument('[version-id]', 'ID of the version to revalidate (uses latest if omitted)')
|
|
15
|
-
.action(async (agentIdArg, versionIdArg) => {
|
|
16
|
-
const output = createOutputWriter();
|
|
17
|
-
// Get agent ID from argument or guild.json
|
|
18
|
-
const { agentId } = await getAgentId(agentIdArg);
|
|
19
|
-
const baseUrl = getGuildcoreUrl();
|
|
20
|
-
const client = new GuildAPIClient({ baseUrl });
|
|
21
|
-
try {
|
|
22
|
-
const resolvedId = await resolveAgentRef(client, agentId);
|
|
23
|
-
let versionId = versionIdArg;
|
|
24
|
-
// If no version ID provided, get the latest version
|
|
25
|
-
if (!versionId) {
|
|
26
|
-
const versions = await client.get(`/agents/${resolvedId}/versions?limit=1&offset=0`);
|
|
27
|
-
if (!versions.items || versions.items.length === 0) {
|
|
28
|
-
output.error('No versions found for this agent.', `The agent may still be initializing. Check status:\n guild agent get ${agentId}`);
|
|
29
|
-
process.exit(1);
|
|
30
|
-
}
|
|
31
|
-
versionId = versions.items[0].id;
|
|
32
|
-
}
|
|
33
|
-
// Revalidate the version
|
|
34
|
-
const result = await client.post(`/agents/${resolvedId}/versions/${versionId}/revalidate`);
|
|
35
|
-
output.data(result);
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
const formattedError = handleAxiosError(error);
|
|
39
|
-
if (formattedError.code === ErrorCodes.AUTH_REQUIRED) {
|
|
40
|
-
output.error('Not authenticated.', 'Please authenticate first:\n guild auth login');
|
|
41
|
-
}
|
|
42
|
-
else if (formattedError.code === ErrorCodes.CONN_REFUSED) {
|
|
43
|
-
output.error('Cannot connect to Guild servers');
|
|
44
|
-
}
|
|
45
|
-
else if (formattedError.code === ErrorCodes.NOT_FOUND) {
|
|
46
|
-
output.error('Agent or version not found', `Check the agent and version IDs:\n guild agent list\n guild agent versions ${agentId}`);
|
|
47
|
-
}
|
|
48
|
-
else {
|
|
49
|
-
output.error(`Failed to revalidate version: ${formattedError.details}`);
|
|
50
|
-
}
|
|
51
|
-
process.exit(1);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
return cmd;
|
|
55
|
-
}
|
|
56
|
-
//# sourceMappingURL=revalidate.js.map
|
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 Guild.ai
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
-
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
6
|
-
import { getOutputMode } from '../../lib/output-mode.js';
|
|
7
|
-
import { createOutputWriter } from '../../lib/output.js';
|
|
8
|
-
import * as fs from 'fs/promises';
|
|
9
|
-
import * as path from 'path';
|
|
10
|
-
import { getAuthenticatedUrl } from '../../lib/auth.js';
|
|
11
|
-
import { runGit, GitError, formatGitError } from '../../lib/git.js';
|
|
12
|
-
import { waitForValidation, waitForPublish } from '../../lib/version-helpers.js';
|
|
13
|
-
export function createAgentSaveCommand() {
|
|
14
|
-
const cmd = new Command('save');
|
|
15
|
-
cmd
|
|
16
|
-
.description('Commit, push, and create a new agent version')
|
|
17
|
-
.option('-A, --all', 'Stage all changes and commit before pushing', false)
|
|
18
|
-
.option('-m, --message <text>', 'Commit message (required with --all)')
|
|
19
|
-
.option('--wait', 'Wait for validation to complete before returning (default: returns immediately)', false)
|
|
20
|
-
.option('--publish', 'Publish after validation passes (implies --wait) (default: does not publish)', false)
|
|
21
|
-
.option('--bump [level]', 'Bump package.json version before saving (patch, or minor/major) (default: patch)', 'patch')
|
|
22
|
-
.option('--no-bump', 'Skip automatic version bump')
|
|
23
|
-
.option('--json', 'Output JSON only, no progress messages (default: off)', false)
|
|
24
|
-
.action(async (options) => {
|
|
25
|
-
const cwd = process.cwd();
|
|
26
|
-
let guildConfig = null;
|
|
27
|
-
const output = createOutputWriter();
|
|
28
|
-
// Resolve bump level: bare --bump defaults to 'patch', --no-bump skips
|
|
29
|
-
const bumpLevel = options.bump === true || options.bump === 'patch'
|
|
30
|
-
? 'patch'
|
|
31
|
-
: options.bump === 'minor'
|
|
32
|
-
? 'minor'
|
|
33
|
-
: options.bump === 'major'
|
|
34
|
-
? 'major'
|
|
35
|
-
: options.bump === false
|
|
36
|
-
? null
|
|
37
|
-
: null;
|
|
38
|
-
if (options.bump !== false && bumpLevel === null) {
|
|
39
|
-
output.error(`Invalid bump level: ${String(options.bump)}`, 'Valid levels are: patch, minor, major\n guild agent save --bump minor');
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
// With --all, a commit message is required (unless bump auto-generates one)
|
|
43
|
-
if (options.all && !options.message && !bumpLevel) {
|
|
44
|
-
output.error('Commit message is required with --all', 'Provide a message describing your changes:\n guild agent save -A --message "Add new feature"');
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
let versionNumber;
|
|
48
|
-
try {
|
|
49
|
-
// Check for guild.json
|
|
50
|
-
const guildJsonPath = path.join(cwd, 'guild.json');
|
|
51
|
-
const guildJsonExists = await fs
|
|
52
|
-
.access(guildJsonPath)
|
|
53
|
-
.then(() => true)
|
|
54
|
-
.catch(() => false);
|
|
55
|
-
if (!guildJsonExists) {
|
|
56
|
-
output.error('Not in an agent directory', 'guild.json not found in current directory.\n\nInitialize an agent directory:\n guild agent init --name my-agent\n\nOr clone an existing agent:\n guild agent clone <agent-id>');
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
// Read guild.json
|
|
60
|
-
guildConfig = JSON.parse(await fs.readFile(guildJsonPath, 'utf-8'));
|
|
61
|
-
// Handle --bump: bump package.json version before git operations
|
|
62
|
-
if (bumpLevel) {
|
|
63
|
-
const packageJsonPath = path.join(cwd, 'package.json');
|
|
64
|
-
let packageJsonContent;
|
|
65
|
-
try {
|
|
66
|
-
packageJsonContent = await fs.readFile(packageJsonPath, 'utf-8');
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
output.error('package.json not found', 'A package.json file is required in the agent directory to use --bump.');
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
const packageJson = JSON.parse(packageJsonContent);
|
|
73
|
-
const currentVersion = packageJson.version || '0.0.0';
|
|
74
|
-
const parts = currentVersion.split('.').map(Number);
|
|
75
|
-
if (parts.length !== 3 || parts.some((p) => isNaN(p))) {
|
|
76
|
-
output.error(`Cannot bump invalid version: ${currentVersion}`, 'package.json version must be in MAJOR.MINOR.PATCH format (e.g. 1.0.0)');
|
|
77
|
-
process.exit(1);
|
|
78
|
-
}
|
|
79
|
-
const [major, minor, patch] = parts;
|
|
80
|
-
let newVersion;
|
|
81
|
-
if (bumpLevel === 'major') {
|
|
82
|
-
newVersion = `${major + 1}.0.0`;
|
|
83
|
-
}
|
|
84
|
-
else if (bumpLevel === 'minor') {
|
|
85
|
-
newVersion = `${major}.${minor + 1}.0`;
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
newVersion = `${major}.${minor}.${patch + 1}`;
|
|
89
|
-
}
|
|
90
|
-
packageJson.version = newVersion;
|
|
91
|
-
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
92
|
-
versionNumber = newVersion;
|
|
93
|
-
output.progress(`✓ Bumped version: ${currentVersion} → ${newVersion}`);
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
// No bump — read version from package.json if it exists
|
|
97
|
-
const packageJsonPath = path.join(cwd, 'package.json');
|
|
98
|
-
try {
|
|
99
|
-
const pkg = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
|
|
100
|
-
if (pkg.version) {
|
|
101
|
-
versionNumber = pkg.version;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
// No package.json or unreadable — version stays undefined
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// Check for uncommitted changes and unpushed commits
|
|
109
|
-
const { stdout: statusOutput } = await runGit(['status', '--porcelain'], {
|
|
110
|
-
cwd,
|
|
111
|
-
});
|
|
112
|
-
const hasUncommittedChanges = statusOutput.trim().length > 0;
|
|
113
|
-
let hasUnpushedCommits = false;
|
|
114
|
-
// Check for unpushed commits
|
|
115
|
-
try {
|
|
116
|
-
const { stdout: branchForCheck } = await runGit(['rev-parse', '--abbrev-ref', 'HEAD'], { cwd });
|
|
117
|
-
const { stdout: unpushed } = await runGit(['log', `origin/${branchForCheck.trim()}..HEAD`, '--oneline'], { cwd });
|
|
118
|
-
hasUnpushedCommits = unpushed.trim().length > 0;
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
// No remote tracking branch yet — if HEAD has commits, treat
|
|
122
|
-
// as unpushed so the push flow can create the remote branch.
|
|
123
|
-
try {
|
|
124
|
-
const { stdout: logOutput } = await runGit(['log', '--oneline', '-1'], {
|
|
125
|
-
cwd,
|
|
126
|
-
});
|
|
127
|
-
hasUnpushedCommits = logOutput.trim().length > 0;
|
|
128
|
-
}
|
|
129
|
-
catch {
|
|
130
|
-
hasUnpushedCommits = false;
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
// --bump implies --all (the version change needs to be committed)
|
|
134
|
-
const shouldStageAll = options.all || !!bumpLevel;
|
|
135
|
-
if (shouldStageAll) {
|
|
136
|
-
// Stage and commit before pushing
|
|
137
|
-
if (hasUncommittedChanges) {
|
|
138
|
-
await runGit(['add', '-A'], { cwd });
|
|
139
|
-
output.progress('✓ Staged changes');
|
|
140
|
-
const commitMsg = options.message || (bumpLevel ? `Bump version` : '');
|
|
141
|
-
await runGit(['commit', '-m', commitMsg], { cwd });
|
|
142
|
-
output.progress('✓ Committed locally');
|
|
143
|
-
hasUnpushedCommits = true;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
// Default: push-only, no staging or committing
|
|
148
|
-
if (!hasUnpushedCommits && hasUncommittedChanges) {
|
|
149
|
-
output.error('Uncommitted changes', 'You have uncommitted changes. Either commit them first:\n git add . && git commit -m "your message"\n\nOr use --all to stage and commit automatically:\n guild agent save -A --message "your message"');
|
|
150
|
-
process.exit(1);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if (!hasUnpushedCommits) {
|
|
154
|
-
output.error('No changes to save', 'Working tree is clean and there are no unpushed commits.');
|
|
155
|
-
process.exit(1);
|
|
156
|
-
}
|
|
157
|
-
// Resolve version summary: use --message if provided, otherwise
|
|
158
|
-
// extract the latest commit message.
|
|
159
|
-
let versionMessage = options.message;
|
|
160
|
-
if (!versionMessage) {
|
|
161
|
-
const { stdout: commitMsg } = await runGit(['log', '-1', '--pretty=%s'], {
|
|
162
|
-
cwd,
|
|
163
|
-
});
|
|
164
|
-
versionMessage = commitMsg.trim();
|
|
165
|
-
}
|
|
166
|
-
// Get remote URL with auth credentials
|
|
167
|
-
const { stdout: remoteUrl } = await runGit(['remote', 'get-url', 'origin'], {
|
|
168
|
-
cwd,
|
|
169
|
-
});
|
|
170
|
-
const authenticatedUrl = await getAuthenticatedUrl(remoteUrl.trim());
|
|
171
|
-
if (!authenticatedUrl) {
|
|
172
|
-
output.error('Not authenticated.', 'Run: guild auth login');
|
|
173
|
-
process.exit(1);
|
|
174
|
-
}
|
|
175
|
-
// Get current branch name
|
|
176
|
-
const { stdout: branchName } = await runGit(['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
177
|
-
cwd,
|
|
178
|
-
});
|
|
179
|
-
const currentBranch = branchName.trim();
|
|
180
|
-
// Pull remote changes first (rebase to avoid merge commits)
|
|
181
|
-
const gitEnv = { GUILD_AGENT_SAVE: '1' };
|
|
182
|
-
try {
|
|
183
|
-
const { stdout: pullOutput } = await runGit(['pull', '--rebase', authenticatedUrl, currentBranch], { cwd, env: gitEnv });
|
|
184
|
-
if (pullOutput.includes('Updating') ||
|
|
185
|
-
pullOutput.includes('Fast-forward')) {
|
|
186
|
-
output.progress('✓ Synced with remote');
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
catch (pullError) {
|
|
190
|
-
const errMessage = pullError instanceof GitError
|
|
191
|
-
? pullError.stderr || pullError.stdout
|
|
192
|
-
: String(pullError);
|
|
193
|
-
// Check for rebase conflicts
|
|
194
|
-
if (errMessage.includes('CONFLICT') ||
|
|
195
|
-
errMessage.includes('could not apply')) {
|
|
196
|
-
output.error('Merge conflict detected', 'Your changes conflict with remote changes.\n\nTo resolve:\n 1. Fix conflicts in the listed files\n 2. git add <resolved-files>\n 3. git rebase --continue\n 4. guild agent save --message "..."\n\nOr abort the rebase:\n git rebase --abort');
|
|
197
|
-
process.exit(1);
|
|
198
|
-
}
|
|
199
|
-
// If pull fails, check if it's because there's no upstream
|
|
200
|
-
if (!errMessage.includes('no tracking information') &&
|
|
201
|
-
!errMessage.includes("couldn't find remote ref")) {
|
|
202
|
-
// Real error we don't understand
|
|
203
|
-
output.error('Failed to sync with remote', errMessage);
|
|
204
|
-
process.exit(1);
|
|
205
|
-
}
|
|
206
|
-
// No upstream branch yet, that's fine - first push will set it
|
|
207
|
-
}
|
|
208
|
-
// Push to remote using authenticated URL
|
|
209
|
-
// Note: We push to the URL directly (not via origin remote) because
|
|
210
|
-
// origin doesn't have auth credentials. This means we must manually
|
|
211
|
-
// update the remote-tracking ref afterward.
|
|
212
|
-
//
|
|
213
|
-
// Retry on transient server-side errors (e.g. GitHub returning
|
|
214
|
-
// "fatal error in commit_refs" when the repo isn't fully ready).
|
|
215
|
-
const maxPushAttempts = 3;
|
|
216
|
-
for (let attempt = 1; attempt <= maxPushAttempts; attempt++) {
|
|
217
|
-
try {
|
|
218
|
-
await runGit(['push', authenticatedUrl, `HEAD:${currentBranch}`], {
|
|
219
|
-
cwd,
|
|
220
|
-
env: gitEnv,
|
|
221
|
-
});
|
|
222
|
-
break;
|
|
223
|
-
}
|
|
224
|
-
catch (pushError) {
|
|
225
|
-
const msg = pushError instanceof GitError
|
|
226
|
-
? pushError.stderr || pushError.stdout
|
|
227
|
-
: String(pushError);
|
|
228
|
-
const isTransient = msg.includes('commit_refs') ||
|
|
229
|
-
msg.includes('remote rejected') ||
|
|
230
|
-
msg.includes('Service Unavailable') ||
|
|
231
|
-
msg.includes('502') ||
|
|
232
|
-
msg.includes('503');
|
|
233
|
-
if (!isTransient || attempt === maxPushAttempts) {
|
|
234
|
-
throw pushError;
|
|
235
|
-
}
|
|
236
|
-
const delaySec = attempt * 2;
|
|
237
|
-
output.progress(`Push failed (attempt ${attempt}/${maxPushAttempts}), retrying in ${delaySec}s...`);
|
|
238
|
-
await new Promise((resolve) => setTimeout(resolve, delaySec * 1000));
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// Update origin's remote-tracking ref so git status stays consistent.
|
|
242
|
-
// Pushing via URL doesn't update refs/remotes/origin/*, which causes
|
|
243
|
-
// "branch is ahead of origin/<branch>" confusion.
|
|
244
|
-
try {
|
|
245
|
-
await runGit(['update-ref', `refs/remotes/origin/${currentBranch}`, 'HEAD'], { cwd });
|
|
246
|
-
}
|
|
247
|
-
catch {
|
|
248
|
-
// Non-fatal: git status will be stale but save still succeeded
|
|
249
|
-
}
|
|
250
|
-
// Set up tracking for future operations
|
|
251
|
-
try {
|
|
252
|
-
await runGit(['branch', '--set-upstream-to', `origin/${currentBranch}`], {
|
|
253
|
-
cwd,
|
|
254
|
-
});
|
|
255
|
-
}
|
|
256
|
-
catch {
|
|
257
|
-
// Ignore if branch tracking already set or doesn't exist on remote yet
|
|
258
|
-
}
|
|
259
|
-
output.progress('✓ Pushed to remote');
|
|
260
|
-
// Get final commit SHA (after potential rebase)
|
|
261
|
-
const { stdout: shaOutput } = await runGit(['rev-parse', 'HEAD'], {
|
|
262
|
-
cwd,
|
|
263
|
-
});
|
|
264
|
-
const commitSha = shaOutput.trim();
|
|
265
|
-
// Create version in guildcore (always as DRAFT, publish happens separately)
|
|
266
|
-
const client = new GuildAPIClient();
|
|
267
|
-
const agentId = guildConfig?.agent_id;
|
|
268
|
-
if (!agentId) {
|
|
269
|
-
output.error('Not in an agent directory');
|
|
270
|
-
process.exit(1);
|
|
271
|
-
}
|
|
272
|
-
let version = await client.post(`/agents/${agentId}/versions`, {
|
|
273
|
-
commit_sha: commitSha,
|
|
274
|
-
summary: versionMessage,
|
|
275
|
-
version_type: 'COMMITTED',
|
|
276
|
-
...(versionNumber ? { version_number: versionNumber } : {}),
|
|
277
|
-
});
|
|
278
|
-
output.progress(`✓ Created version (${version.id})`);
|
|
279
|
-
if (options.wait || options.publish) {
|
|
280
|
-
version = await waitForValidation(version.id, output);
|
|
281
|
-
}
|
|
282
|
-
if (options.publish) {
|
|
283
|
-
output.progress('Validation passed, publishing...');
|
|
284
|
-
version = await client.post(`/versions/${version.id}/publish`, {});
|
|
285
|
-
if (options.wait && version.status !== 'PUBLISHED') {
|
|
286
|
-
version = await waitForPublish(version.id, output);
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
output.progress('✓ Published');
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
output.progress('');
|
|
293
|
-
output.progress('Version details:');
|
|
294
|
-
output.progress(` ID: ${version.id}`);
|
|
295
|
-
output.progress(` SHA: ${version.sha ? version.sha.substring(0, 12) : '-'}`);
|
|
296
|
-
output.progress(` Status: ${version.status}`);
|
|
297
|
-
if (version.published_at) {
|
|
298
|
-
output.progress(` Published at: ${version.published_at}`);
|
|
299
|
-
}
|
|
300
|
-
output.progress(` Summary: ${version.summary}`);
|
|
301
|
-
if (options.publish && version.status === 'PUBLISHED') {
|
|
302
|
-
output.progress('');
|
|
303
|
-
output.progress('Version is now published and available in the catalog.');
|
|
304
|
-
}
|
|
305
|
-
else if (options.publish) {
|
|
306
|
-
output.progress('');
|
|
307
|
-
output.progress('Publish is in progress. Use --wait to wait for completion.');
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
output.progress('');
|
|
311
|
-
output.progress('To publish this version:');
|
|
312
|
-
output.progress(' guild agent save --message "..." --publish');
|
|
313
|
-
}
|
|
314
|
-
// Output JSON to stdout only in --json mode.
|
|
315
|
-
// In interactive mode the progress messages above already
|
|
316
|
-
// show version details; dumping raw JSON is noise.
|
|
317
|
-
if (getOutputMode() === 'json') {
|
|
318
|
-
output.data({ version });
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
catch (error) {
|
|
322
|
-
if (error instanceof GitError) {
|
|
323
|
-
output.error('Git operation failed', formatGitError(error));
|
|
324
|
-
process.exit(1);
|
|
325
|
-
}
|
|
326
|
-
// Handle API errors
|
|
327
|
-
const formattedError = handleAxiosError(error);
|
|
328
|
-
if (formattedError.code === ErrorCodes.AUTH_REQUIRED) {
|
|
329
|
-
output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
|
|
330
|
-
process.exit(1);
|
|
331
|
-
}
|
|
332
|
-
if (formattedError.code === ErrorCodes.NOT_FOUND) {
|
|
333
|
-
output.error(`Agent not found${guildConfig ? ': ' + guildConfig.agent_id : ''}`, 'The agent may have been deleted.');
|
|
334
|
-
process.exit(1);
|
|
335
|
-
}
|
|
336
|
-
if (formattedError.details.includes('does not exist')) {
|
|
337
|
-
output.error('Commit not found in repository', "This might mean:\n • The commit wasn't pushed to the remote repository\n • The git remote is configured incorrectly\n • There's a sync issue with the backend\n\nVerify the commit exists:\n git log --oneline\n\nVerify the remote:\n git remote -v");
|
|
338
|
-
process.exit(1);
|
|
339
|
-
}
|
|
340
|
-
output.error(`Failed to save agent: ${formattedError.details}`);
|
|
341
|
-
process.exit(1);
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
return cmd;
|
|
345
|
-
}
|
|
346
|
-
//# sourceMappingURL=save.js.map
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 Guild.ai
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
5
|
-
import { getAuthToken } from '../../lib/auth.js';
|
|
6
|
-
import { handleAxiosError } from '../../lib/errors.js';
|
|
7
|
-
import { getOutputMode } from '../../lib/output-mode.js';
|
|
8
|
-
import { createOutputWriter, formatAgentTable } from '../../lib/output.js';
|
|
9
|
-
import { DEFAULT_PAGE_LIMIT } from '../../lib/api-types.js';
|
|
10
|
-
const SORT_MAP = {
|
|
11
|
-
updated: 'updated_at',
|
|
12
|
-
newest: 'created_at',
|
|
13
|
-
name: 'name',
|
|
14
|
-
popular: 'cached_likes_count',
|
|
15
|
-
};
|
|
16
|
-
export function createAgentSearchCommand() {
|
|
17
|
-
const cmd = new Command('search');
|
|
18
|
-
cmd
|
|
19
|
-
.description('Search agents')
|
|
20
|
-
.argument('<query>', 'Search query')
|
|
21
|
-
.option('--sort <field>', 'Sort by: updated, newest, name, popular (default: updated)', 'updated')
|
|
22
|
-
.option('--published', 'Only show published agents')
|
|
23
|
-
.option('--limit <number>', `Number of results to return (default: ${DEFAULT_PAGE_LIMIT})`, String(DEFAULT_PAGE_LIMIT))
|
|
24
|
-
.option('--offset <number>', 'Offset for pagination (default: 0)', '0')
|
|
25
|
-
.action(async (query, options) => {
|
|
26
|
-
const output = createOutputWriter();
|
|
27
|
-
try {
|
|
28
|
-
const token = await getAuthToken();
|
|
29
|
-
if (!token) {
|
|
30
|
-
output.error('Not authenticated. Please log in first.', 'Run: guild auth login');
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
const client = new GuildAPIClient();
|
|
34
|
-
const params = new URLSearchParams();
|
|
35
|
-
params.append('search', query);
|
|
36
|
-
params.append('limit', options.limit);
|
|
37
|
-
params.append('offset', options.offset);
|
|
38
|
-
if (options.published) {
|
|
39
|
-
params.append('published_only', 'true');
|
|
40
|
-
}
|
|
41
|
-
const sortField = SORT_MAP[options.sort];
|
|
42
|
-
if (sortField) {
|
|
43
|
-
params.append('sort_by', sortField);
|
|
44
|
-
}
|
|
45
|
-
const response = await client.get(`/agents?${params.toString()}`);
|
|
46
|
-
if (getOutputMode() === 'json') {
|
|
47
|
-
output.data(response);
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
formatAgentTable(response.items, response.pagination);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
const formattedError = handleAxiosError(error);
|
|
55
|
-
output.error(`Failed to search agents: ${formattedError.details}`);
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
return cmd;
|
|
60
|
-
}
|
|
61
|
-
//# sourceMappingURL=search.js.map
|