@ravi-hq/ravi 0.1.0 → 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/README.md +56 -6
- package/dist/auth.d.ts +39 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +97 -0
- package/dist/auth.js.map +1 -0
- package/dist/bin/ravi-secrets.d.ts +23 -0
- package/dist/bin/ravi-secrets.d.ts.map +1 -0
- package/dist/bin/ravi-secrets.js +113 -0
- package/dist/bin/ravi-secrets.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +142 -188
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +4 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +26 -17
- package/dist/client.js.map +1 -1
- package/dist/crypto.d.ts +13 -0
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +45 -5
- package/dist/crypto.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -46
- package/dist/index.js.map +1 -1
- package/dist/service.d.ts +7 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +11 -0
- package/dist/service.js.map +1 -1
- package/dist/sse.d.ts +9 -0
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +20 -2
- package/dist/sse.js.map +1 -1
- package/dist/tools/email-send.js +1 -1
- package/dist/tools/email-send.js.map +1 -1
- package/dist/tools/feedback.d.ts +2 -3
- package/dist/tools/feedback.d.ts.map +1 -1
- package/dist/tools/feedback.js +26 -18
- package/dist/tools/feedback.js.map +1 -1
- package/dist/tools/inbox.d.ts.map +1 -1
- package/dist/tools/inbox.js +15 -56
- package/dist/tools/inbox.js.map +1 -1
- package/dist/tools/passwords.d.ts.map +1 -1
- package/dist/tools/passwords.js +21 -51
- package/dist/tools/passwords.js.map +1 -1
- package/dist/tools/vault.d.ts.map +1 -1
- package/dist/tools/vault.js +4 -8
- package/dist/tools/vault.js.map +1 -1
- package/dist/types.d.ts +10 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/utils.d.ts +6 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +18 -0
- package/dist/utils.js.map +1 -1
- package/openclaw.plugin.json +3 -23
- package/package.json +5 -3
- package/skills/CLAUDE.md +0 -36
- package/skills/ravi/SKILL.md +0 -46
- package/skills/ravi-email-send/SKILL.md +0 -44
- package/skills/ravi-feedback/SKILL.md +0 -37
- package/skills/ravi-identity/SKILL.md +0 -50
- package/skills/ravi-inbox/SKILL.md +0 -58
- package/skills/ravi-login/SKILL.md +0 -42
- package/skills/ravi-passwords/SKILL.md +0 -48
- package/skills/ravi-vault/SKILL.md +0 -54
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ encrypted vault through a single plugin.
|
|
|
10
10
|
## Features
|
|
11
11
|
|
|
12
12
|
- **2 messaging channels** -- real-time email and SMS via Server-Sent Events
|
|
13
|
-
- **
|
|
13
|
+
- **19 agent tools** -- manage identities, inboxes, passwords, vault secrets, and more
|
|
14
14
|
- **E2E encryption** -- PIN-based Argon2id + NaCl SealedBox, compatible with Ravi CLI
|
|
15
15
|
- **DM policy controls** -- allowlist or open policy per channel account
|
|
16
16
|
- **Lazy crypto** -- encryption keys derived on first use, not at startup
|
|
@@ -106,7 +106,9 @@ Real-time email channel powered by SSE events from the Ravi backend.
|
|
|
106
106
|
|
|
107
107
|
### Ravi SMS
|
|
108
108
|
|
|
109
|
-
Real-time SMS channel powered by the same SSE stream.
|
|
109
|
+
Real-time SMS channel powered by the same SSE stream. **Only active when the
|
|
110
|
+
identity has a provisioned phone number** -- identities without a phone skip SMS
|
|
111
|
+
registration silently.
|
|
110
112
|
|
|
111
113
|
- **Threading model:** All messages from one phone number form a single session.
|
|
112
114
|
A new `from_number` creates a new session; subsequent messages from that number
|
|
@@ -118,7 +120,7 @@ Real-time SMS channel powered by the same SSE stream.
|
|
|
118
120
|
|
|
119
121
|
## Agent Tools
|
|
120
122
|
|
|
121
|
-
The plugin registers
|
|
123
|
+
The plugin registers 19 tools that agents can invoke.
|
|
122
124
|
|
|
123
125
|
### Identity
|
|
124
126
|
|
|
@@ -137,12 +139,13 @@ The plugin registers 17 tools that agents can invoke.
|
|
|
137
139
|
| `ravi_email_compose` | Compose and send a new email | `to`, `subject`, `body` (all required) |
|
|
138
140
|
| `ravi_email_reply` | Reply to an existing email | `message_id` (number, required), `body` (required), `reply_all` |
|
|
139
141
|
|
|
140
|
-
### SMS
|
|
142
|
+
### SMS
|
|
141
143
|
|
|
142
144
|
| Tool | Description | Parameters |
|
|
143
145
|
|------|-------------|------------|
|
|
144
146
|
| `ravi_inbox_sms` | List SMS conversations, optionally unread only | `unread` (boolean) |
|
|
145
147
|
| `ravi_read_sms` | Read all messages in an SMS conversation | `conversation_id` (string, required) |
|
|
148
|
+
| `ravi_sms_send` | Send an SMS from the active identity's phone | `to_number` (E.164, required), `body` (required) |
|
|
146
149
|
|
|
147
150
|
### Passwords
|
|
148
151
|
|
|
@@ -160,6 +163,7 @@ The plugin registers 17 tools that agents can invoke.
|
|
|
160
163
|
| `ravi_vault_list` | List all secret keys in the vault | -- |
|
|
161
164
|
| `ravi_vault_get` | Get a secret by key (auto-decrypted) | `key` (string, required) |
|
|
162
165
|
| `ravi_vault_set` | Store a secret (auto-encrypted) | `key` (string, required), `value` (string, required) |
|
|
166
|
+
| `ravi_vault_delete` | Delete a secret by UUID | `uuid` (string, required) |
|
|
163
167
|
|
|
164
168
|
### Feedback
|
|
165
169
|
|
|
@@ -191,6 +195,37 @@ end-to-end using a 6-digit PIN.
|
|
|
191
195
|
The crypto layer is lazy-initialized: keys are only derived when a tool actually
|
|
192
196
|
needs encryption or decryption.
|
|
193
197
|
|
|
198
|
+
## Secrets Provider
|
|
199
|
+
|
|
200
|
+
The plugin ships a `ravi-secrets` binary that implements the OpenClaw exec
|
|
201
|
+
secrets protocol, letting you use the Ravi vault as a secrets provider. The
|
|
202
|
+
binary is installed automatically with the package.
|
|
203
|
+
|
|
204
|
+
### Configuration
|
|
205
|
+
|
|
206
|
+
Add the provider to your OpenClaw config:
|
|
207
|
+
|
|
208
|
+
```yaml
|
|
209
|
+
secrets:
|
|
210
|
+
providers:
|
|
211
|
+
ravi:
|
|
212
|
+
source: exec
|
|
213
|
+
command: ravi-secrets
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Then reference vault secrets anywhere a secret is accepted:
|
|
217
|
+
|
|
218
|
+
```yaml
|
|
219
|
+
{ source: "exec", provider: "ravi", id: "my-api-key" }
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Requirements
|
|
223
|
+
|
|
224
|
+
- You must run `openclaw ravi login` first -- the binary reads credentials
|
|
225
|
+
from `~/.ravi/auth.json`.
|
|
226
|
+
- Vault secrets are decrypted automatically using the E2E keypair stored
|
|
227
|
+
during login. If no keypair is found, raw (encrypted) values are returned.
|
|
228
|
+
|
|
194
229
|
## Architecture
|
|
195
230
|
|
|
196
231
|
```text
|
|
@@ -200,7 +235,7 @@ Agent (OpenClaw runtime)
|
|
|
200
235
|
| '-- SSE stream --> GET /api/events/stream/
|
|
201
236
|
| Events arrive in plaintext (server decrypts before dispatch)
|
|
202
237
|
|
|
|
203
|
-
+-- Tools (
|
|
238
|
+
+-- Tools (19 agent tools)
|
|
204
239
|
| '-- REST calls --> GET/POST/DELETE /api/...
|
|
205
240
|
| Identity-scoped via X-Ravi-Identity header
|
|
206
241
|
|
|
|
@@ -233,7 +268,19 @@ Key points:
|
|
|
233
268
|
npm install
|
|
234
269
|
```
|
|
235
270
|
|
|
236
|
-
###
|
|
271
|
+
### Build Targets
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
make build # Local dev build (reads .env.local for API URL)
|
|
275
|
+
make build-prod # Production build (always uses https://ravi.app)
|
|
276
|
+
make test # Run all tests
|
|
277
|
+
make lint # Type-check without emitting (tsc --noEmit)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Publishing to npm happens only via GitHub Actions -- there is no local
|
|
281
|
+
publish target.
|
|
282
|
+
|
|
283
|
+
### npm Scripts
|
|
237
284
|
|
|
238
285
|
```bash
|
|
239
286
|
npm run build # Compile TypeScript to dist/
|
|
@@ -253,6 +300,8 @@ src/
|
|
|
253
300
|
crypto.ts # E2E encryption (Argon2id + NaCl SealedBox)
|
|
254
301
|
service.ts # Background listener service (manages SSE connections)
|
|
255
302
|
cli.ts # CLI commands (login, status, setup)
|
|
303
|
+
bin/
|
|
304
|
+
ravi-secrets.ts # OpenClaw exec secrets provider binary
|
|
256
305
|
channels/
|
|
257
306
|
email.ts # ravi-email channel definition
|
|
258
307
|
sms.ts # ravi-sms channel definition
|
|
@@ -260,6 +309,7 @@ src/
|
|
|
260
309
|
identity.ts # Identity management tools
|
|
261
310
|
inbox.ts # Email and SMS inbox tools
|
|
262
311
|
email-send.ts # Email compose and reply tools
|
|
312
|
+
sms-send.ts # SMS send tool
|
|
263
313
|
passwords.ts # Password manager tools
|
|
264
314
|
vault.ts # Vault secret tools
|
|
265
315
|
feedback.ts # Feedback tool
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth and config persistence for the Ravi plugin.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Go CLI's config package — reads/writes ~/.ravi/auth.json
|
|
5
|
+
* and ~/.ravi/config.json with the same format and permissions.
|
|
6
|
+
*
|
|
7
|
+
* @module auth
|
|
8
|
+
*/
|
|
9
|
+
/** Auth config matching the Go CLI's AuthConfig struct. */
|
|
10
|
+
export interface AuthConfig {
|
|
11
|
+
access_token: string;
|
|
12
|
+
refresh_token: string;
|
|
13
|
+
expires_at?: string;
|
|
14
|
+
user_email?: string;
|
|
15
|
+
pin_salt?: string;
|
|
16
|
+
public_key?: string;
|
|
17
|
+
private_key?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Identity config matching the Go CLI's Config struct. */
|
|
20
|
+
export interface IdentityConfig {
|
|
21
|
+
identity_uuid?: string;
|
|
22
|
+
identity_name?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Returns the global config directory (~/.ravi/). */
|
|
25
|
+
export declare function configDir(): string;
|
|
26
|
+
/** Load auth config from ~/.ravi/auth.json. Returns null if file doesn't exist. */
|
|
27
|
+
export declare function loadAuth(): AuthConfig | null;
|
|
28
|
+
/** Save auth config to ~/.ravi/auth.json with 0600 permissions. */
|
|
29
|
+
export declare function saveAuth(cfg: AuthConfig): void;
|
|
30
|
+
/** Update specific fields in auth.json without overwriting the rest.
|
|
31
|
+
* Not safe for concurrent callers — serialize externally (e.g. via RaviClient's refreshPromise). */
|
|
32
|
+
export declare function updateAuth(updates: Partial<AuthConfig>): void;
|
|
33
|
+
/** Load identity config from ~/.ravi/config.json. Returns null if file doesn't exist. */
|
|
34
|
+
export declare function loadConfig(): IdentityConfig | null;
|
|
35
|
+
/** Save identity config to ~/.ravi/config.json with 0600 permissions. */
|
|
36
|
+
export declare function saveConfig(cfg: IdentityConfig): void;
|
|
37
|
+
/** Save recovery key to ~/.ravi/recovery-key.txt with 0600 permissions. */
|
|
38
|
+
export declare function saveRecoveryKey(key: string): string;
|
|
39
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,2DAA2D;AAC3D,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,2DAA2D;AAC3D,MAAM,WAAW,cAAc;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,sDAAsD;AACtD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AASD,mFAAmF;AACnF,wBAAgB,QAAQ,IAAI,UAAU,GAAG,IAAI,CAiB5C;AAED,mEAAmE;AACnE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAI9C;AAED;qGACqG;AACrG,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAQ7D;AAID,yFAAyF;AACzF,wBAAgB,UAAU,IAAI,cAAc,GAAG,IAAI,CAiBlD;AAED,yEAAyE;AACzE,wBAAgB,UAAU,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAIpD;AAID,2EAA2E;AAC3E,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKnD"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth and config persistence for the Ravi plugin.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the Go CLI's config package — reads/writes ~/.ravi/auth.json
|
|
5
|
+
* and ~/.ravi/config.json with the same format and permissions.
|
|
6
|
+
*
|
|
7
|
+
* @module auth
|
|
8
|
+
*/
|
|
9
|
+
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { homedir } from "node:os";
|
|
12
|
+
const CONFIG_DIR_NAME = ".ravi";
|
|
13
|
+
const AUTH_FILE_NAME = "auth.json";
|
|
14
|
+
const CONFIG_FILE_NAME = "config.json";
|
|
15
|
+
const RECOVERY_KEY_FILE_NAME = "recovery-key.txt";
|
|
16
|
+
const DIR_PERM = 0o700;
|
|
17
|
+
const FILE_PERM = 0o600;
|
|
18
|
+
/** Returns the global config directory (~/.ravi/). */
|
|
19
|
+
export function configDir() {
|
|
20
|
+
return join(homedir(), CONFIG_DIR_NAME);
|
|
21
|
+
}
|
|
22
|
+
/** Ensure ~/.ravi/ exists with 0700 permissions. */
|
|
23
|
+
function ensureDir() {
|
|
24
|
+
mkdirSync(configDir(), { recursive: true, mode: DIR_PERM });
|
|
25
|
+
}
|
|
26
|
+
// ─── Auth ─────────────────────────────────────────────────────────────────────
|
|
27
|
+
/** Load auth config from ~/.ravi/auth.json. Returns null if file doesn't exist. */
|
|
28
|
+
export function loadAuth() {
|
|
29
|
+
const filePath = join(configDir(), AUTH_FILE_NAME);
|
|
30
|
+
let data;
|
|
31
|
+
try {
|
|
32
|
+
data = readFileSync(filePath, "utf-8");
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
if (err.code === "ENOENT")
|
|
36
|
+
return null;
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
return JSON.parse(data);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
throw new Error(`Failed to parse ${filePath}: file may be corrupted. ` +
|
|
44
|
+
`Delete it and run 'openclaw ravi login' to re-authenticate.`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Save auth config to ~/.ravi/auth.json with 0600 permissions. */
|
|
48
|
+
export function saveAuth(cfg) {
|
|
49
|
+
ensureDir();
|
|
50
|
+
const data = JSON.stringify(cfg, null, 2) + "\n";
|
|
51
|
+
writeFileSync(join(configDir(), AUTH_FILE_NAME), data, { mode: FILE_PERM });
|
|
52
|
+
}
|
|
53
|
+
/** Update specific fields in auth.json without overwriting the rest.
|
|
54
|
+
* Not safe for concurrent callers — serialize externally (e.g. via RaviClient's refreshPromise). */
|
|
55
|
+
export function updateAuth(updates) {
|
|
56
|
+
const existing = loadAuth();
|
|
57
|
+
if (!existing) {
|
|
58
|
+
throw new Error("Cannot update auth: ~/.ravi/auth.json not found. Run 'openclaw ravi login' first.");
|
|
59
|
+
}
|
|
60
|
+
saveAuth({ ...existing, ...updates });
|
|
61
|
+
}
|
|
62
|
+
// ─── Config (identity selector) ───────────────────────────────────────────────
|
|
63
|
+
/** Load identity config from ~/.ravi/config.json. Returns null if file doesn't exist. */
|
|
64
|
+
export function loadConfig() {
|
|
65
|
+
const filePath = join(configDir(), CONFIG_FILE_NAME);
|
|
66
|
+
let data;
|
|
67
|
+
try {
|
|
68
|
+
data = readFileSync(filePath, "utf-8");
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
if (err.code === "ENOENT")
|
|
72
|
+
return null;
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
return JSON.parse(data);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
throw new Error(`Failed to parse ${filePath}: file may be corrupted. ` +
|
|
80
|
+
`Delete it and run 'openclaw ravi login' to reconfigure.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Save identity config to ~/.ravi/config.json with 0600 permissions. */
|
|
84
|
+
export function saveConfig(cfg) {
|
|
85
|
+
ensureDir();
|
|
86
|
+
const data = JSON.stringify(cfg, null, 2) + "\n";
|
|
87
|
+
writeFileSync(join(configDir(), CONFIG_FILE_NAME), data, { mode: FILE_PERM });
|
|
88
|
+
}
|
|
89
|
+
// ─── Recovery Key ─────────────────────────────────────────────────────────────
|
|
90
|
+
/** Save recovery key to ~/.ravi/recovery-key.txt with 0600 permissions. */
|
|
91
|
+
export function saveRecoveryKey(key) {
|
|
92
|
+
ensureDir();
|
|
93
|
+
const filePath = join(configDir(), RECOVERY_KEY_FILE_NAME);
|
|
94
|
+
writeFileSync(filePath, key + "\n", { mode: FILE_PERM });
|
|
95
|
+
return filePath;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OpenClaw exec secrets provider for Ravi vault.
|
|
4
|
+
*
|
|
5
|
+
* Implements the OpenClaw exec secrets protocol:
|
|
6
|
+
* stdin: { "protocolVersion": 1, "provider": "ravi", "ids": ["key1", "key2"] }
|
|
7
|
+
* stdout: { "protocolVersion": 1, "values": { "key1": "val1", "key2": "val2" } }
|
|
8
|
+
*
|
|
9
|
+
* Reads auth credentials from ~/.ravi/auth.json (written by `openclaw ravi login`).
|
|
10
|
+
* Decrypts vault secrets using the stored E2E keypair.
|
|
11
|
+
*
|
|
12
|
+
* Usage in OpenClaw config:
|
|
13
|
+
* secrets:
|
|
14
|
+
* providers:
|
|
15
|
+
* ravi:
|
|
16
|
+
* source: exec
|
|
17
|
+
* command: ravi-secrets
|
|
18
|
+
*
|
|
19
|
+
* Then reference secrets:
|
|
20
|
+
* { source: "exec", provider: "ravi", id: "my-api-key" }
|
|
21
|
+
*/
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=ravi-secrets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ravi-secrets.d.ts","sourceRoot":"","sources":["../../src/bin/ravi-secrets.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* OpenClaw exec secrets provider for Ravi vault.
|
|
4
|
+
*
|
|
5
|
+
* Implements the OpenClaw exec secrets protocol:
|
|
6
|
+
* stdin: { "protocolVersion": 1, "provider": "ravi", "ids": ["key1", "key2"] }
|
|
7
|
+
* stdout: { "protocolVersion": 1, "values": { "key1": "val1", "key2": "val2" } }
|
|
8
|
+
*
|
|
9
|
+
* Reads auth credentials from ~/.ravi/auth.json (written by `openclaw ravi login`).
|
|
10
|
+
* Decrypts vault secrets using the stored E2E keypair.
|
|
11
|
+
*
|
|
12
|
+
* Usage in OpenClaw config:
|
|
13
|
+
* secrets:
|
|
14
|
+
* providers:
|
|
15
|
+
* ravi:
|
|
16
|
+
* source: exec
|
|
17
|
+
* command: ravi-secrets
|
|
18
|
+
*
|
|
19
|
+
* Then reference secrets:
|
|
20
|
+
* { source: "exec", provider: "ravi", id: "my-api-key" }
|
|
21
|
+
*/
|
|
22
|
+
import { RAVI_API_URL } from "../config.js";
|
|
23
|
+
import { RaviClient } from "../client.js";
|
|
24
|
+
import { createCryptoManagerFromKeyPair } from "../crypto.js";
|
|
25
|
+
import { loadAuth } from "../auth.js";
|
|
26
|
+
async function main() {
|
|
27
|
+
// Read JSON request from stdin
|
|
28
|
+
const chunks = [];
|
|
29
|
+
for await (const chunk of process.stdin) {
|
|
30
|
+
chunks.push(chunk);
|
|
31
|
+
}
|
|
32
|
+
const input = Buffer.concat(chunks).toString("utf-8").trim();
|
|
33
|
+
if (!input) {
|
|
34
|
+
writeError("No input received on stdin");
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
let request;
|
|
38
|
+
try {
|
|
39
|
+
request = JSON.parse(input);
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
writeError("Invalid JSON on stdin");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (request.protocolVersion !== 1) {
|
|
46
|
+
writeError(`Unsupported protocol version: ${request.protocolVersion}`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!Array.isArray(request.ids) || request.ids.length === 0) {
|
|
50
|
+
writeResponse({ protocolVersion: 1, values: {} });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Load auth
|
|
54
|
+
const auth = loadAuth();
|
|
55
|
+
if (!auth?.access_token) {
|
|
56
|
+
writeError("Not authenticated. Run 'openclaw ravi login' first.");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Create client
|
|
60
|
+
const client = new RaviClient({
|
|
61
|
+
apiUrl: RAVI_API_URL,
|
|
62
|
+
token: auth.access_token,
|
|
63
|
+
refreshToken: auth.refresh_token,
|
|
64
|
+
});
|
|
65
|
+
// Create crypto manager for decryption
|
|
66
|
+
let decrypt;
|
|
67
|
+
if (auth.public_key && auth.private_key) {
|
|
68
|
+
try {
|
|
69
|
+
const crypto = createCryptoManagerFromKeyPair(auth.public_key, auth.private_key);
|
|
70
|
+
decrypt = (value) => crypto.decrypt(value);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Continue without decryption — return raw (encrypted) values
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Fetch each requested secret
|
|
77
|
+
const values = {};
|
|
78
|
+
const errors = {};
|
|
79
|
+
await Promise.all(request.ids.map(async (key) => {
|
|
80
|
+
try {
|
|
81
|
+
const secret = await client.getSecret(key);
|
|
82
|
+
let value = secret.value;
|
|
83
|
+
if (decrypt && value) {
|
|
84
|
+
try {
|
|
85
|
+
value = await decrypt(value);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Return raw value if decryption fails
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
values[key] = value;
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
errors[key] = err instanceof Error ? err.message : String(err);
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
const response = { protocolVersion: 1, values };
|
|
98
|
+
if (Object.keys(errors).length > 0) {
|
|
99
|
+
response.errors = errors;
|
|
100
|
+
}
|
|
101
|
+
writeResponse(response);
|
|
102
|
+
}
|
|
103
|
+
function writeResponse(response) {
|
|
104
|
+
process.stdout.write(JSON.stringify(response) + "\n");
|
|
105
|
+
}
|
|
106
|
+
function writeError(message) {
|
|
107
|
+
writeResponse({ protocolVersion: 1, values: {}, errors: { _: message } });
|
|
108
|
+
}
|
|
109
|
+
main().catch((err) => {
|
|
110
|
+
writeError(err instanceof Error ? err.message : String(err));
|
|
111
|
+
process.exit(1);
|
|
112
|
+
});
|
|
113
|
+
//# sourceMappingURL=ravi-secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ravi-secrets.js","sourceRoot":"","sources":["../../src/bin/ravi-secrets.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA2GnD,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IACzB,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;;OAMG;IACH,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACxE;AAID;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,UAAU,EA8QnC,CAAC"}
|