@castari/cli 0.1.11 → 0.2.1

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 (70) hide show
  1. package/README.md +79 -90
  2. package/bin/cast.js +2 -0
  3. package/dist/commands/agents.d.ts +6 -0
  4. package/dist/commands/agents.d.ts.map +1 -0
  5. package/dist/commands/agents.js +174 -0
  6. package/dist/commands/agents.js.map +1 -0
  7. package/dist/commands/apikey.d.ts +6 -0
  8. package/dist/commands/apikey.d.ts.map +1 -0
  9. package/dist/commands/apikey.js +57 -0
  10. package/dist/commands/apikey.js.map +1 -0
  11. package/dist/commands/deploy.d.ts +3 -3
  12. package/dist/commands/deploy.d.ts.map +1 -0
  13. package/dist/commands/deploy.js +24 -64
  14. package/dist/commands/deploy.js.map +1 -0
  15. package/dist/commands/invoke.d.ts +3 -0
  16. package/dist/commands/invoke.d.ts.map +1 -0
  17. package/dist/commands/invoke.js +50 -0
  18. package/dist/commands/invoke.js.map +1 -0
  19. package/dist/commands/login.d.ts +3 -0
  20. package/dist/commands/login.d.ts.map +1 -0
  21. package/dist/commands/login.js +123 -0
  22. package/dist/commands/login.js.map +1 -0
  23. package/dist/commands/logout.d.ts +3 -0
  24. package/dist/commands/logout.d.ts.map +1 -0
  25. package/dist/commands/logout.js +16 -0
  26. package/dist/commands/logout.js.map +1 -0
  27. package/dist/commands/secrets.d.ts +6 -0
  28. package/dist/commands/secrets.d.ts.map +1 -0
  29. package/dist/commands/secrets.js +90 -0
  30. package/dist/commands/secrets.js.map +1 -0
  31. package/dist/commands/stop.d.ts +3 -0
  32. package/dist/commands/stop.d.ts.map +1 -0
  33. package/dist/commands/stop.js +25 -0
  34. package/dist/commands/stop.js.map +1 -0
  35. package/dist/commands/usage.d.ts +3 -0
  36. package/dist/commands/usage.d.ts.map +1 -0
  37. package/dist/commands/usage.js +76 -0
  38. package/dist/commands/usage.js.map +1 -0
  39. package/dist/commands/whoami.d.ts +3 -0
  40. package/dist/commands/whoami.d.ts.map +1 -0
  41. package/dist/commands/whoami.js +27 -0
  42. package/dist/commands/whoami.js.map +1 -0
  43. package/dist/index.d.ts +2 -1
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +36 -34
  46. package/dist/index.js.map +1 -0
  47. package/dist/utils/errors.d.ts +6 -0
  48. package/dist/utils/errors.d.ts.map +1 -0
  49. package/dist/utils/errors.js +42 -0
  50. package/dist/utils/errors.js.map +1 -0
  51. package/dist/utils/output.d.ts +45 -0
  52. package/dist/utils/output.d.ts.map +1 -0
  53. package/dist/utils/output.js +75 -0
  54. package/dist/utils/output.js.map +1 -0
  55. package/package.json +56 -35
  56. package/LICENSE +0 -21
  57. package/dist/commands/client-id.d.ts +0 -1
  58. package/dist/commands/client-id.js +0 -25
  59. package/dist/commands/dev.d.ts +0 -1
  60. package/dist/commands/dev.js +0 -17
  61. package/dist/commands/generate-secrets.d.ts +0 -1
  62. package/dist/commands/generate-secrets.js +0 -60
  63. package/dist/commands/init.d.ts +0 -5
  64. package/dist/commands/init.js +0 -899
  65. package/dist/commands/start.d.ts +0 -5
  66. package/dist/commands/start.js +0 -100
  67. package/dist/utils/client-auth.d.ts +0 -11
  68. package/dist/utils/client-auth.js +0 -21
  69. package/dist/utils/client-id.d.ts +0 -10
  70. package/dist/utils/client-id.js +0 -36
