@guildai/cli 0.5.12 → 0.5.13
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.
|
@@ -8,6 +8,7 @@ import * as readline from 'readline';
|
|
|
8
8
|
import { runGit, GitError, formatGitError } from '../../lib/git.js';
|
|
9
9
|
import { createOutputWriter } from '../../lib/output.js';
|
|
10
10
|
import { resolveOwnerId } from '../../lib/owner-helpers.js';
|
|
11
|
+
import { isInteractive } from '../../lib/stdin.js';
|
|
11
12
|
async function promptForName() {
|
|
12
13
|
const rl = readline.createInterface({
|
|
13
14
|
input: process.stdin,
|
|
@@ -32,9 +33,6 @@ async function promptForDescription(defaultDescription) {
|
|
|
32
33
|
});
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
|
-
function isInteractive() {
|
|
36
|
-
return process.stdin.isTTY === true;
|
|
37
|
-
}
|
|
38
36
|
async function isDirectoryEmpty(dirPath) {
|
|
39
37
|
try {
|
|
40
38
|
const files = await fs.readdir(dirPath);
|
|
@@ -11,6 +11,7 @@ import * as readline from 'readline';
|
|
|
11
11
|
import { getAuthenticatedUrl } from '../../lib/auth.js';
|
|
12
12
|
import { runGit, GitError, formatGitError, installPrePushHook } from '../../lib/git.js';
|
|
13
13
|
import { resolveOwnerId } from '../../lib/owner-helpers.js';
|
|
14
|
+
import { isInteractive } from '../../lib/stdin.js';
|
|
14
15
|
const TEMPLATE_CHOICES = [
|
|
15
16
|
{
|
|
16
17
|
name: 'LLM - Simple language model agent (recommended)',
|
|
@@ -71,9 +72,6 @@ async function promptForTemplate() {
|
|
|
71
72
|
]);
|
|
72
73
|
return template;
|
|
73
74
|
}
|
|
74
|
-
function isInteractive() {
|
|
75
|
-
return process.stdin.isTTY === true;
|
|
76
|
-
}
|
|
77
75
|
export function createAgentInitCommand() {
|
|
78
76
|
const cmd = new Command('init');
|
|
79
77
|
cmd
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import * as fs from 'fs/promises';
|
|
5
|
-
import
|
|
5
|
+
import search from '@inquirer/search';
|
|
6
6
|
import { GuildAPIClient } from '../../lib/api-client.js';
|
|
7
7
|
import { handleAxiosError, ErrorCodes } from '../../lib/errors.js';
|
|
8
8
|
import { createOutputWriter } from '../../lib/output.js';
|
|
9
|
+
import { isInteractive } from '../../lib/stdin.js';
|
|
9
10
|
import { isAgentDirectory, loadLocalConfig, getLocalConfigPath, getWorkspaceId, saveGlobalConfig, } from '../../lib/guild-config.js';
|
|
10
11
|
/**
|
|
11
12
|
* Format workspace for display with owner name.
|
|
@@ -68,44 +69,39 @@ export function createWorkspaceSelectCommand() {
|
|
|
68
69
|
}
|
|
69
70
|
return;
|
|
70
71
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
if (!isInteractive()) {
|
|
73
|
+
output.error('Interactive mode requires a terminal.', 'Provide a workspace argument:\n guild workspace select <name|id>');
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
// Interactive mode: fetch all workspaces across all pages
|
|
77
|
+
const workspaces = await client.fetchAll('/me/workspaces?filter=all');
|
|
78
|
+
if (workspaces.length === 0) {
|
|
74
79
|
output.error('No workspaces found.', 'Create a workspace first:\n guild workspace create <name>');
|
|
75
80
|
process.exit(1);
|
|
76
81
|
}
|
|
77
82
|
// Resolve the currently selected workspace (if any)
|
|
78
83
|
const current = await getWorkspaceId();
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
84
|
+
const currentId = current?.workspaceId;
|
|
85
|
+
// Interactive searchable selection
|
|
86
|
+
const selectedId = await search({
|
|
87
|
+
message: 'Select a workspace (type to filter)',
|
|
88
|
+
pageSize: 15,
|
|
89
|
+
default: currentId,
|
|
90
|
+
source: (input) => {
|
|
91
|
+
const term = input?.toLowerCase() ?? '';
|
|
92
|
+
const filtered = term
|
|
93
|
+
? workspaces.filter((w) => w.name.toLowerCase().includes(term) ||
|
|
94
|
+
w.full_name?.toLowerCase().includes(term) ||
|
|
95
|
+
w.owner?.name.toLowerCase().includes(term))
|
|
96
|
+
: workspaces;
|
|
97
|
+
return filtered.map((w) => ({
|
|
98
|
+
name: formatWorkspaceDisplay(w) + (w.id === currentId ? ' (current)' : ''),
|
|
99
|
+
value: w.id,
|
|
100
|
+
short: w.name,
|
|
101
|
+
}));
|
|
102
|
+
},
|
|
96
103
|
});
|
|
97
|
-
|
|
98
|
-
// Empty input keeps current selection
|
|
99
|
-
if (answer.trim() === '' && currentIndex >= 0) {
|
|
100
|
-
console.log('Workspace unchanged.');
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const selection = parseInt(answer.trim(), 10);
|
|
104
|
-
if (isNaN(selection) || selection < 1 || selection > workspaces.items.length) {
|
|
105
|
-
output.error('Invalid selection');
|
|
106
|
-
process.exit(1);
|
|
107
|
-
}
|
|
108
|
-
const selectedWorkspace = workspaces.items[selection - 1];
|
|
104
|
+
const selectedWorkspace = workspaces.find((w) => w.id === selectedId);
|
|
109
105
|
const target = await saveWorkspaceConfig(selectedWorkspace.id, selectedWorkspace.name);
|
|
110
106
|
if (target === 'local') {
|
|
111
107
|
output.success(`Workspace set for this agent: ${formatWorkspaceDisplay(selectedWorkspace)}`);
|
package/dist/lib/stdin.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if stdin is connected to an interactive terminal (TTY).
|
|
3
|
+
*/
|
|
4
|
+
export declare function isInteractive(): boolean;
|
|
1
5
|
/**
|
|
2
6
|
* Exit with a helpful error when stdin is piped but no --mode flag was given.
|
|
3
7
|
* Call this before rendering an interactive UI (Ink render()) so users who
|
package/dist/lib/stdin.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
// Copyright 2026 Guild.ai
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Check if stdin is connected to an interactive terminal (TTY).
|
|
5
|
+
*/
|
|
6
|
+
export function isInteractive() {
|
|
7
|
+
return process.stdin.isTTY === true;
|
|
8
|
+
}
|
|
3
9
|
/**
|
|
4
10
|
* Exit with a helpful error when stdin is piped but no --mode flag was given.
|
|
5
11
|
* Call this before rendering an interactive UI (Ink render()) so users who
|
package/docs/skills/agent-dev.md
CHANGED
|
@@ -151,16 +151,22 @@ import { ask, output, callTools } from '@guildai/agents-sdk';
|
|
|
151
151
|
import { guildTools, userInterfaceTools } from '@guildai/agents-sdk';
|
|
152
152
|
|
|
153
153
|
// Service tools (from separate packages - NOT from SDK)
|
|
154
|
+
import { azureDevOpsTools } from '@guildai-services/guildai~azure-devops';
|
|
155
|
+
import { bitbucketTools } from '@guildai-services/guildai~bitbucket';
|
|
156
|
+
import { confluenceTools } from '@guildai-services/guildai~confluence';
|
|
157
|
+
import { cypressTools } from '@guildai-services/guildai~cypress';
|
|
158
|
+
import { figmaTools } from '@guildai-services/guildai~figma';
|
|
154
159
|
import { gitHubTools } from '@guildai-services/guildai~github';
|
|
155
|
-
import {
|
|
160
|
+
import { googleComputeTools } from '@guildai-services/guildai~google-compute';
|
|
161
|
+
import { googleLoggingTools } from '@guildai-services/guildai~google-logging';
|
|
156
162
|
import { jiraTools } from '@guildai-services/guildai~jira';
|
|
157
|
-
import { bitbucketTools } from '@guildai-services/guildai~bitbucket';
|
|
158
|
-
import { azureDevOpsTools } from '@guildai-services/guildai~azure-devops';
|
|
159
163
|
import { pipedreamTools } from '@guildai-services/guildai~pipedream';
|
|
160
|
-
import {
|
|
164
|
+
import { slackTools } from '@guildai-services/guildai~slack';
|
|
165
|
+
import { testrailTools } from '@guildai-services/guildai~testrail';
|
|
166
|
+
import { zendeskTools } from '@guildai-services/guildai~zendesk';
|
|
161
167
|
|
|
162
168
|
// Utilities
|
|
163
|
-
import { pick, progressLogNotifyEvent } from '@guildai/agents-sdk';
|
|
169
|
+
import { pick, omit, progressLogNotifyEvent } from '@guildai/agents-sdk';
|
|
164
170
|
|
|
165
171
|
// Advanced (for compiled agents with LLM tool loops)
|
|
166
172
|
import { delegatedCallsOf, asToolResultContent } from '@guildai/agents-sdk';
|
|
@@ -173,19 +179,25 @@ import { z } from 'zod';
|
|
|
173
179
|
|
|
174
180
|
Service tools are in separate `@guildai-services/*` packages. The runtime resolves them automatically.
|
|
175
181
|
|
|
176
|
-
| Service | Package
|
|
177
|
-
| -------------- |
|
|
178
|
-
| Azure DevOps | `@guildai-services/guildai~azure-devops`
|
|
179
|
-
| Bitbucket | `@guildai-services/guildai~bitbucket`
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
|
|
|
184
|
-
|
|
|
185
|
-
|
|
|
186
|
-
|
|
|
187
|
-
|
|
|
188
|
-
|
|
|
182
|
+
| Service | Package | Export | Tool Name Prefix |
|
|
183
|
+
| -------------- | ------------------------------------------ | -------------------- | ----------------- |
|
|
184
|
+
| Azure DevOps | `@guildai-services/guildai~azure-devops` | `azureDevOpsTools` | `azure_devops_` |
|
|
185
|
+
| Bitbucket | `@guildai-services/guildai~bitbucket` | `bitbucketTools` | `bitbucket_` |
|
|
186
|
+
| Confluence | `@guildai-services/guildai~confluence` | `confluenceTools` | `confluence_` |
|
|
187
|
+
| Cypress | `@guildai-services/guildai~cypress` | `cypressTools` | `cypress_` |
|
|
188
|
+
| Figma | `@guildai-services/guildai~figma` | `figmaTools` | `figma_` |
|
|
189
|
+
| GitHub | `@guildai-services/guildai~github` | `gitHubTools` | `github_` |
|
|
190
|
+
| Google Compute | `@guildai-services/guildai~google-compute` | `googleComputeTools` | `google_compute_` |
|
|
191
|
+
| Google Logging | `@guildai-services/guildai~google-logging` | `googleLoggingTools` | `google_logging_` |
|
|
192
|
+
| Guild | `@guildai/agents-sdk` | `guildTools` | `guild_` |
|
|
193
|
+
| Jira | `@guildai-services/guildai~jira` | `jiraTools` | `jira_` |
|
|
194
|
+
| Linear | `@guildai-services/guildai~linear` | `linearTools` | `linear_` |
|
|
195
|
+
| NewRelic | `@guildai-services/guildai~newrelic` | `newrelicTools` | `newrelic_` |
|
|
196
|
+
| Pipedream | `@guildai-services/guildai~pipedream` | `pipedreamTools` | `pipedream_` |
|
|
197
|
+
| Slack | `@guildai-services/guildai~slack` | `slackTools` | `slack_` |
|
|
198
|
+
| TestRail | `@guildai-services/guildai~testrail` | `testrailTools` | `testrail_` |
|
|
199
|
+
| User Interface | `@guildai/agents-sdk` | `userInterfaceTools` | `ui_` |
|
|
200
|
+
| Zendesk | `@guildai-services/guildai~zendesk` | `zendeskTools` | `zendesk_` |
|
|
189
201
|
|
|
190
202
|
### Tool Access via `task.tools.*`
|
|
191
203
|
|
|
@@ -220,12 +232,16 @@ await task.tools.guild_credentials_request({ service: 'GITHUB' });
|
|
|
220
232
|
|
|
221
233
|
### Task Properties
|
|
222
234
|
|
|
223
|
-
| Property | Description
|
|
224
|
-
| ---------------- |
|
|
225
|
-
| `task.sessionId` | Session ID for correlating operations
|
|
226
|
-
| `task.
|
|
227
|
-
| `task.
|
|
228
|
-
| `task.
|
|
235
|
+
| Property | Description |
|
|
236
|
+
| ---------------- | ------------------------------------------------------------------------------------------- |
|
|
237
|
+
| `task.sessionId` | Session ID for correlating operations |
|
|
238
|
+
| `task.tools` | Primary API for calling all tools |
|
|
239
|
+
| `task.llm` | LLM service — call `task.llm.generateText({ messages, system, tools })` for AI model access |
|
|
240
|
+
| `task.console` | Debug logging (`task.console.debug(...)`, `.info(...)`, `.warn(...)`, `.error(...)`) |
|
|
241
|
+
| `task.save()` | Persist agent state (self-managed state agents only) |
|
|
242
|
+
| `task.restore()` | Retrieve previously saved state (self-managed state agents only) |
|
|
243
|
+
| `task.guild` | **Deprecated** — use `task.tools.guild_*` instead |
|
|
244
|
+
| `task.ui` | **Deprecated** — use `task.tools.ui_*` instead |
|
|
229
245
|
|
|
230
246
|
---
|
|
231
247
|
|
|
@@ -340,7 +356,7 @@ export default agent({
|
|
|
340
356
|
|
|
341
357
|
- `run()` returns the OUTPUT directly (not wrapped in `{ type: "output", output: ... }`)
|
|
342
358
|
- The runtime handles continuations — you can `await` tool calls inline
|
|
343
|
-
-
|
|
359
|
+
- `"use agent"` directive at top of file is optional (the Babel compiler recognizes it but strips it)
|
|
344
360
|
- No `identifier` field needed
|
|
345
361
|
|
|
346
362
|
### 3. Self-Managed State Agent (`start()`/`onToolResults()`)
|
|
@@ -474,7 +490,7 @@ import {
|
|
|
474
490
|
} from '@guildai/agents-sdk';
|
|
475
491
|
import { gitHubTools } from '@guildai-services/guildai~github';
|
|
476
492
|
import { slackTools } from '@guildai-services/guildai~slack';
|
|
477
|
-
import {
|
|
493
|
+
import type { ModelMessage } from 'ai';
|
|
478
494
|
import { z } from 'zod';
|
|
479
495
|
|
|
480
496
|
const tools = { ...gitHubTools, ...slackTools, ...userInterfaceTools };
|
|
@@ -485,15 +501,12 @@ const llmTools = { ...gitHubTools }; // LLM gets execute access to these
|
|
|
485
501
|
const agentTools = { ...slackTools, ...userInterfaceTools }; // These get delegated
|
|
486
502
|
|
|
487
503
|
async function start(input, task: Task<Tools>) {
|
|
488
|
-
const model = await task.llm.model();
|
|
489
504
|
const messages: ModelMessage[] = [{ role: 'user', content: input.text }];
|
|
490
505
|
|
|
491
|
-
const result = await generateText({
|
|
492
|
-
model,
|
|
506
|
+
const result = await task.llm.generateText({
|
|
493
507
|
system: 'You are a helpful assistant.',
|
|
494
508
|
messages,
|
|
495
509
|
tools: llmTools, // Only give LLM the tools it can execute
|
|
496
|
-
maxSteps: 10,
|
|
497
510
|
});
|
|
498
511
|
|
|
499
512
|
// Check for delegated (unexecuted) tool calls
|
|
@@ -525,6 +538,7 @@ async function onToolResults(
|
|
|
525
538
|
|
|
526
539
|
**Key utilities:**
|
|
527
540
|
|
|
541
|
+
- `task.llm.generateText({ messages, system, tools })` — call the LLM with automatic authentication and provider selection. The runtime handles model selection and credential injection.
|
|
528
542
|
- `delegatedCallsOf<Tools>(content)` — extracts unexecuted tool calls from `generateText` results that need runtime delegation
|
|
529
543
|
- `asToolResultContent(results)` — converts `TypedToolResult[]` into LLM message format for conversation history
|
|
530
544
|
|
|
@@ -572,13 +586,20 @@ await task.tools.slack_chat_post_message({
|
|
|
572
586
|
|
|
573
587
|
**CRITICAL: Only use tool names listed below.** If a tool isn't listed here, it doesn't exist. Do not guess tool names based on API patterns.
|
|
574
588
|
|
|
575
|
-
Use `pick()` to select specific tools:
|
|
589
|
+
Use `pick()` to select specific tools, or `omit()` to exclude specific tools:
|
|
576
590
|
|
|
577
591
|
```typescript
|
|
592
|
+
// Include only specific tools
|
|
578
593
|
const tools = {
|
|
579
594
|
...pick(gitHubTools, ['github_repos_get', 'github_pulls_list']),
|
|
580
595
|
...guildTools,
|
|
581
596
|
};
|
|
597
|
+
|
|
598
|
+
// Include all tools except specific ones
|
|
599
|
+
const tools = {
|
|
600
|
+
...omit(gitHubTools, ['github_repos_delete', 'github_repos_update']),
|
|
601
|
+
...guildTools,
|
|
602
|
+
};
|
|
582
603
|
```
|
|
583
604
|
|
|
584
605
|
#### Azure DevOps (`azure_devops_` prefix, 122 tools)
|
|
@@ -1673,8 +1694,8 @@ export default agent({ run: async (input, task) => { ... } })
|
|
|
1673
1694
|
## Versioning
|
|
1674
1695
|
|
|
1675
1696
|
- Use semver: `1.0.0` → `1.0.1` (patch), `1.1.0` (minor), `2.0.0` (breaking)
|
|
1676
|
-
-
|
|
1677
|
-
-
|
|
1697
|
+
- Use `--bump [patch|minor|major]` with `guild agent save` to auto-bump `package.json` version
|
|
1698
|
+
- Or bump manually in `package.json` before saving
|
|
1678
1699
|
|
|
1679
1700
|
## File Structure
|
|
1680
1701
|
|
|
@@ -1709,15 +1730,21 @@ guild agent pull # Pull remote changes
|
|
|
1709
1730
|
guild agent save # Push commits and create a draft version
|
|
1710
1731
|
guild agent save -A --message "description" # Stage+commit+push in one step
|
|
1711
1732
|
guild agent save --message "v1.0" --wait --publish # Save + validate + publish
|
|
1733
|
+
guild agent save --bump minor --message "v1.1" # Auto-bump version before saving
|
|
1712
1734
|
guild agent test # Interactive test
|
|
1713
1735
|
guild agent test --ephemeral # Ephemeral test
|
|
1714
1736
|
guild agent chat "Hello" # Test with input
|
|
1715
1737
|
guild agent get [agent-id] # View agent info
|
|
1738
|
+
guild agent list # List agents
|
|
1739
|
+
guild agent list --search "github" --published # Search published agents
|
|
1740
|
+
guild agent search <query> # Search published agents
|
|
1716
1741
|
guild agent versions [agent-id] # Version history
|
|
1717
1742
|
guild agent clone <agent-id> # Clone existing agent
|
|
1743
|
+
guild agent fork <agent-id>:<version-id> # Fork a specific version as a new agent
|
|
1718
1744
|
guild agent publish # Publish a version
|
|
1719
1745
|
guild agent unpublish # Remove from catalog
|
|
1720
1746
|
guild agent update # Update agent metadata
|
|
1747
|
+
guild agent workspaces [agent-id] # List workspaces using an agent
|
|
1721
1748
|
guild agent tags list|add|remove|set # Manage agent tags
|
|
1722
1749
|
guild agent revalidate # Re-run validation
|
|
1723
1750
|
guild agent code [agent-id] # View agent source
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guildai/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.13",
|
|
4
4
|
"description": "Guild.ai CLI - Build, test, and deploy AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"url": "https://docs.guild.ai/support"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
+
"@inquirer/search": "^4.1.7",
|
|
58
59
|
"@napi-rs/canvas": "^0.1.85",
|
|
59
60
|
"@napi-rs/keyring": "^1.2.0",
|
|
60
61
|
"axios": "^1.13.2",
|