@agentuity/cli 0.1.14 → 0.1.16
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.d.ts.map +1 -1
- package/dist/auth.js +7 -6
- package/dist/auth.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +69 -11
- package/dist/cli.js.map +1 -1
- package/dist/cmd/ai/index.d.ts.map +1 -1
- package/dist/cmd/ai/index.js +6 -1
- package/dist/cmd/ai/index.js.map +1 -1
- package/dist/cmd/ai/opencode/index.d.ts +3 -0
- package/dist/cmd/ai/opencode/index.d.ts.map +1 -0
- package/dist/cmd/ai/opencode/index.js +27 -0
- package/dist/cmd/ai/opencode/index.js.map +1 -0
- package/dist/cmd/ai/opencode/install.d.ts +3 -0
- package/dist/cmd/ai/opencode/install.d.ts.map +1 -0
- package/dist/cmd/ai/opencode/install.js +102 -0
- package/dist/cmd/ai/opencode/install.js.map +1 -0
- package/dist/cmd/ai/opencode/run.d.ts +3 -0
- package/dist/cmd/ai/opencode/run.d.ts.map +1 -0
- package/dist/cmd/ai/opencode/run.js +88 -0
- package/dist/cmd/ai/opencode/run.js.map +1 -0
- package/dist/cmd/ai/opencode/uninstall.d.ts +3 -0
- package/dist/cmd/ai/opencode/uninstall.d.ts.map +1 -0
- package/dist/cmd/ai/opencode/uninstall.js +82 -0
- package/dist/cmd/ai/opencode/uninstall.js.map +1 -0
- package/dist/cmd/build/vite/beacon-plugin.d.ts.map +1 -1
- package/dist/cmd/build/vite/beacon-plugin.js.map +1 -1
- package/dist/cmd/build/vite/vite-builder.d.ts.map +1 -1
- package/dist/cmd/build/vite/vite-builder.js +1 -1
- package/dist/cmd/build/vite/vite-builder.js.map +1 -1
- package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/env/delete.js +87 -34
- package/dist/cmd/cloud/env/delete.js.map +1 -1
- package/dist/cmd/cloud/env/get.d.ts.map +1 -1
- package/dist/cmd/cloud/env/get.js +50 -16
- package/dist/cmd/cloud/env/get.js.map +1 -1
- package/dist/cmd/cloud/env/import.d.ts.map +1 -1
- package/dist/cmd/cloud/env/import.js +76 -32
- package/dist/cmd/cloud/env/import.js.map +1 -1
- package/dist/cmd/cloud/env/index.d.ts.map +1 -1
- package/dist/cmd/cloud/env/index.js +6 -2
- package/dist/cmd/cloud/env/index.js.map +1 -1
- package/dist/cmd/cloud/env/list.d.ts.map +1 -1
- package/dist/cmd/cloud/env/list.js +94 -23
- package/dist/cmd/cloud/env/list.js.map +1 -1
- package/dist/cmd/cloud/env/org-util.d.ts +16 -0
- package/dist/cmd/cloud/env/org-util.d.ts.map +1 -0
- package/dist/cmd/cloud/env/org-util.js +28 -0
- package/dist/cmd/cloud/env/org-util.js.map +1 -0
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +61 -29
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/env/push.d.ts.map +1 -1
- package/dist/cmd/cloud/env/push.js +69 -23
- package/dist/cmd/cloud/env/push.js.map +1 -1
- package/dist/cmd/cloud/env/set.d.ts.map +1 -1
- package/dist/cmd/cloud/env/set.js +69 -26
- package/dist/cmd/cloud/env/set.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.js +1 -1
- package/dist/cmd/cloud/keyvalue/create-namespace.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete-namespace.js +2 -2
- package/dist/cmd/cloud/keyvalue/delete-namespace.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/delete.js +1 -1
- package/dist/cmd/cloud/keyvalue/delete.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/get.js +1 -1
- package/dist/cmd/cloud/keyvalue/get.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/index.js +1 -1
- package/dist/cmd/cloud/keyvalue/index.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/keys.js +1 -1
- package/dist/cmd/cloud/keyvalue/keys.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/list-namespaces.js +1 -1
- package/dist/cmd/cloud/keyvalue/list-namespaces.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/repl.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/repl.js +8 -5
- package/dist/cmd/cloud/keyvalue/repl.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/search.js +1 -1
- package/dist/cmd/cloud/keyvalue/search.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/set.js +1 -1
- package/dist/cmd/cloud/keyvalue/set.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/stats.js +1 -1
- package/dist/cmd/cloud/keyvalue/stats.js.map +1 -1
- package/dist/cmd/cloud/keyvalue/util.d.ts +4 -4
- package/dist/cmd/cloud/keyvalue/util.d.ts.map +1 -1
- package/dist/cmd/cloud/keyvalue/util.js +4 -9
- package/dist/cmd/cloud/keyvalue/util.js.map +1 -1
- package/dist/cmd/project/create.d.ts.map +1 -1
- package/dist/cmd/project/create.js +20 -2
- package/dist/cmd/project/create.js.map +1 -1
- package/dist/cmd/project/download.d.ts +3 -1
- package/dist/cmd/project/download.d.ts.map +1 -1
- package/dist/cmd/project/download.js +5 -0
- package/dist/cmd/project/download.js.map +1 -1
- package/dist/cmd/project/template-flow.d.ts +5 -0
- package/dist/cmd/project/template-flow.d.ts.map +1 -1
- package/dist/cmd/project/template-flow.js +188 -79
- package/dist/cmd/project/template-flow.js.map +1 -1
- package/dist/cmd/setup/index.d.ts.map +1 -1
- package/dist/cmd/setup/index.js +2 -1
- package/dist/cmd/setup/index.js.map +1 -1
- package/dist/onboarding/agentPrompt.d.ts +8 -0
- package/dist/onboarding/agentPrompt.d.ts.map +1 -0
- package/dist/onboarding/agentPrompt.js +263 -0
- package/dist/onboarding/agentPrompt.js.map +1 -0
- package/dist/schema-generator.d.ts +1 -1
- package/dist/schema-generator.d.ts.map +1 -1
- package/dist/schema-parser.d.ts +1 -1
- package/dist/schema-parser.d.ts.map +1 -1
- package/dist/schema-parser.js +36 -1
- package/dist/schema-parser.js.map +1 -1
- package/dist/tui/prompt.d.ts.map +1 -1
- package/dist/tui/prompt.js +7 -1
- package/dist/tui/prompt.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +91 -28
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +7 -7
- package/src/auth.ts +7 -6
- package/src/cli.ts +84 -11
- package/src/cmd/ai/index.ts +6 -1
- package/src/cmd/ai/opencode/index.ts +28 -0
- package/src/cmd/ai/opencode/install.ts +120 -0
- package/src/cmd/ai/opencode/run.ts +103 -0
- package/src/cmd/ai/opencode/uninstall.ts +90 -0
- package/src/cmd/build/vite/beacon-plugin.ts +3 -1
- package/src/cmd/build/vite/vite-builder.ts +5 -1
- package/src/cmd/cloud/env/delete.ts +100 -41
- package/src/cmd/cloud/env/get.ts +53 -16
- package/src/cmd/cloud/env/import.ts +86 -37
- package/src/cmd/cloud/env/index.ts +6 -2
- package/src/cmd/cloud/env/list.ts +102 -27
- package/src/cmd/cloud/env/org-util.ts +37 -0
- package/src/cmd/cloud/env/pull.ts +67 -31
- package/src/cmd/cloud/env/push.ts +81 -28
- package/src/cmd/cloud/env/set.ts +82 -33
- package/src/cmd/cloud/keyvalue/create-namespace.ts +1 -1
- package/src/cmd/cloud/keyvalue/delete-namespace.ts +2 -2
- package/src/cmd/cloud/keyvalue/delete.ts +1 -1
- package/src/cmd/cloud/keyvalue/get.ts +1 -1
- package/src/cmd/cloud/keyvalue/index.ts +1 -1
- package/src/cmd/cloud/keyvalue/keys.ts +1 -1
- package/src/cmd/cloud/keyvalue/list-namespaces.ts +1 -1
- package/src/cmd/cloud/keyvalue/repl.ts +8 -5
- package/src/cmd/cloud/keyvalue/search.ts +1 -1
- package/src/cmd/cloud/keyvalue/set.ts +1 -1
- package/src/cmd/cloud/keyvalue/stats.ts +1 -1
- package/src/cmd/cloud/keyvalue/util.ts +8 -17
- package/src/cmd/project/create.ts +21 -2
- package/src/cmd/project/download.ts +7 -1
- package/src/cmd/project/template-flow.ts +215 -80
- package/src/cmd/setup/index.ts +2 -1
- package/src/onboarding/agentPrompt.ts +263 -0
- package/src/schema-generator.ts +1 -1
- package/src/schema-parser.ts +42 -3
- package/src/tui/prompt.ts +10 -3
- package/src/tui.ts +95 -31
- package/src/types.ts +1 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Onboarding Prompt
|
|
3
|
+
*
|
|
4
|
+
* This generates the markdown prompt that coding agents use to guide developers
|
|
5
|
+
* through Agentuity setup after the CLI has been installed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export function getAgentPromptMarkdown(): string {
|
|
9
|
+
return `
|
|
10
|
+
**Your goal:** Guide the user from zero to a deployed Agentuity project, then help them understand what they have and what to do next.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What is Agentuity?
|
|
15
|
+
|
|
16
|
+
Agentuity is the full-stack platform for AI agents. Briefly explain to the user:
|
|
17
|
+
|
|
18
|
+
- **Full-stack agents**: Build agents, APIs, and front-end integrations with end-to-end type safety
|
|
19
|
+
- **Bun/TypeScript SDKs**: First-class developer experience with the fastest JavaScript runtime
|
|
20
|
+
- **AI Gateway**: Unified access to LLMs (OpenAI-compatible SDK) with single billing—no separate API keys needed
|
|
21
|
+
- **Observability**: Logs, tracing, and evals built-in so you can debug and improve agents
|
|
22
|
+
- **Production services**: Sandboxes, storage (S3-compatible), Postgres, KV, and enterprise features available as you grow
|
|
23
|
+
|
|
24
|
+
We're going to be setting up the default template quickly.
|
|
25
|
+
|
|
26
|
+
The default template includes AI Gateway integration, thread state persistence, structured logging, Tailwind CSS, and a local Workbench at \`/workbench\` for testing agents.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## How to Guide the User
|
|
31
|
+
|
|
32
|
+
**Your job is to make onboarding as smooth as possible with minimal user interaction.**
|
|
33
|
+
|
|
34
|
+
1. **Start by briefly explaining** what Agentuity is and what you'll help them accomplish
|
|
35
|
+
2. **Run commands automatically** when you have terminal access—don't ask permission for each step
|
|
36
|
+
3. **Only pause for human action** when absolutely required
|
|
37
|
+
4. **At each step**: Briefly explain what it does and why, then execute
|
|
38
|
+
5. **Celebrate success**: When deployment completes, make sure the user knows they earned free credits and show them what to explore next
|
|
39
|
+
|
|
40
|
+
Assume the user is technical but new to Agentuity. Be warm, efficient, and action-oriented. The goal is a successful deployment with as few interruptions as possible.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Onboarding Steps
|
|
45
|
+
|
|
46
|
+
### Step 1: You're Already Logged In!
|
|
47
|
+
|
|
48
|
+
**The install command automatically authenticated you.** No manual login needed.
|
|
49
|
+
|
|
50
|
+
Verify with:
|
|
51
|
+
\`\`\`bash
|
|
52
|
+
agentuity auth whoami
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
This outputs your user info including your \`org_id\`. You'll need this for the create command.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### Step 2: Create a New Project
|
|
60
|
+
|
|
61
|
+
**Why:** This scaffolds a full-stack agent app with AI Gateway, persistence, logging, and a testing UI.
|
|
62
|
+
|
|
63
|
+
**First, get the user's organization ID:**
|
|
64
|
+
\`\`\`bash
|
|
65
|
+
agentuity auth whoami
|
|
66
|
+
\`\`\`
|
|
67
|
+
|
|
68
|
+
This outputs the user's info including their \`org_id\`. You'll need this for the create command.
|
|
69
|
+
|
|
70
|
+
**Then create the project (non-interactive):**
|
|
71
|
+
\`\`\`bash
|
|
72
|
+
agentuity create --name "my-first-agent" --org-id <ORG_ID> --region usc --confirm
|
|
73
|
+
\`\`\`
|
|
74
|
+
|
|
75
|
+
**Required flags for non-interactive mode:**
|
|
76
|
+
- \`--name\`: Project name (use \`my-first-agent\` as default)
|
|
77
|
+
- \`--org-id\`: The organization ID from \`agentuity auth whoami\` (required in non-interactive mode)
|
|
78
|
+
- \`--region\`: Cloud region (use \`usc\` for US Central, or \`use\` for US East)
|
|
79
|
+
- \`--confirm\`: Skips interactive prompts
|
|
80
|
+
|
|
81
|
+
**Example with real org ID:**
|
|
82
|
+
\`\`\`bash
|
|
83
|
+
agentuity create --name "my-first-agent" --org-id ..... --region usc --confirm
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
If the user wants a different location, add \`--dir\`:
|
|
87
|
+
\`\`\`bash
|
|
88
|
+
agentuity create --name "my-first-agent" --org-id <ORG_ID> --region usc --dir ~/projects/my-first-agent --confirm
|
|
89
|
+
\`\`\`
|
|
90
|
+
|
|
91
|
+
After creation, \`cd\` into the project directory.
|
|
92
|
+
|
|
93
|
+
**Docs:** https://agentuity.dev/Get-Started/quickstart
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### Step 3: Run Locally
|
|
98
|
+
|
|
99
|
+
**Why:** Start the development server to test the project locally before deploying.
|
|
100
|
+
|
|
101
|
+
**Command:**
|
|
102
|
+
\`\`\`bash
|
|
103
|
+
agentuity dev
|
|
104
|
+
\`\`\`
|
|
105
|
+
|
|
106
|
+
**⚠️ This is a long-running process!** The dev server runs continuously until killed. Before or after starting it, **immediately tell the user what to do** — don't just wait silently.
|
|
107
|
+
|
|
108
|
+
**What happens:**
|
|
109
|
+
- **Local server** starts at \`http://localhost:3500\` — this is where your APIs and agents are served
|
|
110
|
+
- **Workbench** available at \`http://localhost:3500/workbench\` — a built-in UI for testing and interacting with your agents directly, without needing a frontend
|
|
111
|
+
- **Public tunnel URL** is automatically created — the CLI will display a public URL that tunnels to your local server, useful for testing webhooks or sharing with others
|
|
112
|
+
- **Hot reload** enabled — code changes reflect immediately
|
|
113
|
+
|
|
114
|
+
**Immediately after starting the dev server, tell the user:**
|
|
115
|
+
|
|
116
|
+
> "The dev server is now running! Here's what to try:
|
|
117
|
+
>
|
|
118
|
+
> 1. Open **http://localhost:3500** to see the app
|
|
119
|
+
> 2. Open **http://localhost:3500/workbench** to interact with your agents (this is a key feature!)
|
|
120
|
+
> 3. The public tunnel URL shown in the terminal can be shared with others
|
|
121
|
+
>
|
|
122
|
+
> Take a few minutes to explore. When you're ready to deploy to production, let me know!"
|
|
123
|
+
|
|
124
|
+
**Wait for the user to confirm** they're ready to deploy before proceeding to Step 4.
|
|
125
|
+
|
|
126
|
+
**Keyboard shortcuts** while dev server runs: \`h\` for help, \`r\` to restart, \`q\` to quit.
|
|
127
|
+
|
|
128
|
+
**Docs:** https://agentuity.dev/Reference/CLI/development
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### Step 4: Deploy to Production
|
|
133
|
+
|
|
134
|
+
**Why:** Make the project live with observability, logs, and analytics.
|
|
135
|
+
|
|
136
|
+
**Important:** Deploying their first project earns the user **free credits** to continue experimenting with the platform. Make sure they know this is a reward for completing onboarding!
|
|
137
|
+
|
|
138
|
+
**First, stop the dev server:**
|
|
139
|
+
Before deploying, you must stop the dev server that's still running from Step 3. Send \`Ctrl+C\` or \`q\` to the terminal running \`agentuity dev\` to gracefully shut it down. Don't leave it running or you'll have an orphaned process on port 3500.
|
|
140
|
+
|
|
141
|
+
**Then deploy:**
|
|
142
|
+
\`\`\`bash
|
|
143
|
+
agentuity deploy
|
|
144
|
+
\`\`\`
|
|
145
|
+
|
|
146
|
+
**What happens:**
|
|
147
|
+
- Project builds and deploys to Agentuity's global edge network
|
|
148
|
+
- The CLI will output the production URL when deployment succeeds
|
|
149
|
+
- Observability (logs, tracing, analytics) is now live
|
|
150
|
+
- **Free credits are awarded** for their first deployment
|
|
151
|
+
|
|
152
|
+
**⚠️ CRITICAL: Do not hallucinate URLs!**
|
|
153
|
+
- **Only show the user URLs that the CLI actually outputs**
|
|
154
|
+
- Do not make up or guess production URLs (e.g., don't invent \`https://project-name.agentuity.app\`)
|
|
155
|
+
- If the deploy command fails or doesn't show a URL, tell the user to check the dashboard instead
|
|
156
|
+
- If there's an error, report the actual error message from the CLI
|
|
157
|
+
|
|
158
|
+
**After successful deployment:**
|
|
159
|
+
1. Show the user the **exact production URL from the CLI output**
|
|
160
|
+
2. Direct them to the Agentuity dashboard at https://app.agentuity.com to:
|
|
161
|
+
- View their deployed project
|
|
162
|
+
- Explore logs and traces
|
|
163
|
+
- See their credit balance
|
|
164
|
+
- Monitor analytics
|
|
165
|
+
|
|
166
|
+
**If deployment fails or shows errors:**
|
|
167
|
+
- Report the actual error message
|
|
168
|
+
- Don't claim success if the CLI didn't confirm it
|
|
169
|
+
- Suggest checking the dashboard for deployment status
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## What the Template Provides
|
|
174
|
+
|
|
175
|
+
After deployment, explain what they now have:
|
|
176
|
+
|
|
177
|
+
| Feature | What It Does |
|
|
178
|
+
|---------|--------------|
|
|
179
|
+
| **AI Gateway** | OpenAI-compatible SDK routed through Agentuity—unified billing, no separate API keys |
|
|
180
|
+
| **Thread State** | Conversations and agent state persist automatically for multi-turn flows |
|
|
181
|
+
| **Structured Logging** | Logs and traces captured for debugging and analytics |
|
|
182
|
+
| **Workbench** | Local UI at \`/workbench\` for testing agents without a frontend |
|
|
183
|
+
| **Tailwind CSS** | Pre-configured styling for the frontend |
|
|
184
|
+
| **Type Safety** | End-to-end types from agent schemas to API routes to frontend |
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Next Steps
|
|
189
|
+
|
|
190
|
+
After successful deployment, guide the user through these recommendations:
|
|
191
|
+
|
|
192
|
+
### 1. Celebrate the Free Credits!
|
|
193
|
+
- Remind the user: their first deployment earned them **free credits** to keep experimenting
|
|
194
|
+
- They can view their credit balance in the Agentuity dashboard
|
|
195
|
+
- These credits let them continue building and testing without upfront cost
|
|
196
|
+
|
|
197
|
+
### 2. Join the Community
|
|
198
|
+
- **Discord**: https://discord.gg/agentuity
|
|
199
|
+
- Get help, see examples, share what you're building
|
|
200
|
+
|
|
201
|
+
### 3. Explore the Dashboard
|
|
202
|
+
- **Observability**: View logs, traces, and evals for your deployment
|
|
203
|
+
- **Deployments**: See version history with rollback options
|
|
204
|
+
- **Analytics**: Monitor usage and performance
|
|
205
|
+
|
|
206
|
+
### 4. Connect GitHub
|
|
207
|
+
- Enable GitHub integration in project settings for:
|
|
208
|
+
- Automatic deployments from branches
|
|
209
|
+
- CI/CD workflows
|
|
210
|
+
- Team collaboration
|
|
211
|
+
|
|
212
|
+
### 5. Explore Additional Services
|
|
213
|
+
As your project grows, Agentuity provides:
|
|
214
|
+
- **Postgres**: Relational database
|
|
215
|
+
- **KV**: Fast key-value storage
|
|
216
|
+
- **Storage**: S3-compatible file storage
|
|
217
|
+
- **Sandboxes**: Isolated execution environments
|
|
218
|
+
|
|
219
|
+
### 6. Customize Your Agents
|
|
220
|
+
The SDK makes it easy to:
|
|
221
|
+
- Add new agents in \`src/agent/\` (just add a folder with \`agent.ts\`)
|
|
222
|
+
- Create API routes in \`src/api/\`
|
|
223
|
+
- Build type-safe frontend integrations
|
|
224
|
+
|
|
225
|
+
**Docs:** https://agentuity.dev/Get-Started/project-structure
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Handling Common Issues
|
|
230
|
+
|
|
231
|
+
- **Bun not installed**: The CLI will prompt to install it, or run: \`curl -fsSL https://bun.sh/install | bash\`
|
|
232
|
+
- **Login fails/times out**: Rerun \`agentuity login\` and check browser
|
|
233
|
+
- **Port 3500 in use**: Kill the existing process or use \`agentuity dev --port 8080\`
|
|
234
|
+
- **Deploy fails**: Check build errors in CLI output, ensure you're in the project directory
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Success Criteria
|
|
239
|
+
|
|
240
|
+
**Onboarding is successful when the user has:**
|
|
241
|
+
|
|
242
|
+
1. ✅ **CLI installed** and authenticated
|
|
243
|
+
2. ✅ **Local dev environment running** — they've seen \`localhost:3500\` and tried the Workbench
|
|
244
|
+
3. ✅ **First deployment complete** — they have a live production URL
|
|
245
|
+
4. ✅ **Free credits earned** — they know they've been rewarded and can keep building
|
|
246
|
+
5. ✅ **Clear next steps** — they know about Discord, the dashboard, and how to extend their project
|
|
247
|
+
|
|
248
|
+
**Make them feel accomplished!** They just went from zero to a deployed AI agent platform in minutes.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Style Guidelines
|
|
253
|
+
|
|
254
|
+
- Keep explanations short and practical
|
|
255
|
+
- Explain what & why at each step
|
|
256
|
+
- Give exact commands
|
|
257
|
+
- Handle errors calmly with concrete suggestions
|
|
258
|
+
- Be explicit when human action is required
|
|
259
|
+
- Use non-interactive CLI flags (\`--confirm\`, \`--name\`, \`--org-id\`, \`--region usc\`, \`--dir\`) for smooth automation
|
|
260
|
+
- **Never hallucinate or make up information** — only report URLs, IDs, and status from actual CLI output
|
|
261
|
+
- If something fails or you're unsure, say so honestly and direct the user to the dashboard
|
|
262
|
+
`;
|
|
263
|
+
}
|
package/src/schema-generator.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface SchemaArgument {
|
|
|
13
13
|
|
|
14
14
|
export interface SchemaOption {
|
|
15
15
|
name: string;
|
|
16
|
-
type: 'string' | 'number' | 'boolean' | 'array';
|
|
16
|
+
type: 'string' | 'number' | 'boolean' | 'array' | 'optionalString';
|
|
17
17
|
required: boolean;
|
|
18
18
|
default?: unknown;
|
|
19
19
|
description?: string;
|
package/src/schema-parser.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface ParsedArgs {
|
|
|
13
13
|
export interface ParsedOption {
|
|
14
14
|
name: string;
|
|
15
15
|
description?: string;
|
|
16
|
-
type: 'string' | 'number' | 'boolean' | 'array';
|
|
16
|
+
type: 'string' | 'number' | 'boolean' | 'array' | 'optionalString';
|
|
17
17
|
hasDefault?: boolean;
|
|
18
18
|
defaultValue?: unknown;
|
|
19
19
|
enumValues?: string[];
|
|
@@ -57,6 +57,42 @@ function unwrapSchema(schema: unknown): unknown {
|
|
|
57
57
|
return current;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Check if a schema is a union of boolean and string (for optional string flags like --org [value])
|
|
62
|
+
* This pattern is used when a flag can be used as a boolean (--org) or with a value (--org=myOrgId)
|
|
63
|
+
*/
|
|
64
|
+
function isBooleanStringUnion(schema: unknown): boolean {
|
|
65
|
+
const unwrapped = unwrapSchema(schema) as ZodTypeInternal;
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
+
const def = unwrapped?._def as any;
|
|
68
|
+
// Zod 3 uses typeName, Zod 4 uses type
|
|
69
|
+
const typeId = def?.typeName || def?.type;
|
|
70
|
+
|
|
71
|
+
if (typeId !== 'ZodUnion' && typeId !== 'union') {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Zod 3 uses _def.options, Zod 4 uses .options directly on the schema or _def.options
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
+
const options = def?.options || (unwrapped as any)?.options;
|
|
78
|
+
if (!Array.isArray(options) || options.length !== 2) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const types = new Set<string>();
|
|
83
|
+
for (const opt of options) {
|
|
84
|
+
// Zod 4: type is directly on the object as .type
|
|
85
|
+
// Zod 3: type is _def.typeName
|
|
86
|
+
const optUnknown = opt as unknown as Record<string, unknown>;
|
|
87
|
+
const optDef = optUnknown?._def as Record<string, unknown> | undefined;
|
|
88
|
+
const optType = (optUnknown?.type as string) || (optDef?.typeName as string) || (optDef?.type as string);
|
|
89
|
+
types.add(optType);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return (types.has('boolean') || types.has('ZodBoolean')) &&
|
|
93
|
+
(types.has('string') || types.has('ZodString'));
|
|
94
|
+
}
|
|
95
|
+
|
|
60
96
|
function getShape(schema: ZodType): Record<string, unknown> {
|
|
61
97
|
const unwrapped = unwrapSchema(schema) as ZodTypeInternal;
|
|
62
98
|
const typeId = unwrapped?._def?.typeName || unwrapped?._def?.type;
|
|
@@ -182,9 +218,12 @@ export function parseOptionsSchema(schema: ZodType): ParsedOption[] {
|
|
|
182
218
|
}
|
|
183
219
|
}
|
|
184
220
|
|
|
185
|
-
let type: 'string' | 'number' | 'boolean' | 'array' = 'string';
|
|
221
|
+
let type: 'string' | 'number' | 'boolean' | 'array' | 'optionalString' = 'string';
|
|
186
222
|
let enumValues: string[] | undefined;
|
|
187
|
-
if (
|
|
223
|
+
if (isBooleanStringUnion(value)) {
|
|
224
|
+
// z.union([z.boolean(), z.string()]) - flag can be used as --flag or --flag=value
|
|
225
|
+
type = 'optionalString';
|
|
226
|
+
} else if (typeId === 'ZodNumber' || typeId === 'number') {
|
|
188
227
|
type = 'number';
|
|
189
228
|
} else if (typeId === 'ZodBoolean' || typeId === 'boolean') {
|
|
190
229
|
type = 'boolean';
|
package/src/tui/prompt.ts
CHANGED
|
@@ -166,9 +166,16 @@ export class PromptFlow {
|
|
|
166
166
|
readline.moveCursor(process.stdout, 0, -linesToClear);
|
|
167
167
|
readline.clearScreenDown(process.stdout);
|
|
168
168
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
// If value is empty, only show message and separator (no value line)
|
|
170
|
+
if (value === '') {
|
|
171
|
+
process.stdout.write(
|
|
172
|
+
`${colors.completed(symbols.completed)} ${message}\n${colors.secondary(symbols.bar)}\n`
|
|
173
|
+
);
|
|
174
|
+
} else {
|
|
175
|
+
process.stdout.write(
|
|
176
|
+
`${colors.completed(symbols.completed)} ${message}\n${colors.secondary(symbols.bar)} ${colors.muted(value)}\n${colors.secondary(symbols.bar)}\n`
|
|
177
|
+
);
|
|
178
|
+
}
|
|
172
179
|
|
|
173
180
|
this.states.push({
|
|
174
181
|
type: 'completed',
|
package/src/tui.ts
CHANGED
|
@@ -247,7 +247,8 @@ export function getSeverityColor(severity: string): (text: string) => string {
|
|
|
247
247
|
export function success(message: string): void {
|
|
248
248
|
const color = getColor('success');
|
|
249
249
|
const reset = getColor('reset');
|
|
250
|
-
|
|
250
|
+
// Clear line first to ensure no leftover content from previous output
|
|
251
|
+
process.stderr.write(`\r\x1b[2K${color}${ICONS.success} ${message}${reset}\n`);
|
|
251
252
|
}
|
|
252
253
|
|
|
253
254
|
/**
|
|
@@ -829,7 +830,11 @@ export function showLoggedOutMessage(appBaseUrl: string, hasProfile = false): vo
|
|
|
829
830
|
// Padding needed: 46 - 17 - signupTitle.length - 1 (space before link) = 28 - signupTitle.length
|
|
830
831
|
const paddingLength = 28 - signupTitle.length;
|
|
831
832
|
const padding = ' '.repeat(paddingLength);
|
|
832
|
-
|
|
833
|
+
// When not showing inline hyperlink, show URL on separate line with proper padding
|
|
834
|
+
// Box format: "║ " + content + "║" = 48 chars total
|
|
835
|
+
// Content area = 46 chars, with leading space = 45 chars for URL + padding
|
|
836
|
+
const urlPadding = Math.max(0, 45 - signupURL.length);
|
|
837
|
+
const showNewLine = showInline ? '' : `║ ${RESET}${link(signupURL)}${YELLOW}${' '.repeat(urlPadding)}║`;
|
|
833
838
|
|
|
834
839
|
const lines = [
|
|
835
840
|
'╔══════════════════════════════════════════════╗',
|
|
@@ -844,6 +849,8 @@ export function showLoggedOutMessage(appBaseUrl: string, hasProfile = false): vo
|
|
|
844
849
|
|
|
845
850
|
console.log('');
|
|
846
851
|
lines.filter(Boolean).map((line) => console.log(YELLOW + line + RESET));
|
|
852
|
+
console.log('');
|
|
853
|
+
console.log('');
|
|
847
854
|
}
|
|
848
855
|
|
|
849
856
|
/**
|
|
@@ -1303,11 +1310,17 @@ export async function spinner<T>(
|
|
|
1303
1310
|
// Stop animation
|
|
1304
1311
|
clearInterval(interval);
|
|
1305
1312
|
|
|
1306
|
-
// Move cursor to start of output, clear
|
|
1313
|
+
// Move cursor to start of output, clear only our lines (not to end of screen)
|
|
1307
1314
|
if (linesRendered > 0) {
|
|
1308
1315
|
process.stderr.write(`\x1b[${linesRendered}A`);
|
|
1316
|
+
for (let i = 0; i < linesRendered; i++) {
|
|
1317
|
+
process.stderr.write('\x1b[2K'); // Clear entire line
|
|
1318
|
+
if (i < linesRendered - 1) {
|
|
1319
|
+
process.stderr.write('\x1b[B'); // Move down one line
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
process.stderr.write(`\x1b[${linesRendered}A\r`); // Move back up
|
|
1309
1323
|
}
|
|
1310
|
-
process.stderr.write('\x1b[J'); // Clear from cursor to end of screen
|
|
1311
1324
|
process.stderr.write('\x1B[?25h'); // Show cursor
|
|
1312
1325
|
|
|
1313
1326
|
process.exit(130); // Standard exit code for SIGINT
|
|
@@ -1363,11 +1376,22 @@ export async function spinner<T>(
|
|
|
1363
1376
|
// Stop animation first
|
|
1364
1377
|
clearInterval(interval);
|
|
1365
1378
|
|
|
1366
|
-
// Move cursor to start of output, clear
|
|
1379
|
+
// Move cursor to start of output, clear only our lines (not to end of screen)
|
|
1367
1380
|
if (linesRendered > 0) {
|
|
1368
1381
|
process.stderr.write(`\x1b[${linesRendered}A`);
|
|
1382
|
+
for (let i = 0; i < linesRendered; i++) {
|
|
1383
|
+
process.stderr.write('\r\x1b[2K'); // Clear entire line
|
|
1384
|
+
if (i < linesRendered - 1) {
|
|
1385
|
+
process.stderr.write('\x1b[B'); // Move down one line
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
// After loop, cursor is at last cleared line (linesRendered - 1 from start)
|
|
1389
|
+
// Move up (linesRendered - 1) to get back to start position
|
|
1390
|
+
if (linesRendered > 1) {
|
|
1391
|
+
process.stderr.write(`\x1b[${linesRendered - 1}A`);
|
|
1392
|
+
}
|
|
1393
|
+
process.stderr.write('\r');
|
|
1369
1394
|
}
|
|
1370
|
-
process.stderr.write('\x1b[J'); // Clear from cursor to end of screen
|
|
1371
1395
|
process.stderr.write('\x1B[?25h'); // Show cursor
|
|
1372
1396
|
|
|
1373
1397
|
// If clearOnSuccess is false, show success message
|
|
@@ -1384,11 +1408,22 @@ export async function spinner<T>(
|
|
|
1384
1408
|
// Stop animation first
|
|
1385
1409
|
clearInterval(interval);
|
|
1386
1410
|
|
|
1387
|
-
// Move cursor to start of output, clear
|
|
1411
|
+
// Move cursor to start of output, clear only our lines (not to end of screen)
|
|
1388
1412
|
if (linesRendered > 0) {
|
|
1389
1413
|
process.stderr.write(`\x1b[${linesRendered}A`);
|
|
1414
|
+
for (let i = 0; i < linesRendered; i++) {
|
|
1415
|
+
process.stderr.write('\r\x1b[2K'); // Clear entire line
|
|
1416
|
+
if (i < linesRendered - 1) {
|
|
1417
|
+
process.stderr.write('\x1b[B'); // Move down one line
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
// After loop, cursor is at last cleared line (linesRendered - 1 from start)
|
|
1421
|
+
// Move up (linesRendered - 1) to get back to start position
|
|
1422
|
+
if (linesRendered > 1) {
|
|
1423
|
+
process.stderr.write(`\x1b[${linesRendered - 1}A`);
|
|
1424
|
+
}
|
|
1425
|
+
process.stderr.write('\r');
|
|
1390
1426
|
}
|
|
1391
|
-
process.stderr.write('\x1b[J'); // Clear from cursor to end of screen
|
|
1392
1427
|
process.stderr.write('\x1B[?25h'); // Show cursor
|
|
1393
1428
|
|
|
1394
1429
|
// Show error
|
|
@@ -1561,7 +1596,8 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
1561
1596
|
|
|
1562
1597
|
for (const line of lines) {
|
|
1563
1598
|
if (line.trim()) {
|
|
1564
|
-
|
|
1599
|
+
// Strip ANSI codes from command output to prevent cursor/display issues
|
|
1600
|
+
allOutputLines.push(stripAnsi(line));
|
|
1565
1601
|
renderOutput(maxLinesOutput); // Show last N lines while streaming
|
|
1566
1602
|
}
|
|
1567
1603
|
}
|
|
@@ -1582,25 +1618,44 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
1582
1618
|
if (linesRendered > 0) {
|
|
1583
1619
|
// Move up to the command line
|
|
1584
1620
|
process.stdout.write(`\x1b[${linesRendered}A`);
|
|
1585
|
-
// Clear each line (entire line)
|
|
1621
|
+
// Clear each line (entire line)
|
|
1586
1622
|
for (let i = 0; i < linesRendered; i++) {
|
|
1587
|
-
process.stdout.write('\x1b[2K'); // Clear entire line
|
|
1623
|
+
process.stdout.write('\r\x1b[2K'); // Clear entire line
|
|
1588
1624
|
if (i < linesRendered - 1) {
|
|
1589
1625
|
process.stdout.write('\x1b[B'); // Move down one line
|
|
1590
1626
|
}
|
|
1591
1627
|
}
|
|
1592
|
-
//
|
|
1593
|
-
|
|
1628
|
+
// After loop, cursor is at last cleared line (linesRendered - 1 from start)
|
|
1629
|
+
// Move up (linesRendered - 1) to get back to start position
|
|
1630
|
+
if (linesRendered > 1) {
|
|
1631
|
+
process.stdout.write(`\x1b[${linesRendered - 1}A`);
|
|
1632
|
+
}
|
|
1633
|
+
process.stdout.write('\r');
|
|
1594
1634
|
}
|
|
1595
1635
|
return exitCode;
|
|
1596
1636
|
}
|
|
1597
1637
|
|
|
1598
|
-
//
|
|
1638
|
+
// Determine how many lines to show in final output
|
|
1639
|
+
const finalLinesToShow = exitCode === 0 ? maxLinesOutput : maxLinesOnFailure;
|
|
1640
|
+
const finalOutputLines = allOutputLines.slice(-finalLinesToShow);
|
|
1641
|
+
|
|
1642
|
+
// Clear all rendered lines completely (only our lines, not previous output)
|
|
1599
1643
|
if (linesRendered > 0) {
|
|
1600
1644
|
// Move up to the command line (first line of our output)
|
|
1601
1645
|
process.stdout.write(`\x1b[${linesRendered}A`);
|
|
1602
|
-
//
|
|
1603
|
-
|
|
1646
|
+
// Clear the lines we rendered during streaming
|
|
1647
|
+
for (let i = 0; i < linesRendered; i++) {
|
|
1648
|
+
process.stdout.write('\r\x1b[2K'); // Clear entire line
|
|
1649
|
+
if (i < linesRendered - 1) {
|
|
1650
|
+
process.stdout.write('\x1b[B'); // Move down one line
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
// After loop, cursor is at last cleared line (linesRendered - 1 from start)
|
|
1654
|
+
// Move up (linesRendered - 1) to get back to start position
|
|
1655
|
+
if (linesRendered > 1) {
|
|
1656
|
+
process.stdout.write(`\x1b[${linesRendered - 1}A`);
|
|
1657
|
+
}
|
|
1658
|
+
process.stdout.write('\r');
|
|
1604
1659
|
}
|
|
1605
1660
|
|
|
1606
1661
|
// Determine icon based on exit code
|
|
@@ -1612,19 +1667,18 @@ export async function runCommand(options: CommandRunnerOptions): Promise<number>
|
|
|
1612
1667
|
`\r\x1b[K${statusColor}${icon}${reset} ${cmdColor}${displayCmd}${reset}\n`
|
|
1613
1668
|
);
|
|
1614
1669
|
|
|
1615
|
-
//
|
|
1616
|
-
const finalLinesToShow = exitCode === 0 ? maxLinesOutput : maxLinesOnFailure;
|
|
1617
|
-
|
|
1618
|
-
// Show final output lines
|
|
1619
|
-
const finalOutputLines = allOutputLines.slice(-finalLinesToShow);
|
|
1670
|
+
// Show final output lines (clearing each line first in case we're using more lines than before)
|
|
1620
1671
|
for (const line of finalOutputLines) {
|
|
1621
1672
|
const displayLine =
|
|
1622
1673
|
truncate && getDisplayWidth(line) > maxLineWidth
|
|
1623
1674
|
? truncateToWidth(line, maxLineWidth)
|
|
1624
1675
|
: line;
|
|
1625
|
-
process.stdout.write(`\
|
|
1676
|
+
process.stdout.write(`\x1b[2K${mutedColor}${displayLine}${reset}\n`);
|
|
1626
1677
|
}
|
|
1627
1678
|
|
|
1679
|
+
// If we're showing more lines than we had before, the extra lines may contain old content
|
|
1680
|
+
// We've already written over them, so they're clean now
|
|
1681
|
+
|
|
1628
1682
|
return exitCode;
|
|
1629
1683
|
} catch (err) {
|
|
1630
1684
|
// Move cursor up to clear our UI
|
|
@@ -1705,23 +1759,33 @@ export async function selectOrganization(
|
|
|
1705
1759
|
return orgs[0].id;
|
|
1706
1760
|
}
|
|
1707
1761
|
|
|
1708
|
-
if (
|
|
1709
|
-
|
|
1710
|
-
|
|
1762
|
+
// Use saved preference if available (regardless of TTY mode)
|
|
1763
|
+
// This allows consistent behavior without prompting on every command
|
|
1764
|
+
if (initial) {
|
|
1765
|
+
const initialOrg = orgs.find((o) => o.id === initial);
|
|
1766
|
+
if (initialOrg) {
|
|
1767
|
+
return initialOrg.id;
|
|
1711
1768
|
}
|
|
1712
|
-
fatal(
|
|
1713
|
-
'Organization selection required but cannot prompt in non-interactive environment. Set AGENTUITY_CLOUD_ORG_ID or provide a default organization using --org-id'
|
|
1714
|
-
);
|
|
1715
1769
|
}
|
|
1716
1770
|
|
|
1717
|
-
//
|
|
1718
|
-
const
|
|
1771
|
+
// Check for non-interactive environment (check both stdin and stdout)
|
|
1772
|
+
const isNonInteractive = !process.stdin.isTTY || !process.stdout.isTTY;
|
|
1773
|
+
if (isNonInteractive) {
|
|
1774
|
+
// In non-interactive mode with multiple orgs, auto-select first org
|
|
1775
|
+
// This allows scripts and CI/CD to work without explicit org selection
|
|
1776
|
+
warning(
|
|
1777
|
+
`Multiple organizations found. Auto-selecting first org: ${orgs[0].name}. ` +
|
|
1778
|
+
`Set AGENTUITY_CLOUD_ORG_ID or use --org-id to specify a different org.`
|
|
1779
|
+
);
|
|
1780
|
+
return orgs[0].id;
|
|
1781
|
+
}
|
|
1719
1782
|
|
|
1783
|
+
// Interactive mode with no saved preference - prompt user
|
|
1720
1784
|
const response = await enquirer.prompt<{ action: string }>({
|
|
1721
1785
|
type: 'select',
|
|
1722
1786
|
name: 'action',
|
|
1723
1787
|
message: 'Select an organization',
|
|
1724
|
-
initial:
|
|
1788
|
+
initial: 0,
|
|
1725
1789
|
choices: orgs.map((o) => ({ message: o.name, name: o.id })),
|
|
1726
1790
|
});
|
|
1727
1791
|
|