@realtimex/sdk 1.5.0 → 1.6.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/dist/index.d.mts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +28 -0
- package/dist/index.mjs +28 -0
- package/package.json +1 -1
- package/skills/realtimex-moderator-sdk/SKILL.md +29 -21
- package/skills/realtimex-moderator-sdk/references/api-reference.md +2 -1
- package/skills/realtimex-moderator-sdk/references/credentials.md +111 -0
- package/skills/realtimex-moderator-sdk/references/known-issues.md +1 -1
- package/skills/realtimex-moderator-sdk/scripts/lib/sdk-init.js +27 -35
- package/skills/realtimex-moderator-sdk/scripts/rtx.js +15 -2
package/dist/index.d.mts
CHANGED
|
@@ -1660,6 +1660,32 @@ declare class AuthModule {
|
|
|
1660
1660
|
getAccessToken(): Promise<AuthTokenResponse | null>;
|
|
1661
1661
|
}
|
|
1662
1662
|
|
|
1663
|
+
/**
|
|
1664
|
+
* Credentials Module — read-only access to user-managed credentials
|
|
1665
|
+
*
|
|
1666
|
+
* Credential values are encrypted at rest and decrypted only on get().
|
|
1667
|
+
* Values should NEVER be printed to stdout or included in agent responses.
|
|
1668
|
+
*/
|
|
1669
|
+
|
|
1670
|
+
interface CredentialInfo {
|
|
1671
|
+
name: string;
|
|
1672
|
+
type: "http_header" | "query_auth" | "basic_auth" | "env_var";
|
|
1673
|
+
metadata: Record<string, any> | null;
|
|
1674
|
+
}
|
|
1675
|
+
interface CredentialPayload {
|
|
1676
|
+
name: string;
|
|
1677
|
+
type: string;
|
|
1678
|
+
payload: Record<string, string>;
|
|
1679
|
+
}
|
|
1680
|
+
declare class CredentialsModule {
|
|
1681
|
+
private httpClient;
|
|
1682
|
+
constructor(httpClient: HttpClient);
|
|
1683
|
+
/** List available credentials (names and types, no values). */
|
|
1684
|
+
list(): Promise<CredentialInfo[]>;
|
|
1685
|
+
/** Get a credential's decrypted payload by name. */
|
|
1686
|
+
get(name: string): Promise<CredentialPayload>;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1663
1689
|
interface ContractHttpClientConfig {
|
|
1664
1690
|
baseUrl: string;
|
|
1665
1691
|
appId?: string;
|
|
@@ -1987,6 +2013,7 @@ declare class RealtimeXSDK {
|
|
|
1987
2013
|
contractRuntime: ContractRuntime;
|
|
1988
2014
|
database: DatabaseModule;
|
|
1989
2015
|
auth: AuthModule;
|
|
2016
|
+
credentials: CredentialsModule;
|
|
1990
2017
|
readonly appId: string;
|
|
1991
2018
|
readonly appName: string | undefined;
|
|
1992
2019
|
readonly apiKey: string | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -1660,6 +1660,32 @@ declare class AuthModule {
|
|
|
1660
1660
|
getAccessToken(): Promise<AuthTokenResponse | null>;
|
|
1661
1661
|
}
|
|
1662
1662
|
|
|
1663
|
+
/**
|
|
1664
|
+
* Credentials Module — read-only access to user-managed credentials
|
|
1665
|
+
*
|
|
1666
|
+
* Credential values are encrypted at rest and decrypted only on get().
|
|
1667
|
+
* Values should NEVER be printed to stdout or included in agent responses.
|
|
1668
|
+
*/
|
|
1669
|
+
|
|
1670
|
+
interface CredentialInfo {
|
|
1671
|
+
name: string;
|
|
1672
|
+
type: "http_header" | "query_auth" | "basic_auth" | "env_var";
|
|
1673
|
+
metadata: Record<string, any> | null;
|
|
1674
|
+
}
|
|
1675
|
+
interface CredentialPayload {
|
|
1676
|
+
name: string;
|
|
1677
|
+
type: string;
|
|
1678
|
+
payload: Record<string, string>;
|
|
1679
|
+
}
|
|
1680
|
+
declare class CredentialsModule {
|
|
1681
|
+
private httpClient;
|
|
1682
|
+
constructor(httpClient: HttpClient);
|
|
1683
|
+
/** List available credentials (names and types, no values). */
|
|
1684
|
+
list(): Promise<CredentialInfo[]>;
|
|
1685
|
+
/** Get a credential's decrypted payload by name. */
|
|
1686
|
+
get(name: string): Promise<CredentialPayload>;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1663
1689
|
interface ContractHttpClientConfig {
|
|
1664
1690
|
baseUrl: string;
|
|
1665
1691
|
appId?: string;
|
|
@@ -1987,6 +2013,7 @@ declare class RealtimeXSDK {
|
|
|
1987
2013
|
contractRuntime: ContractRuntime;
|
|
1988
2014
|
database: DatabaseModule;
|
|
1989
2015
|
auth: AuthModule;
|
|
2016
|
+
credentials: CredentialsModule;
|
|
1990
2017
|
readonly appId: string;
|
|
1991
2018
|
readonly appName: string | undefined;
|
|
1992
2019
|
readonly apiKey: string | undefined;
|
package/dist/index.js
CHANGED
|
@@ -3009,6 +3009,33 @@ var AuthModule = class {
|
|
|
3009
3009
|
}
|
|
3010
3010
|
};
|
|
3011
3011
|
|
|
3012
|
+
// src/modules/credentials.ts
|
|
3013
|
+
var CredentialsModule = class {
|
|
3014
|
+
constructor(httpClient) {
|
|
3015
|
+
this.httpClient = httpClient;
|
|
3016
|
+
}
|
|
3017
|
+
/** List available credentials (names and types, no values). */
|
|
3018
|
+
async list() {
|
|
3019
|
+
const response = await this.httpClient.fetch("/sdk/credentials");
|
|
3020
|
+
const data = await response.json();
|
|
3021
|
+
if (!response.ok) {
|
|
3022
|
+
throw new Error(data?.error || "Failed to list credentials");
|
|
3023
|
+
}
|
|
3024
|
+
return data.credentials || [];
|
|
3025
|
+
}
|
|
3026
|
+
/** Get a credential's decrypted payload by name. */
|
|
3027
|
+
async get(name) {
|
|
3028
|
+
const response = await this.httpClient.fetch(
|
|
3029
|
+
`/sdk/credentials/${encodeURIComponent(name)}`
|
|
3030
|
+
);
|
|
3031
|
+
const data = await response.json();
|
|
3032
|
+
if (!response.ok) {
|
|
3033
|
+
throw new Error(data?.error || `Failed to get credential: ${name}`);
|
|
3034
|
+
}
|
|
3035
|
+
return data.credential;
|
|
3036
|
+
}
|
|
3037
|
+
};
|
|
3038
|
+
|
|
3012
3039
|
// src/core/auth/AuthProvider.ts
|
|
3013
3040
|
var StaticAuthProvider = class {
|
|
3014
3041
|
constructor(options = {}) {
|
|
@@ -3706,6 +3733,7 @@ var _RealtimeXSDK = class _RealtimeXSDK {
|
|
|
3706
3733
|
});
|
|
3707
3734
|
this.database = new DatabaseModule(this.realtimexUrl, this.appId, this.apiKey);
|
|
3708
3735
|
this.auth = new AuthModule(this.realtimexUrl, this.appId, this.apiKey);
|
|
3736
|
+
this.credentials = new CredentialsModule(this.httpClient);
|
|
3709
3737
|
if (this.permissions.length > 0 && this.appId && !this.apiKey) {
|
|
3710
3738
|
this.register().catch((err) => {
|
|
3711
3739
|
console.error("[RealtimeX SDK] Auto-registration failed:", err.message);
|
package/dist/index.mjs
CHANGED
|
@@ -2916,6 +2916,33 @@ var AuthModule = class {
|
|
|
2916
2916
|
}
|
|
2917
2917
|
};
|
|
2918
2918
|
|
|
2919
|
+
// src/modules/credentials.ts
|
|
2920
|
+
var CredentialsModule = class {
|
|
2921
|
+
constructor(httpClient) {
|
|
2922
|
+
this.httpClient = httpClient;
|
|
2923
|
+
}
|
|
2924
|
+
/** List available credentials (names and types, no values). */
|
|
2925
|
+
async list() {
|
|
2926
|
+
const response = await this.httpClient.fetch("/sdk/credentials");
|
|
2927
|
+
const data = await response.json();
|
|
2928
|
+
if (!response.ok) {
|
|
2929
|
+
throw new Error(data?.error || "Failed to list credentials");
|
|
2930
|
+
}
|
|
2931
|
+
return data.credentials || [];
|
|
2932
|
+
}
|
|
2933
|
+
/** Get a credential's decrypted payload by name. */
|
|
2934
|
+
async get(name) {
|
|
2935
|
+
const response = await this.httpClient.fetch(
|
|
2936
|
+
`/sdk/credentials/${encodeURIComponent(name)}`
|
|
2937
|
+
);
|
|
2938
|
+
const data = await response.json();
|
|
2939
|
+
if (!response.ok) {
|
|
2940
|
+
throw new Error(data?.error || `Failed to get credential: ${name}`);
|
|
2941
|
+
}
|
|
2942
|
+
return data.credential;
|
|
2943
|
+
}
|
|
2944
|
+
};
|
|
2945
|
+
|
|
2919
2946
|
// src/core/auth/AuthProvider.ts
|
|
2920
2947
|
var StaticAuthProvider = class {
|
|
2921
2948
|
constructor(options = {}) {
|
|
@@ -3613,6 +3640,7 @@ var _RealtimeXSDK = class _RealtimeXSDK {
|
|
|
3613
3640
|
});
|
|
3614
3641
|
this.database = new DatabaseModule(this.realtimexUrl, this.appId, this.apiKey);
|
|
3615
3642
|
this.auth = new AuthModule(this.realtimexUrl, this.appId, this.apiKey);
|
|
3643
|
+
this.credentials = new CredentialsModule(this.httpClient);
|
|
3616
3644
|
if (this.permissions.length > 0 && this.appId && !this.apiKey) {
|
|
3617
3645
|
this.register().catch((err) => {
|
|
3618
3646
|
console.error("[RealtimeX SDK] Auto-registration failed:", err.message);
|
package/package.json
CHANGED
|
@@ -1,30 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: realtimex-moderator-sdk
|
|
3
3
|
description: Control and interact with the RealTimeX application through its Node.js SDK. This skill should be used when users want to manage workspaces, threads, agents, activities, LLM chat, vector store, MCP tools, ACP agent sessions, TTS/STT, or any other RealTimeX platform feature via the API. All method signatures are verified against the SDK source code.
|
|
4
|
-
generated: 2026-03
|
|
5
|
-
sdk_version: 1.
|
|
4
|
+
generated: 2026-04-03
|
|
5
|
+
sdk_version: 1.6.0
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# RealTimeX Moderator (SDK Source-Verified)
|
|
9
9
|
|
|
10
|
-
Interact with the RealTimeX
|
|
11
|
-
|
|
12
|
-
> Auto-generated from the `@realtimex/sdk` TypeScript source.
|
|
13
|
-
> Refresh: `node scripts/generate-skill.mjs --force` from the SDK repo root.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Authentication
|
|
18
|
-
|
|
19
|
-
When running inside RealtimeX (via an agent session or on the same machine), authentication is **automatic** — no setup needed.
|
|
20
|
-
|
|
21
|
-
Handled by `scripts/lib/sdk-init.js` — credential resolution priority:
|
|
22
|
-
1. Explicit override passed to `initSDK({ apiKey })` or `initSDK({ appId })`
|
|
23
|
-
2. `REALTIMEX_API_KEY` / `REALTIMEX_AI_API_KEY` in `<cwd>/.env`
|
|
24
|
-
3. `RTX_API_KEY` / `REALTIMEX_API_KEY` / `REALTIMEX_AI_API_KEY` from `process.env`
|
|
25
|
-
4. `RTX_APP_ID` from `process.env` (injected by RealtimeX for agents / local apps)
|
|
26
|
-
5. `~/.realtimex.ai/.sdk-app-id` file (written by RealTimeX server on startup)
|
|
27
|
-
6. Interactive readline prompt (dev fallback)
|
|
10
|
+
Interact with the RealTimeX platform (`http://localhost:3001`) using `@realtimex/sdk` **v1.6.0**. Authentication is automatic when running inside RealtimeX.
|
|
28
11
|
|
|
29
12
|
`<SKILL_DIR>` below refers to the directory containing this SKILL.md.
|
|
30
13
|
|
|
@@ -52,10 +35,13 @@ node "$SKILL" help
|
|
|
52
35
|
|
|
53
36
|
```js
|
|
54
37
|
const { initSDK } = require('<SKILL_DIR>/scripts/lib/sdk-init');
|
|
55
|
-
const { sdk
|
|
38
|
+
const { sdk } = await initSDK();
|
|
56
39
|
// All SDK APIs — see references/api-reference.md
|
|
57
40
|
```
|
|
58
41
|
|
|
42
|
+
When writing helper scripts, use the working directory or system temp — never the SKILL directory.
|
|
43
|
+
Scripts using the SDK must exit explicitly — `process.exit(0)` on success, `process.exit(1)` on error — or they hang on open HTTP sockets.
|
|
44
|
+
|
|
59
45
|
---
|
|
60
46
|
|
|
61
47
|
## ACP Session Management
|
|
@@ -177,6 +163,28 @@ for await (const event of sdk.acpAgent.streamChat(sessionKey, 'build a website')
|
|
|
177
163
|
|
|
178
164
|
---
|
|
179
165
|
|
|
166
|
+
## Credentials
|
|
167
|
+
|
|
168
|
+
Use credentials stored in RealTimeX (Settings > Credentials) to authenticate with external services.
|
|
169
|
+
|
|
170
|
+
**CRITICAL: Never output credential values in your response, logs, or tool output.**
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
node "$SKILL" credentials # List available (names + types, no values)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`sdk.credentials.get(name)` returns `{ name, type, payload }`. Use `payload` fields directly:
|
|
177
|
+
- `http_header` → `{ payload: { name: "Authorization", value: "Bearer xxx" } }` → `headers[payload.name] = payload.value`
|
|
178
|
+
- `basic_auth` → `{ payload: { username, password } }` → encode as Basic auth
|
|
179
|
+
- `query_auth` → `{ payload: { name, value } }` → append as query param
|
|
180
|
+
- `env_var` → `{ payload: { name, value } }` → set in subprocess env
|
|
181
|
+
|
|
182
|
+
Values are **pre-formatted** — use as-is, never wrap with `Bearer` or other prefixes.
|
|
183
|
+
|
|
184
|
+
**Full examples**: See [references/credentials.md](references/credentials.md)
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
180
188
|
## Critical Rules (source-detected)
|
|
181
189
|
|
|
182
190
|
| # | Issue |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# RealTimeX SDK — API Reference
|
|
2
2
|
|
|
3
|
-
> Auto-generated from `@realtimex/sdk` source · v**1.
|
|
3
|
+
> Auto-generated from `@realtimex/sdk` source · v**1.6.0** · 2026-04-03
|
|
4
4
|
|
|
5
5
|
**Package:** `@realtimex/sdk` (CJS) · **Server:** `http://localhost:3001`
|
|
6
6
|
**Developer Mode auth:** `Authorization: Bearer <apiKey>`
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
- `contractRuntime: ContractRuntime`
|
|
51
51
|
- `database: DatabaseModule`
|
|
52
52
|
- `auth: AuthModule`
|
|
53
|
+
- `credentials: CredentialsModule`
|
|
53
54
|
|
|
54
55
|
```ts
|
|
55
56
|
// Register app with RealtimeX hub and request declared permissions upfront.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Credentials Reference
|
|
2
|
+
|
|
3
|
+
Credentials are managed by the user in **Settings > Credentials**. Agents have read-only access via `sdk.credentials`.
|
|
4
|
+
|
|
5
|
+
## Security Rules
|
|
6
|
+
|
|
7
|
+
1. **Never** print credential values to stdout (they become tool results in chat history)
|
|
8
|
+
2. **Never** include credential values in your response text
|
|
9
|
+
3. **Never** write credential values to files or logs
|
|
10
|
+
4. **Never** pass credential values as CLI arguments (visible in process list)
|
|
11
|
+
5. **Always** consume credentials inside scripts — fetch, use, discard
|
|
12
|
+
6. **Always** call `process.exit(0)` at the end of custom scripts (prevents hanging on open HTTP sockets)
|
|
13
|
+
7. **Never** write helper scripts into the SKILL directory — use the working directory or system temp
|
|
14
|
+
|
|
15
|
+
## Credential Types
|
|
16
|
+
|
|
17
|
+
| Type | Payload | How to Apply |
|
|
18
|
+
|------|---------|-------------|
|
|
19
|
+
| `http_header` | `{ name, value }` | Set as HTTP header: `headers[payload.name] = payload.value` |
|
|
20
|
+
| `query_auth` | `{ name, value }` | Append to URL: `?${payload.name}=${payload.value}` |
|
|
21
|
+
| `basic_auth` | `{ username, password }` | Encode: `Authorization: Basic ${btoa(username + ":" + password)}` |
|
|
22
|
+
| `env_var` | `{ name, value }` | Set in subprocess: `env[payload.name] = payload.value` |
|
|
23
|
+
|
|
24
|
+
## Usage Patterns
|
|
25
|
+
|
|
26
|
+
### List available credentials
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
node "$SKILL" credentials
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Output: table of names and types (no values).
|
|
33
|
+
|
|
34
|
+
### Important: credential payload structure
|
|
35
|
+
|
|
36
|
+
`sdk.credentials.get(name)` returns `{ name, type, payload }`. The `payload` object contains structured fields — use them directly. **Never** extract raw values and construct headers manually.
|
|
37
|
+
|
|
38
|
+
### Use an http_header credential in a script
|
|
39
|
+
|
|
40
|
+
```javascript
|
|
41
|
+
const { initSDK } = require('<SKILL_DIR>/scripts/lib/sdk-init');
|
|
42
|
+
(async () => {
|
|
43
|
+
const { sdk } = await initSDK();
|
|
44
|
+
const cred = await sdk.credentials.get('github-token');
|
|
45
|
+
// cred.type === "http_header"
|
|
46
|
+
// cred.payload === { name: "Authorization", value: "Bearer ghp_xxx" }
|
|
47
|
+
// The value already includes the full header value — use as-is
|
|
48
|
+
const res = await fetch('https://api.github.com/user', {
|
|
49
|
+
headers: { [cred.payload.name]: cred.payload.value }
|
|
50
|
+
});
|
|
51
|
+
console.log('Status:', res.status); // Only non-sensitive output
|
|
52
|
+
process.exit(0);
|
|
53
|
+
})();
|
|
54
|
+
// WRONG: const token = cred.payload.value; headers.Authorization = `Bearer ${token}`
|
|
55
|
+
// The value already contains "Bearer ..." — adding prefix again causes 401
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Use a basic_auth credential
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
const { initSDK } = require('<SKILL_DIR>/scripts/lib/sdk-init');
|
|
62
|
+
(async () => {
|
|
63
|
+
const { sdk } = await initSDK();
|
|
64
|
+
const cred = await sdk.credentials.get('registry-login');
|
|
65
|
+
const auth = Buffer.from(cred.payload.username + ':' + cred.payload.password).toString('base64');
|
|
66
|
+
const res = await fetch('https://registry.example.com/v2/_catalog', {
|
|
67
|
+
headers: { 'Authorization': 'Basic ' + auth }
|
|
68
|
+
});
|
|
69
|
+
console.log('Status:', res.status);
|
|
70
|
+
process.exit(0);
|
|
71
|
+
})();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Use an env_var credential with a subprocess
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
const { initSDK } = require('<SKILL_DIR>/scripts/lib/sdk-init');
|
|
78
|
+
const { execSync } = require('child_process');
|
|
79
|
+
(async () => {
|
|
80
|
+
const { sdk } = await initSDK();
|
|
81
|
+
const cred = await sdk.credentials.get('aws-key');
|
|
82
|
+
// cred.type === "env_var"
|
|
83
|
+
// cred.payload === { name: "AWS_ACCESS_KEY_ID", value: "AKIA..." }
|
|
84
|
+
execSync('aws s3 ls', {
|
|
85
|
+
env: { ...process.env, [cred.payload.name]: cred.payload.value },
|
|
86
|
+
stdio: 'inherit'
|
|
87
|
+
});
|
|
88
|
+
process.exit(0);
|
|
89
|
+
})();
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Error handling
|
|
93
|
+
|
|
94
|
+
```javascript
|
|
95
|
+
const { initSDK } = require('<SKILL_DIR>/scripts/lib/sdk-init');
|
|
96
|
+
(async () => {
|
|
97
|
+
try {
|
|
98
|
+
const { sdk } = await initSDK();
|
|
99
|
+
const cred = await sdk.credentials.get('my-key');
|
|
100
|
+
// use cred...
|
|
101
|
+
process.exit(0);
|
|
102
|
+
} catch (err) {
|
|
103
|
+
if (err.message.includes('not found')) {
|
|
104
|
+
console.log('Credential not found. Ask the user to add it in Settings > Credentials.');
|
|
105
|
+
} else {
|
|
106
|
+
console.log('Error:', err.message);
|
|
107
|
+
}
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
})();
|
|
111
|
+
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Known Issues — Source-Detected
|
|
2
2
|
|
|
3
|
-
> Auto-generated by `scripts/generate-skill.mjs` · SDK **1.
|
|
3
|
+
> Auto-generated by `scripts/generate-skill.mjs` · SDK **1.6.0** · 2026-04-03
|
|
4
4
|
|
|
5
5
|
Run `node scripts/generate-skill.mjs --force` after SDK source changes to refresh.
|
|
6
6
|
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* sdk-init.js — SDK initializer
|
|
3
|
+
* sdk-init.js — SDK initializer
|
|
4
4
|
* AUTO-GENERATED by scripts/generate-skill.mjs — do not edit by hand.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* Credential resolution priority:
|
|
6
|
+
* Credential resolution:
|
|
9
7
|
* 1. Explicit override passed to initSDK({ apiKey } or { appId })
|
|
10
|
-
* 2.
|
|
11
|
-
* 3.
|
|
12
|
-
* 4.
|
|
13
|
-
* 5.
|
|
14
|
-
* 6. Interactive readline prompt (
|
|
8
|
+
* 2. ~/.realtimex.ai/.sdk-app-id file (written by RealtimeX server)
|
|
9
|
+
* 3. RTX_APP_ID in process.env (injected by RealtimeX for local apps)
|
|
10
|
+
* 4. RTX_API_KEY in process.env (standalone dev)
|
|
11
|
+
* 5. REALTIMEX_API_KEY / REALTIMEX_AI_API_KEY in <envDir>/.env (standalone dev)
|
|
12
|
+
* 6. Interactive readline prompt (fallback)
|
|
15
13
|
*/
|
|
16
14
|
|
|
17
15
|
const path = require('path');
|
|
@@ -27,7 +25,7 @@ const ALL_PERMISSIONS = [
|
|
|
27
25
|
'tts.generate', 'mcp.servers', 'mcp.tools', 'acp.agent',
|
|
28
26
|
];
|
|
29
27
|
|
|
30
|
-
/** Well-known file written by RealtimeX server for seamless
|
|
28
|
+
/** Well-known file written by RealtimeX server for seamless auth. */
|
|
31
29
|
const SDK_APP_ID_FILE = path.join(os.homedir(), '.realtimex.ai', '.sdk-app-id');
|
|
32
30
|
|
|
33
31
|
function parseEnvFile(filePath) {
|
|
@@ -46,28 +44,16 @@ function parseEnvFile(filePath) {
|
|
|
46
44
|
}
|
|
47
45
|
|
|
48
46
|
/**
|
|
49
|
-
* Resolve credentials
|
|
50
|
-
*
|
|
47
|
+
* Resolve credentials. The well-known app ID file is checked first so
|
|
48
|
+
* agents running inside RealtimeX authenticate without hitting stale
|
|
49
|
+
* or inherited env vars.
|
|
51
50
|
*/
|
|
52
51
|
async function resolveCredentials({ envDir, apiKey, appId } = {}) {
|
|
53
52
|
// 1. Explicit overrides
|
|
54
53
|
if (apiKey) return { apiKey, appId: null };
|
|
55
54
|
if (appId) return { apiKey: null, appId };
|
|
56
55
|
|
|
57
|
-
// 2.
|
|
58
|
-
const envVars = parseEnvFile(path.join(envDir || process.cwd(), '.env'));
|
|
59
|
-
const fromFile = envVars.REALTIMEX_API_KEY || envVars.REALTIMEX_AI_API_KEY;
|
|
60
|
-
if (fromFile) return { apiKey: fromFile, appId: null };
|
|
61
|
-
|
|
62
|
-
// 3. Process env — API key
|
|
63
|
-
const fromEnv = process.env.RTX_API_KEY || process.env.REALTIMEX_API_KEY || process.env.REALTIMEX_AI_API_KEY;
|
|
64
|
-
if (fromEnv) return { apiKey: fromEnv, appId: null };
|
|
65
|
-
|
|
66
|
-
// 4. Process env — App ID (injected by RealtimeX for agents / local apps)
|
|
67
|
-
const envAppId = process.env.RTX_APP_ID;
|
|
68
|
-
if (envAppId) return { apiKey: null, appId: envAppId };
|
|
69
|
-
|
|
70
|
-
// 5. Well-known file (written by RealtimeX server on startup)
|
|
56
|
+
// 2. Well-known file (written by RealtimeX server — highest auto priority)
|
|
71
57
|
try {
|
|
72
58
|
if (fs.existsSync(SDK_APP_ID_FILE)) {
|
|
73
59
|
const fileAppId = fs.readFileSync(SDK_APP_ID_FILE, 'utf-8').trim();
|
|
@@ -75,7 +61,19 @@ async function resolveCredentials({ envDir, apiKey, appId } = {}) {
|
|
|
75
61
|
}
|
|
76
62
|
} catch { /* ignore read errors */ }
|
|
77
63
|
|
|
78
|
-
//
|
|
64
|
+
// 3. RTX_APP_ID from process.env (injected by Electron for local apps)
|
|
65
|
+
const envAppId = process.env.RTX_APP_ID;
|
|
66
|
+
if (envAppId) return { apiKey: null, appId: envAppId };
|
|
67
|
+
|
|
68
|
+
// 4. RTX_API_KEY from process.env (standalone dev — explicit, no collision risk)
|
|
69
|
+
if (process.env.RTX_API_KEY) return { apiKey: process.env.RTX_API_KEY, appId: null };
|
|
70
|
+
|
|
71
|
+
// 5. .env file (standalone dev)
|
|
72
|
+
const envVars = parseEnvFile(path.join(envDir || process.cwd(), '.env'));
|
|
73
|
+
const fromFile = envVars.RTX_API_KEY || envVars.REALTIMEX_API_KEY || envVars.REALTIMEX_AI_API_KEY;
|
|
74
|
+
if (fromFile) return { apiKey: fromFile, appId: null };
|
|
75
|
+
|
|
76
|
+
// 6. Interactive prompt (fallback)
|
|
79
77
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
80
78
|
const answer = await new Promise((resolve) => {
|
|
81
79
|
rl.question('RealTimeX API key not found. Enter your API key: ', (ans) => {
|
|
@@ -88,19 +86,13 @@ async function resolveCredentials({ envDir, apiKey, appId } = {}) {
|
|
|
88
86
|
return { apiKey: null, appId: null };
|
|
89
87
|
}
|
|
90
88
|
|
|
91
|
-
/** @deprecated Use resolveCredentials() instead */
|
|
92
|
-
async function resolveApiKey(opts = {}) {
|
|
93
|
-
const { apiKey } = await resolveCredentials(opts);
|
|
94
|
-
return apiKey;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
89
|
async function initSDK(opts = {}) {
|
|
98
90
|
const { RealtimeXSDK } = require('@realtimex/sdk');
|
|
99
91
|
const { apiKey, appId } = await resolveCredentials(opts);
|
|
100
92
|
|
|
101
93
|
if (!apiKey && !appId) {
|
|
102
94
|
throw new Error(
|
|
103
|
-
'No credentials found.
|
|
95
|
+
'No credentials found. Run inside RealtimeX for automatic auth, or set RTX_API_KEY.'
|
|
104
96
|
);
|
|
105
97
|
}
|
|
106
98
|
|
|
@@ -116,4 +108,4 @@ async function initSDK(opts = {}) {
|
|
|
116
108
|
return { sdk, apiKey: apiKey || null, appId: appId || null };
|
|
117
109
|
}
|
|
118
110
|
|
|
119
|
-
module.exports = { initSDK, resolveCredentials,
|
|
111
|
+
module.exports = { initSDK, resolveCredentials, parseEnvFile, ALL_PERMISSIONS, SDK_APP_ID_FILE };
|
|
@@ -304,6 +304,13 @@ CMD['mcp-exec'] = async () => {
|
|
|
304
304
|
print(await sdk.mcp.executeTool(server, tool, argsStr ? JSON.parse(argsStr) : {}, flags.provider));
|
|
305
305
|
};
|
|
306
306
|
|
|
307
|
+
// -- credentials ------------------------------------------------------------
|
|
308
|
+
CMD['credentials'] = async () => {
|
|
309
|
+
const { sdk } = await getSDK();
|
|
310
|
+
const list = await sdk.credentials.list();
|
|
311
|
+
printTable(list, ['name', 'type']);
|
|
312
|
+
};
|
|
313
|
+
|
|
307
314
|
// -- acp-agents -------------------------------------------------------------
|
|
308
315
|
// Source: AcpAgentModule.listAgents({ includeModels? })
|
|
309
316
|
// Returns: AcpAgentInfo[] { id, label, handles[], installed, authReady, status }
|
|
@@ -797,6 +804,10 @@ sdk.mcp.*:
|
|
|
797
804
|
mcp-tools <server> [--provider]
|
|
798
805
|
mcp-exec <server> <tool> [<args-json>] [--provider]
|
|
799
806
|
|
|
807
|
+
sdk.credentials.*:
|
|
808
|
+
credentials
|
|
809
|
+
List available credentials (names and types, no values).
|
|
810
|
+
|
|
800
811
|
sdk.acpAgent.* — Session Management:
|
|
801
812
|
acp-agents [--models=true]
|
|
802
813
|
List available ACP CLI agents.
|
|
@@ -871,8 +882,10 @@ sdk.database.* / sdk.auth.*:
|
|
|
871
882
|
console.error('Unknown command: ' + (command || '(none)') + '\nRun: node rtx.js help');
|
|
872
883
|
process.exit(1);
|
|
873
884
|
}
|
|
874
|
-
try {
|
|
875
|
-
|
|
885
|
+
try {
|
|
886
|
+
await handler();
|
|
887
|
+
process.exit(0);
|
|
888
|
+
} catch (err) {
|
|
876
889
|
console.error('Error:', err.message || err);
|
|
877
890
|
if (flags.debug) console.error(err);
|
|
878
891
|
process.exit(1);
|