agent-army 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +162 -0
- package/dist/adapters/api-adapter.d.ts +76 -0
- package/dist/adapters/api-adapter.js +251 -0
- package/dist/adapters/api-adapter.js.map +1 -0
- package/dist/adapters/cli-adapter.d.ts +15 -0
- package/dist/adapters/cli-adapter.js +207 -0
- package/dist/adapters/cli-adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +22 -0
- package/dist/adapters/index.js +32 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/types.d.ts +135 -0
- package/dist/adapters/types.js +14 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/bin.d.ts +8 -0
- package/dist/bin.js +83 -0
- package/dist/bin.js.map +1 -0
- package/dist/commands/deploy.d.ts +7 -0
- package/dist/commands/deploy.js +13 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/destroy.d.ts +7 -0
- package/dist/commands/destroy.js +13 -0
- package/dist/commands/destroy.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +538 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +8 -0
- package/dist/commands/list.js +42 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/ssh.d.ts +9 -0
- package/dist/commands/ssh.js +101 -0
- package/dist/commands/ssh.js.map +1 -0
- package/dist/commands/status.d.ts +7 -0
- package/dist/commands/status.js +13 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/validate.d.ts +7 -0
- package/dist/commands/validate.js +13 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/lib/config.d.ts +66 -0
- package/dist/lib/config.js +239 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +147 -0
- package/dist/lib/constants.js +307 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/exec.d.ts +22 -0
- package/dist/lib/exec.js +60 -0
- package/dist/lib/exec.js.map +1 -0
- package/dist/lib/prerequisites.d.ts +8 -0
- package/dist/lib/prerequisites.js +124 -0
- package/dist/lib/prerequisites.js.map +1 -0
- package/dist/lib/process.d.ts +18 -0
- package/dist/lib/process.js +37 -0
- package/dist/lib/process.js.map +1 -0
- package/dist/lib/pulumi.d.ts +39 -0
- package/dist/lib/pulumi.js +87 -0
- package/dist/lib/pulumi.js.map +1 -0
- package/dist/lib/tailscale.d.ts +24 -0
- package/dist/lib/tailscale.js +71 -0
- package/dist/lib/tailscale.js.map +1 -0
- package/dist/lib/ui.d.ts +27 -0
- package/dist/lib/ui.js +89 -0
- package/dist/lib/ui.js.map +1 -0
- package/dist/tools/deploy.d.ts +16 -0
- package/dist/tools/deploy.js +133 -0
- package/dist/tools/deploy.js.map +1 -0
- package/dist/tools/destroy.d.ts +16 -0
- package/dist/tools/destroy.js +186 -0
- package/dist/tools/destroy.js.map +1 -0
- package/dist/tools/index.d.ts +17 -0
- package/dist/tools/index.js +28 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/status.d.ts +16 -0
- package/dist/tools/status.js +213 -0
- package/dist/tools/status.js.map +1 -0
- package/dist/tools/validate.d.ts +16 -0
- package/dist/tools/validate.js +215 -0
- package/dist/tools/validate.js.map +1 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Agent Army CLI
|
|
2
|
+
|
|
3
|
+
Interactive command-line tool for deploying and managing your fleet of [OpenClaw](https://openclaw.bot/) AI agents on AWS.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Global install
|
|
9
|
+
npm install -g @agent-army/cli
|
|
10
|
+
|
|
11
|
+
# Or run directly
|
|
12
|
+
npx @agent-army/cli init
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Commands
|
|
16
|
+
|
|
17
|
+
### `agent-army init`
|
|
18
|
+
|
|
19
|
+
Interactive setup wizard that walks you through the full configuration:
|
|
20
|
+
|
|
21
|
+
1. **Prerequisites check** — verifies Pulumi CLI, Node.js, AWS CLI, and Tailscale are installed
|
|
22
|
+
2. **Stack configuration** — stack name, AWS region, instance type, owner name
|
|
23
|
+
3. **Secrets** — Anthropic API key, Tailscale auth key, tailnet DNS name (with inline instructions for obtaining each)
|
|
24
|
+
4. **Agent selection** — choose from presets, define custom agents, or mix both
|
|
25
|
+
5. **Summary & confirmation** — review config and estimated cost before proceeding
|
|
26
|
+
|
|
27
|
+
Outputs an `agent-army.json` manifest and sets all Pulumi config values.
|
|
28
|
+
|
|
29
|
+
### `agent-army deploy`
|
|
30
|
+
|
|
31
|
+
Deploy your agents with `pulumi up`. Runs prerequisite checks before deploying.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
agent-army deploy # Deploy with confirmation prompt
|
|
35
|
+
agent-army deploy -y # Skip confirmation
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### `agent-army status`
|
|
39
|
+
|
|
40
|
+
Show agent statuses from Pulumi stack outputs.
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
agent-army status # Pretty-printed output
|
|
44
|
+
agent-army status --json # JSON output
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### `agent-army ssh <agent>`
|
|
48
|
+
|
|
49
|
+
SSH to an agent by name, role, or alias. Resolves agents flexibly — all of these work:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
agent-army ssh sage # By alias
|
|
53
|
+
agent-army ssh pm # By role
|
|
54
|
+
agent-army ssh agent-pm # By resource name
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Run a command on the agent instead of opening an interactive session:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
agent-army ssh sage 'openclaw gateway status'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Options:
|
|
64
|
+
|
|
65
|
+
| Flag | Description |
|
|
66
|
+
|------|-------------|
|
|
67
|
+
| `-u, --user <user>` | SSH user (default: `ubuntu`) |
|
|
68
|
+
|
|
69
|
+
### `agent-army validate`
|
|
70
|
+
|
|
71
|
+
Health check all agents via Tailscale SSH.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
agent-army validate
|
|
75
|
+
agent-army validate -t 60 # 60-second timeout
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### `agent-army destroy`
|
|
79
|
+
|
|
80
|
+
Tear down all resources with safety confirmations.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
agent-army destroy # With confirmation prompts
|
|
84
|
+
agent-army destroy -y # Skip confirmations (dangerous!)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Preset Agents
|
|
88
|
+
|
|
89
|
+
The CLI ships with three preset agent configurations:
|
|
90
|
+
|
|
91
|
+
| Alias | Role | Name | Description |
|
|
92
|
+
|-------|------|------|-------------|
|
|
93
|
+
| **Juno** | PM | `agent-pm` | Break down tickets, research, plan and sequence work, track progress, unblock teams |
|
|
94
|
+
| **Titus** | Engineer | `agent-eng` | Lead engineering, coding, shipping |
|
|
95
|
+
| **Scout** | Tester | `agent-tester` | Quality assurance, verification, bug hunting |
|
|
96
|
+
|
|
97
|
+
You can also define fully custom agents during `init`.
|
|
98
|
+
|
|
99
|
+
## Configuration
|
|
100
|
+
|
|
101
|
+
### `agent-army.json`
|
|
102
|
+
|
|
103
|
+
The `init` command generates an `agent-army.json` manifest in the project root:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"stackName": "dev",
|
|
108
|
+
"region": "us-east-1",
|
|
109
|
+
"instanceType": "t3.medium",
|
|
110
|
+
"ownerName": "Boss",
|
|
111
|
+
"agents": [
|
|
112
|
+
{
|
|
113
|
+
"name": "agent-pm",
|
|
114
|
+
"displayName": "Juno",
|
|
115
|
+
"role": "pm",
|
|
116
|
+
"preset": "pm",
|
|
117
|
+
"volumeSize": 30
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
This manifest is read by the Pulumi program at deploy time to dynamically create the agent stack.
|
|
124
|
+
|
|
125
|
+
### Pulumi Config
|
|
126
|
+
|
|
127
|
+
Secrets and stack configuration are stored in Pulumi config (encrypted). The `init` command sets these automatically:
|
|
128
|
+
|
|
129
|
+
- `anthropicApiKey` (secret)
|
|
130
|
+
- `tailscaleAuthKey` (secret)
|
|
131
|
+
- `tailnetDnsName`
|
|
132
|
+
- `aws:region`
|
|
133
|
+
- `instanceType`
|
|
134
|
+
- `ownerName`
|
|
135
|
+
|
|
136
|
+
## Project Structure
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
cli/
|
|
140
|
+
├── bin.ts # Entry point (Commander.js program)
|
|
141
|
+
├── types.ts # TypeScript type definitions
|
|
142
|
+
├── commands/
|
|
143
|
+
│ ├── init.ts # Interactive setup wizard
|
|
144
|
+
│ ├── deploy.ts # Deploy agents
|
|
145
|
+
│ ├── status.ts # Show agent statuses
|
|
146
|
+
│ ├── ssh.ts # SSH to agents
|
|
147
|
+
│ ├── validate.ts # Health check agents
|
|
148
|
+
│ └── destroy.ts # Tear down resources
|
|
149
|
+
└── lib/
|
|
150
|
+
├── config.ts # Load/save agent-army.json manifest
|
|
151
|
+
├── constants.ts # Presets, aliases, regions, instance types
|
|
152
|
+
├── exec.ts # Shell command execution
|
|
153
|
+
├── prerequisites.ts # Prerequisite checks
|
|
154
|
+
├── pulumi.ts # Pulumi stack & config operations
|
|
155
|
+
└── ui.ts # UI helpers (banners, spinners, formatting)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Dependencies
|
|
159
|
+
|
|
160
|
+
- [Commander.js](https://github.com/tj/commander.js) — CLI argument parsing
|
|
161
|
+
- [@clack/prompts](https://github.com/natemoo-re/clack) — Interactive terminal prompts
|
|
162
|
+
- [picocolors](https://github.com/alexeyraspopov/picocolors) — Terminal colors
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Runtime Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implements RuntimeAdapter for HTTP API usage.
|
|
5
|
+
* Instead of interactive prompts, collects inputs from a request body
|
|
6
|
+
* and accumulates responses as structured JSON.
|
|
7
|
+
*/
|
|
8
|
+
import type { RuntimeAdapter } from "./types";
|
|
9
|
+
/** A field descriptor returned instead of prompting */
|
|
10
|
+
export interface FieldDescriptor {
|
|
11
|
+
type: "text" | "confirm" | "select" | "multiSelect";
|
|
12
|
+
name: string;
|
|
13
|
+
message: string;
|
|
14
|
+
placeholder?: string;
|
|
15
|
+
defaultValue?: unknown;
|
|
16
|
+
options?: Array<{
|
|
17
|
+
value: unknown;
|
|
18
|
+
label: string;
|
|
19
|
+
hint?: string;
|
|
20
|
+
}>;
|
|
21
|
+
required?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** A log entry accumulated during execution */
|
|
24
|
+
export interface LogEntry {
|
|
25
|
+
level: "info" | "step" | "success" | "warn" | "error";
|
|
26
|
+
message: string;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
}
|
|
29
|
+
/** Accumulated API response */
|
|
30
|
+
export interface APIResponse {
|
|
31
|
+
/** Fields that need user input (wizard mode) */
|
|
32
|
+
fields: FieldDescriptor[];
|
|
33
|
+
/** Log messages accumulated during execution */
|
|
34
|
+
logs: LogEntry[];
|
|
35
|
+
/** Notes/messages shown to the user */
|
|
36
|
+
messages: Array<{
|
|
37
|
+
type: "intro" | "note" | "outro" | "cancel";
|
|
38
|
+
content: string;
|
|
39
|
+
title?: string;
|
|
40
|
+
}>;
|
|
41
|
+
/** Whether the operation completed or needs more input */
|
|
42
|
+
status: "needsInput" | "complete" | "cancelled" | "error";
|
|
43
|
+
}
|
|
44
|
+
/** Thrown when the adapter needs more input from the client */
|
|
45
|
+
export declare class APIAdapterNeedsInputError extends Error {
|
|
46
|
+
fieldName: string;
|
|
47
|
+
constructor(fieldName: string);
|
|
48
|
+
}
|
|
49
|
+
/** Thrown when validation fails on a provided input */
|
|
50
|
+
export declare class APIAdapterValidationError extends Error {
|
|
51
|
+
fieldName: string;
|
|
52
|
+
validationMessage: string;
|
|
53
|
+
constructor(fieldName: string, validationMessage: string);
|
|
54
|
+
}
|
|
55
|
+
/** Thrown when the operation is cancelled */
|
|
56
|
+
export declare class APIAdapterCancelError extends Error {
|
|
57
|
+
constructor(message: string);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Create an API runtime adapter for HTTP request handling.
|
|
61
|
+
*
|
|
62
|
+
* @param inputs - Key-value pairs from the request body providing answers to wizard fields
|
|
63
|
+
* @returns A tuple of [RuntimeAdapter, APIResponse] — use the response to send back to the client
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const [adapter, response] = createAPIAdapter({ field_0: "my-project", field_1: "aws" });
|
|
67
|
+
* try {
|
|
68
|
+
* await initTool(adapter, {});
|
|
69
|
+
* } catch (e) {
|
|
70
|
+
* if (e instanceof APIAdapterNeedsInputError) {
|
|
71
|
+
* // Return response.fields to client for more input
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* res.json(response);
|
|
75
|
+
*/
|
|
76
|
+
export declare function createAPIAdapter(inputs?: Record<string, unknown>): [RuntimeAdapter, APIResponse];
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* API Runtime Adapter
|
|
4
|
+
*
|
|
5
|
+
* Implements RuntimeAdapter for HTTP API usage.
|
|
6
|
+
* Instead of interactive prompts, collects inputs from a request body
|
|
7
|
+
* and accumulates responses as structured JSON.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.APIAdapterCancelError = exports.APIAdapterValidationError = exports.APIAdapterNeedsInputError = void 0;
|
|
11
|
+
exports.createAPIAdapter = createAPIAdapter;
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Execution Adapter Implementation
|
|
14
|
+
// ============================================================================
|
|
15
|
+
class APIExecAdapter {
|
|
16
|
+
capture(command, args = [], cwd) {
|
|
17
|
+
const { execFileSync } = require("child_process");
|
|
18
|
+
try {
|
|
19
|
+
const result = execFileSync(command, args, {
|
|
20
|
+
cwd,
|
|
21
|
+
encoding: "utf-8",
|
|
22
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
23
|
+
});
|
|
24
|
+
return { stdout: result.trim(), stderr: "", exitCode: 0 };
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
const e = err;
|
|
28
|
+
return {
|
|
29
|
+
stdout: (e.stdout ?? "").toString().trim(),
|
|
30
|
+
stderr: (e.stderr ?? "").toString().trim(),
|
|
31
|
+
exitCode: e.status ?? 1,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async stream(command, args = [], options) {
|
|
36
|
+
// In API context, always capture output
|
|
37
|
+
const result = this.capture(command, args, options?.cwd);
|
|
38
|
+
return result.exitCode;
|
|
39
|
+
}
|
|
40
|
+
commandExists(command) {
|
|
41
|
+
const { spawnSync } = require("child_process");
|
|
42
|
+
const bin = process.platform === "win32" ? "where" : "which";
|
|
43
|
+
const result = spawnSync(bin, [command], { shell: false, stdio: "ignore" });
|
|
44
|
+
return result.status === 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// UI Adapter Implementation
|
|
49
|
+
// ============================================================================
|
|
50
|
+
class APIUIAdapter {
|
|
51
|
+
response;
|
|
52
|
+
inputs;
|
|
53
|
+
fieldIndex = 0;
|
|
54
|
+
constructor(inputs, response) {
|
|
55
|
+
this.inputs = inputs;
|
|
56
|
+
this.response = response;
|
|
57
|
+
}
|
|
58
|
+
intro(message) {
|
|
59
|
+
this.response.messages.push({ type: "intro", content: message });
|
|
60
|
+
}
|
|
61
|
+
note(content, title) {
|
|
62
|
+
this.response.messages.push({ type: "note", content, title });
|
|
63
|
+
}
|
|
64
|
+
outro(message) {
|
|
65
|
+
this.response.messages.push({ type: "outro", content: message });
|
|
66
|
+
this.response.status = "complete";
|
|
67
|
+
}
|
|
68
|
+
cancel(message) {
|
|
69
|
+
this.response.messages.push({ type: "cancel", content: message });
|
|
70
|
+
this.response.status = "cancelled";
|
|
71
|
+
throw new APIAdapterCancelError(message);
|
|
72
|
+
}
|
|
73
|
+
log = {
|
|
74
|
+
info: (message) => {
|
|
75
|
+
this.response.logs.push({ level: "info", message, timestamp: Date.now() });
|
|
76
|
+
},
|
|
77
|
+
step: (message) => {
|
|
78
|
+
this.response.logs.push({ level: "step", message, timestamp: Date.now() });
|
|
79
|
+
},
|
|
80
|
+
success: (message) => {
|
|
81
|
+
this.response.logs.push({ level: "success", message, timestamp: Date.now() });
|
|
82
|
+
},
|
|
83
|
+
warn: (message) => {
|
|
84
|
+
this.response.logs.push({ level: "warn", message, timestamp: Date.now() });
|
|
85
|
+
},
|
|
86
|
+
error: (message) => {
|
|
87
|
+
this.response.logs.push({ level: "error", message, timestamp: Date.now() });
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
async text(options) {
|
|
91
|
+
const fieldName = `field_${this.fieldIndex++}`;
|
|
92
|
+
// Check if input was provided
|
|
93
|
+
if (fieldName in this.inputs || options.message in this.inputs) {
|
|
94
|
+
const key = fieldName in this.inputs ? fieldName : options.message;
|
|
95
|
+
const value = String(this.inputs[key]);
|
|
96
|
+
if (options.validate) {
|
|
97
|
+
const error = options.validate(value);
|
|
98
|
+
if (error) {
|
|
99
|
+
throw new APIAdapterValidationError(fieldName, error);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
// No input provided — add field descriptor for client
|
|
105
|
+
this.response.fields.push({
|
|
106
|
+
type: "text",
|
|
107
|
+
name: fieldName,
|
|
108
|
+
message: options.message,
|
|
109
|
+
placeholder: options.placeholder,
|
|
110
|
+
defaultValue: options.defaultValue,
|
|
111
|
+
});
|
|
112
|
+
this.response.status = "needsInput";
|
|
113
|
+
throw new APIAdapterNeedsInputError(fieldName);
|
|
114
|
+
}
|
|
115
|
+
async confirm(options) {
|
|
116
|
+
const fieldName = `field_${this.fieldIndex++}`;
|
|
117
|
+
if (fieldName in this.inputs || options.message in this.inputs) {
|
|
118
|
+
const key = fieldName in this.inputs ? fieldName : options.message;
|
|
119
|
+
return Boolean(this.inputs[key]);
|
|
120
|
+
}
|
|
121
|
+
this.response.fields.push({
|
|
122
|
+
type: "confirm",
|
|
123
|
+
name: fieldName,
|
|
124
|
+
message: options.message,
|
|
125
|
+
defaultValue: options.initialValue,
|
|
126
|
+
});
|
|
127
|
+
this.response.status = "needsInput";
|
|
128
|
+
throw new APIAdapterNeedsInputError(fieldName);
|
|
129
|
+
}
|
|
130
|
+
async select(options) {
|
|
131
|
+
const fieldName = `field_${this.fieldIndex++}`;
|
|
132
|
+
if (fieldName in this.inputs || options.message in this.inputs) {
|
|
133
|
+
const key = fieldName in this.inputs ? fieldName : options.message;
|
|
134
|
+
return this.inputs[key];
|
|
135
|
+
}
|
|
136
|
+
this.response.fields.push({
|
|
137
|
+
type: "select",
|
|
138
|
+
name: fieldName,
|
|
139
|
+
message: options.message,
|
|
140
|
+
options: options.options.map((o) => ({
|
|
141
|
+
value: o.value,
|
|
142
|
+
label: o.label,
|
|
143
|
+
hint: o.hint,
|
|
144
|
+
})),
|
|
145
|
+
defaultValue: options.initialValue,
|
|
146
|
+
});
|
|
147
|
+
this.response.status = "needsInput";
|
|
148
|
+
throw new APIAdapterNeedsInputError(fieldName);
|
|
149
|
+
}
|
|
150
|
+
async multiSelect(options) {
|
|
151
|
+
const fieldName = `field_${this.fieldIndex++}`;
|
|
152
|
+
if (fieldName in this.inputs || options.message in this.inputs) {
|
|
153
|
+
const key = fieldName in this.inputs ? fieldName : options.message;
|
|
154
|
+
const value = this.inputs[key];
|
|
155
|
+
return Array.isArray(value) ? value : [value];
|
|
156
|
+
}
|
|
157
|
+
this.response.fields.push({
|
|
158
|
+
type: "multiSelect",
|
|
159
|
+
name: fieldName,
|
|
160
|
+
message: options.message,
|
|
161
|
+
options: options.options.map((o) => ({
|
|
162
|
+
value: o.value,
|
|
163
|
+
label: o.label,
|
|
164
|
+
hint: o.hint,
|
|
165
|
+
})),
|
|
166
|
+
defaultValue: options.initialValues,
|
|
167
|
+
required: options.required,
|
|
168
|
+
});
|
|
169
|
+
this.response.status = "needsInput";
|
|
170
|
+
throw new APIAdapterNeedsInputError(fieldName);
|
|
171
|
+
}
|
|
172
|
+
spinner(message) {
|
|
173
|
+
this.response.logs.push({ level: "info", message: `[spinner] ${message}`, timestamp: Date.now() });
|
|
174
|
+
return {
|
|
175
|
+
stop(msg) {
|
|
176
|
+
// No-op in API mode
|
|
177
|
+
},
|
|
178
|
+
message(_msg) {
|
|
179
|
+
// No-op in API mode
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// ============================================================================
|
|
185
|
+
// Error Types
|
|
186
|
+
// ============================================================================
|
|
187
|
+
/** Thrown when the adapter needs more input from the client */
|
|
188
|
+
class APIAdapterNeedsInputError extends Error {
|
|
189
|
+
fieldName;
|
|
190
|
+
constructor(fieldName) {
|
|
191
|
+
super(`Input required for field: ${fieldName}`);
|
|
192
|
+
this.fieldName = fieldName;
|
|
193
|
+
this.name = "APIAdapterNeedsInputError";
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
exports.APIAdapterNeedsInputError = APIAdapterNeedsInputError;
|
|
197
|
+
/** Thrown when validation fails on a provided input */
|
|
198
|
+
class APIAdapterValidationError extends Error {
|
|
199
|
+
fieldName;
|
|
200
|
+
validationMessage;
|
|
201
|
+
constructor(fieldName, validationMessage) {
|
|
202
|
+
super(`Validation failed for ${fieldName}: ${validationMessage}`);
|
|
203
|
+
this.fieldName = fieldName;
|
|
204
|
+
this.validationMessage = validationMessage;
|
|
205
|
+
this.name = "APIAdapterValidationError";
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
exports.APIAdapterValidationError = APIAdapterValidationError;
|
|
209
|
+
/** Thrown when the operation is cancelled */
|
|
210
|
+
class APIAdapterCancelError extends Error {
|
|
211
|
+
constructor(message) {
|
|
212
|
+
super(message);
|
|
213
|
+
this.name = "APIAdapterCancelError";
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
exports.APIAdapterCancelError = APIAdapterCancelError;
|
|
217
|
+
// ============================================================================
|
|
218
|
+
// Runtime Adapter
|
|
219
|
+
// ============================================================================
|
|
220
|
+
/**
|
|
221
|
+
* Create an API runtime adapter for HTTP request handling.
|
|
222
|
+
*
|
|
223
|
+
* @param inputs - Key-value pairs from the request body providing answers to wizard fields
|
|
224
|
+
* @returns A tuple of [RuntimeAdapter, APIResponse] — use the response to send back to the client
|
|
225
|
+
*
|
|
226
|
+
* @example
|
|
227
|
+
* const [adapter, response] = createAPIAdapter({ field_0: "my-project", field_1: "aws" });
|
|
228
|
+
* try {
|
|
229
|
+
* await initTool(adapter, {});
|
|
230
|
+
* } catch (e) {
|
|
231
|
+
* if (e instanceof APIAdapterNeedsInputError) {
|
|
232
|
+
* // Return response.fields to client for more input
|
|
233
|
+
* }
|
|
234
|
+
* }
|
|
235
|
+
* res.json(response);
|
|
236
|
+
*/
|
|
237
|
+
function createAPIAdapter(inputs = {}) {
|
|
238
|
+
const response = {
|
|
239
|
+
fields: [],
|
|
240
|
+
logs: [],
|
|
241
|
+
messages: [],
|
|
242
|
+
status: "complete",
|
|
243
|
+
};
|
|
244
|
+
const adapter = {
|
|
245
|
+
ui: new APIUIAdapter(inputs, response),
|
|
246
|
+
exec: new APIExecAdapter(),
|
|
247
|
+
platform: "api",
|
|
248
|
+
};
|
|
249
|
+
return [adapter, response];
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=api-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-adapter.js","sourceRoot":"","sources":["../../adapters/api-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Runtime Adapter
|
|
3
|
+
*
|
|
4
|
+
* Implements RuntimeAdapter for interactive terminal usage
|
|
5
|
+
* using @clack/prompts for UI and child_process for execution.
|
|
6
|
+
*/
|
|
7
|
+
import type { RuntimeAdapter } from "./types";
|
|
8
|
+
/**
|
|
9
|
+
* Create a CLI runtime adapter for interactive terminal usage
|
|
10
|
+
*/
|
|
11
|
+
export declare function createCLIAdapter(): RuntimeAdapter;
|
|
12
|
+
/**
|
|
13
|
+
* Singleton CLI adapter instance for convenience
|
|
14
|
+
*/
|
|
15
|
+
export declare const cliAdapter: RuntimeAdapter;
|