@alfe.ai/agent-api-client 0.10.0 → 0.11.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.cjs +81 -25
- package/dist/index.d.cts +70 -14
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +70 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +81 -25
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -137,6 +137,7 @@ var AgentApiClient = class {
|
|
|
137
137
|
if (!res.ok) {
|
|
138
138
|
await res.text();
|
|
139
139
|
const error = /* @__PURE__ */ new Error(`Agent API request failed (${String(res.status)})`);
|
|
140
|
+
error.status = res.status;
|
|
140
141
|
if (attempt === 1 && RETRYABLE_STATUS.has(res.status)) {
|
|
141
142
|
lastError = error;
|
|
142
143
|
await sleep(RETRY_DELAY_MS);
|
|
@@ -210,7 +211,17 @@ var AgentApiClient = class {
|
|
|
210
211
|
return this.request("/agent/integrations");
|
|
211
212
|
}
|
|
212
213
|
async getIntegrationConfig(integrationId) {
|
|
213
|
-
|
|
214
|
+
try {
|
|
215
|
+
return await this.request(`/agent/integrations/${encodeURIComponent(integrationId)}/config`);
|
|
216
|
+
} catch (err) {
|
|
217
|
+
if (err.status === 404) return {
|
|
218
|
+
integrationId,
|
|
219
|
+
config: {},
|
|
220
|
+
configSchema: [],
|
|
221
|
+
installed: false
|
|
222
|
+
};
|
|
223
|
+
throw err;
|
|
224
|
+
}
|
|
214
225
|
}
|
|
215
226
|
async updateIntegrationConfig(integrationId, config) {
|
|
216
227
|
await this.request(`/agent/integrations/${encodeURIComponent(integrationId)}`, {
|
|
@@ -314,49 +325,71 @@ var AgentApiClient = class {
|
|
|
314
325
|
* Pattern A: multi-account credential fetch for cTrader.
|
|
315
326
|
*
|
|
316
327
|
* Unlike atlassian/salesforce (one Connection row per account/site), a
|
|
317
|
-
*
|
|
318
|
-
*
|
|
319
|
-
*
|
|
320
|
-
*
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
328
|
+
* cTrader is MULTI-grant per agent: an agent may connect several distinct
|
|
329
|
+
* cTrader logins, each its own Connection row keyed on `accountIdentifier =
|
|
330
|
+
* ctid:<userId>` (Phase 1). This aggregates the *trading accounts* across
|
|
331
|
+
* ALL of those Connection rows — each row contributes its `availableAccounts`
|
|
332
|
+
* flattened, and every account carries ITS OWN grant's `accessToken` (the
|
|
333
|
+
* token that authenticates that account against the cTrader Open API). One
|
|
334
|
+
* OAuth grant still covers all accounts under that single login on one shared
|
|
335
|
+
* token; only the `ctidTraderAccountId` and the protobuf socket `host` (live
|
|
336
|
+
* vs demo) differ within a grant. Across grants the tokens differ, so the
|
|
337
|
+
* token is now PER-ACCOUNT rather than hoisted to the top level.
|
|
325
338
|
*
|
|
326
339
|
* `host` per account is derived from the account's `isLive` flag
|
|
327
340
|
* (`live.ctraderapi.com` / `demo.ctraderapi.com`) — the same mapping the
|
|
328
341
|
* connect provider applies server-side when an account is auto-selected.
|
|
329
342
|
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
343
|
+
* `clientId` / `clientSecret` are the SST-sourced GLOBAL app credentials the
|
|
344
|
+
* connect endpoint injects — identical across every Connection row (one
|
|
345
|
+
* cTrader app), never persisted on a connection. We take them from the first
|
|
346
|
+
* row that carries them.
|
|
347
|
+
*
|
|
348
|
+
* Accounts are deduped on `ctidTraderAccountId` first-wins: Spotware ids are
|
|
349
|
+
* globally unique across logins, so a duplicate can only appear if the same
|
|
350
|
+
* account somehow surfaced under two grants — first-wins keeps it
|
|
351
|
+
* deterministic.
|
|
352
|
+
*
|
|
353
|
+
* `accounts` may be empty (no cTrader Connection at all), in which case we
|
|
354
|
+
* return empty creds rather than throwing.
|
|
334
355
|
*/
|
|
335
356
|
async getCTraderAccounts() {
|
|
336
357
|
const raw = await this.request("/agent/connect/ctrader/accounts");
|
|
337
358
|
if (raw.accounts.length === 0) return {
|
|
338
359
|
accounts: [],
|
|
339
360
|
clientId: "",
|
|
340
|
-
clientSecret: ""
|
|
341
|
-
accessToken: ""
|
|
361
|
+
clientSecret: ""
|
|
342
362
|
};
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
363
|
+
let clientId = "";
|
|
364
|
+
let clientSecret = "";
|
|
365
|
+
for (const row of raw.accounts) {
|
|
366
|
+
if (!clientId && row.clientId) clientId = row.clientId;
|
|
367
|
+
if (!clientSecret && row.clientSecret) clientSecret = row.clientSecret;
|
|
368
|
+
if (clientId && clientSecret) break;
|
|
369
|
+
}
|
|
370
|
+
const seen = /* @__PURE__ */ new Set();
|
|
371
|
+
const accounts = [];
|
|
372
|
+
for (const row of raw.accounts) {
|
|
373
|
+
const rowToken = row.accessToken ?? "";
|
|
374
|
+
for (const a of row.availableAccounts ?? []) {
|
|
347
375
|
const id = a.ctidTraderAccountId != null ? String(a.ctidTraderAccountId) : a.accountId != null ? String(a.accountId) : "";
|
|
376
|
+
if (id.length === 0 || seen.has(id)) continue;
|
|
377
|
+
seen.add(id);
|
|
348
378
|
const isLive = a.isLive === true;
|
|
349
|
-
|
|
379
|
+
accounts.push({
|
|
350
380
|
ctidTraderAccountId: id,
|
|
351
381
|
host: isLive ? "live.ctraderapi.com" : "demo.ctraderapi.com",
|
|
352
382
|
isLive,
|
|
353
383
|
...a.brokerName != null ? { brokerName: a.brokerName } : {},
|
|
354
|
-
...a.accountNumber != null ? { accountNumber: String(a.accountNumber) } : {}
|
|
355
|
-
|
|
356
|
-
|
|
384
|
+
...a.accountNumber != null ? { accountNumber: String(a.accountNumber) } : {},
|
|
385
|
+
accessToken: rowToken
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
accounts,
|
|
357
391
|
clientId,
|
|
358
|
-
clientSecret
|
|
359
|
-
accessToken
|
|
392
|
+
clientSecret
|
|
360
393
|
};
|
|
361
394
|
}
|
|
362
395
|
/**
|
|
@@ -1139,6 +1172,15 @@ var AgentApiClient = class {
|
|
|
1139
1172
|
...scope ? { body: JSON.stringify({ scope }) } : {}
|
|
1140
1173
|
});
|
|
1141
1174
|
}
|
|
1175
|
+
async sendSms(args) {
|
|
1176
|
+
return this.request("/mobile/sms/send", {
|
|
1177
|
+
method: "POST",
|
|
1178
|
+
body: JSON.stringify({
|
|
1179
|
+
to: args.to,
|
|
1180
|
+
body: args.body
|
|
1181
|
+
})
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1142
1184
|
async searchWeb(params) {
|
|
1143
1185
|
return this.request("/agent/search/web", {
|
|
1144
1186
|
method: "POST",
|
|
@@ -1157,6 +1199,20 @@ var AgentApiClient = class {
|
|
|
1157
1199
|
body: JSON.stringify(params)
|
|
1158
1200
|
});
|
|
1159
1201
|
}
|
|
1202
|
+
/** Search news across the selected provider's corpus. → POST /agent/news/search */
|
|
1203
|
+
async newsSearch(params) {
|
|
1204
|
+
return this.request("/agent/news/search", {
|
|
1205
|
+
method: "POST",
|
|
1206
|
+
body: JSON.stringify(params)
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
/** Top headlines for the selected provider. → POST /agent/news/headlines */
|
|
1210
|
+
async newsHeadlines(params) {
|
|
1211
|
+
return this.request("/agent/news/headlines", {
|
|
1212
|
+
method: "POST",
|
|
1213
|
+
body: JSON.stringify(params ?? {})
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1160
1216
|
/**
|
|
1161
1217
|
* Semantic search across the agent's member scopes. Fan-out is gated
|
|
1162
1218
|
* server-side by `listScopes` set-inclusion (fail-closed). Pass
|