@realtimex/sdk 1.4.0 → 1.4.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.
@@ -0,0 +1,237 @@
1
+ # Known Issues — Source-Detected
2
+
3
+ > Auto-generated by `scripts/generate-skill.mjs` · SDK **1.4.3** · 2026-03-26
4
+
5
+ Run `node scripts/generate-skill.mjs --force` after SDK source changes to refresh.
6
+
7
+ **12/12 issues confirmed in current source.**
8
+
9
+ ---
10
+
11
+ ## 1. `sdk.webhook.triggerAgent()` sends `event: "task.trigger"` — server expects `"trigger-agent"`
12
+
13
+ **Status:** 🔴 DETECTED
14
+ **File:** `modules/webhook.ts`
15
+ **Evidence:** `Found `event: "task.trigger"` hardcoded in triggerAgent() body (line ~100)`
16
+
17
+ **Correct usage:**
18
+ ```js
19
+ // ❌ WRONG — SDK sends 'task.trigger' but server enum only accepts 'trigger-agent'
20
+ await sdk.webhook.triggerAgent({ auto_run: true, agent_name: 'agent', ... });
21
+
22
+ // ✅ CORRECT — raw fetch with server-expected event string
23
+ const resp = await fetch('http://localhost:3001/webhooks/realtimex', {
24
+ method: 'POST',
25
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${apiKey}` },
26
+ body: JSON.stringify({
27
+ event: 'trigger-agent',
28
+ payload: { auto_run: true, agent_name: 'document2speech', workspace_slug: 'sdfsdf', prompt: '...' },
29
+ }),
30
+ });
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 2. `sdk.task.start/complete/fail` take positional `(taskUuid, ...)` — NOT `{ task_uuid }` object
36
+
37
+ **Status:** 🔴 DETECTED
38
+ **File:** `modules/task.ts`
39
+ **Evidence:** `start(taskUuid: string, ...) | complete(taskUuid, result, ...) | fail(taskUuid, error: string, ...)`
40
+
41
+ **Correct usage:**
42
+ ```js
43
+ // ❌ WRONG
44
+ await sdk.task.start({ task_uuid: uuid });
45
+ await sdk.task.complete({ task_uuid: uuid, result: { out: 'done' } });
46
+
47
+ // ✅ CORRECT
48
+ await sdk.task.start(uuid);
49
+ await sdk.task.complete(uuid, { out: 'done' });
50
+ await sdk.task.fail(uuid, 'error message');
51
+ await sdk.task.start(uuid, { machineId: 'machine-01' });
52
+ ```
53
+
54
+ ---
55
+
56
+ ## 3. `sdk.activities.list()` returns `Activity[]` directly — NOT `{ activities: [...] }`
57
+
58
+ **Status:** 🔴 DETECTED
59
+ **File:** `modules/activities.ts`
60
+ **Evidence:** `Return type is Promise<Activity[]>`
61
+
62
+ **Correct usage:**
63
+ ```js
64
+ // ❌ WRONG
65
+ const { activities } = await sdk.activities.list();
66
+
67
+ // ✅ CORRECT
68
+ const activities = await sdk.activities.list();
69
+ for (const a of activities) { ... }
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 4. `sdk.llm.chat()` response is `res.response?.content` — NOT `choices[0].message.content`
75
+
76
+ **Status:** 🔴 DETECTED
77
+ **File:** `modules/llm.ts`
78
+ **Evidence:** `ChatResponse shape: { success, response?: { content, model, metrics } }`
79
+
80
+ **Correct usage:**
81
+ ```js
82
+ // ❌ WRONG (OpenAI style)
83
+ console.log(res.choices[0].message.content);
84
+
85
+ // ✅ CORRECT
86
+ const res = await sdk.llm.chat([{ role: 'user', content: 'Hello' }]);
87
+ console.log(res.response?.content);
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 5. `sdk.llm.chatStream()` yields `chunk.textResponse` — NOT `choices[0].delta.content`
93
+
94
+ **Status:** 🔴 DETECTED
95
+ **File:** `modules/llm.ts`
96
+ **Evidence:** `StreamChunk interface has textResponse?: string`
97
+
98
+ **Correct usage:**
99
+ ```js
100
+ // ❌ WRONG
101
+ chunk.choices?.[0]?.delta?.content
102
+
103
+ // ✅ CORRECT
104
+ for await (const chunk of sdk.llm.chatStream(messages)) {
105
+ if (chunk.textResponse) process.stdout.write(chunk.textResponse);
106
+ if (chunk.close) break;
107
+ }
108
+ ```
109
+
110
+ ---
111
+
112
+ ## 6. `sdk.llm.embedAndStore()` takes `{ texts: string[], documentId?, workspaceId?, ... }` — NOT `(text, options)`
113
+
114
+ **Status:** 🔴 DETECTED
115
+ **File:** `modules/llm.ts`
116
+ **Evidence:** `embedAndStore(params: { texts: string[]; documentId?; workspaceId?; ... })`
117
+
118
+ **Correct usage:**
119
+ ```js
120
+ // ❌ WRONG
121
+ await sdk.llm.embedAndStore('text content', { id: 'doc-1' });
122
+
123
+ // ✅ CORRECT
124
+ await sdk.llm.embedAndStore({ texts: ['chunk 1', 'chunk 2'], documentId: 'doc-1', workspaceId: 'ws-123' });
125
+ ```
126
+
127
+ ---
128
+
129
+ ## 7. `sdk.llm.vectors.query()` takes a raw `number[]` embedding — NOT a text string
130
+
131
+ **Status:** 🔴 DETECTED
132
+ **File:** `modules/llm.ts`
133
+ **Evidence:** `query(vector: number[], options?)`
134
+
135
+ **Correct usage:**
136
+ ```js
137
+ // ❌ WRONG
138
+ await sdk.llm.vectors.query('search text');
139
+
140
+ // ✅ CORRECT — raw vector
141
+ const { embeddings } = await sdk.llm.embed('search text');
142
+ await sdk.llm.vectors.query(embeddings[0], { topK: 5 });
143
+
144
+ // ✅ EASIER — high-level helper
145
+ const hits = await sdk.llm.search('search text', { topK: 5 });
146
+ ```
147
+
148
+ ---
149
+
150
+ ## 8. `sdk.llm.vectors.delete()` requires `{ deleteAll: true }` — delete-by-ID not supported
151
+
152
+ **Status:** 🔴 DETECTED
153
+ **File:** `modules/llm.ts`
154
+ **Evidence:** `VectorDeleteOptions: { workspaceId?, deleteAll: true } (literal true)`
155
+
156
+ **Correct usage:**
157
+ ```js
158
+ // ❌ WRONG
159
+ await sdk.llm.vectors.delete(['id-1', 'id-2']);
160
+
161
+ // ✅ CORRECT
162
+ await sdk.llm.vectors.delete({ deleteAll: true, workspaceId: 'ws-123' });
163
+ ```
164
+
165
+ ---
166
+
167
+ ## 9. `sdk.mcp.getServers()` takes a plain string — NOT `{ provider: "all" }`
168
+
169
+ **Status:** 🔴 DETECTED
170
+ **File:** `modules/mcp.ts`
171
+ **Evidence:** `getServers(provider: 'local' | 'remote' | 'all' = 'all')`
172
+
173
+ **Correct usage:**
174
+ ```js
175
+ // ❌ WRONG
176
+ await sdk.mcp.getServers({ provider: 'all' });
177
+
178
+ // ✅ CORRECT
179
+ await sdk.mcp.getServers('all');
180
+ await sdk.mcp.getServers(); // defaults to 'all'
181
+ ```
182
+
183
+ ---
184
+
185
+ ## 10. `getAgents/getWorkspaces/getThreads/getTask` live on `sdk.api.*` — NOT directly on `sdk.*`
186
+
187
+ **Status:** 🔴 DETECTED
188
+ **File:** `index.ts`
189
+ **Evidence:** `this.api = new ApiModule(...) — separate sub-module in constructor`
190
+
191
+ **Correct usage:**
192
+ ```js
193
+ // ❌ WRONG
194
+ await sdk.getAgents();
195
+ await sdk.getWorkspaces();
196
+
197
+ // ✅ CORRECT
198
+ await sdk.api.getAgents();
199
+ await sdk.api.getWorkspaces();
200
+ await sdk.api.getThreads('workspace-slug');
201
+ await sdk.api.getTask('task-uuid');
202
+ ```
203
+
204
+ ---
205
+
206
+ ## 11. ACP `streamChat` uses named SSE (`event:` line); `text_delta.data.type === "thinking"` = internal reasoning
207
+
208
+ **Status:** 🔴 DETECTED
209
+ **File:** `modules/acpAgent.ts`
210
+ **Evidence:** `Uses parseNamedSSEStream() — reads both event: and data: SSE lines per spec`
211
+
212
+ **Correct usage:**
213
+ ```js
214
+ for await (const event of sdk.acpAgent.streamChat(key, message)) {
215
+ if (event.type === 'text_delta') {
216
+ if (event.data.type !== 'thinking') { // skip internal reasoning
217
+ process.stdout.write(String(event.data.text ?? ''));
218
+ }
219
+ }
220
+ }
221
+ ```
222
+
223
+ ---
224
+
225
+ ## 12. ACP sessions stall without `approvalPolicy: "approve-all"` when tools need permission
226
+
227
+ **Status:** 🔴 DETECTED
228
+ **File:** `modules/acpAgent.ts`
229
+ **Evidence:** `AcpSessionOptions.approvalPolicy?: 'approve-all' | 'approve-reads' | 'deny-all'`
230
+
231
+ **Correct usage:**
232
+ ```js
233
+ // ✅ Always set for autonomous scripts
234
+ await sdk.acpAgent.createSession({ agent_id: 'qwen', approvalPolicy: 'approve-all', cwd });
235
+ ```
236
+
237
+ ---
@@ -0,0 +1,119 @@
1
+ 'use strict';
2
+ /**
3
+ * sdk-init.js — SDK initializer with automatic credential resolution
4
+ * AUTO-GENERATED by scripts/generate-skill.mjs — do not edit by hand.
5
+ *
6
+ * Source reference: typescript/src/index.ts (RealtimeXSDK constructor)
7
+ *
8
+ * Credential resolution priority:
9
+ * 1. Explicit override passed to initSDK({ apiKey } or { appId })
10
+ * 2. REALTIMEX_API_KEY / REALTIMEX_AI_API_KEY in <envDir>/.env
11
+ * 3. RTX_API_KEY / REALTIMEX_API_KEY / REALTIMEX_AI_API_KEY in process.env
12
+ * 4. RTX_APP_ID in process.env (injected by RealtimeX for agents / local apps)
13
+ * 5. ~/.realtimex.ai/.sdk-app-id file (written by RealtimeX server on startup)
14
+ * 6. Interactive readline prompt (dev fallback)
15
+ */
16
+
17
+ const path = require('path');
18
+ const fs = require('fs');
19
+ const os = require('os');
20
+ const readline = require('readline');
21
+
22
+ const ALL_PERMISSIONS = [
23
+ 'api.agents', 'api.workspaces', 'api.threads', 'api.task',
24
+ 'webhook.trigger', 'activities.read', 'activities.write',
25
+ 'llm.chat', 'llm.embed', 'llm.providers',
26
+ 'vectors.read', 'vectors.write',
27
+ 'tts.generate', 'mcp.servers', 'mcp.tools', 'acp.agent',
28
+ ];
29
+
30
+ /** Well-known file written by RealtimeX server for seamless SDK auth. */
31
+ const SDK_APP_ID_FILE = path.join(os.homedir(), '.realtimex.ai', '.sdk-app-id');
32
+
33
+ function parseEnvFile(filePath) {
34
+ const vars = {};
35
+ if (!fs.existsSync(filePath)) return vars;
36
+ for (const raw of fs.readFileSync(filePath, 'utf-8').split('\n')) {
37
+ const line = raw.trim();
38
+ if (!line || line.startsWith('#')) continue;
39
+ const eq = line.indexOf('=');
40
+ if (eq === -1) continue;
41
+ const key = line.slice(0, eq).trim();
42
+ const val = line.slice(eq + 1).trim().replace(/^["']|["']$/g, '');
43
+ vars[key] = val;
44
+ }
45
+ return vars;
46
+ }
47
+
48
+ /**
49
+ * Resolve credentials using the full priority chain.
50
+ * Returns { apiKey, appId } — exactly one will be set.
51
+ */
52
+ async function resolveCredentials({ envDir, apiKey, appId } = {}) {
53
+ // 1. Explicit overrides
54
+ if (apiKey) return { apiKey, appId: null };
55
+ if (appId) return { apiKey: null, appId };
56
+
57
+ // 2. .env file
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)
71
+ try {
72
+ if (fs.existsSync(SDK_APP_ID_FILE)) {
73
+ const fileAppId = fs.readFileSync(SDK_APP_ID_FILE, 'utf-8').trim();
74
+ if (fileAppId) return { apiKey: null, appId: fileAppId };
75
+ }
76
+ } catch { /* ignore read errors */ }
77
+
78
+ // 6. Interactive prompt (dev fallback)
79
+ const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
80
+ const answer = await new Promise((resolve) => {
81
+ rl.question('RealTimeX API key not found. Enter your API key: ', (ans) => {
82
+ rl.close();
83
+ resolve(ans.trim());
84
+ });
85
+ });
86
+ if (answer) return { apiKey: answer, appId: null };
87
+
88
+ return { apiKey: null, appId: null };
89
+ }
90
+
91
+ /** @deprecated Use resolveCredentials() instead */
92
+ async function resolveApiKey(opts = {}) {
93
+ const { apiKey } = await resolveCredentials(opts);
94
+ return apiKey;
95
+ }
96
+
97
+ async function initSDK(opts = {}) {
98
+ const { RealtimeXSDK } = require('@realtimex/sdk');
99
+ const { apiKey, appId } = await resolveCredentials(opts);
100
+
101
+ if (!apiKey && !appId) {
102
+ throw new Error(
103
+ 'No credentials found. Set REALTIMEX_API_KEY in .env, or run inside RealtimeX for automatic auth.'
104
+ );
105
+ }
106
+
107
+ const sdk = new RealtimeXSDK({
108
+ realtimex: {
109
+ url: opts.url || 'http://localhost:3001',
110
+ ...(apiKey ? { apiKey } : {}),
111
+ ...(appId ? { appId } : {}),
112
+ },
113
+ permissions: opts.permissions || ALL_PERMISSIONS,
114
+ });
115
+
116
+ return { sdk, apiKey: apiKey || null, appId: appId || null };
117
+ }
118
+
119
+ module.exports = { initSDK, resolveCredentials, resolveApiKey, parseEnvFile, ALL_PERMISSIONS, SDK_APP_ID_FILE };