@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.
Files changed (203) hide show
  1. package/dist/auth-CRMO5O3N.js +29 -0
  2. package/dist/auth-CRMO5O3N.js.map +7 -0
  3. package/dist/chat-5VX2WJH2.js +303 -0
  4. package/dist/chat-5VX2WJH2.js.map +7 -0
  5. package/dist/chat-SIKDYZQK.js +31 -0
  6. package/dist/chat-SIKDYZQK.js.map +7 -0
  7. package/dist/chunk-56YCMGL3.js +522 -0
  8. package/dist/chunk-56YCMGL3.js.map +7 -0
  9. package/dist/chunk-6EX6E7WP.js +7042 -0
  10. package/dist/chunk-6EX6E7WP.js.map +7 -0
  11. package/dist/chunk-B7VAF5UG.js +532 -0
  12. package/dist/chunk-B7VAF5UG.js.map +7 -0
  13. package/dist/chunk-DOIYVBNY.js +3057 -0
  14. package/dist/chunk-DOIYVBNY.js.map +7 -0
  15. package/dist/chunk-ENKEEJ45.js +17 -0
  16. package/dist/chunk-ENKEEJ45.js.map +7 -0
  17. package/dist/chunk-IBRKVGMZ.js +97041 -0
  18. package/dist/chunk-IBRKVGMZ.js.map +7 -0
  19. package/dist/chunk-LFMQJOKC.js +19778 -0
  20. package/dist/chunk-LFMQJOKC.js.map +7 -0
  21. package/dist/chunk-M347HP6M.js +22896 -0
  22. package/dist/chunk-M347HP6M.js.map +7 -0
  23. package/dist/chunk-OYQ476FQ.js +44 -0
  24. package/dist/chunk-OYQ476FQ.js.map +7 -0
  25. package/dist/chunk-PNCUR4OB.js +257 -0
  26. package/dist/chunk-PNCUR4OB.js.map +7 -0
  27. package/dist/chunk-RIG2HZWM.js +317 -0
  28. package/dist/chunk-RIG2HZWM.js.map +7 -0
  29. package/dist/chunk-SPZPZXUN.js +826 -0
  30. package/dist/chunk-SPZPZXUN.js.map +7 -0
  31. package/dist/chunk-VVSOU6ON.js +53 -0
  32. package/dist/chunk-VVSOU6ON.js.map +7 -0
  33. package/dist/chunk-X3ADGWOF.js +3643 -0
  34. package/dist/chunk-X3ADGWOF.js.map +7 -0
  35. package/dist/commands/agent/logs.d.ts +3 -0
  36. package/dist/commands/setup.d.ts +16 -0
  37. package/dist/commands/skill/create.d.ts +3 -0
  38. package/dist/commands/skill/get.d.ts +3 -0
  39. package/dist/commands/skill/list.d.ts +3 -0
  40. package/dist/commands/skill/update.d.ts +3 -0
  41. package/dist/commands/skill/version/create.d.ts +3 -0
  42. package/dist/commands/skill/version/get.d.ts +3 -0
  43. package/dist/commands/skill/version/list.d.ts +3 -0
  44. package/dist/devtools-AO7YSDOD.js +67 -0
  45. package/dist/devtools-AO7YSDOD.js.map +7 -0
  46. package/dist/dist-4CBK6X5H.js +1566 -0
  47. package/dist/dist-4CBK6X5H.js.map +7 -0
  48. package/dist/esm-FRAVZP4J.js +13 -0
  49. package/dist/esm-FRAVZP4J.js.map +7 -0
  50. package/dist/execa-XQMWSABC.js +35 -0
  51. package/dist/execa-XQMWSABC.js.map +7 -0
  52. package/dist/index.js +8231 -253
  53. package/dist/index.js.map +7 -0
  54. package/dist/lib/api-types.d.ts +44 -0
  55. package/dist/lib/auth.d.ts +1 -1
  56. package/dist/lib/config.d.ts +9 -0
  57. package/dist/lib/errors.d.ts +1 -1
  58. package/dist/lib/output-mode.d.ts +9 -2
  59. package/dist/lib/output.d.ts +17 -1
  60. package/dist/lib/session-events.d.ts +14 -3
  61. package/dist/lib/session-polling.d.ts +24 -1
  62. package/dist/lib/session-resume.d.ts +15 -1
  63. package/dist/lib/stdin.d.ts +5 -1
  64. package/dist/lib/websocket-client.d.ts +46 -0
  65. package/dist/open-RF4X5MOP.js +13 -0
  66. package/dist/open-RF4X5MOP.js.map +7 -0
  67. package/dist/server-JYVH64FD.js +27659 -0
  68. package/dist/server-JYVH64FD.js.map +7 -0
  69. package/dist/test-SNIYRJ32.js +692 -0
  70. package/dist/test-SNIYRJ32.js.map +7 -0
  71. package/docs/skills/codex-agent-dev.md +2 -2
  72. package/package.json +8 -12
  73. package/dist/commands/agent/chat.js +0 -278
  74. package/dist/commands/agent/clone.js +0 -116
  75. package/dist/commands/agent/code.js +0 -87
  76. package/dist/commands/agent/fork.js +0 -218
  77. package/dist/commands/agent/get.js +0 -37
  78. package/dist/commands/agent/grep.js +0 -107
  79. package/dist/commands/agent/init.js +0 -390
  80. package/dist/commands/agent/list.js +0 -110
  81. package/dist/commands/agent/owners.js +0 -74
  82. package/dist/commands/agent/publish.js +0 -91
  83. package/dist/commands/agent/pull.js +0 -198
  84. package/dist/commands/agent/revalidate.js +0 -56
  85. package/dist/commands/agent/save.js +0 -346
  86. package/dist/commands/agent/search.js +0 -61
  87. package/dist/commands/agent/tags/add.js +0 -73
  88. package/dist/commands/agent/tags/list.js +0 -43
  89. package/dist/commands/agent/tags/remove.js +0 -84
  90. package/dist/commands/agent/tags/set.js +0 -71
  91. package/dist/commands/agent/test.js +0 -486
  92. package/dist/commands/agent/unpublish.js +0 -64
  93. package/dist/commands/agent/update.js +0 -110
  94. package/dist/commands/agent/versions.js +0 -55
  95. package/dist/commands/agent/workspaces.js +0 -54
  96. package/dist/commands/auth/login.js +0 -33
  97. package/dist/commands/auth/logout.js +0 -24
  98. package/dist/commands/auth/status.js +0 -38
  99. package/dist/commands/auth/token.js +0 -19
  100. package/dist/commands/chat.js +0 -1345
  101. package/dist/commands/config/get.js +0 -64
  102. package/dist/commands/config/list.js +0 -47
  103. package/dist/commands/config/path.js +0 -38
  104. package/dist/commands/config/set.js +0 -132
  105. package/dist/commands/credentials/endpoint-list.js +0 -88
  106. package/dist/commands/credentials/list.js +0 -50
  107. package/dist/commands/credentials/policy-create.js +0 -66
  108. package/dist/commands/credentials/policy-delete.js +0 -33
  109. package/dist/commands/credentials/policy-list.js +0 -45
  110. package/dist/commands/credentials/policy-update.js +0 -66
  111. package/dist/commands/doctor.js +0 -233
  112. package/dist/commands/integration/connect.js +0 -76
  113. package/dist/commands/integration/create.js +0 -298
  114. package/dist/commands/integration/get.js +0 -95
  115. package/dist/commands/integration/list.js +0 -62
  116. package/dist/commands/integration/operation/create.js +0 -164
  117. package/dist/commands/integration/operation/list.js +0 -92
  118. package/dist/commands/integration/update.js +0 -139
  119. package/dist/commands/integration/version/build.js +0 -86
  120. package/dist/commands/integration/version/create.js +0 -45
  121. package/dist/commands/integration/version/get.js +0 -72
  122. package/dist/commands/integration/version/list.js +0 -45
  123. package/dist/commands/integration/version/publish.js +0 -79
  124. package/dist/commands/integration/version/test.js +0 -104
  125. package/dist/commands/job/get-step.js +0 -40
  126. package/dist/commands/job/get.js +0 -44
  127. package/dist/commands/mcp.js +0 -34
  128. package/dist/commands/session/create.js +0 -59
  129. package/dist/commands/session/events.js +0 -56
  130. package/dist/commands/session/get.js +0 -33
  131. package/dist/commands/session/interrupt.js +0 -33
  132. package/dist/commands/session/list.js +0 -59
  133. package/dist/commands/session/send.js +0 -54
  134. package/dist/commands/session/tasks.js +0 -45
  135. package/dist/commands/setup.js +0 -230
  136. package/dist/commands/trigger/activate.js +0 -41
  137. package/dist/commands/trigger/create.js +0 -197
  138. package/dist/commands/trigger/deactivate.js +0 -41
  139. package/dist/commands/trigger/get.js +0 -33
  140. package/dist/commands/trigger/list.js +0 -57
  141. package/dist/commands/trigger/sessions.js +0 -48
  142. package/dist/commands/trigger/update.js +0 -128
  143. package/dist/commands/version.js +0 -24
  144. package/dist/commands/workspace/agent/add.js +0 -114
  145. package/dist/commands/workspace/agent/list.js +0 -78
  146. package/dist/commands/workspace/agent/remove.js +0 -78
  147. package/dist/commands/workspace/clear.js +0 -45
  148. package/dist/commands/workspace/context/edit.js +0 -107
  149. package/dist/commands/workspace/context/get.js +0 -47
  150. package/dist/commands/workspace/context/list.js +0 -51
  151. package/dist/commands/workspace/context/publish.js +0 -42
  152. package/dist/commands/workspace/create.js +0 -51
  153. package/dist/commands/workspace/current.js +0 -63
  154. package/dist/commands/workspace/get.js +0 -39
  155. package/dist/commands/workspace/list.js +0 -70
  156. package/dist/commands/workspace/select.js +0 -184
  157. package/dist/components/AgentInstallPrompt.js +0 -97
  158. package/dist/components/SplashAnimation.js +0 -321
  159. package/dist/components/TaskView.js +0 -268
  160. package/dist/lib/agent-helpers.js +0 -306
  161. package/dist/lib/alternate-screen.js +0 -59
  162. package/dist/lib/api-client.js +0 -154
  163. package/dist/lib/api-types.js +0 -10
  164. package/dist/lib/auth.js +0 -284
  165. package/dist/lib/braille-canvas.js +0 -321
  166. package/dist/lib/colors.js +0 -46
  167. package/dist/lib/config-cache.js +0 -45
  168. package/dist/lib/config.js +0 -153
  169. package/dist/lib/did-you-mean.js +0 -144
  170. package/dist/lib/errors.js +0 -375
  171. package/dist/lib/event-filter.js +0 -91
  172. package/dist/lib/generated-types.js +0 -56
  173. package/dist/lib/git.js +0 -176
  174. package/dist/lib/gk.js +0 -91
  175. package/dist/lib/guild-config.js +0 -178
  176. package/dist/lib/iap.js +0 -117
  177. package/dist/lib/integration-helpers.js +0 -38
  178. package/dist/lib/loading-messages.js +0 -72
  179. package/dist/lib/logo.js +0 -141
  180. package/dist/lib/lottie-serverside.js +0 -181
  181. package/dist/lib/markdown.js +0 -38
  182. package/dist/lib/npmrc.js +0 -59
  183. package/dist/lib/output-mode.js +0 -33
  184. package/dist/lib/output.js +0 -591
  185. package/dist/lib/owner-helpers.js +0 -112
  186. package/dist/lib/polling.js +0 -76
  187. package/dist/lib/progress.js +0 -324
  188. package/dist/lib/session-events-fetch.js +0 -25
  189. package/dist/lib/session-events.js +0 -112
  190. package/dist/lib/session-polling.js +0 -160
  191. package/dist/lib/session-resume.js +0 -96
  192. package/dist/lib/spinners.js +0 -770
  193. package/dist/lib/splash.js +0 -41
  194. package/dist/lib/stdin.js +0 -84
  195. package/dist/lib/svg-to-braille.js +0 -76
  196. package/dist/lib/table.js +0 -59
  197. package/dist/lib/update-check.js +0 -65
  198. package/dist/lib/validate-input-schema.js +0 -208
  199. package/dist/lib/version-helpers.js +0 -121
  200. package/dist/lib/workspace-helpers.js +0 -49
  201. package/dist/mcp/resources.js +0 -67
  202. package/dist/mcp/server.js +0 -64
  203. 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