@clawops/cli 1.7.1 → 1.7.3
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 +37 -92
- package/dist/{apply-BTZFFGAD.js → apply-PZ5IIU7Z.js} +5 -4
- package/dist/{aws-D7Y6LCGK.js → aws-L4RR2LSE.js} +1 -1
- package/dist/{azure-JQAMNVHN.js → azure-7OXQENQL.js} +1 -1
- package/dist/{bootstrap-RY4VOSDJ.js → bootstrap-HL4DNUNG.js} +13 -4
- package/dist/bootstrap.sh.tmpl +204 -0
- package/dist/chunk-2YOP6N7X.js +126 -0
- package/dist/{chunk-GJEF6UQA.js → chunk-3XK66DKK.js} +100 -16
- package/dist/{chunk-ISFHLA4G.js → chunk-5SPESD5N.js} +8 -6
- package/dist/{chunk-YTH4L2GN.js → chunk-6X45DDGH.js} +5 -4
- package/dist/{chunk-XKT42M34.js → chunk-C5X375RO.js} +14 -1
- package/dist/{chunk-LCKD7L7X.js → chunk-DQDAWNGB.js} +1 -1
- package/dist/{chunk-CG3Y7Y2R.js → chunk-FSUWPL7Q.js} +9 -9
- package/dist/{chunk-FQ4JXUCR.js → chunk-NESXDU5F.js} +7 -4
- package/dist/{chunk-ZFNPM2WG.js → chunk-O3F7OGH7.js} +40 -3
- package/dist/{chunk-3MFZ7E74.js → chunk-P5LKWRPL.js} +3 -3
- package/dist/chunk-PVUVI35Y.js +29 -0
- package/dist/cli.js +122 -68
- package/dist/{context-ALSJMTHE.js → context-5LCUG2QR.js} +1 -1
- package/dist/{gcp-6FT2A45S.js → gcp-UG6AWPIZ.js} +1 -1
- package/dist/{generate-SPT7PJKR.js → generate-6E7J6BTM.js} +4 -3
- package/dist/{harden-BDVYW567.js → harden-URPXLSVF.js} +2 -2
- package/dist/{mcp-wire-ZWIYMLEW.js → mcp-wire-SLL4TLSC.js} +1 -1
- package/dist/{package-OMPI6RMV.js → package-QE7V2JAT.js} +3 -2
- package/dist/{pool-JZGKPP6K.js → pool-QGFQRMGU.js} +2 -2
- package/dist/{remote-config-QF5TT7GU.js → remote-config-PFB66RPY.js} +3 -1
- package/dist/{server-RGLKKCCU.js → server-L22AJQZO.js} +19 -18
- package/dist/{ssh-E2AMBPZY.js → ssh-CNJNLM3E.js} +1 -1
- package/dist/{validate-T5M5EHSJ.js → validate-CFQ4FH2T.js} +2 -1
- package/dist/version-guard-MZAO4KHS.js +25 -0
- package/dist/versions-OEPAS2EL.js +24 -0
- package/package.json +3 -2
- package/spec/_gen-schemas.md +136 -0
- package/spec/deploy-plan.schema.json +193 -0
- package/spec/errors.yaml +175 -0
- package/spec/integrations.yaml +97 -0
- package/spec/invariants.yaml +81 -0
- package/spec/mcp-tools.yaml +532 -0
- package/spec/models.yaml +113 -0
- package/spec/openclaw-versions.yaml +67 -0
- package/spec/providers.schema.json +120 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
applyPlan
|
|
4
|
+
} from "./chunk-5SPESD5N.js";
|
|
5
|
+
import "./chunk-6ZFIFDBJ.js";
|
|
6
|
+
import "./chunk-BOPSG2LI.js";
|
|
2
7
|
import {
|
|
3
8
|
extractBaseOutputs
|
|
4
9
|
} from "./chunk-3QJBNAHW.js";
|
|
5
10
|
import {
|
|
6
11
|
generatePlan
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import {
|
|
9
|
-
applyPlan
|
|
10
|
-
} from "./chunk-ISFHLA4G.js";
|
|
12
|
+
} from "./chunk-NESXDU5F.js";
|
|
11
13
|
import {
|
|
12
14
|
validatePlan
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-6ZFIFDBJ.js";
|
|
15
|
-
import "./chunk-BOPSG2LI.js";
|
|
15
|
+
} from "./chunk-6X45DDGH.js";
|
|
16
16
|
import {
|
|
17
17
|
errText,
|
|
18
18
|
formatUptime,
|
|
@@ -23,16 +23,17 @@ import {
|
|
|
23
23
|
handleConfigValidate,
|
|
24
24
|
okText,
|
|
25
25
|
resolveConn
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import "./chunk-ZFNPM2WG.js";
|
|
28
|
-
import {
|
|
29
|
-
buildContext
|
|
30
|
-
} from "./chunk-3MFZ7E74.js";
|
|
26
|
+
} from "./chunk-FSUWPL7Q.js";
|
|
31
27
|
import {
|
|
32
28
|
acquireSession,
|
|
33
29
|
drainPool
|
|
34
|
-
} from "./chunk-
|
|
35
|
-
import "./chunk-
|
|
30
|
+
} from "./chunk-DQDAWNGB.js";
|
|
31
|
+
import "./chunk-O3F7OGH7.js";
|
|
32
|
+
import {
|
|
33
|
+
buildContext
|
|
34
|
+
} from "./chunk-P5LKWRPL.js";
|
|
35
|
+
import "./chunk-PVUVI35Y.js";
|
|
36
|
+
import "./chunk-3XK66DKK.js";
|
|
36
37
|
import "./chunk-Q7NQY5HV.js";
|
|
37
38
|
import "./chunk-A2I76FTA.js";
|
|
38
39
|
import {
|
|
@@ -535,7 +536,7 @@ async function handleGatewayRestart(input, server) {
|
|
|
535
536
|
const cmd = [
|
|
536
537
|
"docker stop openclaw 2>/dev/null || true",
|
|
537
538
|
"docker rm openclaw 2>/dev/null || true",
|
|
538
|
-
`docker run -d --name openclaw --restart unless-stopped -p 18789:18789 ${image}`
|
|
539
|
+
`docker run -d --name openclaw --restart unless-stopped -p 18789:18789 -e OPENCLAW_CONFIG_PATH=/app/config.json --add-host=host.docker.internal:host-gateway -v /home/clawops/openclaw.json:/app/config.json:ro ${image}`
|
|
539
540
|
].join(" && ");
|
|
540
541
|
const result = await session.exec(cmd);
|
|
541
542
|
if (result.code !== 0) {
|
|
@@ -631,7 +632,7 @@ async function handleUp(input, server) {
|
|
|
631
632
|
);
|
|
632
633
|
}
|
|
633
634
|
const { localOpts } = stackConfig;
|
|
634
|
-
const { localBootstrap } = await import("./bootstrap-
|
|
635
|
+
const { localBootstrap } = await import("./bootstrap-HL4DNUNG.js");
|
|
635
636
|
const ac = new AbortController();
|
|
636
637
|
const state = await localBootstrap({
|
|
637
638
|
host: localOpts.host,
|
|
@@ -854,7 +855,7 @@ async function handleTaskStatus(input, _server) {
|
|
|
854
855
|
|
|
855
856
|
// src/mcp/tools/cli/monitor.ts
|
|
856
857
|
async function handleMonitor(input, _server) {
|
|
857
|
-
const { acquireSession: acquireSession2, drainPool: drainPool2 } = await import("./pool-
|
|
858
|
+
const { acquireSession: acquireSession2, drainPool: drainPool2 } = await import("./pool-QGFQRMGU.js");
|
|
858
859
|
const ctx = buildContext({ stack: input.stackName });
|
|
859
860
|
const tailLines = input.tailLines ?? 5;
|
|
860
861
|
let conn;
|
|
@@ -1306,7 +1307,7 @@ If none of the above resolves the issue:
|
|
|
1306
1307
|
|
|
1307
1308
|
// src/mcp/server.ts
|
|
1308
1309
|
async function serveMcp(opts) {
|
|
1309
|
-
const { version } = await import("./package-
|
|
1310
|
+
const { version } = await import("./package-QE7V2JAT.js");
|
|
1310
1311
|
const server = new McpServer({ name: "clawops", version });
|
|
1311
1312
|
registerTools(server, opts);
|
|
1312
1313
|
registerResources(server);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
assertSupportedVersion,
|
|
4
|
+
loadVersionSpec
|
|
5
|
+
} from "./chunk-2YOP6N7X.js";
|
|
6
|
+
import "./chunk-PVUVI35Y.js";
|
|
7
|
+
import {
|
|
8
|
+
UsageError
|
|
9
|
+
} from "./chunk-KGXPLI7W.js";
|
|
10
|
+
|
|
11
|
+
// src/cli/version-guard.ts
|
|
12
|
+
async function defaultOpenclawVersion() {
|
|
13
|
+
const yaml = await import("./js-yaml-PTEEG4FO.js");
|
|
14
|
+
return loadVersionSpec(yaml).support.recommended;
|
|
15
|
+
}
|
|
16
|
+
async function guardOpenclawVersion(version, resolver) {
|
|
17
|
+
const yaml = await import("./js-yaml-PTEEG4FO.js");
|
|
18
|
+
const result = await assertSupportedVersion(version, yaml, resolver);
|
|
19
|
+
if (result.ok) return result.value;
|
|
20
|
+
throw new UsageError(result.error.message);
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
defaultOpenclawVersion,
|
|
24
|
+
guardOpenclawVersion
|
|
25
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
MOVING_TAGS,
|
|
4
|
+
_resetVersionSpecCache,
|
|
5
|
+
assertSupportedVersion,
|
|
6
|
+
checkVersion,
|
|
7
|
+
compareVersions,
|
|
8
|
+
describeRange,
|
|
9
|
+
isMovingTag,
|
|
10
|
+
loadVersionSpec,
|
|
11
|
+
resolveVersion
|
|
12
|
+
} from "./chunk-2YOP6N7X.js";
|
|
13
|
+
import "./chunk-PVUVI35Y.js";
|
|
14
|
+
export {
|
|
15
|
+
MOVING_TAGS,
|
|
16
|
+
_resetVersionSpecCache,
|
|
17
|
+
assertSupportedVersion,
|
|
18
|
+
checkVersion,
|
|
19
|
+
compareVersions,
|
|
20
|
+
describeRange,
|
|
21
|
+
isMovingTag,
|
|
22
|
+
loadVersionSpec,
|
|
23
|
+
resolveVersion
|
|
24
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clawops/cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.3",
|
|
4
4
|
"description": "Deploy and manage self-hosted OpenClaw instances across clouds",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
".": "./dist/index.js"
|
|
11
11
|
},
|
|
12
12
|
"files": [
|
|
13
|
-
"dist"
|
|
13
|
+
"dist",
|
|
14
|
+
"spec"
|
|
14
15
|
],
|
|
15
16
|
"repository": {
|
|
16
17
|
"type": "git",
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# Schema Code Generation — `pnpm gen:schemas`
|
|
2
|
+
|
|
3
|
+
This document specifies the contract for `scripts/gen-schemas.ts`, the codegen pipeline that emits TypeScript types and Zod schemas from the machine-readable specs in `spec/`.
|
|
4
|
+
|
|
5
|
+
## Why This Exists
|
|
6
|
+
|
|
7
|
+
R-meta-1 declares schema files as ground truth. To make this enforceable rather than aspirational, generated TypeScript artifacts must mechanically derive from the schemas. CI verifies no drift via `pnpm gen:schemas --check`.
|
|
8
|
+
|
|
9
|
+
## Inputs
|
|
10
|
+
|
|
11
|
+
| File | Format | Purpose |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `spec/providers.schema.json` | JSON Schema | Drives `ProviderAdapter` interface |
|
|
14
|
+
| `spec/mcp-tools.yaml` | YAML | Drives MCP tool Zod schemas + tool registration |
|
|
15
|
+
| `spec/deploy-plan.schema.json` | JSON Schema | Drives `DeployPlan` type + ajv validator |
|
|
16
|
+
| `spec/errors.yaml` | YAML | Drives error class hierarchy + taxonomy IDs |
|
|
17
|
+
| `spec/openclaw-versions.yaml` | YAML | Drives version compatibility check |
|
|
18
|
+
| `spec/invariants.yaml` | YAML | Drives invariants test runner |
|
|
19
|
+
|
|
20
|
+
## Outputs
|
|
21
|
+
|
|
22
|
+
| File | Source | Purpose |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| `src/providers/types.ts` | `providers.schema.json` | `ProviderAdapter` TS interface |
|
|
25
|
+
| `src/providers/_schema.ts` | `providers.schema.json` | Embedded JSON Schema for runtime ajv |
|
|
26
|
+
| `src/mcp/tools/_generated.ts` | `mcp-tools.yaml` | Zod schemas for every tool's input/output, tool registration helper |
|
|
27
|
+
| `src/plan/_schema.ts` | `deploy-plan.schema.json` | Embedded JSON Schema for `apply` validation |
|
|
28
|
+
| `src/plan/types.ts` | `deploy-plan.schema.json` | TS types for `DeployPlan` |
|
|
29
|
+
| `src/errors/_generated.ts` | `errors.yaml` | Error class hierarchy, taxonomy IDs as enums |
|
|
30
|
+
| `src/openclaw/versions.ts` | `openclaw-versions.yaml` | Version constants and quirks lookup |
|
|
31
|
+
|
|
32
|
+
All generated files MUST start with a banner comment:
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// AUTO-GENERATED by scripts/gen-schemas.ts. DO NOT EDIT.
|
|
36
|
+
// Source: spec/<filename>
|
|
37
|
+
// Run `pnpm gen:schemas` to regenerate.
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Behavior
|
|
41
|
+
|
|
42
|
+
### `pnpm gen:schemas`
|
|
43
|
+
|
|
44
|
+
1. Read all input files
|
|
45
|
+
2. Parse and validate each against its meta-schema (JSON Schema validates JSON Schema; YAML files validate against `spec/_meta/*.schema.json`)
|
|
46
|
+
3. For each output file:
|
|
47
|
+
a. Generate the new content
|
|
48
|
+
b. Compare to existing file (if present)
|
|
49
|
+
c. Write if different; preserve mtime if identical
|
|
50
|
+
4. Format output via `prettier --config .prettierrc <files>`
|
|
51
|
+
5. Exit 0 on success; non-zero on any validation failure
|
|
52
|
+
|
|
53
|
+
### `pnpm gen:schemas --check`
|
|
54
|
+
|
|
55
|
+
Same as above, but step 3c becomes:
|
|
56
|
+
- If existing file differs from new content: print diff + exit 1
|
|
57
|
+
- If files match: exit 0
|
|
58
|
+
|
|
59
|
+
This is the CI mode — fails the build if generated files are stale.
|
|
60
|
+
|
|
61
|
+
## Tooling
|
|
62
|
+
|
|
63
|
+
- **JSON Schema → TypeScript:** `json-schema-to-typescript`
|
|
64
|
+
- **JSON Schema → Zod:** `json-schema-to-zod`
|
|
65
|
+
- **YAML parsing:** `yaml` package
|
|
66
|
+
- **Diff display:** `diff` package + colorized output
|
|
67
|
+
- **Formatting:** `prettier` (programmatic API)
|
|
68
|
+
|
|
69
|
+
## Validation Rules
|
|
70
|
+
|
|
71
|
+
The generator MUST enforce:
|
|
72
|
+
|
|
73
|
+
1. **Provider schema:**
|
|
74
|
+
- Every provider name in the enum must have an implementation under `src/providers/<name>/` (warning if missing; not error, to allow scaffolding)
|
|
75
|
+
- Every required field has a `description`
|
|
76
|
+
|
|
77
|
+
2. **MCP tools:**
|
|
78
|
+
- All tool names start with `clawops_` (R1, I5)
|
|
79
|
+
- Total tool count ≤ 30 (R1, I4)
|
|
80
|
+
- Every tool has all four annotation hints set explicitly (R10, I3)
|
|
81
|
+
- Every description contains "Do NOT use" substring (R3, I6)
|
|
82
|
+
- Every tool is in at least one toolset
|
|
83
|
+
|
|
84
|
+
3. **Deploy plan schema:**
|
|
85
|
+
- `apiVersion` is a const literal (semantic versioning safety)
|
|
86
|
+
- `secrets[]` items only allow `ref`, never `value` (R6 enforcement)
|
|
87
|
+
|
|
88
|
+
4. **Errors:**
|
|
89
|
+
- Every taxonomy ID maps to exactly one class
|
|
90
|
+
- Class IDs in the taxonomy must exist in the `classes` list
|
|
91
|
+
|
|
92
|
+
If any validation fails, the generator exits non-zero with a clear error message before writing anything.
|
|
93
|
+
|
|
94
|
+
## Running in CI
|
|
95
|
+
|
|
96
|
+
In `.github/workflows/ci.yml`:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
- name: Verify generated files are up-to-date
|
|
100
|
+
run: pnpm gen:schemas --check
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
This runs BEFORE typecheck so failures surface clearly.
|
|
104
|
+
|
|
105
|
+
## Editor Integration
|
|
106
|
+
|
|
107
|
+
For local dev, recommend adding a watcher (in CONTRIBUTING.md):
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Watch spec/ and regenerate on change
|
|
111
|
+
pnpm exec chokidar 'spec/**/*' -c 'pnpm gen:schemas'
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Failure Modes and Recovery
|
|
115
|
+
|
|
116
|
+
| Symptom | Likely Cause | Fix |
|
|
117
|
+
|---|---|---|
|
|
118
|
+
| `gen:schemas --check` fails after spec edit | Forgot to commit generated files | Run `pnpm gen:schemas`, commit |
|
|
119
|
+
| Generator throws "validation failed" | Spec violates meta-schema | Fix the spec to match meta-schema |
|
|
120
|
+
| Generated TS doesn't typecheck | Generator template bug | File issue; revert to last working commit |
|
|
121
|
+
| Tool count exceeds 30 | New MCP tool tipped over R1 | Move a tool to a different toolset, deprecate, or merge |
|
|
122
|
+
| Tool missing "Do NOT use" | Description doesn't include negative guidance | Update spec entry; R3 violation |
|
|
123
|
+
|
|
124
|
+
## Versioning the Generator Itself
|
|
125
|
+
|
|
126
|
+
The generator's logic is part of the project's interface contract. Major changes to its output format MUST be accompanied by:
|
|
127
|
+
|
|
128
|
+
1. An ADR documenting the format change
|
|
129
|
+
2. A migration script if downstream code is affected
|
|
130
|
+
3. A CHANGELOG entry
|
|
131
|
+
|
|
132
|
+
## Future Extensions (Not in v1)
|
|
133
|
+
|
|
134
|
+
- Generate OpenAPI spec for the standalone HTTP MCP server from `spec/mcp-tools.yaml`
|
|
135
|
+
- Generate Markdown docs for each provider/tool/error from the specs
|
|
136
|
+
- Generate JSON Schema for `~/.clawops/config.json` from `spec/config.schema.json` (not yet authored)
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://clawops.dev/schemas/deploy-plan.json",
|
|
4
|
+
"title": "DeployPlan",
|
|
5
|
+
"description": "The Maker plan artifact (borrowed from Clanker pattern). Generated by `clawops plan`, applied by `clawops apply`. Reviewable, diff-able, version-controllable.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["apiVersion", "kind", "metadata", "spec"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"apiVersion": {
|
|
10
|
+
"const": "clawops.dev/v1",
|
|
11
|
+
"description": "Schema version pinning"
|
|
12
|
+
},
|
|
13
|
+
"kind": {
|
|
14
|
+
"const": "DeployPlan"
|
|
15
|
+
},
|
|
16
|
+
"metadata": {
|
|
17
|
+
"type": "object",
|
|
18
|
+
"required": ["name", "generatedAt"],
|
|
19
|
+
"properties": {
|
|
20
|
+
"name": {
|
|
21
|
+
"type": "string",
|
|
22
|
+
"pattern": "^[a-z][a-z0-9-]{0,62}$",
|
|
23
|
+
"description": "Stack name"
|
|
24
|
+
},
|
|
25
|
+
"generatedAt": {
|
|
26
|
+
"type": "string",
|
|
27
|
+
"format": "date-time",
|
|
28
|
+
"description": "ISO-8601 timestamp"
|
|
29
|
+
},
|
|
30
|
+
"generator": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"default": "clawops",
|
|
33
|
+
"description": "Tool that produced this plan; agents can identify themselves here"
|
|
34
|
+
},
|
|
35
|
+
"generatorVersion": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "semver of generator"
|
|
38
|
+
},
|
|
39
|
+
"labels": {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"additionalProperties": { "type": "string" },
|
|
42
|
+
"description": "User-supplied labels (env=prod, team=platform, etc.)"
|
|
43
|
+
},
|
|
44
|
+
"stackVersion": {
|
|
45
|
+
"type": "integer",
|
|
46
|
+
"description": "Pulumi stack version at plan generation time (from UpdateSummary.version). Compared at apply time to detect drift. Absent for new stacks with no history."
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"spec": {
|
|
51
|
+
"type": "object",
|
|
52
|
+
"required": ["provider", "stackName", "instanceType", "openclaw", "network"],
|
|
53
|
+
"properties": {
|
|
54
|
+
"provider": {
|
|
55
|
+
"enum": ["aws", "gcp", "azure", "local"]
|
|
56
|
+
},
|
|
57
|
+
"region": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"description": "Cloud region. Required for non-local providers"
|
|
60
|
+
},
|
|
61
|
+
"stackName": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"pattern": "^[a-z][a-z0-9-]{0,62}$"
|
|
64
|
+
},
|
|
65
|
+
"instanceType": {
|
|
66
|
+
"type": "string",
|
|
67
|
+
"description": "Provider-native instance type. Adapter normalizes from clawops alias before plan emission"
|
|
68
|
+
},
|
|
69
|
+
"openclaw": {
|
|
70
|
+
"type": "object",
|
|
71
|
+
"required": ["version"],
|
|
72
|
+
"properties": {
|
|
73
|
+
"version": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"description": "semver or 'stable'/'dev'"
|
|
76
|
+
},
|
|
77
|
+
"config": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"description": "Overrides applied on top of default openclaw.json. Secrets must use $secret references, never inline values"
|
|
80
|
+
},
|
|
81
|
+
"channels": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"description": "OpenClaw channel integrations keyed by provider name (e.g. {\"discord\":{\"botToken\":\"...\"}}). Values are provider-specific config objects. Sensitive fields must use $secret references.",
|
|
84
|
+
"additionalProperties": { "type": "object" }
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
"secrets": {
|
|
89
|
+
"type": "array",
|
|
90
|
+
"description": "Secret references (R6: never inline values)",
|
|
91
|
+
"items": {
|
|
92
|
+
"type": "object",
|
|
93
|
+
"required": ["name", "source"],
|
|
94
|
+
"properties": {
|
|
95
|
+
"name": { "type": "string" },
|
|
96
|
+
"source": {
|
|
97
|
+
"enum": ["env", "aws-sm", "aws-ssm", "gcp-sm", "azure-kv", "file"]
|
|
98
|
+
},
|
|
99
|
+
"ref": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"description": "Source-specific reference (env var name, ARN, secret URI, file path)"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"network": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"required": ["allowedSshCidrs", "allowedGatewayCidrs"],
|
|
109
|
+
"properties": {
|
|
110
|
+
"allowedSshCidrs": {
|
|
111
|
+
"type": "array",
|
|
112
|
+
"items": { "type": "string", "format": "cidr" },
|
|
113
|
+
"minItems": 0,
|
|
114
|
+
"description": "Empty array = no SSH access (unusual but allowed). Defaults applied at plan generation, not in schema"
|
|
115
|
+
},
|
|
116
|
+
"allowedGatewayCidrs": {
|
|
117
|
+
"type": "array",
|
|
118
|
+
"items": { "type": "string", "format": "cidr" },
|
|
119
|
+
"description": "CIDRs allowed to reach the OpenClaw gateway port (default 18789)"
|
|
120
|
+
},
|
|
121
|
+
"tailscale": {
|
|
122
|
+
"type": "object",
|
|
123
|
+
"description": "Optional Tailscale sidecar (borrowed pattern from schmitthub)",
|
|
124
|
+
"properties": {
|
|
125
|
+
"enabled": { "type": "boolean" },
|
|
126
|
+
"authKeyRef": { "type": "string", "description": "Reference to a secret containing the Tailscale auth key" }
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"ssh": {
|
|
132
|
+
"type": "object",
|
|
133
|
+
"properties": {
|
|
134
|
+
"publicKey": {
|
|
135
|
+
"type": "string",
|
|
136
|
+
"description": "Public key contents (safe to inline). Private key never in plan"
|
|
137
|
+
},
|
|
138
|
+
"user": { "type": "string", "default": "ubuntu" }
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"tags": {
|
|
142
|
+
"type": "object",
|
|
143
|
+
"additionalProperties": { "type": "string" },
|
|
144
|
+
"description": "Cloud-resource tags propagated to all created resources"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
"diff": {
|
|
149
|
+
"type": "object",
|
|
150
|
+
"description": "Optional resource diff populated by `clawops plan` for human review. Not used by `apply`",
|
|
151
|
+
"properties": {
|
|
152
|
+
"create": {
|
|
153
|
+
"type": "array",
|
|
154
|
+
"items": { "$ref": "#/$defs/ResourceRef" }
|
|
155
|
+
},
|
|
156
|
+
"update": {
|
|
157
|
+
"type": "array",
|
|
158
|
+
"items": {
|
|
159
|
+
"type": "object",
|
|
160
|
+
"required": ["resource", "before", "after"],
|
|
161
|
+
"properties": {
|
|
162
|
+
"resource": { "$ref": "#/$defs/ResourceRef" },
|
|
163
|
+
"before": {},
|
|
164
|
+
"after": {}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"delete": {
|
|
169
|
+
"type": "array",
|
|
170
|
+
"items": { "$ref": "#/$defs/ResourceRef" }
|
|
171
|
+
},
|
|
172
|
+
"totalChanges": { "type": "integer" }
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"$defs": {
|
|
177
|
+
"ResourceRef": {
|
|
178
|
+
"type": "object",
|
|
179
|
+
"required": ["urn", "type"],
|
|
180
|
+
"properties": {
|
|
181
|
+
"urn": {
|
|
182
|
+
"type": "string",
|
|
183
|
+
"description": "Pulumi URN, e.g., urn:pulumi:prod::clawops::clawops:app:Gateway::main-gateway"
|
|
184
|
+
},
|
|
185
|
+
"type": {
|
|
186
|
+
"type": "string",
|
|
187
|
+
"description": "Pulumi resource type token"
|
|
188
|
+
},
|
|
189
|
+
"name": { "type": "string" }
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
package/spec/errors.yaml
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# Error Taxonomy — machine-readable companion to ADR 0005.
|
|
2
|
+
# Used by `pnpm gen:schemas` to emit src/errors/_generated.ts.
|
|
3
|
+
# Update via PR; CI verifies generated file matches.
|
|
4
|
+
|
|
5
|
+
version: 1
|
|
6
|
+
|
|
7
|
+
# Top-level error classes; each maps to an exit code (ADR 0005).
|
|
8
|
+
classes:
|
|
9
|
+
- id: UsageError
|
|
10
|
+
exitCode: 2
|
|
11
|
+
description: User input is invalid; user must change input
|
|
12
|
+
retryable: false
|
|
13
|
+
userActionRequired: true
|
|
14
|
+
|
|
15
|
+
- id: AuthError
|
|
16
|
+
exitCode: 3
|
|
17
|
+
description: Credentials missing, invalid, or insufficient
|
|
18
|
+
retryable: false
|
|
19
|
+
userActionRequired: true
|
|
20
|
+
|
|
21
|
+
- id: StateError
|
|
22
|
+
exitCode: 4
|
|
23
|
+
description: clawops-managed state is corrupt or inconsistent
|
|
24
|
+
retryable: false
|
|
25
|
+
userActionRequired: true
|
|
26
|
+
|
|
27
|
+
- id: ProviderError
|
|
28
|
+
exitCode: 5
|
|
29
|
+
description: Cloud provider rejected the request (non-auth)
|
|
30
|
+
retryable: depends # per-taxon
|
|
31
|
+
userActionRequired: depends
|
|
32
|
+
|
|
33
|
+
- id: NetworkError
|
|
34
|
+
exitCode: 6
|
|
35
|
+
description: Network connectivity failure
|
|
36
|
+
retryable: true
|
|
37
|
+
userActionRequired: false
|
|
38
|
+
|
|
39
|
+
- id: OperationalError
|
|
40
|
+
exitCode: 1
|
|
41
|
+
description: Operation-time error during a valid operation
|
|
42
|
+
retryable: depends
|
|
43
|
+
userActionRequired: depends
|
|
44
|
+
|
|
45
|
+
- id: CancelledError
|
|
46
|
+
exitCode: 130
|
|
47
|
+
description: User-initiated cancellation
|
|
48
|
+
retryable: true
|
|
49
|
+
userActionRequired: false
|
|
50
|
+
|
|
51
|
+
# Specific taxonomy IDs that errors must use as their `errorClass` field.
|
|
52
|
+
# Every thrown ClawopsError MUST have one of these IDs.
|
|
53
|
+
taxonomy:
|
|
54
|
+
# Usage
|
|
55
|
+
- id: usage.invalid_flag
|
|
56
|
+
class: UsageError
|
|
57
|
+
suggestedAction: "Check the flag spelling and value with `clawops <command> --help`."
|
|
58
|
+
- id: usage.missing_arg
|
|
59
|
+
class: UsageError
|
|
60
|
+
suggestedAction: "Provide the missing argument; see `clawops <command> --help`."
|
|
61
|
+
- id: usage.invalid_path
|
|
62
|
+
class: UsageError
|
|
63
|
+
suggestedAction: "Provide an absolute path. Relative paths are not accepted (R7)."
|
|
64
|
+
- id: usage.invalid_plan
|
|
65
|
+
class: UsageError
|
|
66
|
+
suggestedAction: "Plan failed schema validation. Regenerate with `clawops plan`."
|
|
67
|
+
|
|
68
|
+
# Auth
|
|
69
|
+
- id: auth.no_credentials
|
|
70
|
+
class: AuthError
|
|
71
|
+
suggestedAction: "Run `clawops init` to configure credentials."
|
|
72
|
+
- id: auth.expired
|
|
73
|
+
class: AuthError
|
|
74
|
+
suggestedAction: "Re-authenticate with your cloud provider; for AWS run `aws sso login`."
|
|
75
|
+
- id: auth.insufficient_permissions
|
|
76
|
+
class: AuthError
|
|
77
|
+
suggestedAction: "The configured credentials lack required IAM permissions; see docs/providers/<name>.md."
|
|
78
|
+
|
|
79
|
+
# State
|
|
80
|
+
- id: state.lock_held
|
|
81
|
+
class: StateError
|
|
82
|
+
suggestedAction: "Another clawops operation may be in progress; wait or run `clawops stacks unlock <name>` if certain it's stale."
|
|
83
|
+
- id: state.signature_mismatch
|
|
84
|
+
class: StateError
|
|
85
|
+
suggestedAction: "The plan file has been modified since generation; regenerate with `clawops plan`."
|
|
86
|
+
- id: state.backend_unreachable
|
|
87
|
+
class: StateError
|
|
88
|
+
suggestedAction: "Cannot reach the state backend (e.g., S3 bucket); verify access and connectivity."
|
|
89
|
+
- id: state.corrupt
|
|
90
|
+
class: StateError
|
|
91
|
+
suggestedAction: "State file is corrupt; consider `clawops state recover` or contact support."
|
|
92
|
+
|
|
93
|
+
# Provider
|
|
94
|
+
- id: provider.quota_exceeded
|
|
95
|
+
class: ProviderError
|
|
96
|
+
retryable: true
|
|
97
|
+
suggestedAction: "Cloud quota exceeded; wait or request a quota increase from your provider."
|
|
98
|
+
- id: provider.region_unsupported
|
|
99
|
+
class: ProviderError
|
|
100
|
+
retryable: false
|
|
101
|
+
userActionRequired: true
|
|
102
|
+
suggestedAction: "Selected region does not support the requested resource; choose a different region."
|
|
103
|
+
- id: provider.api_rate_limited
|
|
104
|
+
class: ProviderError
|
|
105
|
+
retryable: true
|
|
106
|
+
suggestedAction: "Cloud API rate-limited; clawops will retry with backoff."
|
|
107
|
+
- id: provider.resource_not_found
|
|
108
|
+
class: ProviderError
|
|
109
|
+
retryable: false
|
|
110
|
+
suggestedAction: "Required cloud resource not found; check stack state with `clawops status`."
|
|
111
|
+
- id: provider.resource_exists
|
|
112
|
+
class: ProviderError
|
|
113
|
+
retryable: false
|
|
114
|
+
suggestedAction: "Resource with this name already exists; use `--stack` to deploy to a different name."
|
|
115
|
+
|
|
116
|
+
# Network
|
|
117
|
+
- id: network.timeout
|
|
118
|
+
class: NetworkError
|
|
119
|
+
suggestedAction: "Network timeout; check connectivity and retry."
|
|
120
|
+
- id: network.dns_failure
|
|
121
|
+
class: NetworkError
|
|
122
|
+
suggestedAction: "DNS resolution failed; check DNS configuration."
|
|
123
|
+
- id: network.tls_failure
|
|
124
|
+
class: NetworkError
|
|
125
|
+
retryable: false
|
|
126
|
+
userActionRequired: true
|
|
127
|
+
suggestedAction: "TLS handshake failed; check certificate validity and trust chain."
|
|
128
|
+
|
|
129
|
+
# Operational
|
|
130
|
+
- id: op.timeout
|
|
131
|
+
class: OperationalError
|
|
132
|
+
retryable: true
|
|
133
|
+
suggestedAction: "Operation timed out; retry. If persistent, increase timeout via --timeout flag."
|
|
134
|
+
- id: op.unexpected_state
|
|
135
|
+
class: OperationalError
|
|
136
|
+
retryable: false
|
|
137
|
+
suggestedAction: "Cloud resource in unexpected state; run `clawops refresh` then `clawops status`."
|
|
138
|
+
- id: op.openclaw_unhealthy
|
|
139
|
+
class: OperationalError
|
|
140
|
+
retryable: true
|
|
141
|
+
suggestedAction: "OpenClaw gateway not responding; check `clawops logs` for issues."
|
|
142
|
+
- id: op.ssh_connect_failed
|
|
143
|
+
class: OperationalError
|
|
144
|
+
retryable: true
|
|
145
|
+
suggestedAction: "SSH connection failed; check key path, host availability, and security group."
|
|
146
|
+
|
|
147
|
+
# Cancellation
|
|
148
|
+
- id: op.cancelled
|
|
149
|
+
class: CancelledError
|
|
150
|
+
suggestedAction: "Operation cancelled by user."
|
|
151
|
+
|
|
152
|
+
# Sensitive field patterns for redaction (R21).
|
|
153
|
+
# Used by both pino logger config and src/mcp/audit.ts.
|
|
154
|
+
redaction:
|
|
155
|
+
patterns:
|
|
156
|
+
- authorization
|
|
157
|
+
- "*.authorization"
|
|
158
|
+
- token
|
|
159
|
+
- "*.token"
|
|
160
|
+
- password
|
|
161
|
+
- "*.password"
|
|
162
|
+
- secret
|
|
163
|
+
- "*.secret"
|
|
164
|
+
- connectionString
|
|
165
|
+
- "*.connectionString"
|
|
166
|
+
- aws_access_key_id
|
|
167
|
+
- "*.aws_access_key_id"
|
|
168
|
+
- aws_secret_access_key
|
|
169
|
+
- "*.aws_secret_access_key"
|
|
170
|
+
- GOOGLE_APPLICATION_CREDENTIALS
|
|
171
|
+
- AZURE_CLIENT_SECRET
|
|
172
|
+
- HCLOUD_TOKEN
|
|
173
|
+
- DO_API_TOKEN
|
|
174
|
+
- CLOUDFLARE_API_TOKEN
|
|
175
|
+
censor: "***"
|