@guildai/cli 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +190 -42
- package/dist/commands/agent/chat.js +5 -5
- package/dist/commands/agent/save.js +57 -5
- package/dist/commands/agent/test.js +5 -5
- package/dist/commands/chat.js +15 -1
- package/dist/commands/config/set.js +19 -27
- package/dist/commands/session/list.js +1 -1
- package/dist/lib/api-client.d.ts +0 -3
- package/dist/lib/api-client.js +0 -2
- package/dist/lib/owner-helpers.d.ts +5 -0
- package/dist/lib/owner-helpers.js +31 -25
- package/docs/DESIGN.md +27 -61
- package/package.json +3 -3
- package/dist/lib/formatters.d.ts +0 -44
- package/dist/lib/formatters.js +0 -51
- package/docs/getting-started.md +0 -440
- package/docs/output-format.md +0 -126
- package/docs/session-events.md +0 -143
|
@@ -17,49 +17,55 @@
|
|
|
17
17
|
import inquirer from 'inquirer';
|
|
18
18
|
import { loadGlobalConfig } from './guild-config.js';
|
|
19
19
|
import { debug } from './errors.js';
|
|
20
|
+
/**
|
|
21
|
+
* Look up an owner by ID or name against the current user and their organizations.
|
|
22
|
+
* Returns the resolved owner, or undefined if no match is found.
|
|
23
|
+
*/
|
|
24
|
+
export async function lookupOwner(client, val) {
|
|
25
|
+
const me = await client.get('/me');
|
|
26
|
+
if (me.id === val || me.name === val) {
|
|
27
|
+
return { id: me.id, name: me.name, type: 'user' };
|
|
28
|
+
}
|
|
29
|
+
const orgs = await client.fetchAll('/me/organizations');
|
|
30
|
+
const org = orgs.find((o) => o.id === val || o.name === val);
|
|
31
|
+
if (org) {
|
|
32
|
+
return { id: org.id, name: org.name, type: 'organization' };
|
|
33
|
+
}
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
20
36
|
export async function resolveOwnerId(options) {
|
|
21
37
|
const { ownerFlag, client, interactive } = options;
|
|
22
38
|
// Priority 1: --owner flag
|
|
23
39
|
if (ownerFlag) {
|
|
24
40
|
debug('Using owner from --owner flag: %s', ownerFlag);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return { id: me.id, name: me.name, type: 'user' };
|
|
29
|
-
}
|
|
30
|
-
const orgs = await client.fetchAll('/me/organizations');
|
|
31
|
-
const org = orgs.find((o) => o.id === ownerFlag);
|
|
32
|
-
if (org) {
|
|
33
|
-
return { id: org.id, name: org.name, type: 'organization' };
|
|
34
|
-
}
|
|
41
|
+
const match = await lookupOwner(client, ownerFlag);
|
|
42
|
+
if (match)
|
|
43
|
+
return match;
|
|
35
44
|
// Not found in user or orgs — pass through and let backend validate
|
|
36
45
|
return { id: ownerFlag, name: ownerFlag, type: 'organization' };
|
|
37
46
|
}
|
|
38
47
|
// Priority 2: GUILD_OWNER_ID environment variable
|
|
39
48
|
if (process.env.GUILD_OWNER_ID) {
|
|
40
49
|
debug('Using owner from GUILD_OWNER_ID env var: %s', process.env.GUILD_OWNER_ID);
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return { id: me.id, name: me.name, type: 'user' };
|
|
45
|
-
}
|
|
46
|
-
const orgs = await client.fetchAll('/me/organizations');
|
|
47
|
-
const org = orgs.find((o) => o.id === envOwnerId);
|
|
48
|
-
if (org) {
|
|
49
|
-
return { id: org.id, name: org.name, type: 'organization' };
|
|
50
|
-
}
|
|
50
|
+
const match = await lookupOwner(client, process.env.GUILD_OWNER_ID);
|
|
51
|
+
if (match)
|
|
52
|
+
return match;
|
|
51
53
|
// Not found in user or orgs — pass through and let backend validate
|
|
52
|
-
return {
|
|
54
|
+
return {
|
|
55
|
+
id: process.env.GUILD_OWNER_ID,
|
|
56
|
+
name: process.env.GUILD_OWNER_ID,
|
|
57
|
+
type: 'organization',
|
|
58
|
+
};
|
|
53
59
|
}
|
|
54
60
|
// Priority 3: default_owner from config
|
|
55
61
|
const globalConfig = await loadGlobalConfig();
|
|
56
62
|
if (globalConfig?.default_owner) {
|
|
57
63
|
debug('Using owner from global config: %s', globalConfig.default_owner);
|
|
64
|
+
const match = await lookupOwner(client, globalConfig.default_owner);
|
|
65
|
+
if (match)
|
|
66
|
+
return match;
|
|
58
67
|
const name = globalConfig.default_owner_name || globalConfig.default_owner;
|
|
59
|
-
|
|
60
|
-
const me = await client.get('/me');
|
|
61
|
-
const type = me.id === globalConfig.default_owner ? 'user' : 'organization';
|
|
62
|
-
return { id: globalConfig.default_owner, name, type };
|
|
68
|
+
return { id: globalConfig.default_owner, name, type: 'organization' };
|
|
63
69
|
}
|
|
64
70
|
// Priority 4: Fetch user + orgs
|
|
65
71
|
const me = await client.get('/me');
|
package/docs/DESIGN.md
CHANGED
|
@@ -39,52 +39,51 @@ guild env go # Create environment and connect interactively
|
|
|
39
39
|
|
|
40
40
|
### Agent Management
|
|
41
41
|
|
|
42
|
-
Manage agents via
|
|
43
|
-
|
|
44
|
-
**Basic Operations:**
|
|
42
|
+
Manage agents via the GuildCore API with git-backed versioning:
|
|
45
43
|
|
|
46
44
|
```bash
|
|
47
|
-
guild agent
|
|
48
|
-
guild agent
|
|
49
|
-
guild agent
|
|
50
|
-
guild agent
|
|
51
|
-
guild agent get
|
|
52
|
-
guild agent
|
|
45
|
+
guild agent init --name my-agent --template LLM # Initialize a new agent
|
|
46
|
+
guild agent clone owner/agent-name # Clone an existing agent
|
|
47
|
+
guild agent list # List all agents
|
|
48
|
+
guild agent search "analytics" # Search published agents
|
|
49
|
+
guild agent get [identifier] # Get agent details
|
|
50
|
+
guild agent versions [identifier] # List all versions
|
|
51
|
+
guild agent code [identifier] # Fetch latest published code
|
|
53
52
|
```
|
|
54
53
|
|
|
55
54
|
**Version Control** (git-backed):
|
|
56
55
|
|
|
57
56
|
```bash
|
|
58
|
-
guild agent save
|
|
59
|
-
guild agent save
|
|
60
|
-
guild agent
|
|
61
|
-
guild agent code <agent-id> # Fetch latest published code
|
|
62
|
-
guild agent code <agent-id> --draft # Include draft versions
|
|
63
|
-
guild agent code <agent-id> --output ./my-agent # Download to directory
|
|
57
|
+
guild agent save --message "Initial version" # Save as draft
|
|
58
|
+
guild agent save --message "v1.0" --wait --publish # Save + validate + publish
|
|
59
|
+
guild agent pull # Pull remote changes
|
|
64
60
|
```
|
|
65
61
|
|
|
66
62
|
**How it works:**
|
|
67
63
|
|
|
68
|
-
- Each agent stores code in a git repository (managed by
|
|
69
|
-
- `save`
|
|
64
|
+
- Each agent stores code in a git repository (managed by GuildCore)
|
|
65
|
+
- `save` commits and pushes code, creating a new version
|
|
70
66
|
- Versions can be DRAFT or PUBLISHED
|
|
71
67
|
- `code` fetches the latest version's files
|
|
72
68
|
- Every version has a git commit SHA for traceability
|
|
73
69
|
|
|
74
|
-
All agent commands interact with the
|
|
70
|
+
All agent commands interact with the GuildCore backend API. The CLI is a remote client, similar to the web UI.
|
|
75
71
|
|
|
76
72
|
### Chat
|
|
77
73
|
|
|
78
74
|
Interactive chat with streaming:
|
|
79
75
|
|
|
80
76
|
```bash
|
|
81
|
-
guild chat
|
|
82
|
-
guild chat
|
|
77
|
+
guild chat # Interactive chat session
|
|
78
|
+
guild chat "your message" # One-shot message
|
|
79
|
+
guild agent test # Test agent interactively
|
|
80
|
+
guild agent chat "Hello" # Send single message to agent
|
|
83
81
|
```
|
|
84
82
|
|
|
85
|
-
###
|
|
83
|
+
### Diagnostics
|
|
86
84
|
|
|
87
85
|
```bash
|
|
86
|
+
guild doctor # Check CLI setup and diagnose issues
|
|
88
87
|
guild version # Show CLI version info
|
|
89
88
|
guild --version # Show version number
|
|
90
89
|
```
|
|
@@ -151,7 +150,7 @@ No YAML files. No terraform. No kubectl. Just simple commands.
|
|
|
151
150
|
└────────────────────────┘
|
|
152
151
|
```
|
|
153
152
|
|
|
154
|
-
The CLI is a thin client that communicates with GuildCore API (default: `
|
|
153
|
+
The CLI is a thin client that communicates with the GuildCore API (default: `https://app.guild.ai/api`).
|
|
155
154
|
|
|
156
155
|
---
|
|
157
156
|
|
|
@@ -187,49 +186,16 @@ Environments are Docker containers managed by GuildCore. The CLI provides a simp
|
|
|
187
186
|
|
|
188
187
|
---
|
|
189
188
|
|
|
190
|
-
## Implementation Status
|
|
191
|
-
|
|
192
|
-
**Implemented (v0.1.0):**
|
|
193
|
-
|
|
194
|
-
- ✅ OAuth device flow authentication
|
|
195
|
-
- ✅ System keyring integration
|
|
196
|
-
- ✅ Environment management (create, list, destroy, cleanup, exec, go)
|
|
197
|
-
- ✅ Agent management (list, create, get, update)
|
|
198
|
-
- ✅ Agent version control (save, versions, code) with git backing
|
|
199
|
-
- ✅ Chat with streaming responses
|
|
200
|
-
- ✅ JSON output for all commands
|
|
201
|
-
- ✅ E2E test coverage
|
|
202
|
-
- ✅ TypeScript implementation with Commander.js
|
|
203
|
-
|
|
204
|
-
---
|
|
205
|
-
|
|
206
189
|
## Integration with Developer Tools
|
|
207
190
|
|
|
208
|
-
The CLI
|
|
191
|
+
The CLI integrates with AI coding assistants like Claude Code, Cursor, and others. Run `guild setup` to install Guild skills into your project.
|
|
209
192
|
|
|
210
193
|
**Typical Workflow:**
|
|
211
194
|
|
|
212
|
-
1.
|
|
195
|
+
1. Initialize agent: `guild agent init --name my-agent --template LLM`
|
|
213
196
|
2. Write agent code locally in your editor
|
|
214
|
-
3.
|
|
215
|
-
4.
|
|
197
|
+
3. Test interactively: `guild agent test --ephemeral`
|
|
198
|
+
4. Save as draft: `guild agent save --message "WIP"`
|
|
216
199
|
5. Iterate on code and save new drafts
|
|
217
|
-
6. Publish stable version: `guild agent save
|
|
218
|
-
7.
|
|
219
|
-
|
|
220
|
-
**Version Control Benefits:**
|
|
221
|
-
|
|
222
|
-
- Edit code in your favorite editor (VS Code, Vim, etc.)
|
|
223
|
-
- AI assistants can help write agent code
|
|
224
|
-
- Save drafts for testing without affecting published versions
|
|
225
|
-
- Full git history for every change
|
|
226
|
-
- Download code to any machine
|
|
227
|
-
|
|
228
|
-
The CLI meets developers where they are - use your preferred editor, AI assistant, and workflow.
|
|
229
|
-
|
|
230
|
-
---
|
|
231
|
-
|
|
232
|
-
## Related Documentation
|
|
233
|
-
|
|
234
|
-
- [Specifications](../specs/) - Executable specs for all features
|
|
235
|
-
- [CLI README](../README.md) - Installation and quick start
|
|
200
|
+
6. Publish stable version: `guild agent save --message "v1.0" --wait --publish`
|
|
201
|
+
7. Clone on another machine: `guild agent clone owner/my-agent`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guildai/cli",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "Guild.ai CLI - Build, test, and deploy AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -89,12 +89,12 @@
|
|
|
89
89
|
"@types/ws": "^8.5.13",
|
|
90
90
|
"@typescript-eslint/eslint-plugin": "^8.50.0",
|
|
91
91
|
"@typescript-eslint/parser": "^8.50.0",
|
|
92
|
-
"@vitest/coverage-v8": "^
|
|
92
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
93
93
|
"eslint": "^9.39.2",
|
|
94
94
|
"prettier": "^3.7.4",
|
|
95
95
|
"tsx": "^4.21.0",
|
|
96
96
|
"typescript": "^5.7.2",
|
|
97
|
-
"vitest": "^
|
|
97
|
+
"vitest": "^4.1.2"
|
|
98
98
|
},
|
|
99
99
|
"engines": {
|
|
100
100
|
"node": ">=18.0.0"
|
package/dist/lib/formatters.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* JSON-serializable value type
|
|
3
|
-
*/
|
|
4
|
-
type JsonValue = string | number | boolean | null | JsonObject | JsonArray;
|
|
5
|
-
interface JsonObject {
|
|
6
|
-
[key: string]: JsonValue;
|
|
7
|
-
}
|
|
8
|
-
type JsonArray = JsonValue[];
|
|
9
|
-
/**
|
|
10
|
-
* Interface for output formatting in the CLI.
|
|
11
|
-
* Implementations can provide different output styles (rich terminal, JSON, etc.)
|
|
12
|
-
*/
|
|
13
|
-
export interface OutputFormatter {
|
|
14
|
-
/**
|
|
15
|
-
* Print an error message
|
|
16
|
-
* @param message - The error message
|
|
17
|
-
* @param details - Optional detailed error information
|
|
18
|
-
*/
|
|
19
|
-
printError(message: string, details?: string): void;
|
|
20
|
-
/**
|
|
21
|
-
* Print a success message
|
|
22
|
-
* @param message - The success message
|
|
23
|
-
* @param data - Optional data to display with the message
|
|
24
|
-
*/
|
|
25
|
-
printSuccess(message: string, data?: JsonObject): void;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* JSON output formatter - outputs all messages as JSON
|
|
29
|
-
* Useful for scripting and programmatic consumption
|
|
30
|
-
*/
|
|
31
|
-
export declare class JSONOutputFormatter implements OutputFormatter {
|
|
32
|
-
printError(message: string, details?: string): void;
|
|
33
|
-
printSuccess(message: string, data?: JsonObject): void;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Rich terminal output formatter - uses colors and symbols
|
|
37
|
-
* Provides a better user experience in interactive terminals
|
|
38
|
-
*/
|
|
39
|
-
export declare class RichOutputFormatter implements OutputFormatter {
|
|
40
|
-
printError(message: string, details?: string): void;
|
|
41
|
-
printSuccess(message: string, data?: JsonObject): void;
|
|
42
|
-
}
|
|
43
|
-
export {};
|
|
44
|
-
//# sourceMappingURL=formatters.d.ts.map
|
package/dist/lib/formatters.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// Copyright (c) 2026 Guild.ai All Rights Reserved
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import { brand } from './colors.js';
|
|
4
|
-
/**
|
|
5
|
-
* JSON output formatter - outputs all messages as JSON
|
|
6
|
-
* Useful for scripting and programmatic consumption
|
|
7
|
-
*/
|
|
8
|
-
export class JSONOutputFormatter {
|
|
9
|
-
printError(message, details) {
|
|
10
|
-
const error = { error: message };
|
|
11
|
-
if (details) {
|
|
12
|
-
error.details = details;
|
|
13
|
-
}
|
|
14
|
-
console.log(JSON.stringify(error, null, 2));
|
|
15
|
-
}
|
|
16
|
-
printSuccess(message, data) {
|
|
17
|
-
const result = { success: message };
|
|
18
|
-
if (data) {
|
|
19
|
-
Object.assign(result, data);
|
|
20
|
-
}
|
|
21
|
-
console.log(JSON.stringify(result, null, 2));
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Rich terminal output formatter - uses colors and symbols
|
|
26
|
-
* Provides a better user experience in interactive terminals
|
|
27
|
-
*/
|
|
28
|
-
export class RichOutputFormatter {
|
|
29
|
-
printError(message, details) {
|
|
30
|
-
console.error(chalk.red(message));
|
|
31
|
-
if (details) {
|
|
32
|
-
console.error(chalk.dim(details));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
printSuccess(message, data) {
|
|
36
|
-
console.log(chalk.green('✓'), message);
|
|
37
|
-
if (data) {
|
|
38
|
-
for (const [key, value] of Object.entries(data)) {
|
|
39
|
-
const strValue = value === null
|
|
40
|
-
? 'null'
|
|
41
|
-
: value === undefined
|
|
42
|
-
? 'undefined'
|
|
43
|
-
: typeof value === 'object'
|
|
44
|
-
? JSON.stringify(value)
|
|
45
|
-
: String(value);
|
|
46
|
-
console.log(` ${key}: ${brand(strValue)}`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
//# sourceMappingURL=formatters.js.map
|