apcore-cli 0.2.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/CHANGELOG.md +59 -0
- package/LICENSE +21 -0
- package/README.md +290 -0
- package/dist/bin/apcore-cli.d.ts +1 -0
- package/dist/bin/apcore-cli.js +197 -0
- package/dist/bin/apcore-cli.js.map +1 -0
- package/dist/src/index.d.ts +421 -0
- package/dist/src/index.js +1755 -0
- package/dist/src/index.js.map +1 -0
- package/package.json +54 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to apcore-cli (TypeScript SDK) will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.2.0] - 2026-03-18
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Core dispatch pipeline: `buildModuleCommand` now fully wires schema resolution, built-in options (`--input`, `--yes`, `--large-input`, `--format`, `--sandbox`), input collection, approval gate, sandbox execution, audit logging, and output formatting
|
|
12
|
+
- `LazyModuleGroup.getCommand` now calls `buildModuleCommand` instead of creating bare Commander commands
|
|
13
|
+
- `createCli` wired with program name resolution from `argv`, `--extensions-dir` and `--log-level` global options, and log level resolution from `APCORE_CLI_LOGGING_LEVEL` / `APCORE_LOGGING_LEVEL` env vars
|
|
14
|
+
- Commander `.exitOverride()` — custom exit code mapping via `exitCodeForError` is now active (previously dead code because Commander calls `process.exit()` internally)
|
|
15
|
+
- `src/logger.ts` — structured logger utility with `setLogLevel`, `getLogLevel`, `debug`, `info`, `warn`, `error` functions respecting `logging.level` config
|
|
16
|
+
- `setAuditLogger` / `getAuditLogger` — module-level audit logger getter/setter (ported from Python SDK)
|
|
17
|
+
- `tests/main.test.ts` — 14 new tests covering `createCli`, Commander exitOverride, `buildModuleCommand` action execution, and SIGINT handling
|
|
18
|
+
- `APCORE_CLI_LOGGING_LEVEL` env var support — CLI-specific log level that takes priority over `APCORE_LOGGING_LEVEL`; 3-tier precedence: `--log-level` flag > `APCORE_CLI_LOGGING_LEVEL` > `APCORE_LOGGING_LEVEL` > `WARNING`
|
|
19
|
+
- 181 tests total (up from 167)
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- `schemaToCommanderOptions` renamed to `schemaToCliOptions` — framework-agnostic name matching spec canonical form
|
|
23
|
+
- `AuditLogger` constructor parameter renamed from `logPath` to `path` — matches spec and Python SDK
|
|
24
|
+
- `ConfigResolver.DEFAULTS` keys normalized to snake_case: `cli.stdinBufferLimit` → `cli.stdin_buffer_limit`, `cli.autoApprove` → `cli.auto_approve` — matches spec and Python SDK
|
|
25
|
+
- `ConfigResolver.DEFAULTS` `logging.level` default changed from `"INFO"` to `"WARNING"` — matches updated spec
|
|
26
|
+
- `ConfigEncryptor.store` / `ConfigEncryptor.retrieve` now async — required by keytar dynamic import change
|
|
27
|
+
- `AuthProvider.getApiKey` / `AuthProvider.authenticateRequest` now async — propagated from ConfigEncryptor async change
|
|
28
|
+
- Version string read from `package.json` at runtime instead of hardcoded in 3 places
|
|
29
|
+
- `readStdin()` properly removes event listeners on completion/error — prevents listener accumulation
|
|
30
|
+
- Removed duplicate `resolveFormat` re-export from `main.ts` (index.ts already exports from output.ts)
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
- **Commander exit code mapping was dead code**: `program.parse()` calls `process.exit()` internally; added `.exitOverride()` so errors throw `CommanderError` and the catch block in `main()` can apply `exitCodeForError` mapping
|
|
34
|
+
- **`LazyModuleGroup.getCommand` bypassed `buildModuleCommand`**: was creating bare `new Command(cmdName)` instead of building a fully wired command with schema options and execution callback
|
|
35
|
+
- **`require('keytar')` in ESM module**: replaced with dynamic `await import('keytar')` via cached helper; keytar is an optional peer dependency (archived/deprecated)
|
|
36
|
+
- **README `--stdin json` flag**: corrected to `--input -`
|
|
37
|
+
- **README missing Features and API Overview sections**: added comprehensive sections
|
|
38
|
+
|
|
39
|
+
### Security
|
|
40
|
+
- `AuditLogger._hashInput`: uses `crypto.randomBytes(16)` per-invocation salt before SHA-256 hashing, preventing cross-invocation input correlation
|
|
41
|
+
- Added security comment on AES key derivation fallback (best-effort when OS keyring unavailable — key derived from hostname + username)
|
|
42
|
+
|
|
43
|
+
## [0.1.0] - 2026-03-17
|
|
44
|
+
|
|
45
|
+
### Added
|
|
46
|
+
- Core Dispatcher (FE-01): `LazyModuleGroup`, `buildModuleCommand`, `collectInput`, `validateModuleId`, `createCli`, `main`
|
|
47
|
+
- Schema Parser (FE-02): `schemaToCliOptions`, `mapType`, `extractHelp`, `reconvertEnumValues`
|
|
48
|
+
- Ref Resolver (FE-02): `resolveRefs` with `$ref`, `allOf`, `anyOf`, `oneOf` support, max depth 32
|
|
49
|
+
- Config Resolver (FE-07): `ConfigResolver` with 4-tier precedence (CLI > Env > File > Default), YAML config loading
|
|
50
|
+
- Approval Gate (FE-03): `checkApproval` with TTY detection, `--yes` bypass, `APCORE_CLI_AUTO_APPROVE` env var, 60s timeout
|
|
51
|
+
- Discovery (FE-04): `list` and `describe` commands with `--tag` AND-filtering and `--format json|table`
|
|
52
|
+
- Output Formatter (FE-08): `formatModuleList`, `formatModuleDetail`, `formatExecResult` with TTY-adaptive JSON/table rendering
|
|
53
|
+
- Security Manager (FE-05): `AuthProvider` (API key auth with keyring/AES), `ConfigEncryptor` (keyring + AES-256-GCM fallback), `AuditLogger` (JSON Lines with salted SHA-256), `Sandbox` (subprocess isolation)
|
|
54
|
+
- Shell Integration (FE-06): bash/zsh/fish completion generators, roff man page generator
|
|
55
|
+
- Error classes: `ApprovalTimeoutError`, `ApprovalDeniedError`, `AuthenticationError`, `ConfigDecryptionError`, `ModuleExecutionError`, `ModuleNotFoundError`, `SchemaValidationError`
|
|
56
|
+
- Exit code mapping: `EXIT_CODES` constant and `exitCodeForError` helper (0, 1, 2, 44, 45, 46, 47, 48, 77, 130)
|
|
57
|
+
- 167 tests (unit and integration)
|
|
58
|
+
- TypeScript strict mode with full type coverage
|
|
59
|
+
- Pre-commit hooks: `apdev-js check-chars`, `apdev-js check-imports`, `tsc --noEmit`
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AI Partner Up
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/aipartnerup/apcore-cli/main/apcore-cli-logo.svg" alt="apcore-cli logo" width="200"/>
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
# apcore-cli
|
|
6
|
+
|
|
7
|
+
Terminal adapter for apcore. Execute AI-Perceivable modules from the command line.
|
|
8
|
+
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
[](https://nodejs.org)
|
|
11
|
+
[]()
|
|
12
|
+
|
|
13
|
+
| | |
|
|
14
|
+
|---|---|
|
|
15
|
+
| **TypeScript SDK** | [github.com/aipartnerup/apcore-cli-typescript](https://github.com/aipartnerup/apcore-cli-typescript) |
|
|
16
|
+
| **Python SDK** | [github.com/aipartnerup/apcore-cli-python](https://github.com/aipartnerup/apcore-cli-python) |
|
|
17
|
+
| **Spec repo** | [github.com/aipartnerup/apcore-cli](https://github.com/aipartnerup/apcore-cli) |
|
|
18
|
+
| **apcore core** | [github.com/aipartnerup/apcore](https://github.com/aipartnerup/apcore) |
|
|
19
|
+
|
|
20
|
+
**apcore-cli** turns any [apcore](https://github.com/aipartnerup/apcore)-based project into a fully featured CLI tool — with **zero code changes** to your existing modules.
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
┌──────────────────┐
|
|
24
|
+
│ nestjs-apcore │ <- your existing apcore project (unchanged)
|
|
25
|
+
│ express-apcore │
|
|
26
|
+
│ ... │
|
|
27
|
+
└────────┬─────────┘
|
|
28
|
+
│ extensions directory
|
|
29
|
+
v
|
|
30
|
+
┌──────────────────┐
|
|
31
|
+
│ apcore-cli │ <- just install & point to extensions dir
|
|
32
|
+
└───┬──────────┬───┘
|
|
33
|
+
│ │
|
|
34
|
+
v v
|
|
35
|
+
Terminal Unix
|
|
36
|
+
Commands Pipes
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Design Philosophy
|
|
40
|
+
|
|
41
|
+
- **Zero intrusion** -- your apcore project needs no code changes, no imports, no dependencies on apcore-cli
|
|
42
|
+
- **Zero configuration** -- point to an extensions directory, everything is auto-discovered
|
|
43
|
+
- **Pure adapter** -- apcore-cli reads from the apcore Registry; it never modifies your modules
|
|
44
|
+
- **Unix-native** -- JSON output for pipes, rich tables for terminals, STDIN input, shell completions
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
pnpm add apcore-cli apcore-js
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Requires Node.js 18+ and `apcore-js >= 0.13.0`.
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
### Zero-code approach
|
|
57
|
+
|
|
58
|
+
If you already have an apcore-based project with an extensions directory:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Execute a module
|
|
62
|
+
apcore-cli --extensions-dir ./extensions math.add --a 42 --b 58
|
|
63
|
+
|
|
64
|
+
# Or set the env var once
|
|
65
|
+
export APCORE_EXTENSIONS_ROOT=./extensions
|
|
66
|
+
apcore-cli math.add --a 42 --b 58
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
All modules are auto-discovered. CLI flags are auto-generated from each module's JSON Schema.
|
|
70
|
+
|
|
71
|
+
### Programmatic approach (TypeScript API)
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { createCli } from "apcore-cli";
|
|
75
|
+
|
|
76
|
+
// Build the CLI from your registry
|
|
77
|
+
const cli = createCli("./extensions");
|
|
78
|
+
cli.parse(process.argv);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Or use the `LazyModuleGroup` directly with Commander:
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
import { LazyModuleGroup, buildModuleCommand } from "apcore-cli";
|
|
85
|
+
import { Registry, Executor } from "apcore-js";
|
|
86
|
+
|
|
87
|
+
const registry = new Registry("./extensions");
|
|
88
|
+
registry.discover();
|
|
89
|
+
const executor = new Executor(registry);
|
|
90
|
+
|
|
91
|
+
const group = new LazyModuleGroup(registry, executor);
|
|
92
|
+
const cmd = group.getCommand("math.add");
|
|
93
|
+
cmd?.parse(process.argv);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Integration with Existing Projects
|
|
97
|
+
|
|
98
|
+
### Typical apcore project structure
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
your-project/
|
|
102
|
+
├── extensions/ <- modules live here
|
|
103
|
+
│ ├── math/
|
|
104
|
+
│ │ └── add.ts
|
|
105
|
+
│ ├── text/
|
|
106
|
+
│ │ └── upper.ts
|
|
107
|
+
│ └── ...
|
|
108
|
+
├── your_app.ts <- your existing code (untouched)
|
|
109
|
+
└── ...
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Adding CLI support
|
|
113
|
+
|
|
114
|
+
No changes to your project. Just install and run:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pnpm add apcore-cli apcore-js
|
|
118
|
+
apcore-cli --extensions-dir ./extensions list
|
|
119
|
+
apcore-cli --extensions-dir ./extensions math.add --a 5 --b 10
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### STDIN piping (Unix pipes)
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Pipe JSON input
|
|
126
|
+
echo '{"a": 100, "b": 200}' | apcore-cli math.add --input -
|
|
127
|
+
# {"sum": 300}
|
|
128
|
+
|
|
129
|
+
# CLI flags override STDIN values
|
|
130
|
+
echo '{"a": 1, "b": 2}' | apcore-cli math.add --input - --a 999
|
|
131
|
+
# {"sum": 1001}
|
|
132
|
+
|
|
133
|
+
# Chain with other tools
|
|
134
|
+
apcore-cli sysutil.info | jq '.os, .hostname'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## CLI Reference
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
apcore-cli [OPTIONS] COMMAND [ARGS]
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Global Options
|
|
144
|
+
|
|
145
|
+
| Option | Default | Description |
|
|
146
|
+
|--------|---------|-------------|
|
|
147
|
+
| `--extensions-dir` | `./extensions` | Path to apcore extensions directory |
|
|
148
|
+
| `--log-level` | `WARNING` | Logging: `DEBUG`, `INFO`, `WARNING`, `ERROR` |
|
|
149
|
+
| `--version` | | Show version and exit |
|
|
150
|
+
| `--help` | | Show help and exit |
|
|
151
|
+
|
|
152
|
+
### Built-in Commands
|
|
153
|
+
|
|
154
|
+
| Command | Description |
|
|
155
|
+
|---------|-------------|
|
|
156
|
+
| `list` | List available modules with optional tag filtering |
|
|
157
|
+
| `describe <module_id>` | Show full module metadata and schemas |
|
|
158
|
+
| `exec <module_id>` | Internal routing alias for module execution |
|
|
159
|
+
| `completion <shell>` | Generate shell completion script (bash/zsh/fish) |
|
|
160
|
+
| `man <command>` | Generate man page in roff format |
|
|
161
|
+
|
|
162
|
+
### Module Execution Options
|
|
163
|
+
|
|
164
|
+
When executing a module (e.g. `apcore-cli math.add`), these built-in options are always available:
|
|
165
|
+
|
|
166
|
+
| Option | Description |
|
|
167
|
+
|--------|-------------|
|
|
168
|
+
| `--input -` | Read JSON input from STDIN |
|
|
169
|
+
| `--yes` / `-y` | Bypass approval prompts |
|
|
170
|
+
| `--large-input` | Allow STDIN input larger than 10MB |
|
|
171
|
+
| `--format` | Output format: `json` or `table` |
|
|
172
|
+
| `--sandbox` | Run module in subprocess sandbox |
|
|
173
|
+
|
|
174
|
+
Schema-generated flags (e.g. `--a`, `--b`) are added automatically from the module's `input_schema`.
|
|
175
|
+
|
|
176
|
+
### Exit Codes
|
|
177
|
+
|
|
178
|
+
| Code | Meaning |
|
|
179
|
+
|------|---------|
|
|
180
|
+
| `0` | Success |
|
|
181
|
+
| `1` | Module execution error |
|
|
182
|
+
| `2` | Invalid CLI input |
|
|
183
|
+
| `44` | Module not found / disabled / load error |
|
|
184
|
+
| `45` | Schema validation error |
|
|
185
|
+
| `46` | Approval denied or timed out |
|
|
186
|
+
| `47` | Configuration error |
|
|
187
|
+
| `48` | Schema circular reference |
|
|
188
|
+
| `77` | ACL denied |
|
|
189
|
+
| `130` | Execution cancelled (Ctrl+C) |
|
|
190
|
+
|
|
191
|
+
## Configuration
|
|
192
|
+
|
|
193
|
+
apcore-cli uses a 4-tier configuration precedence:
|
|
194
|
+
|
|
195
|
+
1. **CLI flag** (highest): `--extensions-dir ./custom`
|
|
196
|
+
2. **Environment variable**: `APCORE_EXTENSIONS_ROOT=./custom`
|
|
197
|
+
3. **Config file**: `apcore.yaml`
|
|
198
|
+
4. **Default** (lowest): `./extensions`
|
|
199
|
+
|
|
200
|
+
### Environment Variables
|
|
201
|
+
|
|
202
|
+
| Variable | Description | Default |
|
|
203
|
+
|----------|-------------|---------|
|
|
204
|
+
| `APCORE_EXTENSIONS_ROOT` | Path to extensions directory | `./extensions` |
|
|
205
|
+
| `APCORE_CLI_AUTO_APPROVE` | Set to `1` to bypass all approval prompts | *(unset)* |
|
|
206
|
+
| `APCORE_CLI_LOGGING_LEVEL` | CLI-specific log level (takes priority over `APCORE_LOGGING_LEVEL`) | `WARNING` |
|
|
207
|
+
| `APCORE_LOGGING_LEVEL` | Global apcore log level (fallback when `APCORE_CLI_LOGGING_LEVEL` is unset) | `WARNING` |
|
|
208
|
+
| `APCORE_AUTH_API_KEY` | API key for remote registry authentication | *(unset)* |
|
|
209
|
+
| `APCORE_CLI_SANDBOX` | Set to `1` to enable subprocess sandboxing | *(unset)* |
|
|
210
|
+
|
|
211
|
+
### Config File (`apcore.yaml`)
|
|
212
|
+
|
|
213
|
+
```yaml
|
|
214
|
+
extensions:
|
|
215
|
+
root: ./extensions
|
|
216
|
+
logging:
|
|
217
|
+
level: DEBUG
|
|
218
|
+
sandbox:
|
|
219
|
+
enabled: false
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Features
|
|
223
|
+
|
|
224
|
+
- **Auto-discovery** -- all modules in the extensions directory are found and exposed as CLI commands
|
|
225
|
+
- **Auto-generated flags** -- JSON Schema `input_schema` is converted to `--flag value` CLI options with type validation
|
|
226
|
+
- **Boolean flag pairs** -- `--verbose` / `--no-verbose` from `"type": "boolean"` schema properties
|
|
227
|
+
- **Enum choices** -- `"enum": ["json", "csv"]` becomes `--format json` with Commander validation
|
|
228
|
+
- **STDIN piping** -- `--input -` reads JSON from STDIN, CLI flags override for duplicate keys
|
|
229
|
+
- **TTY-adaptive output** -- rich tables for terminals, JSON for pipes (configurable via `--format`)
|
|
230
|
+
- **Approval gate** -- TTY-aware HITL prompts for modules with `requires_approval: true`, with `--yes` bypass and 60s timeout
|
|
231
|
+
- **Schema validation** -- inputs validated against JSON Schema before execution, with `$ref`/`allOf`/`anyOf`/`oneOf` resolution
|
|
232
|
+
- **Security** -- API key auth (keyring + AES-256-GCM), append-only audit logging, subprocess sandboxing
|
|
233
|
+
- **Shell completions** -- `apcore-cli completion bash|zsh|fish` generates completion scripts with dynamic module ID completion
|
|
234
|
+
- **Man pages** -- `apcore-cli man <command>` generates roff-formatted man pages
|
|
235
|
+
- **Audit logging** -- all executions logged to `~/.apcore-cli/audit.jsonl` with SHA-256 input hashing
|
|
236
|
+
|
|
237
|
+
## How It Works
|
|
238
|
+
|
|
239
|
+
### Mapping: apcore to CLI
|
|
240
|
+
|
|
241
|
+
| apcore | CLI |
|
|
242
|
+
|--------|-----|
|
|
243
|
+
| `module_id` (`math.add`) | Command name (`apcore-cli math.add`) |
|
|
244
|
+
| `description` | `--help` text |
|
|
245
|
+
| `input_schema.properties` | CLI flags (`--a`, `--b`) |
|
|
246
|
+
| `input_schema.required` | Validated post-collection via ajv (required fields shown as `[required]` in `--help`) |
|
|
247
|
+
| `annotations.requires_approval` | HITL approval prompt |
|
|
248
|
+
|
|
249
|
+
### Architecture
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
User / AI Agent (terminal)
|
|
253
|
+
|
|
|
254
|
+
v
|
|
255
|
+
apcore-cli (the adapter)
|
|
256
|
+
|
|
|
257
|
+
+-- ConfigResolver 4-tier config precedence
|
|
258
|
+
+-- LazyModuleGroup Dynamic Commander command generation
|
|
259
|
+
+-- schema_parser JSON Schema -> Commander options
|
|
260
|
+
+-- ref_resolver $ref / allOf / anyOf / oneOf
|
|
261
|
+
+-- approval TTY-aware HITL approval
|
|
262
|
+
+-- output TTY-adaptive JSON/table output
|
|
263
|
+
+-- AuditLogger JSON Lines execution logging
|
|
264
|
+
+-- Sandbox Subprocess isolation
|
|
265
|
+
|
|
|
266
|
+
v
|
|
267
|
+
apcore Registry + Executor (your modules, unchanged)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## API Overview
|
|
271
|
+
|
|
272
|
+
**Classes:** `LazyModuleGroup`, `ConfigResolver`, `AuthProvider`, `ConfigEncryptor`, `AuditLogger`, `Sandbox`
|
|
273
|
+
|
|
274
|
+
**Functions:** `createCli`, `main`, `buildModuleCommand`, `validateModuleId`, `collectInput`, `schemaToCliOptions`, `reconvertEnumValues`, `resolveRefs`, `checkApproval`, `resolveFormat`, `formatModuleList`, `formatModuleDetail`, `formatExecResult`, `registerDiscoveryCommands`, `registerShellCommands`, `setAuditLogger`, `getAuditLogger`, `exitCodeForError`, `mapType`, `extractHelp`, `truncate`
|
|
275
|
+
|
|
276
|
+
**Errors:** `ApprovalTimeoutError`, `ApprovalDeniedError`, `AuthenticationError`, `ConfigDecryptionError`, `ModuleExecutionError`, `ModuleNotFoundError`, `SchemaValidationError`
|
|
277
|
+
|
|
278
|
+
## Development
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
git clone https://github.com/aipartnerup/apcore-cli-typescript.git
|
|
282
|
+
cd apcore-cli-typescript
|
|
283
|
+
pnpm install
|
|
284
|
+
pnpm test # 181 tests
|
|
285
|
+
pnpm build # compile TypeScript
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
## License
|
|
289
|
+
|
|
290
|
+
Apache-2.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __esm = (fn, res) => function __init() {
|
|
4
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js
|
|
8
|
+
import path from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
var init_esm_shims = __esm({
|
|
11
|
+
"node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_typescript@5.9.3/node_modules/tsup/assets/esm_shims.js"() {
|
|
12
|
+
"use strict";
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
// src/errors.ts
|
|
17
|
+
function exitCodeForError(error) {
|
|
18
|
+
if (error instanceof ApprovalTimeoutError) {
|
|
19
|
+
return EXIT_CODES.APPROVAL_TIMEOUT;
|
|
20
|
+
}
|
|
21
|
+
if (error instanceof ApprovalDeniedError) {
|
|
22
|
+
return EXIT_CODES.APPROVAL_DENIED;
|
|
23
|
+
}
|
|
24
|
+
if (error instanceof AuthenticationError) {
|
|
25
|
+
return EXIT_CODES.ACL_DENIED;
|
|
26
|
+
}
|
|
27
|
+
if (error instanceof ConfigDecryptionError) {
|
|
28
|
+
return EXIT_CODES.CONFIG_INVALID;
|
|
29
|
+
}
|
|
30
|
+
if (error instanceof SchemaValidationError) {
|
|
31
|
+
return EXIT_CODES.SCHEMA_VALIDATION_ERROR;
|
|
32
|
+
}
|
|
33
|
+
if (error instanceof ModuleNotFoundError) {
|
|
34
|
+
return EXIT_CODES.MODULE_NOT_FOUND;
|
|
35
|
+
}
|
|
36
|
+
if (error instanceof ModuleExecutionError) {
|
|
37
|
+
return EXIT_CODES.MODULE_EXECUTE_ERROR;
|
|
38
|
+
}
|
|
39
|
+
if (error instanceof Error) {
|
|
40
|
+
const code = error.code;
|
|
41
|
+
const codeMap = {
|
|
42
|
+
MODULE_NOT_FOUND: EXIT_CODES.MODULE_NOT_FOUND,
|
|
43
|
+
MODULE_LOAD_ERROR: EXIT_CODES.MODULE_LOAD_ERROR,
|
|
44
|
+
MODULE_DISABLED: EXIT_CODES.MODULE_DISABLED,
|
|
45
|
+
SCHEMA_VALIDATION_ERROR: EXIT_CODES.SCHEMA_VALIDATION_ERROR,
|
|
46
|
+
SCHEMA_CIRCULAR_REF: EXIT_CODES.SCHEMA_CIRCULAR_REF,
|
|
47
|
+
APPROVAL_DENIED: EXIT_CODES.APPROVAL_DENIED,
|
|
48
|
+
APPROVAL_TIMEOUT: EXIT_CODES.APPROVAL_TIMEOUT,
|
|
49
|
+
CONFIG_NOT_FOUND: EXIT_CODES.CONFIG_NOT_FOUND,
|
|
50
|
+
CONFIG_INVALID: EXIT_CODES.CONFIG_INVALID,
|
|
51
|
+
MODULE_EXECUTE_ERROR: EXIT_CODES.MODULE_EXECUTE_ERROR,
|
|
52
|
+
MODULE_TIMEOUT: EXIT_CODES.MODULE_TIMEOUT,
|
|
53
|
+
ACL_DENIED: EXIT_CODES.ACL_DENIED
|
|
54
|
+
};
|
|
55
|
+
if (code && code in codeMap) {
|
|
56
|
+
return codeMap[code];
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return EXIT_CODES.MODULE_EXECUTE_ERROR;
|
|
60
|
+
}
|
|
61
|
+
var ApprovalTimeoutError, AuthenticationError, ConfigDecryptionError, ModuleExecutionError, ApprovalDeniedError, SchemaValidationError, ModuleNotFoundError, EXIT_CODES;
|
|
62
|
+
var init_errors = __esm({
|
|
63
|
+
"src/errors.ts"() {
|
|
64
|
+
"use strict";
|
|
65
|
+
init_esm_shims();
|
|
66
|
+
ApprovalTimeoutError = class extends Error {
|
|
67
|
+
constructor(message = "Approval timed out") {
|
|
68
|
+
super(message);
|
|
69
|
+
this.name = "ApprovalTimeoutError";
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
AuthenticationError = class extends Error {
|
|
73
|
+
constructor(message = "Authentication failed") {
|
|
74
|
+
super(message);
|
|
75
|
+
this.name = "AuthenticationError";
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
ConfigDecryptionError = class extends Error {
|
|
79
|
+
constructor(message = "Config decryption failed") {
|
|
80
|
+
super(message);
|
|
81
|
+
this.name = "ConfigDecryptionError";
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
ModuleExecutionError = class extends Error {
|
|
85
|
+
constructor(message = "Module execution failed") {
|
|
86
|
+
super(message);
|
|
87
|
+
this.name = "ModuleExecutionError";
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
ApprovalDeniedError = class extends Error {
|
|
91
|
+
constructor(message = "Approval denied") {
|
|
92
|
+
super(message);
|
|
93
|
+
this.name = "ApprovalDeniedError";
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
SchemaValidationError = class extends Error {
|
|
97
|
+
constructor(message = "Schema validation failed") {
|
|
98
|
+
super(message);
|
|
99
|
+
this.name = "SchemaValidationError";
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
ModuleNotFoundError = class extends Error {
|
|
103
|
+
constructor(message = "Module not found") {
|
|
104
|
+
super(message);
|
|
105
|
+
this.name = "ModuleNotFoundError";
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
EXIT_CODES = {
|
|
109
|
+
SUCCESS: 0,
|
|
110
|
+
MODULE_EXECUTE_ERROR: 1,
|
|
111
|
+
MODULE_TIMEOUT: 1,
|
|
112
|
+
INVALID_CLI_INPUT: 2,
|
|
113
|
+
MODULE_NOT_FOUND: 44,
|
|
114
|
+
MODULE_LOAD_ERROR: 44,
|
|
115
|
+
MODULE_DISABLED: 44,
|
|
116
|
+
SCHEMA_VALIDATION_ERROR: 45,
|
|
117
|
+
APPROVAL_DENIED: 46,
|
|
118
|
+
APPROVAL_TIMEOUT: 46,
|
|
119
|
+
CONFIG_NOT_FOUND: 47,
|
|
120
|
+
CONFIG_INVALID: 47,
|
|
121
|
+
SCHEMA_CIRCULAR_REF: 48,
|
|
122
|
+
ACL_DENIED: 77,
|
|
123
|
+
KEYBOARD_INTERRUPT: 130
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// bin/apcore-cli.ts
|
|
129
|
+
init_esm_shims();
|
|
130
|
+
|
|
131
|
+
// src/main.ts
|
|
132
|
+
init_esm_shims();
|
|
133
|
+
init_errors();
|
|
134
|
+
import { readFileSync } from "fs";
|
|
135
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
136
|
+
import * as path2 from "path";
|
|
137
|
+
import { Command, CommanderError } from "commander";
|
|
138
|
+
|
|
139
|
+
// src/ref-resolver.ts
|
|
140
|
+
init_esm_shims();
|
|
141
|
+
init_errors();
|
|
142
|
+
|
|
143
|
+
// src/schema-parser.ts
|
|
144
|
+
init_esm_shims();
|
|
145
|
+
init_errors();
|
|
146
|
+
|
|
147
|
+
// src/approval.ts
|
|
148
|
+
init_esm_shims();
|
|
149
|
+
init_errors();
|
|
150
|
+
import * as readline from "readline";
|
|
151
|
+
|
|
152
|
+
// src/output.ts
|
|
153
|
+
init_esm_shims();
|
|
154
|
+
|
|
155
|
+
// src/logger.ts
|
|
156
|
+
init_esm_shims();
|
|
157
|
+
var LEVELS = { DEBUG: 0, INFO: 1, WARNING: 2, ERROR: 3 };
|
|
158
|
+
var currentLevel = "WARNING";
|
|
159
|
+
function setLogLevel(level) {
|
|
160
|
+
const upper = level.toUpperCase();
|
|
161
|
+
if (upper in LEVELS) {
|
|
162
|
+
currentLevel = upper;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/main.ts
|
|
167
|
+
var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
|
|
168
|
+
var pkg = JSON.parse(readFileSync(path2.resolve(__dirname2, "../package.json"), "utf-8"));
|
|
169
|
+
var VERSION = pkg.version;
|
|
170
|
+
function createCli(extensionsDir, progName) {
|
|
171
|
+
const resolvedProgName = progName ?? path2.basename(process.argv[1] ?? "apcore-cli") ?? "apcore-cli";
|
|
172
|
+
const cliLogLevel = process.env.APCORE_CLI_LOGGING_LEVEL ?? process.env.APCORE_LOGGING_LEVEL ?? "WARNING";
|
|
173
|
+
setLogLevel(cliLogLevel);
|
|
174
|
+
const program = new Command(resolvedProgName).exitOverride().version(VERSION, "--version", `Show ${resolvedProgName} version`).description("apcore CLI \u2014 execute apcore modules from the command line").option("--extensions-dir <path>", "Path to extensions directory").option("--log-level <level>", "Logging level (DEBUG|INFO|WARNING|ERROR)", "WARNING");
|
|
175
|
+
void extensionsDir;
|
|
176
|
+
return program;
|
|
177
|
+
}
|
|
178
|
+
function main(progName) {
|
|
179
|
+
const program = createCli(void 0, progName);
|
|
180
|
+
try {
|
|
181
|
+
program.parse(process.argv);
|
|
182
|
+
} catch (error) {
|
|
183
|
+
if (error instanceof CommanderError) {
|
|
184
|
+
process.exit(error.exitCode);
|
|
185
|
+
}
|
|
186
|
+
const code = exitCodeForError(error);
|
|
187
|
+
if (error instanceof Error) {
|
|
188
|
+
process.stderr.write(`Error: ${error.message}
|
|
189
|
+
`);
|
|
190
|
+
}
|
|
191
|
+
process.exit(code);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// bin/apcore-cli.ts
|
|
196
|
+
main("apcore-cli");
|
|
197
|
+
//# sourceMappingURL=apcore-cli.js.map
|