@xenosystem/agents-client 0.1.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/LICENSE +67 -0
- package/dist/index.d.ts +322 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +528 -0
- package/dist/index.js.map +1 -0
- package/dist/modelCatalog.d.ts +29 -0
- package/dist/modelCatalog.d.ts.map +1 -0
- package/dist/modelCatalog.js +137 -0
- package/dist/modelCatalog.js.map +1 -0
- package/dist/node.d.ts +45 -0
- package/dist/node.d.ts.map +1 -0
- package/dist/node.js +106 -0
- package/dist/node.js.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const DEFAULT_DIRECT_API_BASE = 'https://api.xenostudio.ai';
|
|
2
|
+
const DEFAULT_PLATFORM_MODELS_URL = 'https://xenostudio.ai/api/models';
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 10_000;
|
|
4
|
+
/**
|
|
5
|
+
* Loads only live, server-advertised model identifiers. There is deliberately
|
|
6
|
+
* no bundled model-family fallback: a failed catalog lookup leaves the
|
|
7
|
+
* provider unavailable instead of presenting stale or invented choices.
|
|
8
|
+
*/
|
|
9
|
+
export async function loadXenoCloudModelCatalog(options = {}) {
|
|
10
|
+
const apiKey = cleanSecret(options.apiKey);
|
|
11
|
+
const webToken = cleanSecret(options.webToken);
|
|
12
|
+
if (!apiKey && !webToken) {
|
|
13
|
+
return {
|
|
14
|
+
models: [],
|
|
15
|
+
error: 'Sign in to load the live XENO model catalog.',
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const fetchImpl = options.fetchImpl || fetch;
|
|
19
|
+
const failures = [];
|
|
20
|
+
if (apiKey) {
|
|
21
|
+
try {
|
|
22
|
+
const response = await fetchImpl(`${normalizeBase(options.directApiBase || DEFAULT_DIRECT_API_BASE)}/v1/models`, {
|
|
23
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
24
|
+
signal: requestSignal(options.signal, options.timeoutMs),
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok)
|
|
27
|
+
throw new Error(`Direct model catalog returned HTTP ${response.status}.`);
|
|
28
|
+
const payload = await response.json();
|
|
29
|
+
const models = decorateCloudModels(readModelRecords(payload), 'api', 'available', null);
|
|
30
|
+
if (models.length > 0)
|
|
31
|
+
return { models, error: null };
|
|
32
|
+
failures.push('The direct model catalog returned no chat models.');
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
failures.push(safeError(error, 'The direct model catalog is unavailable.'));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (webToken) {
|
|
39
|
+
try {
|
|
40
|
+
const response = await fetchImpl(options.platformModelsUrl || DEFAULT_PLATFORM_MODELS_URL, {
|
|
41
|
+
headers: { Authorization: `Bearer ${webToken}` },
|
|
42
|
+
signal: requestSignal(options.signal, options.timeoutMs),
|
|
43
|
+
});
|
|
44
|
+
if (!response.ok)
|
|
45
|
+
throw new Error(`Platform model catalog returned HTTP ${response.status}.`);
|
|
46
|
+
const payload = await response.json();
|
|
47
|
+
const models = decorateCloudModels(readModelRecords(payload), 'platform-auth', 'degraded', apiKey
|
|
48
|
+
? 'The direct catalog was unavailable; these models came from the authenticated XENO platform catalog.'
|
|
49
|
+
: 'These models came from the authenticated XENO platform catalog.');
|
|
50
|
+
if (models.length > 0)
|
|
51
|
+
return { models, error: failures[0] || null };
|
|
52
|
+
failures.push('The authenticated platform catalog returned no chat models.');
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
failures.push(safeError(error, 'The authenticated platform model catalog is unavailable.'));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
models: [],
|
|
60
|
+
error: failures.join(' ')
|
|
61
|
+
|| 'The live XENO model catalog is unavailable.',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function readModelRecords(payload) {
|
|
65
|
+
if (!isRecord(payload))
|
|
66
|
+
return [];
|
|
67
|
+
if (Array.isArray(payload.data))
|
|
68
|
+
return payload.data.filter(isRecord);
|
|
69
|
+
if (!isRecord(payload.companies))
|
|
70
|
+
return [];
|
|
71
|
+
const records = [];
|
|
72
|
+
for (const entries of Object.values(payload.companies)) {
|
|
73
|
+
if (!Array.isArray(entries))
|
|
74
|
+
continue;
|
|
75
|
+
for (const entry of entries) {
|
|
76
|
+
if (isRecord(entry))
|
|
77
|
+
records.push(entry);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return records;
|
|
81
|
+
}
|
|
82
|
+
function decorateCloudModels(models, source, availability, availabilityReason) {
|
|
83
|
+
return normalizeCloudChatModels(models).map((model) => ({
|
|
84
|
+
...model,
|
|
85
|
+
source,
|
|
86
|
+
availability,
|
|
87
|
+
availabilityReason,
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
90
|
+
function normalizeCloudChatModels(models) {
|
|
91
|
+
const normalized = [];
|
|
92
|
+
const seen = new Set();
|
|
93
|
+
for (const model of models) {
|
|
94
|
+
const id = typeof model.id === 'string' ? model.id.trim() : '';
|
|
95
|
+
if (!id || seen.has(id) || !isCloudChatModelId(id))
|
|
96
|
+
continue;
|
|
97
|
+
const type = typeof model.type === 'string' ? model.type.toLowerCase() : '';
|
|
98
|
+
if (type && !['model', 'text', 'chat', 'llm'].includes(type))
|
|
99
|
+
continue;
|
|
100
|
+
seen.add(id);
|
|
101
|
+
normalized.push({
|
|
102
|
+
id,
|
|
103
|
+
object: typeof model.object === 'string' ? model.object : 'model',
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return normalized;
|
|
107
|
+
}
|
|
108
|
+
function isCloudChatModelId(id) {
|
|
109
|
+
if (!/^[a-z0-9][a-z0-9._:/-]*$/i.test(id))
|
|
110
|
+
return false;
|
|
111
|
+
return !/(^|[/_-])(imagen|nano[_-]?banana|veo|lyria|tts|whisper|audio|image|video|embed|embedding|moderation|rerank|search)([/_.-]|$)/i.test(id);
|
|
112
|
+
}
|
|
113
|
+
function requestSignal(signal, timeoutMs) {
|
|
114
|
+
const timeout = AbortSignal.timeout(positiveTimeout(timeoutMs));
|
|
115
|
+
return signal ? AbortSignal.any([signal, timeout]) : timeout;
|
|
116
|
+
}
|
|
117
|
+
function positiveTimeout(value) {
|
|
118
|
+
return typeof value === 'number' && Number.isFinite(value) && value > 0
|
|
119
|
+
? Math.min(Math.floor(value), 60_000)
|
|
120
|
+
: DEFAULT_TIMEOUT_MS;
|
|
121
|
+
}
|
|
122
|
+
function normalizeBase(value) {
|
|
123
|
+
return value.trim().replace(/\/+$/, '');
|
|
124
|
+
}
|
|
125
|
+
function cleanSecret(value) {
|
|
126
|
+
const cleaned = typeof value === 'string' ? value.trim() : '';
|
|
127
|
+
return cleaned || undefined;
|
|
128
|
+
}
|
|
129
|
+
function safeError(error, fallback) {
|
|
130
|
+
if (error instanceof Error && error.message.trim())
|
|
131
|
+
return error.message.trim().slice(0, 500);
|
|
132
|
+
return fallback;
|
|
133
|
+
}
|
|
134
|
+
function isRecord(value) {
|
|
135
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=modelCatalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelCatalog.js","sourceRoot":"","sources":["../src/modelCatalog.ts"],"names":[],"mappings":"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"}
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type AgentsClient } from './index.js';
|
|
2
|
+
import { type XenoCloudModelCatalog } from './modelCatalog.js';
|
|
3
|
+
export * from './index.js';
|
|
4
|
+
export interface XenoCloudCredentialSnapshot {
|
|
5
|
+
apiKey?: string;
|
|
6
|
+
webToken?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface XenoCloudCredentialSourceOptions {
|
|
9
|
+
homeDirectory?: string;
|
|
10
|
+
credentialsFile?: string;
|
|
11
|
+
settingsFile?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface XenoCloudNodeClientOptions extends XenoCloudCredentialSourceOptions {
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
fetchImpl?: typeof fetch;
|
|
16
|
+
}
|
|
17
|
+
export interface DiscoverXenoCloudNodeRuntimeOptions extends XenoCloudNodeClientOptions {
|
|
18
|
+
directApiBase?: string;
|
|
19
|
+
platformModelsUrl?: string;
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
}
|
|
23
|
+
export interface XenoCloudHostedStatus {
|
|
24
|
+
authenticated: boolean;
|
|
25
|
+
ok: boolean;
|
|
26
|
+
capabilities: string[];
|
|
27
|
+
version?: string;
|
|
28
|
+
service?: string;
|
|
29
|
+
safeUnavailableReason?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface XenoCloudNodeRuntimeDiscovery {
|
|
32
|
+
authenticated: boolean;
|
|
33
|
+
directCredentialAvailable: boolean;
|
|
34
|
+
hostedStatus: XenoCloudHostedStatus;
|
|
35
|
+
modelCatalog: XenoCloudModelCatalog;
|
|
36
|
+
}
|
|
37
|
+
export declare function readXenoCloudCredentials(options?: XenoCloudCredentialSourceOptions): XenoCloudCredentialSnapshot;
|
|
38
|
+
/**
|
|
39
|
+
* Returns a main-process client whose token callback rereads the brokered
|
|
40
|
+
* credential snapshot for every request. Secrets never enter renderer state.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createXenoCloudNodeAgentsClient(options?: XenoCloudNodeClientOptions): AgentsClient;
|
|
43
|
+
export declare function discoverXenoCloudNodeRuntime(options?: DiscoverXenoCloudNodeRuntimeOptions): Promise<XenoCloudNodeRuntimeDiscovery>;
|
|
44
|
+
export declare function probeXenoCloudHostedStatus(options?: DiscoverXenoCloudNodeRuntimeOptions): Promise<XenoCloudHostedStatus>;
|
|
45
|
+
//# sourceMappingURL=node.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,YAAY,CAAA;AACnB,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAA;AAE1B,cAAc,YAAY,CAAA;AAE1B,MAAM,WAAW,2BAA2B;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,gCAAgC;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,MAAM,WAAW,0BAA2B,SAAQ,gCAAgC;IAClF,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CACzB;AAED,MAAM,WAAW,mCAAoC,SAAQ,0BAA0B;IACrF,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,OAAO,CAAA;IACtB,EAAE,EAAE,OAAO,CAAA;IACX,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,qBAAqB,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED,MAAM,WAAW,6BAA6B;IAC5C,aAAa,EAAE,OAAO,CAAA;IACtB,yBAAyB,EAAE,OAAO,CAAA;IAClC,YAAY,EAAE,qBAAqB,CAAA;IACnC,YAAY,EAAE,qBAAqB,CAAA;CACpC;AAED,wBAAgB,wBAAwB,CACtC,OAAO,GAAE,gCAAqC,GAC7C,2BAA2B,CAc7B;AAED;;;GAGG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,GAAE,0BAA+B,GACvC,YAAY,CAMd;AAED,wBAAsB,4BAA4B,CAChD,OAAO,GAAE,mCAAwC,GAChD,OAAO,CAAC,6BAA6B,CAAC,CAqBxC;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,GAAE,mCAAwC,GAChD,OAAO,CAAC,qBAAqB,CAAC,CAEhC"}
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { createAgentsClient, } from './index.js';
|
|
5
|
+
import { loadXenoCloudModelCatalog, } from './modelCatalog.js';
|
|
6
|
+
export * from './index.js';
|
|
7
|
+
export function readXenoCloudCredentials(options = {}) {
|
|
8
|
+
const homeDirectory = options.homeDirectory || homedir();
|
|
9
|
+
const credentials = readJsonRecord(options.credentialsFile || join(homeDirectory, '.xeno', 'credentials.json'));
|
|
10
|
+
const settings = readJsonRecord(options.settingsFile || join(homeDirectory, '.xeno', 'settings.json'));
|
|
11
|
+
const apiKey = cleanSecret(settings?.llmApiKey) || cleanSecret(credentials?.apiKey);
|
|
12
|
+
const webToken = cleanSecret(credentials?.webToken);
|
|
13
|
+
return {
|
|
14
|
+
...(apiKey ? { apiKey } : {}),
|
|
15
|
+
...(webToken ? { webToken } : {}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Returns a main-process client whose token callback rereads the brokered
|
|
20
|
+
* credential snapshot for every request. Secrets never enter renderer state.
|
|
21
|
+
*/
|
|
22
|
+
export function createXenoCloudNodeAgentsClient(options = {}) {
|
|
23
|
+
return createAgentsClient({
|
|
24
|
+
...(options.baseUrl ? { baseUrl: options.baseUrl } : {}),
|
|
25
|
+
token: () => readXenoCloudCredentials(options).webToken || '',
|
|
26
|
+
...(options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
export async function discoverXenoCloudNodeRuntime(options = {}) {
|
|
30
|
+
const credentials = readXenoCloudCredentials(options);
|
|
31
|
+
const modelOptions = {
|
|
32
|
+
...(credentials.apiKey ? { apiKey: credentials.apiKey } : {}),
|
|
33
|
+
...(credentials.webToken ? { webToken: credentials.webToken } : {}),
|
|
34
|
+
...(options.directApiBase ? { directApiBase: options.directApiBase } : {}),
|
|
35
|
+
...(options.platformModelsUrl ? { platformModelsUrl: options.platformModelsUrl } : {}),
|
|
36
|
+
...(options.fetchImpl ? { fetchImpl: options.fetchImpl } : {}),
|
|
37
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
38
|
+
...(options.timeoutMs ? { timeoutMs: options.timeoutMs } : {}),
|
|
39
|
+
};
|
|
40
|
+
const [modelCatalog, hostedStatus] = await Promise.all([
|
|
41
|
+
loadXenoCloudModelCatalog(modelOptions),
|
|
42
|
+
loadHostedStatusWithToken(credentials.webToken, options),
|
|
43
|
+
]);
|
|
44
|
+
return {
|
|
45
|
+
authenticated: Boolean(credentials.webToken),
|
|
46
|
+
directCredentialAvailable: Boolean(credentials.apiKey),
|
|
47
|
+
hostedStatus,
|
|
48
|
+
modelCatalog,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export async function probeXenoCloudHostedStatus(options = {}) {
|
|
52
|
+
return loadHostedStatusWithToken(readXenoCloudCredentials(options).webToken, options);
|
|
53
|
+
}
|
|
54
|
+
async function loadHostedStatusWithToken(webToken, options) {
|
|
55
|
+
if (!webToken) {
|
|
56
|
+
return {
|
|
57
|
+
authenticated: false,
|
|
58
|
+
ok: false,
|
|
59
|
+
capabilities: [],
|
|
60
|
+
safeUnavailableReason: 'Sign in to use hosted XENO Agent runs.',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
try {
|
|
64
|
+
const status = await createXenoCloudNodeAgentsClient(options).status(options.signal ? { signal: options.signal } : undefined);
|
|
65
|
+
return {
|
|
66
|
+
authenticated: true,
|
|
67
|
+
ok: status.ok === true,
|
|
68
|
+
capabilities: Array.isArray(status.capabilities) ? [...status.capabilities] : [],
|
|
69
|
+
...(status.version ? { version: status.version } : {}),
|
|
70
|
+
...(status.service ? { service: status.service } : {}),
|
|
71
|
+
...(status.ok === true ? {} : { safeUnavailableReason: 'The hosted XENO Agent service is unavailable.' }),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
return {
|
|
76
|
+
authenticated: true,
|
|
77
|
+
ok: false,
|
|
78
|
+
capabilities: [],
|
|
79
|
+
safeUnavailableReason: safeError(error),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function readJsonRecord(path) {
|
|
84
|
+
try {
|
|
85
|
+
if (!existsSync(path))
|
|
86
|
+
return undefined;
|
|
87
|
+
const value = JSON.parse(readFileSync(path, 'utf8'));
|
|
88
|
+
return isRecord(value) ? value : undefined;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function cleanSecret(value) {
|
|
95
|
+
const cleaned = typeof value === 'string' ? value.trim() : '';
|
|
96
|
+
return cleaned || undefined;
|
|
97
|
+
}
|
|
98
|
+
function safeError(error) {
|
|
99
|
+
if (error instanceof Error && error.message.trim())
|
|
100
|
+
return error.message.trim().slice(0, 500);
|
|
101
|
+
return 'The hosted XENO Agent service is unavailable.';
|
|
102
|
+
}
|
|
103
|
+
function isRecord(value) {
|
|
104
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@xenosystem/agents-client",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"license": "UNLICENSED",
|
|
5
|
+
"description": "Portable authenticated client for the hosted XENO Agents run API.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./node": {
|
|
15
|
+
"types": "./dist/node.d.ts",
|
|
16
|
+
"import": "./dist/node.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/XENO-CORPORATION/xeno-agent-interface.git",
|
|
28
|
+
"directory": "packages/cloud-client"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {}
|
|
31
|
+
}
|