@oneentry/mcp-platform-server 0.1.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 +189 -0
- package/data/catalog.json +1 -0
- package/data/knowledge.json +1 -0
- package/dist/api/audit.d.ts +32 -0
- package/dist/api/audit.d.ts.map +1 -0
- package/dist/api/audit.js +35 -0
- package/dist/api/audit.js.map +1 -0
- package/dist/api/auth.d.ts +53 -0
- package/dist/api/auth.d.ts.map +1 -0
- package/dist/api/auth.js +126 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/catalog.d.ts +39 -0
- package/dist/api/catalog.d.ts.map +1 -0
- package/dist/api/catalog.js +108 -0
- package/dist/api/catalog.js.map +1 -0
- package/dist/api/client.d.ts +60 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +196 -0
- package/dist/api/client.js.map +1 -0
- package/dist/api/policy.d.ts +52 -0
- package/dist/api/policy.d.ts.map +1 -0
- package/dist/api/policy.js +0 -0
- package/dist/api/policy.js.map +1 -0
- package/dist/api/shape.d.ts +19 -0
- package/dist/api/shape.d.ts.map +1 -0
- package/dist/api/shape.js +151 -0
- package/dist/api/shape.js.map +1 -0
- package/dist/api/types.d.ts +85 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +2 -0
- package/dist/api/types.js.map +1 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +48 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/config/config.d.ts +108 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +167 -0
- package/dist/config/config.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/knowledge/chunk.d.ts +35 -0
- package/dist/knowledge/chunk.d.ts.map +1 -0
- package/dist/knowledge/chunk.js +87 -0
- package/dist/knowledge/chunk.js.map +1 -0
- package/dist/knowledge/loader.d.ts +27 -0
- package/dist/knowledge/loader.d.ts.map +1 -0
- package/dist/knowledge/loader.js +125 -0
- package/dist/knowledge/loader.js.map +1 -0
- package/dist/knowledge/search.d.ts +34 -0
- package/dist/knowledge/search.d.ts.map +1 -0
- package/dist/knowledge/search.js +95 -0
- package/dist/knowledge/search.js.map +1 -0
- package/dist/knowledge/types.d.ts +47 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +2 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/server.d.ts +16 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +48 -0
- package/dist/server.js.map +1 -0
- package/dist/session.d.ts +43 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +75 -0
- package/dist/session.js.map +1 -0
- package/dist/tools/api-call.d.ts +5 -0
- package/dist/tools/api-call.d.ts.map +1 -0
- package/dist/tools/api-call.js +169 -0
- package/dist/tools/api-call.js.map +1 -0
- package/dist/tools/api-discovery.d.ts +5 -0
- package/dist/tools/api-discovery.d.ts.map +1 -0
- package/dist/tools/api-discovery.js +80 -0
- package/dist/tools/api-discovery.js.map +1 -0
- package/dist/tools/docs.d.ts +5 -0
- package/dist/tools/docs.d.ts.map +1 -0
- package/dist/tools/docs.js +113 -0
- package/dist/tools/docs.js.map +1 -0
- package/dist/tools/guide.d.ts +11 -0
- package/dist/tools/guide.d.ts.map +1 -0
- package/dist/tools/guide.js +67 -0
- package/dist/tools/guide.js.map +1 -0
- package/dist/tools/result.d.ts +19 -0
- package/dist/tools/result.d.ts.map +1 -0
- package/dist/tools/result.js +19 -0
- package/dist/tools/result.js.map +1 -0
- package/dist/tools/whoami.d.ts +5 -0
- package/dist/tools/whoami.d.ts.map +1 -0
- package/dist/tools/whoami.js +42 -0
- package/dist/tools/whoami.js.map +1 -0
- package/dist/transports/http.d.ts +10 -0
- package/dist/transports/http.d.ts.map +1 -0
- package/dist/transports/http.js +126 -0
- package/dist/transports/http.js.map +1 -0
- package/dist/transports/stdio.d.ts +8 -0
- package/dist/transports/stdio.d.ts.map +1 -0
- package/dist/transports/stdio.js +15 -0
- package/dist/transports/stdio.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Одна запись аудита изменяющего вызова. */
|
|
2
|
+
export interface AuditEntry {
|
|
3
|
+
at: string;
|
|
4
|
+
mode: string;
|
|
5
|
+
adminId?: number;
|
|
6
|
+
opId: string;
|
|
7
|
+
method: string;
|
|
8
|
+
path: string;
|
|
9
|
+
argsHash: string;
|
|
10
|
+
outcome: 'denied' | 'needs-confirm' | 'sent';
|
|
11
|
+
status?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Журнал изменяющих вызовов в формате JSONL.
|
|
15
|
+
* Пишем хэш аргументов, а не сами аргументы: тела запросов содержат
|
|
16
|
+
* пользовательские данные, а для разбора инцидента достаточно связать вызовы между собой.
|
|
17
|
+
*/
|
|
18
|
+
export declare class AuditLog {
|
|
19
|
+
private readonly path;
|
|
20
|
+
private readonly mode;
|
|
21
|
+
constructor(params: {
|
|
22
|
+
path?: string;
|
|
23
|
+
mode: string;
|
|
24
|
+
});
|
|
25
|
+
static hashArgs(args: unknown): string;
|
|
26
|
+
/**
|
|
27
|
+
* Пишет запись, не роняя вызов при недоступности файла: аудит важен,
|
|
28
|
+
* но потеря строки лога — не причина провалить операцию, о которой уже отчитались.
|
|
29
|
+
*/
|
|
30
|
+
record(entry: Omit<AuditEntry, 'at' | 'mode'>): void;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/api/audit.ts"],"names":[],"mappings":"AAGA,6CAA6C;AAC7C,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,QAAQ,GAAG,eAAe,GAAG,MAAM,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAqB;IAC1C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;gBAElB,MAAM,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAKnD,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM;IAItC;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,MAAM,CAAC,GAAG,IAAI;CAWrD"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { appendFileSync } from 'node:fs';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
/**
|
|
4
|
+
* Журнал изменяющих вызовов в формате JSONL.
|
|
5
|
+
* Пишем хэш аргументов, а не сами аргументы: тела запросов содержат
|
|
6
|
+
* пользовательские данные, а для разбора инцидента достаточно связать вызовы между собой.
|
|
7
|
+
*/
|
|
8
|
+
export class AuditLog {
|
|
9
|
+
path;
|
|
10
|
+
mode;
|
|
11
|
+
constructor(params) {
|
|
12
|
+
this.path = params.path;
|
|
13
|
+
this.mode = params.mode;
|
|
14
|
+
}
|
|
15
|
+
static hashArgs(args) {
|
|
16
|
+
return createHash('sha256').update(JSON.stringify(args ?? null)).digest('hex').slice(0, 16);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Пишет запись, не роняя вызов при недоступности файла: аудит важен,
|
|
20
|
+
* но потеря строки лога — не причина провалить операцию, о которой уже отчитались.
|
|
21
|
+
*/
|
|
22
|
+
record(entry) {
|
|
23
|
+
if (!this.path) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const line = JSON.stringify({ at: new Date().toISOString(), mode: this.mode, ...entry });
|
|
27
|
+
try {
|
|
28
|
+
appendFileSync(this.path, `${line}\n`);
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
process.stderr.write(`oneentry-mcp-platform: audit write failed: ${String(error)}\n`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/api/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAezC;;;;GAIG;AACH,MAAM,OAAO,QAAQ;IACF,IAAI,CAAqB;IACzB,IAAI,CAAS;IAE9B,YAAY,MAAuC;QACjD,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,QAAQ,CAAC,IAAa;QAC3B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,KAAsC;QAC3C,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;QACzF,IAAI,CAAC;YACH,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8CAA8C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Config } from '../config/config.js';
|
|
2
|
+
/** Пара токенов Admin API, как её отдаёт `POST /auth/login`. */
|
|
3
|
+
export interface TokenPair {
|
|
4
|
+
accessToken: string;
|
|
5
|
+
refreshToken: string;
|
|
6
|
+
}
|
|
7
|
+
/** Данные аутентифицированного админа, восстановленные из токена и API. */
|
|
8
|
+
export interface AdminIdentity {
|
|
9
|
+
id: number;
|
|
10
|
+
login?: string;
|
|
11
|
+
permissions: string[];
|
|
12
|
+
}
|
|
13
|
+
/** Учётные данные одной сессии. В remote-режиме у каждой сессии свои. */
|
|
14
|
+
export interface Credentials {
|
|
15
|
+
login?: string;
|
|
16
|
+
password?: string;
|
|
17
|
+
token?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Ошибка аутентификации с текстом, пригодным для показа модели. */
|
|
20
|
+
export declare class AuthError extends Error {
|
|
21
|
+
}
|
|
22
|
+
/** Достаёт идентификатор админа из payload access-токена. */
|
|
23
|
+
export declare const adminIdFromToken: (token: string) => number;
|
|
24
|
+
/**
|
|
25
|
+
* Держит пару токенов для одного набора учётных данных.
|
|
26
|
+
* Токены живут только в памяти и только внутри сессии: в remote-режиме
|
|
27
|
+
* это то, что не даёт токену одной сессии утечь в другую.
|
|
28
|
+
*/
|
|
29
|
+
export declare class TokenStore {
|
|
30
|
+
private pair;
|
|
31
|
+
private readonly baseUrl;
|
|
32
|
+
private readonly timeoutMs;
|
|
33
|
+
private readonly credentials;
|
|
34
|
+
constructor(params: {
|
|
35
|
+
baseUrl: string;
|
|
36
|
+
timeoutMs: number;
|
|
37
|
+
credentials: Credentials;
|
|
38
|
+
});
|
|
39
|
+
/** Есть ли чем аутентифицироваться вообще. */
|
|
40
|
+
get isConfigured(): boolean;
|
|
41
|
+
private post;
|
|
42
|
+
private static readPair;
|
|
43
|
+
/** Возвращает access-токен, логинясь при первом обращении. */
|
|
44
|
+
accessToken(): Promise<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Обновляет пару после 401. Если refresh невозможен (передан готовый токен
|
|
47
|
+
* или refresh отвергнут) — пробует полный логин, и только потом сдаётся.
|
|
48
|
+
*/
|
|
49
|
+
refresh(): Promise<string>;
|
|
50
|
+
}
|
|
51
|
+
/** Учётные данные из конфигурации — источник по умолчанию для local-режима. */
|
|
52
|
+
export declare const credentialsFromConfig: (config: Config) => Credentials;
|
|
53
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,yEAAyE;AACzE,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,oEAAoE;AACpE,qBAAa,SAAU,SAAQ,KAAK;CAAG;AAevC,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAQhD,CAAC;AAEF;;;;GAIG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAAwB;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;gBAE9B,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,WAAW,CAAA;KAAE;IASpF,8CAA8C;IAC9C,IAAI,YAAY,IAAI,OAAO,CAI1B;YAEa,IAAI;IAuBlB,OAAO,CAAC,MAAM,CAAC,QAAQ;IAgBvB,8DAA8D;IACxD,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAkBpC;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CAgBjC;AAED,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,GAAI,QAAQ,MAAM,KAAG,WAIrD,CAAC"}
|
package/dist/api/auth.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/** Ошибка аутентификации с текстом, пригодным для показа модели. */
|
|
2
|
+
export class AuthError extends Error {
|
|
3
|
+
}
|
|
4
|
+
const decodeJwtPayload = (token) => {
|
|
5
|
+
const part = token.split('.')[1];
|
|
6
|
+
if (!part) {
|
|
7
|
+
throw new AuthError('Access token is not a JWT');
|
|
8
|
+
}
|
|
9
|
+
const json = Buffer.from(part.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8');
|
|
10
|
+
const parsed = JSON.parse(json);
|
|
11
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
12
|
+
throw new AuthError('Access token payload is not an object');
|
|
13
|
+
}
|
|
14
|
+
return parsed;
|
|
15
|
+
};
|
|
16
|
+
/** Достаёт идентификатор админа из payload access-токена. */
|
|
17
|
+
export const adminIdFromToken = (token) => {
|
|
18
|
+
const payload = decodeJwtPayload(token);
|
|
19
|
+
const id = payload['id'] ?? payload['sub'] ?? payload['userId'];
|
|
20
|
+
const numeric = typeof id === 'string' ? Number(id) : id;
|
|
21
|
+
if (typeof numeric !== 'number' || !Number.isFinite(numeric)) {
|
|
22
|
+
throw new AuthError('Access token payload has no numeric admin id');
|
|
23
|
+
}
|
|
24
|
+
return numeric;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Держит пару токенов для одного набора учётных данных.
|
|
28
|
+
* Токены живут только в памяти и только внутри сессии: в remote-режиме
|
|
29
|
+
* это то, что не даёт токену одной сессии утечь в другую.
|
|
30
|
+
*/
|
|
31
|
+
export class TokenStore {
|
|
32
|
+
pair;
|
|
33
|
+
baseUrl;
|
|
34
|
+
timeoutMs;
|
|
35
|
+
credentials;
|
|
36
|
+
constructor(params) {
|
|
37
|
+
this.baseUrl = params.baseUrl;
|
|
38
|
+
this.timeoutMs = params.timeoutMs;
|
|
39
|
+
this.credentials = params.credentials;
|
|
40
|
+
if (params.credentials.token) {
|
|
41
|
+
this.pair = { accessToken: params.credentials.token, refreshToken: '' };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Есть ли чем аутентифицироваться вообще. */
|
|
45
|
+
get isConfigured() {
|
|
46
|
+
return Boolean(this.credentials.token || (this.credentials.login && this.credentials.password));
|
|
47
|
+
}
|
|
48
|
+
async post(path, body) {
|
|
49
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
headers: { 'content-type': 'application/json' },
|
|
52
|
+
body: JSON.stringify(body),
|
|
53
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
54
|
+
});
|
|
55
|
+
const text = await response.text();
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
/**
|
|
58
|
+
* Admin API отвечает 401 «Login or password incorrect» и на developer-аккаунт:
|
|
59
|
+
* контроллер отбрасывает админов с isDeveloper. Без этой подсказки агент
|
|
60
|
+
* будет бесконечно перепроверять пароль.
|
|
61
|
+
*/
|
|
62
|
+
const hint = response.status === 401
|
|
63
|
+
? ' The Admin API also returns 401 for accounts flagged isDeveloper — those belong to the Developer API, which this server does not expose.'
|
|
64
|
+
: '';
|
|
65
|
+
throw new AuthError(`${path} failed with ${response.status}: ${text.slice(0, 200)}${hint}`);
|
|
66
|
+
}
|
|
67
|
+
return JSON.parse(text);
|
|
68
|
+
}
|
|
69
|
+
static readPair(raw) {
|
|
70
|
+
if (typeof raw !== 'object' || raw === null) {
|
|
71
|
+
throw new AuthError('Auth response is not an object');
|
|
72
|
+
}
|
|
73
|
+
const record = raw;
|
|
74
|
+
const accessToken = record['accessToken'];
|
|
75
|
+
const refreshToken = record['refreshToken'];
|
|
76
|
+
if (typeof accessToken !== 'string') {
|
|
77
|
+
throw new AuthError('Auth response has no accessToken');
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
accessToken,
|
|
81
|
+
refreshToken: typeof refreshToken === 'string' ? refreshToken : '',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** Возвращает access-токен, логинясь при первом обращении. */
|
|
85
|
+
async accessToken() {
|
|
86
|
+
if (this.pair) {
|
|
87
|
+
return this.pair.accessToken;
|
|
88
|
+
}
|
|
89
|
+
if (!this.credentials.login || !this.credentials.password) {
|
|
90
|
+
throw new AuthError('No credentials: set ONEENTRY_CMS_LOGIN + ONEENTRY_CMS_PASSWORD, or ONEENTRY_CMS_TOKEN.');
|
|
91
|
+
}
|
|
92
|
+
this.pair = TokenStore.readPair(await this.post('/auth/login', {
|
|
93
|
+
login: this.credentials.login,
|
|
94
|
+
password: this.credentials.password,
|
|
95
|
+
}));
|
|
96
|
+
return this.pair.accessToken;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Обновляет пару после 401. Если refresh невозможен (передан готовый токен
|
|
100
|
+
* или refresh отвергнут) — пробует полный логин, и только потом сдаётся.
|
|
101
|
+
*/
|
|
102
|
+
async refresh() {
|
|
103
|
+
const refreshToken = this.pair?.refreshToken;
|
|
104
|
+
this.pair = undefined;
|
|
105
|
+
if (refreshToken) {
|
|
106
|
+
try {
|
|
107
|
+
this.pair = TokenStore.readPair(await this.post('/auth/refresh', { refreshToken }));
|
|
108
|
+
return this.pair.accessToken;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
this.pair = undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (!this.credentials.login || !this.credentials.password) {
|
|
115
|
+
throw new AuthError('Access token rejected and no login/password available to re-authenticate.');
|
|
116
|
+
}
|
|
117
|
+
return this.accessToken();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** Учётные данные из конфигурации — источник по умолчанию для local-режима. */
|
|
121
|
+
export const credentialsFromConfig = (config) => ({
|
|
122
|
+
...(config.login ? { login: config.login } : {}),
|
|
123
|
+
...(config.password ? { password: config.password } : {}),
|
|
124
|
+
...(config.token ? { token: config.token } : {}),
|
|
125
|
+
});
|
|
126
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/api/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Catalog, Operation } from './types.js';
|
|
2
|
+
/** Найденная операция с оценкой релевантности. */
|
|
3
|
+
export interface OperationHit {
|
|
4
|
+
opId: string;
|
|
5
|
+
method: string;
|
|
6
|
+
path: string;
|
|
7
|
+
tag: string;
|
|
8
|
+
summary: string;
|
|
9
|
+
permission?: string;
|
|
10
|
+
risk: Operation['risk'];
|
|
11
|
+
score: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Индекс каталога операций.
|
|
15
|
+
* Поиск здесь примитивный — подсчёт совпадений термов по склеенной строке.
|
|
16
|
+
* Это осознанно: путей 478, они короткие и хорошо самоописаны,
|
|
17
|
+
* полнотекстовый движок дал бы ту же выдачу при большем весе.
|
|
18
|
+
*/
|
|
19
|
+
export declare class OperationCatalog {
|
|
20
|
+
private readonly byOpId;
|
|
21
|
+
readonly catalog: Catalog;
|
|
22
|
+
constructor(catalog: Catalog);
|
|
23
|
+
static load(): OperationCatalog;
|
|
24
|
+
get(opId: string): Operation | undefined;
|
|
25
|
+
operations(): readonly Operation[];
|
|
26
|
+
/**
|
|
27
|
+
* Подсказывает похожие `opId` — нужна для внятной ошибки, когда модель
|
|
28
|
+
* угадала имя операции вместо того, чтобы взять его из поиска.
|
|
29
|
+
*/
|
|
30
|
+
suggest(opId: string, limit?: number): string[];
|
|
31
|
+
search(params: {
|
|
32
|
+
query: string;
|
|
33
|
+
tag?: string;
|
|
34
|
+
method?: string;
|
|
35
|
+
mutating?: boolean;
|
|
36
|
+
limit?: number;
|
|
37
|
+
}): OperationHit[];
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/api/catalog.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAErD,kDAAkD;AAClD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;gBAEd,OAAO,EAAE,OAAO;IAS5B,MAAM,CAAC,IAAI,IAAI,gBAAgB;IAK/B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAIxC,UAAU,IAAI,SAAS,SAAS,EAAE;IAIlC;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE;IAU1C,MAAM,CAAC,MAAM,EAAE;QACb,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,GAAG,YAAY,EAAE;CA+CnB"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { dataDir } from '../knowledge/loader.js';
|
|
4
|
+
/**
|
|
5
|
+
* Индекс каталога операций.
|
|
6
|
+
* Поиск здесь примитивный — подсчёт совпадений термов по склеенной строке.
|
|
7
|
+
* Это осознанно: путей 478, они короткие и хорошо самоописаны,
|
|
8
|
+
* полнотекстовый движок дал бы ту же выдачу при большем весе.
|
|
9
|
+
*/
|
|
10
|
+
export class OperationCatalog {
|
|
11
|
+
byOpId;
|
|
12
|
+
catalog;
|
|
13
|
+
constructor(catalog) {
|
|
14
|
+
if (catalog.version !== 1) {
|
|
15
|
+
throw new Error(`Unsupported catalog version ${String(catalog.version)}`);
|
|
16
|
+
}
|
|
17
|
+
/** Снапшот приходит из файла, поэтому необязательные поля нормализуем на входе. */
|
|
18
|
+
this.catalog = { ...catalog, warnings: catalog.warnings ?? [] };
|
|
19
|
+
this.byOpId = new Map(catalog.operations.map((o) => [o.opId, o]));
|
|
20
|
+
}
|
|
21
|
+
static load() {
|
|
22
|
+
const file = resolve(dataDir(), 'catalog.json');
|
|
23
|
+
return new OperationCatalog(JSON.parse(readFileSync(file, 'utf8')));
|
|
24
|
+
}
|
|
25
|
+
get(opId) {
|
|
26
|
+
return this.byOpId.get(opId);
|
|
27
|
+
}
|
|
28
|
+
operations() {
|
|
29
|
+
return this.catalog.operations;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Подсказывает похожие `opId` — нужна для внятной ошибки, когда модель
|
|
33
|
+
* угадала имя операции вместо того, чтобы взять его из поиска.
|
|
34
|
+
*/
|
|
35
|
+
suggest(opId, limit = 5) {
|
|
36
|
+
const needle = opId.toLowerCase();
|
|
37
|
+
return this.catalog.operations
|
|
38
|
+
.map((o) => ({ opId: o.opId, score: overlap(o.opId.toLowerCase(), needle) }))
|
|
39
|
+
.filter((entry) => entry.score > 0)
|
|
40
|
+
.sort((a, b) => b.score - a.score)
|
|
41
|
+
.slice(0, limit)
|
|
42
|
+
.map((entry) => entry.opId);
|
|
43
|
+
}
|
|
44
|
+
search(params) {
|
|
45
|
+
const terms = params.query
|
|
46
|
+
.toLowerCase()
|
|
47
|
+
.split(/[\s/.]+/)
|
|
48
|
+
.filter((t) => t.length > 1);
|
|
49
|
+
const hits = [];
|
|
50
|
+
for (const operation of this.catalog.operations) {
|
|
51
|
+
if (params.tag && operation.tag.toLowerCase() !== params.tag.toLowerCase()) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (params.method && operation.method !== params.method.toLowerCase()) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (params.mutating !== undefined && params.mutating !== (operation.risk !== 'read')) {
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
let score = terms.length === 0 ? 1 : 0;
|
|
61
|
+
for (const term of terms) {
|
|
62
|
+
if (operation.path.toLowerCase().includes(term)) {
|
|
63
|
+
score += 3;
|
|
64
|
+
}
|
|
65
|
+
if (operation.tag.toLowerCase().includes(term)) {
|
|
66
|
+
score += 2;
|
|
67
|
+
}
|
|
68
|
+
if (operation.searchText.includes(term)) {
|
|
69
|
+
score += 1;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (score > 0) {
|
|
73
|
+
hits.push({
|
|
74
|
+
opId: operation.opId,
|
|
75
|
+
method: operation.method.toUpperCase(),
|
|
76
|
+
path: operation.path,
|
|
77
|
+
tag: operation.tag,
|
|
78
|
+
summary: operation.summary,
|
|
79
|
+
...(operation.permission ? { permission: operation.permission } : {}),
|
|
80
|
+
risk: operation.risk,
|
|
81
|
+
score,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
hits.sort((a, b) => b.score - a.score || a.path.length - b.path.length);
|
|
86
|
+
return hits.slice(0, params.limit ?? 15);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Доля общих триграмм — грубая, но достаточная мера похожести имён операций. */
|
|
90
|
+
const overlap = (a, b) => {
|
|
91
|
+
const grams = (value) => {
|
|
92
|
+
const out = new Set();
|
|
93
|
+
for (let i = 0; i + 3 <= value.length; i++) {
|
|
94
|
+
out.add(value.slice(i, i + 3));
|
|
95
|
+
}
|
|
96
|
+
return out;
|
|
97
|
+
};
|
|
98
|
+
const left = grams(a);
|
|
99
|
+
const right = grams(b);
|
|
100
|
+
let shared = 0;
|
|
101
|
+
for (const gram of right) {
|
|
102
|
+
if (left.has(gram)) {
|
|
103
|
+
shared += 1;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return right.size === 0 ? 0 : shared / right.size;
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/api/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { TokenStore } from './auth.js';
|
|
2
|
+
import type { Operation } from './types.js';
|
|
3
|
+
/** Аргументы вызова операции, как их присылает модель. */
|
|
4
|
+
export interface CallArgs {
|
|
5
|
+
path?: Record<string, string | number>;
|
|
6
|
+
query?: Record<string, string | number | boolean>;
|
|
7
|
+
body?: unknown;
|
|
8
|
+
}
|
|
9
|
+
/** Нормализованный неуспех вызова. */
|
|
10
|
+
export interface NormalizedError {
|
|
11
|
+
status: number;
|
|
12
|
+
message: string;
|
|
13
|
+
hint?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Результат вызова: либо тело ответа, либо нормализованная ошибка. */
|
|
16
|
+
export type CallResult = {
|
|
17
|
+
ok: true;
|
|
18
|
+
status: number;
|
|
19
|
+
body: unknown;
|
|
20
|
+
} | {
|
|
21
|
+
ok: false;
|
|
22
|
+
error: NormalizedError;
|
|
23
|
+
};
|
|
24
|
+
/** Ошибка на стороне вызывающего — до отправки запроса. */
|
|
25
|
+
export declare class RequestBuildError extends Error {
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Возвращает тело в том виде, в каком его надо сериализовать в запрос.
|
|
29
|
+
* Часть MCP-клиентов передаёт объектный аргумент уже сериализованным в строку;
|
|
30
|
+
* без этой нормализации `JSON.stringify` завернул бы его второй раз, и на сервер
|
|
31
|
+
* ушла бы JSON-строка вместо объекта — любая запись падала бы с невнятным 400.
|
|
32
|
+
* Разворачивается только строка, которая целиком является объектом или массивом:
|
|
33
|
+
* скалярная строка — законное тело, и трогать её нельзя.
|
|
34
|
+
*/
|
|
35
|
+
export declare const normalizeBody: (body: unknown) => unknown;
|
|
36
|
+
/**
|
|
37
|
+
* Подставляет path-параметры и собирает query-строку.
|
|
38
|
+
* Отсутствующий обязательный path-параметр — ошибка здесь, а не 404 от сервера:
|
|
39
|
+
* иначе агент получает загадочный ответ вместо указания, чего не хватает.
|
|
40
|
+
*/
|
|
41
|
+
export declare const buildUrl: (baseUrl: string, operation: Operation, args: CallArgs) => string;
|
|
42
|
+
/**
|
|
43
|
+
* HTTP-клиент Admin API.
|
|
44
|
+
* Единственный ретрай — на 401 после обновления токена: любой другой повтор
|
|
45
|
+
* на изменяющей операции рискует создать дубль, поэтому его здесь нет.
|
|
46
|
+
*/
|
|
47
|
+
export declare class AdminApiClient {
|
|
48
|
+
private readonly baseUrl;
|
|
49
|
+
private readonly tokens;
|
|
50
|
+
private readonly timeoutMs;
|
|
51
|
+
constructor(params: {
|
|
52
|
+
baseUrl: string;
|
|
53
|
+
tokens: TokenStore;
|
|
54
|
+
timeoutMs: number;
|
|
55
|
+
});
|
|
56
|
+
call(operation: Operation, args: CallArgs): Promise<CallResult>;
|
|
57
|
+
/** Читает набор прав админа. Пустой массив означает «не удалось выяснить». */
|
|
58
|
+
fetchPermissions(adminId: number): Promise<string[]>;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,0DAA0D;AAC1D,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAClD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,sCAAsC;AACtC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,uEAAuE;AACvE,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAC3C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,eAAe,CAAA;CAAE,CAAC;AAE1C,2DAA2D;AAC3D,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAE/C;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,OAAO,KAAG,OAc7C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,GACnB,SAAS,MAAM,EACf,WAAW,SAAS,EACpB,MAAM,QAAQ,KACb,MAkCF,CAAC;AAqDF;;;;GAIG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE;IAMxE,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAiDrE,8EAA8E;IACxE,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;CAyB3D"}
|