package/README.md CHANGED
@@ -1,151 +1,140 @@
1
- # @castari/cli
1
+ # Castari CLI
2
2
 
3
- The command line interface for building and deploying Castari agents.
3
+ Deploy AI agents with one command.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@castari/cli.svg)](https://www.npmjs.com/package/@castari/cli)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
7
 
5
8
  ## Installation
6
9
 
7
10
  ```bash
8
11
  npm install -g @castari/cli
9
- # or
10
- bun add -g @castari/cli
11
12
  ```
12
13
 
13
14
  ## Quick Start
14
15
 
15
16
  ```bash
16
- # Create a new agent project
17
- castari init
17
+ # Authenticate with Castari
18
+ cast login
18
19
 
19
- # Run locally for development
20
- castari dev
20
+ # Create an agent from a git repository
21
+ cast agents create my-agent https://github.com/user/my-agent --slug my-agent
21
22
 
22
- # Deploy to Castari Platform
23
- castari deploy
23
+ # Deploy the agent
24
+ cast deploy my-agent
24
25
 
25
- # Start a cloud sandbox and connect
26
- castari start
26
+ # Invoke the agent
27
+ cast invoke my-agent "Hello, world!"
27
28
  ```
28
29
 
29
30
  ## Commands
30
31
 
31
- ### `castari init`
32
-
33
- Scaffolds a new Castari agent project.
32
+ ### Authentication
34
33
 
35
34
  ```bash
36
- castari init # Basic agent scaffold
37
- castari init --demo # Full demo with agent + Next.js chat UI
35
+ cast login # Authenticate via browser (OAuth)
36
+ cast logout # Clear stored credentials
37
+ cast whoami # Show current user info
38
+ cast apikey create # Create an API key for CI/CD
39
+ cast apikey revoke # Revoke your API key
38
40
  ```
39
41
 
40
- **Creates:**
41
- - `package.json` - Configured with dependencies
42
- - `tsconfig.json` - TypeScript configuration
43
- - `src/agent.ts` - Starter agent code
44
- - `.env.example` - Environment variable template
45
-
46
- The `--demo` option creates a complete working example with:
47
- - A sample agent with custom tools
48
- - A Next.js chat interface
49
- - Real-time streaming responses
50
-
51
- ### `castari dev`
52
-
53
- Runs the agent locally for development.
42
+ ### Agent Management
54
43
 
55
44
  ```bash
56
- castari dev
45
+ cast agents list # List all agents
46
+ cast agents create <name> <git-url> --slug <slug> # Create a new agent
47
+ cast agents get <slug> # Get agent details
48
+ cast agents delete <slug> [--force] # Delete an agent
57
49
  ```
58
50
 
59
- Starts a local server at `http://localhost:3000`. Connect to it using the SDK's `CastariClient` with `connectionUrl: 'http://localhost:3000'`.
51
+ ### Deployment & Invocation
60
52
 
61
- ### `castari deploy`
53
+ ```bash
54
+ cast deploy <slug> # Deploy an agent
55
+ cast invoke <slug> "<prompt>" # Invoke an agent
56
+ cast invoke <slug> --input <file> # Invoke with prompt from file
57
+ ```
62
58
 
63
- Uploads your agent to the Castari Platform and creates a snapshot.
59
+ ### Secrets
64
60
 
65
61
  ```bash
66
- castari deploy
67
- castari deploy --name my-custom-name
62
+ cast secrets list <slug> # List secret keys
63
+ cast secrets set <slug> <key> <value> # Set a secret
64
+ cast secrets delete <slug> <key> # Delete a secret
68
65
  ```
69
66
 
70
- **Options:**
71
- - `--name <name>` - Override the snapshot name (defaults to package.json name)
67
+ ### Usage Statistics
72
68
 
73
- **Requires:** `CASTARI_CLIENT_ID` and `CASTARI_API_KEY` environment variables
69
+ ```bash
70
+ cast usage # Show usage summary (last 30 days)
71
+ cast usage --days 7 # Show usage for specific period
72
+ cast usage --daily # Show daily breakdown
73
+ ```
74
74
 
75
- After deploying, your snapshot is available to start via `castari start` or the SDK.
75
+ ## Authentication
76
76
 
77
- ### `castari start`
77
+ ### Interactive (OAuth)
78
78
 
79
- Starts a cloud sandbox running your agent and connects interactively.
79
+ For local development, authenticate via browser:
80
80
 
81
81
  ```bash
82
- castari start
83
- castari start --snapshot my-agent
84
- castari start --snapshot my-agent --volume my-data
82
+ cast login
85
83
  ```
86
84
 
87
- **Options:**
88
- - `--snapshot <name>` - Snapshot to use (defaults to package.json name)
89
- - `--volume <name>` - Volume to mount for persistent storage
90
-
91
- **Requires:** `CASTARI_CLIENT_ID`, `CASTARI_API_KEY`, and `ANTHROPIC_API_KEY` environment variables
92
-
93
- Press `Ctrl+C` to gracefully shut down.
85
+ This opens your browser to sign in and stores credentials in `~/.castari/credentials.yaml`.
94
86
 
95
- ### `castari generate-secrets`
87
+ ### CI/CD (API Key)
96
88
 
97
- Generates Castari credentials (client ID and API key) and stores them in `~/.castari/client.json`.
89
+ For automated environments, use an API key:
98
90
 
99
91
  ```bash
100
- castari generate-secrets
101
- ```
102
-
103
- Outputs both values so you can copy them to your `.env` file:
92
+ # Create an API key
93
+ cast apikey create
104
94
 
95
+ # Use it in CI/CD
96
+ export CASTARI_API_KEY="cast_..."
97
+ cast deploy my-agent
105
98
  ```
106
- CASTARI_CLIENT_ID=your-client-id
107
- CASTARI_API_KEY=castari_your-api-key
108
- ```
109
-
110
- ## Configuration
111
99
 
112
- ### Environment Variables
100
+ ## SDK
113
101
 
114
- Create a `.env` file in your project:
102
+ The CLI is built on `@castari/sdk`, which you can use directly for programmatic access:
115
103
 
116
- ```env
117
- ANTHROPIC_API_KEY=sk-ant-...
118
- CASTARI_CLIENT_ID=your-client-id
119
- CASTARI_API_KEY=castari_your-api-key
104
+ ```bash
105
+ npm install @castari/sdk
120
106
  ```
121
107
 
122
- ### package.json
108
+ ```typescript
109
+ import { CastariClient } from '@castari/sdk';
123
110
 
124
- Configure Castari settings in your package.json:
111
+ const client = new CastariClient({
112
+ apiKey: process.env.CASTARI_API_KEY,
113
+ });
125
114
 
126
- ```json
127
- {
128
- "name": "my-agent",
129
- "castari": {
130
- "volume": "my-volume-name"
131
- }
132
- }
133
- ```
115
+ // List agents
116
+ const agents = await client.agents.list();
134
117
 
135
- ## Workflow
118
+ // Deploy an agent
119
+ await client.agents.deploy('my-agent');
136
120
 
137
- 1. **Initialize** - `castari init` to scaffold a new project
138
- 2. **Develop** - `castari dev` to run locally and test
139
- 3. **Deploy** - `castari deploy` to upload to the platform
140
- 4. **Run** - `castari start` to launch in a cloud sandbox
121
+ // Invoke an agent
122
+ const result = await client.agents.invoke('my-agent', {
123
+ prompt: 'Hello, world!',
124
+ });
141
125
 
142
- For production applications, use the `@castari/sdk` client to connect programmatically.
126
+ console.log(result.response_content);
127
+ console.log(`Cost: $${result.total_cost_usd}`);
128
+ ```
129
+
130
+ ## Configuration
143
131
 
144
- ## Prerequisites
132
+ Credentials are stored in `~/.castari/credentials.yaml` (mode 0600).
145
133
 
146
- - [Bun](https://bun.sh) v1.0+
147
- - [Anthropic](https://anthropic.com) API key
134
+ Environment variables:
135
+ - `CASTARI_API_KEY` - API key for authentication
136
+ - `CASTARI_API_URL` - Override API base URL (default: https://api.castari.dev)
148
137
 
149
138
  ## License
150
139
 
151
- MIT
140
+ MIT - see [LICENSE](https://github.com/castari/cli/blob/main/LICENSE) for details.
package/bin/cast.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import '../dist/index.js';
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * cast agents
4
+ */
5
+ export declare const agentsCommand: Command;
6
+ //# sourceMappingURL=agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwLpC;;GAEG;AACH,eAAO,MAAM,aAAa,SAKE,CAAC"}
@@ -0,0 +1,174 @@
1
+ import { Command } from 'commander';
2
+ import ora from 'ora';
3
+ import Table from 'cli-table3';
4
+ import chalk from 'chalk';
5
+ import { CastariClient } from '@castari/sdk';
6
+ import { hint, keyValue, blank, formatDate, info } from '../utils/output.js';
7
+ import { handleError } from '../utils/errors.js';
8
+ /**
9
+ * Format agent status with color
10
+ */
11
+ function formatStatus(status) {
12
+ switch (status) {
13
+ case 'active':
14
+ return chalk.green(status);
15
+ case 'deploying':
16
+ return chalk.yellow(status);
17
+ case 'pending':
18
+ return chalk.blue(status);
19
+ case 'stopped':
20
+ return chalk.gray(status);
21
+ case 'failed':
22
+ return chalk.red(status);
23
+ default:
24
+ return status;
25
+ }
26
+ }
27
+ /**
28
+ * cast agents list
29
+ */
30
+ const listCommand = new Command('list')
31
+ .description('List all agents')
32
+ .action(async () => {
33
+ const spinner = ora('Fetching agents...').start();
34
+ try {
35
+ const client = new CastariClient();
36
+ await client.ensureAuthenticated();
37
+ const agents = await client.agents.list();
38
+ spinner.stop();
39
+ if (agents.length === 0) {
40
+ info('No agents found');
41
+ hint("Create one with 'cast agents create <name> <git-url>'");
42
+ return;
43
+ }
44
+ const table = new Table({
45
+ head: [
46
+ chalk.white('Slug'),
47
+ chalk.white('Name'),
48
+ chalk.white('Status'),
49
+ chalk.white('Created'),
50
+ ],
51
+ style: {
52
+ head: [],
53
+ border: [],
54
+ },
55
+ });
56
+ for (const agent of agents) {
57
+ table.push([
58
+ agent.slug,
59
+ agent.name,
60
+ formatStatus(agent.status),
61
+ formatDate(agent.created_at),
62
+ ]);
63
+ }
64
+ console.log(table.toString());
65
+ }
66
+ catch (err) {
67
+ spinner.fail('Failed to list agents');
68
+ handleError(err);
69
+ }
70
+ });
71
+ /**
72
+ * cast agents create <name> <git-url>
73
+ */
74
+ const createCommand = new Command('create')
75
+ .description('Create a new agent')
76
+ .argument('<name>', 'Agent name')
77
+ .argument('<git-url>', 'Git repository URL')
78
+ .option('--slug <slug>', 'Custom slug (default: auto-generated from name)')
79
+ .action(async (name, gitUrl, options) => {
80
+ const spinner = ora('Creating agent...').start();
81
+ try {
82
+ const client = new CastariClient();
83
+ await client.ensureAuthenticated();
84
+ const agent = await client.agents.create({
85
+ name,
86
+ gitRepoUrl: gitUrl,
87
+ slug: options.slug,
88
+ });
89
+ spinner.succeed(`Agent '${agent.name}' created!`);
90
+ blank();
91
+ keyValue('Slug', agent.slug);
92
+ keyValue('Git URL', agent.git_repo_url);
93
+ keyValue('Status', agent.status);
94
+ blank();
95
+ hint(`Deploy with: cast deploy ${agent.slug}`);
96
+ }
97
+ catch (err) {
98
+ spinner.fail('Failed to create agent');
99
+ handleError(err);
100
+ }
101
+ });
102
+ /**
103
+ * cast agents get <slug>
104
+ */
105
+ const getCommand = new Command('get')
106
+ .description('Get agent details')
107
+ .argument('<slug>', 'Agent slug')
108
+ .action(async (slug) => {
109
+ const spinner = ora('Fetching agent...').start();
110
+ try {
111
+ const client = new CastariClient();
112
+ await client.ensureAuthenticated();
113
+ const agent = await client.agents.get(slug);
114
+ spinner.stop();
115
+ blank();
116
+ keyValue('Name', agent.name);
117
+ keyValue('Slug', agent.slug);
118
+ keyValue('Git URL', agent.git_repo_url);
119
+ keyValue('Status', formatStatus(agent.status));
120
+ keyValue('Sandbox ID', agent.sandbox_id ?? undefined);
121
+ keyValue('Created', formatDate(agent.created_at));
122
+ keyValue('Updated', formatDate(agent.updated_at));
123
+ blank();
124
+ }
125
+ catch (err) {
126
+ spinner.fail('Failed to get agent');
127
+ handleError(err);
128
+ }
129
+ });
130
+ /**
131
+ * cast agents delete <slug>
132
+ */
133
+ const deleteCommand = new Command('delete')
134
+ .description('Delete an agent')
135
+ .argument('<slug>', 'Agent slug')
136
+ .option('-f, --force', 'Skip confirmation')
137
+ .action(async (slug, options) => {
138
+ try {
139
+ const client = new CastariClient();
140
+ await client.ensureAuthenticated();
141
+ // Confirm deletion unless --force is used
142
+ if (!options.force) {
143
+ const readline = await import('node:readline');
144
+ const rl = readline.createInterface({
145
+ input: process.stdin,
146
+ output: process.stdout,
147
+ });
148
+ const answer = await new Promise((resolve) => {
149
+ rl.question(chalk.yellow(`Are you sure you want to delete agent '${slug}'? [y/N] `), resolve);
150
+ });
151
+ rl.close();
152
+ if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
153
+ info('Deletion cancelled');
154
+ return;
155
+ }
156
+ }
157
+ const spinner = ora('Deleting agent...').start();
158
+ await client.agents.delete(slug);
159
+ spinner.succeed(`Agent '${slug}' deleted`);
160
+ }
161
+ catch (err) {
162
+ handleError(err);
163
+ }
164
+ });
165
+ /**
166
+ * cast agents
167
+ */
168
+ export const agentsCommand = new Command('agents')
169
+ .description('Manage agents')
170
+ .addCommand(listCommand)
171
+ .addCommand(createCommand)
172
+ .addCommand(getCommand)
173
+ .addCommand(deleteCommand);
174
+ //# sourceMappingURL=agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents.js","sourceRoot":"","sources":["../../src/commands/agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * cast apikey
4
+ */
5
+ export declare const apikeyCommand: Command;
6
+ //# sourceMappingURL=apikey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apikey.d.ts","sourceRoot":"","sources":["../../src/commands/apikey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsDpC;;GAEG;AACH,eAAO,MAAM,aAAa,SAGE,CAAC"}
@@ -0,0 +1,57 @@
1
+ import { Command } from 'commander';
2
+ import ora from 'ora';
3
+ import chalk from 'chalk';
4
+ import { CastariClient } from '@castari/sdk';
5
+ import { info, blank, keyValue } from '../utils/output.js';
6
+ import { handleError } from '../utils/errors.js';
7
+ /**
8
+ * cast apikey create
9
+ */
10
+ const createCommand = new Command('create')
11
+ .description('Create a new API key (only one per user)')
12
+ .action(async () => {
13
+ const spinner = ora('Creating API key...').start();
14
+ try {
15
+ const client = new CastariClient();
16
+ await client.ensureAuthenticated();
17
+ const result = await client.auth.createApiKey();
18
+ spinner.succeed('API key created!');
19
+ blank();
20
+ console.log(chalk.yellow('⚠ Save this key - it will only be shown once!'));
21
+ blank();
22
+ keyValue('API Key', chalk.green(result.api_key));
23
+ keyValue('Prefix', result.prefix);
24
+ blank();
25
+ info('Use with: CASTARI_API_KEY=<key> cast <command>');
26
+ }
27
+ catch (err) {
28
+ spinner.fail('Failed to create API key');
29
+ handleError(err);
30
+ }
31
+ });
32
+ /**
33
+ * cast apikey revoke
34
+ */
35
+ const revokeCommand = new Command('revoke')
36
+ .description('Revoke your API key')
37
+ .action(async () => {
38
+ const spinner = ora('Revoking API key...').start();
39
+ try {
40
+ const client = new CastariClient();
41
+ await client.ensureAuthenticated();
42
+ await client.auth.revokeApiKey();
43
+ spinner.succeed('API key revoked');
44
+ }
45
+ catch (err) {
46
+ spinner.fail('Failed to revoke API key');
47
+ handleError(err);
48
+ }
49
+ });
50
+ /**
51
+ * cast apikey
52
+ */
53
+ export const apikeyCommand = new Command('apikey')
54
+ .description('Manage API keys')
55
+ .addCommand(createCommand)
56
+ .addCommand(revokeCommand);
57
+ //# sourceMappingURL=apikey.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apikey.js","sourceRoot":"","sources":["../../src/commands/apikey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAW,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD;;GAEG;AACH,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KACxC,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,OAAO,GAAG,GAAG,CAAC,qBAAqB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEnD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QAEhD,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACpC,KAAK,EAAE,CAAC;QACR,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,+CAA+C,CAAC,CAAC,CAAC;QAC3E,KAAK,EAAE,CAAC;QACR,QAAQ,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAClC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,gDAAgD,CAAC,CAAC;IACzD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACzC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL;;GAEG;AACH,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KACxC,WAAW,CAAC,qBAAqB,CAAC;KAClC,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,OAAO,GAAG,GAAG,CAAC,qBAAqB,CAAC,CAAC,KAAK,EAAE,CAAC;IAEnD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;QACnC,MAAM,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QAEjC,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACzC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,iBAAiB,CAAC;KAC9B,UAAU,CAAC,aAAa,CAAC;KACzB,UAAU,CAAC,aAAa,CAAC,CAAC"}
@@ -1,3 +1,3 @@
1
- export declare function deploy(options: {
2
- snapshot?: string;
3
- }): Promise<void>;
1
+ import { Command } from 'commander';
2
+ export declare const deployCommand: Command;
3
+ //# sourceMappingURL=deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAOpC,eAAO,MAAM,aAAa,SAuBtB,CAAC"}
@@ -1,69 +1,29 @@
1
- import { readFile } from 'fs/promises';
1
+ import { Command } from 'commander';
2
+ import ora from 'ora';
2
3
  import chalk from 'chalk';
3
- import AdmZip from 'adm-zip';
4
- import { getClientAuthOrExit } from '../utils/client-auth';
5
- export async function deploy(options) {
6
- const { clientId, apiKey } = await getClientAuthOrExit();
7
- // Read package.json to get default snapshot name
8
- let snapshotName = options.snapshot;
9
- if (!snapshotName) {
10
- try {
11
- const pkg = JSON.parse(await readFile('package.json', 'utf-8'));
12
- snapshotName = pkg.name;
13
- }
14
- catch (e) {
15
- console.warn(chalk.yellow('Warning: Could not read package.json. Using default name.'));
16
- snapshotName = 'castari-agent';
17
- }
18
- }
19
- if (!snapshotName) {
20
- console.error(chalk.red('Error: Snapshot name is required (via --snapshot or package.json name).'));
21
- process.exit(1);
22
- }
23
- console.log(chalk.blue(`📦 Packaging source code...`));
24
- const zip = new AdmZip();
25
- const projectRoot = process.cwd();
26
- // Add local files, respecting a simple ignore list for now
27
- // Ideally we'd parse .gitignore, but for MVP let's just ignore common heavy folders
28
- const ignoreList = ['node_modules', '.git', 'dist', '.env'];
29
- zip.addLocalFolder(projectRoot, undefined, (filename) => {
30
- // Simple filter: return false to exclude
31
- // filename is the relative path in the zip? No, it seems to be the absolute path or filename.
32
- // AdmZip filter is a bit tricky. Let's assume it passes the name.
33
- // Actually addLocalFolder filter takes a RegExp or function.
34
- // If function: (filename: string) => boolean.
35
- // Note: filename passed to filter is usually the relative path.
36
- // Let's try to be safe and just add everything except node_modules at the root.
37
- // Actually, addLocalFolder adds everything.
38
- // We might want to use addLocalFile loop or similar if we want strict control.
39
- // But let's try the filter.
40
- return !ignoreList.some(ignore => filename.includes(ignore));
41
- });
42
- const zipBuffer = zip.toBuffer();
43
- console.log(chalk.blue(`🚀 Uploading to Castari Platform...`));
44
- const platformUrl = process.env.CASTARI_PLATFORM_URL || 'https://castari-api-12511-04c55b73-g4p2s9om.onporter.run';
45
- const formData = new FormData();
46
- formData.append('file', new Blob([zipBuffer]), 'source.zip');
47
- formData.append('snapshot', snapshotName);
48
- formData.append('clientId', clientId);
4
+ import { CastariClient } from '@castari/sdk';
5
+ import { keyValue, blank, hint } from '../utils/output.js';
6
+ import { handleError } from '../utils/errors.js';
7
+ export const deployCommand = new Command('deploy')
8
+ .description('Deploy an agent')
9
+ .argument('<slug>', 'Agent slug')
10
+ .action(async (slug) => {
11
+ const spinner = ora(`Deploying ${slug}...`).start();
49
12
  try {
50
- const headers = {};
51
- if (apiKey)
52
- headers['Authorization'] = `Bearer ${apiKey}`;
53
- const response = await fetch(`${platformUrl}/deploy`, {
54
- method: 'POST',
55
- body: formData,
56
- headers,
57
- });
58
- if (!response.ok) {
59
- const errorText = await response.text();
60
- throw new Error(`Platform error (${response.status}): ${errorText}`);
61
- }
62
- const result = await response.json();
63
- console.log(chalk.green(`✅ Snapshot "${result.snapshot}" created successfully for client ${clientId}`));
13
+ const client = new CastariClient();
14
+ await client.ensureAuthenticated();
15
+ spinner.text = `Deploying ${slug}... (this may take a minute)`;
16
+ const agent = await client.agents.deploy(slug);
17
+ spinner.succeed(`Agent '${slug}' deployed!`);
18
+ blank();
19
+ keyValue('Status', chalk.green(agent.status));
20
+ keyValue('Sandbox ID', agent.sandbox_id ?? undefined);
21
+ blank();
22
+ hint(`Invoke with: cast invoke ${slug} "your prompt here"`);
64
23
  }
65
24
  catch (err) {
66
- console.error(chalk.red('Deploy failed:'), err.message || err);
67
- process.exit(1);
25
+ spinner.fail('Deployment failed');
26
+ handleError(err);
68
27
  }
69
- }
28
+ });
29
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAW,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,iBAAiB,CAAC;KAC9B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;KAChC,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;IAC7B,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,IAAI,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAEnC,OAAO,CAAC,IAAI,GAAG,aAAa,IAAI,8BAA8B,CAAC;QAC/D,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAE/C,OAAO,CAAC,OAAO,CAAC,UAAU,IAAI,aAAa,CAAC,CAAC;QAC7C,KAAK,EAAE,CAAC;QACR,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,UAAU,IAAI,SAAS,CAAC,CAAC;QACtD,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,4BAA4B,IAAI,qBAAqB,CAAC,CAAC;IAC9D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare const invokeCommand: Command;
3
+ //# sourceMappingURL=invoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/commands/invoke.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,eAAO,MAAM,aAAa,SAiDtB,CAAC"}