@aaronsb/kg-cli 0.6.1
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 +112 -0
- package/dist/api/client.d.ts +867 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +1362 -0
- package/dist/api/client.js.map +1 -0
- package/dist/cli/admin/backup.d.ts +9 -0
- package/dist/cli/admin/backup.d.ts.map +1 -0
- package/dist/cli/admin/backup.js +363 -0
- package/dist/cli/admin/backup.js.map +1 -0
- package/dist/cli/admin/index.d.ts +7 -0
- package/dist/cli/admin/index.d.ts.map +1 -0
- package/dist/cli/admin/index.js +52 -0
- package/dist/cli/admin/index.js.map +1 -0
- package/dist/cli/admin/scheduler.d.ts +7 -0
- package/dist/cli/admin/scheduler.d.ts.map +1 -0
- package/dist/cli/admin/scheduler.js +125 -0
- package/dist/cli/admin/scheduler.js.map +1 -0
- package/dist/cli/admin/status.d.ts +7 -0
- package/dist/cli/admin/status.d.ts.map +1 -0
- package/dist/cli/admin/status.js +134 -0
- package/dist/cli/admin/status.js.map +1 -0
- package/dist/cli/admin/utils.d.ts +34 -0
- package/dist/cli/admin/utils.d.ts.map +1 -0
- package/dist/cli/admin/utils.js +441 -0
- package/dist/cli/admin/utils.js.map +1 -0
- package/dist/cli/ai-config/embedding.d.ts +11 -0
- package/dist/cli/ai-config/embedding.d.ts.map +1 -0
- package/dist/cli/ai-config/embedding.js +598 -0
- package/dist/cli/ai-config/embedding.js.map +1 -0
- package/dist/cli/ai-config/extraction.d.ts +11 -0
- package/dist/cli/ai-config/extraction.d.ts.map +1 -0
- package/dist/cli/ai-config/extraction.js +206 -0
- package/dist/cli/ai-config/extraction.js.map +1 -0
- package/dist/cli/ai-config/index.d.ts +21 -0
- package/dist/cli/ai-config/index.d.ts.map +1 -0
- package/dist/cli/ai-config/index.js +27 -0
- package/dist/cli/ai-config/index.js.map +1 -0
- package/dist/cli/ai-config/keys.d.ts +11 -0
- package/dist/cli/ai-config/keys.d.ts.map +1 -0
- package/dist/cli/ai-config/keys.js +182 -0
- package/dist/cli/ai-config/keys.js.map +1 -0
- package/dist/cli/ai-config/utils.d.ts +13 -0
- package/dist/cli/ai-config/utils.d.ts.map +1 -0
- package/dist/cli/ai-config/utils.js +84 -0
- package/dist/cli/ai-config/utils.js.map +1 -0
- package/dist/cli/artifact.d.ts +8 -0
- package/dist/cli/artifact.d.ts.map +1 -0
- package/dist/cli/artifact.js +296 -0
- package/dist/cli/artifact.js.map +1 -0
- package/dist/cli/auth-admin.d.ts +11 -0
- package/dist/cli/auth-admin.d.ts.map +1 -0
- package/dist/cli/auth-admin.js +415 -0
- package/dist/cli/auth-admin.js.map +1 -0
- package/dist/cli/colors.d.ts +105 -0
- package/dist/cli/colors.d.ts.map +1 -0
- package/dist/cli/colors.js +164 -0
- package/dist/cli/colors.js.map +1 -0
- package/dist/cli/commands.d.ts +6 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +164 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/config.d.ts +6 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +694 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/curve-viz.d.ts +89 -0
- package/dist/cli/curve-viz.d.ts.map +1 -0
- package/dist/cli/curve-viz.js +228 -0
- package/dist/cli/curve-viz.js.map +1 -0
- package/dist/cli/database.d.ts +6 -0
- package/dist/cli/database.d.ts.map +1 -0
- package/dist/cli/database.js +324 -0
- package/dist/cli/database.js.map +1 -0
- package/dist/cli/document.d.ts +6 -0
- package/dist/cli/document.d.ts.map +1 -0
- package/dist/cli/document.js +458 -0
- package/dist/cli/document.js.map +1 -0
- package/dist/cli/group.d.ts +8 -0
- package/dist/cli/group.d.ts.map +1 -0
- package/dist/cli/group.js +174 -0
- package/dist/cli/group.js.map +1 -0
- package/dist/cli/health.d.ts +6 -0
- package/dist/cli/health.d.ts.map +1 -0
- package/dist/cli/health.js +34 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/help-formatter.d.ts +16 -0
- package/dist/cli/help-formatter.d.ts.map +1 -0
- package/dist/cli/help-formatter.js +248 -0
- package/dist/cli/help-formatter.js.map +1 -0
- package/dist/cli/help.d.ts +9 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +227 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/ingest.d.ts +6 -0
- package/dist/cli/ingest.d.ts.map +1 -0
- package/dist/cli/ingest.js +722 -0
- package/dist/cli/ingest.js.map +1 -0
- package/dist/cli/jobs.d.ts +6 -0
- package/dist/cli/jobs.d.ts.map +1 -0
- package/dist/cli/jobs.js +663 -0
- package/dist/cli/jobs.js.map +1 -0
- package/dist/cli/login.d.ts +21 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +221 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/logout.d.ts +16 -0
- package/dist/cli/logout.d.ts.map +1 -0
- package/dist/cli/logout.js +141 -0
- package/dist/cli/logout.js.map +1 -0
- package/dist/cli/mcp-config.d.ts +10 -0
- package/dist/cli/mcp-config.d.ts.map +1 -0
- package/dist/cli/mcp-config.js +358 -0
- package/dist/cli/mcp-config.js.map +1 -0
- package/dist/cli/oauth.d.ts +15 -0
- package/dist/cli/oauth.d.ts.map +1 -0
- package/dist/cli/oauth.js +296 -0
- package/dist/cli/oauth.js.map +1 -0
- package/dist/cli/ontology.d.ts +6 -0
- package/dist/cli/ontology.d.ts.map +1 -0
- package/dist/cli/ontology.js +231 -0
- package/dist/cli/ontology.js.map +1 -0
- package/dist/cli/polarity.d.ts +6 -0
- package/dist/cli/polarity.d.ts.map +1 -0
- package/dist/cli/polarity.js +295 -0
- package/dist/cli/polarity.js.map +1 -0
- package/dist/cli/projection.d.ts +8 -0
- package/dist/cli/projection.d.ts.map +1 -0
- package/dist/cli/projection.js +297 -0
- package/dist/cli/projection.js.map +1 -0
- package/dist/cli/query-def.d.ts +8 -0
- package/dist/cli/query-def.d.ts.map +1 -0
- package/dist/cli/query-def.js +163 -0
- package/dist/cli/query-def.js.map +1 -0
- package/dist/cli/rbac.d.ts +12 -0
- package/dist/cli/rbac.d.ts.map +1 -0
- package/dist/cli/rbac.js +615 -0
- package/dist/cli/rbac.js.map +1 -0
- package/dist/cli/search.d.ts +6 -0
- package/dist/cli/search.d.ts.map +1 -0
- package/dist/cli/search.js +829 -0
- package/dist/cli/search.js.map +1 -0
- package/dist/cli/source.d.ts +6 -0
- package/dist/cli/source.d.ts.map +1 -0
- package/dist/cli/source.js +202 -0
- package/dist/cli/source.js.map +1 -0
- package/dist/cli/verb-router.d.ts +25 -0
- package/dist/cli/verb-router.d.ts.map +1 -0
- package/dist/cli/verb-router.js +415 -0
- package/dist/cli/verb-router.js.map +1 -0
- package/dist/cli/vocabulary/config.d.ts +7 -0
- package/dist/cli/vocabulary/config.d.ts.map +1 -0
- package/dist/cli/vocabulary/config.js +201 -0
- package/dist/cli/vocabulary/config.js.map +1 -0
- package/dist/cli/vocabulary/consolidate.d.ts +8 -0
- package/dist/cli/vocabulary/consolidate.d.ts.map +1 -0
- package/dist/cli/vocabulary/consolidate.js +192 -0
- package/dist/cli/vocabulary/consolidate.js.map +1 -0
- package/dist/cli/vocabulary/embeddings.d.ts +9 -0
- package/dist/cli/vocabulary/embeddings.d.ts.map +1 -0
- package/dist/cli/vocabulary/embeddings.js +205 -0
- package/dist/cli/vocabulary/embeddings.js.map +1 -0
- package/dist/cli/vocabulary/epistemic.d.ts +7 -0
- package/dist/cli/vocabulary/epistemic.d.ts.map +1 -0
- package/dist/cli/vocabulary/epistemic.js +315 -0
- package/dist/cli/vocabulary/epistemic.js.map +1 -0
- package/dist/cli/vocabulary/index.d.ts +7 -0
- package/dist/cli/vocabulary/index.d.ts.map +1 -0
- package/dist/cli/vocabulary/index.js +45 -0
- package/dist/cli/vocabulary/index.js.map +1 -0
- package/dist/cli/vocabulary/profiles.d.ts +7 -0
- package/dist/cli/vocabulary/profiles.d.ts.map +1 -0
- package/dist/cli/vocabulary/profiles.js +171 -0
- package/dist/cli/vocabulary/profiles.js.map +1 -0
- package/dist/cli/vocabulary/similarity.d.ts +9 -0
- package/dist/cli/vocabulary/similarity.d.ts.map +1 -0
- package/dist/cli/vocabulary/similarity.js +199 -0
- package/dist/cli/vocabulary/similarity.js.map +1 -0
- package/dist/cli/vocabulary/status.d.ts +8 -0
- package/dist/cli/vocabulary/status.d.ts.map +1 -0
- package/dist/cli/vocabulary/status.js +280 -0
- package/dist/cli/vocabulary/status.js.map +1 -0
- package/dist/cli/vocabulary/sync.d.ts +7 -0
- package/dist/cli/vocabulary/sync.d.ts.map +1 -0
- package/dist/cli/vocabulary/sync.js +111 -0
- package/dist/cli/vocabulary/sync.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auth/auth-client.d.ts +247 -0
- package/dist/lib/auth/auth-client.d.ts.map +1 -0
- package/dist/lib/auth/auth-client.js +305 -0
- package/dist/lib/auth/auth-client.js.map +1 -0
- package/dist/lib/auth/challenge.d.ts +39 -0
- package/dist/lib/auth/challenge.d.ts.map +1 -0
- package/dist/lib/auth/challenge.js +125 -0
- package/dist/lib/auth/challenge.js.map +1 -0
- package/dist/lib/auth/client-credentials-flow.d.ts +58 -0
- package/dist/lib/auth/client-credentials-flow.d.ts.map +1 -0
- package/dist/lib/auth/client-credentials-flow.js +118 -0
- package/dist/lib/auth/client-credentials-flow.js.map +1 -0
- package/dist/lib/auth/device-flow.d.ts +75 -0
- package/dist/lib/auth/device-flow.d.ts.map +1 -0
- package/dist/lib/auth/device-flow.js +177 -0
- package/dist/lib/auth/device-flow.js.map +1 -0
- package/dist/lib/auth/index.d.ts +14 -0
- package/dist/lib/auth/index.d.ts.map +1 -0
- package/dist/lib/auth/index.js +34 -0
- package/dist/lib/auth/index.js.map +1 -0
- package/dist/lib/auth/oauth-types.d.ts +69 -0
- package/dist/lib/auth/oauth-types.d.ts.map +1 -0
- package/dist/lib/auth/oauth-types.js +10 -0
- package/dist/lib/auth/oauth-types.js.map +1 -0
- package/dist/lib/auth/oauth-utils.d.ts +51 -0
- package/dist/lib/auth/oauth-utils.d.ts.map +1 -0
- package/dist/lib/auth/oauth-utils.js +110 -0
- package/dist/lib/auth/oauth-utils.js.map +1 -0
- package/dist/lib/auth/token-manager.d.ts +87 -0
- package/dist/lib/auth/token-manager.d.ts.map +1 -0
- package/dist/lib/auth/token-manager.js +139 -0
- package/dist/lib/auth/token-manager.js.map +1 -0
- package/dist/lib/auth/token-refresh.d.ts +63 -0
- package/dist/lib/auth/token-refresh.d.ts.map +1 -0
- package/dist/lib/auth/token-refresh.js +141 -0
- package/dist/lib/auth/token-refresh.js.map +1 -0
- package/dist/lib/config.d.ts +286 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +537 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/job-stream.d.ts +53 -0
- package/dist/lib/job-stream.d.ts.map +1 -0
- package/dist/lib/job-stream.js +153 -0
- package/dist/lib/job-stream.js.map +1 -0
- package/dist/lib/mcp-allowlist.d.ts +101 -0
- package/dist/lib/mcp-allowlist.d.ts.map +1 -0
- package/dist/lib/mcp-allowlist.js +340 -0
- package/dist/lib/mcp-allowlist.js.map +1 -0
- package/dist/lib/table-example.d.ts +7 -0
- package/dist/lib/table-example.d.ts.map +1 -0
- package/dist/lib/table-example.js +105 -0
- package/dist/lib/table-example.js.map +1 -0
- package/dist/lib/table.d.ts +95 -0
- package/dist/lib/table.d.ts.map +1 -0
- package/dist/lib/table.js +263 -0
- package/dist/lib/table.js.map +1 -0
- package/dist/lib/terminal-images.d.ts +66 -0
- package/dist/lib/terminal-images.d.ts.map +1 -0
- package/dist/lib/terminal-images.js +268 -0
- package/dist/lib/terminal-images.js.map +1 -0
- package/dist/mcp/formatters.d.ts +100 -0
- package/dist/mcp/formatters.d.ts.map +1 -0
- package/dist/mcp/formatters.js +1411 -0
- package/dist/mcp/formatters.js.map +1 -0
- package/dist/mcp-server.d.ts +9 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +1810 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/types/index.d.ts +742 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/version.d.ts +10 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,1362 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Knowledge Graph API Client
|
|
4
|
+
*
|
|
5
|
+
* Wraps HTTP calls to the FastAPI server
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.KnowledgeGraphClient = void 0;
|
|
45
|
+
exports.createClientFromEnv = createClientFromEnv;
|
|
46
|
+
const axios_1 = __importDefault(require("axios"));
|
|
47
|
+
const form_data_1 = __importDefault(require("form-data"));
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
class KnowledgeGraphClient {
|
|
50
|
+
constructor(config) {
|
|
51
|
+
this.mcpJwtToken = null; // JWT token for MCP server authentication
|
|
52
|
+
this.config = config;
|
|
53
|
+
this.client = axios_1.default.create({
|
|
54
|
+
baseURL: config.baseUrl,
|
|
55
|
+
headers: {
|
|
56
|
+
...(config.clientId && { 'X-Client-ID': config.clientId }),
|
|
57
|
+
...(config.apiKey && { 'X-API-Key': config.apiKey }),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
// ADR-054: Add request interceptor for OAuth authentication
|
|
61
|
+
this.client.interceptors.request.use(async (requestConfig) => {
|
|
62
|
+
// Priority 1: Use MCP JWT token if set (for MCP server - legacy)
|
|
63
|
+
if (this.mcpJwtToken) {
|
|
64
|
+
requestConfig.headers.Authorization = `Bearer ${this.mcpJwtToken}`;
|
|
65
|
+
return requestConfig;
|
|
66
|
+
}
|
|
67
|
+
// Priority 2: Get OAuth client credentials from config and fetch fresh access token
|
|
68
|
+
try {
|
|
69
|
+
const { getConfig } = require('../lib/config');
|
|
70
|
+
const { AuthClient } = require('../lib/auth/auth-client');
|
|
71
|
+
const configManager = getConfig();
|
|
72
|
+
// Check for OAuth client credentials (ADR-054)
|
|
73
|
+
const oauthCreds = configManager.getOAuthCredentials();
|
|
74
|
+
if (oauthCreds) {
|
|
75
|
+
// Get fresh access token using client credentials grant
|
|
76
|
+
const authClient = new AuthClient(this.config.baseUrl);
|
|
77
|
+
const tokenResponse = await authClient.getOAuthToken({
|
|
78
|
+
grant_type: 'client_credentials',
|
|
79
|
+
client_id: oauthCreds.client_id,
|
|
80
|
+
client_secret: oauthCreds.client_secret,
|
|
81
|
+
scope: oauthCreds.scopes.join(' ')
|
|
82
|
+
});
|
|
83
|
+
requestConfig.headers.Authorization = `Bearer ${tokenResponse.access_token}`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
// Config not available or OAuth credentials not found - continue without auth
|
|
88
|
+
}
|
|
89
|
+
return requestConfig;
|
|
90
|
+
});
|
|
91
|
+
// ADR-054: Add response interceptor for 401 errors (invalid OAuth token)
|
|
92
|
+
this.client.interceptors.response.use((response) => response, (error) => {
|
|
93
|
+
if (error.response?.status === 401) {
|
|
94
|
+
// Check if we have OAuth credentials
|
|
95
|
+
try {
|
|
96
|
+
const { getConfig } = require('../lib/config');
|
|
97
|
+
const configManager = getConfig();
|
|
98
|
+
if (configManager.isAuthenticated()) {
|
|
99
|
+
// User has OAuth credentials but got 401 - client may be revoked
|
|
100
|
+
console.error('\n\x1b[31m❌ Authentication failed\x1b[0m');
|
|
101
|
+
console.error(' Your OAuth credentials may be invalid or revoked.');
|
|
102
|
+
console.error(' Please login again:');
|
|
103
|
+
console.error(' \x1b[36mkg login\x1b[0m\n');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
// Ignore errors from config loading
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return Promise.reject(error);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Set JWT token for MCP server authentication
|
|
115
|
+
*
|
|
116
|
+
* This allows the MCP server to inject a JWT token obtained via automatic login,
|
|
117
|
+
* making authentication transparent to the AI using the MCP tools.
|
|
118
|
+
*
|
|
119
|
+
* @param token JWT access token from login response
|
|
120
|
+
*/
|
|
121
|
+
setMcpJwtToken(token) {
|
|
122
|
+
this.mcpJwtToken = token;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Health check
|
|
126
|
+
*/
|
|
127
|
+
async health() {
|
|
128
|
+
const response = await this.client.get('/health');
|
|
129
|
+
return response.data;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get API info
|
|
133
|
+
*/
|
|
134
|
+
async info() {
|
|
135
|
+
const response = await this.client.get('/');
|
|
136
|
+
return response.data;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Ingest a document file
|
|
140
|
+
*/
|
|
141
|
+
async ingestFile(filePath, request) {
|
|
142
|
+
const form = new form_data_1.default();
|
|
143
|
+
form.append('file', fs.createReadStream(filePath));
|
|
144
|
+
form.append('ontology', request.ontology);
|
|
145
|
+
if (request.filename) {
|
|
146
|
+
form.append('filename', request.filename);
|
|
147
|
+
}
|
|
148
|
+
if (request.force) {
|
|
149
|
+
form.append('force', 'true');
|
|
150
|
+
}
|
|
151
|
+
if (request.auto_approve) {
|
|
152
|
+
form.append('auto_approve', 'true');
|
|
153
|
+
}
|
|
154
|
+
if (request.processing_mode) {
|
|
155
|
+
form.append('processing_mode', request.processing_mode);
|
|
156
|
+
}
|
|
157
|
+
if (request.options) {
|
|
158
|
+
if (request.options.target_words !== undefined) {
|
|
159
|
+
form.append('target_words', String(request.options.target_words));
|
|
160
|
+
}
|
|
161
|
+
if (request.options.min_words !== undefined) {
|
|
162
|
+
form.append('min_words', String(request.options.min_words));
|
|
163
|
+
}
|
|
164
|
+
if (request.options.max_words !== undefined) {
|
|
165
|
+
form.append('max_words', String(request.options.max_words));
|
|
166
|
+
}
|
|
167
|
+
if (request.options.overlap_words !== undefined) {
|
|
168
|
+
form.append('overlap_words', String(request.options.overlap_words));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// ADR-051: Source provenance metadata
|
|
172
|
+
if (request.source_type) {
|
|
173
|
+
form.append('source_type', request.source_type);
|
|
174
|
+
}
|
|
175
|
+
if (request.source_path) {
|
|
176
|
+
form.append('source_path', request.source_path);
|
|
177
|
+
}
|
|
178
|
+
if (request.source_hostname) {
|
|
179
|
+
form.append('source_hostname', request.source_hostname);
|
|
180
|
+
}
|
|
181
|
+
const response = await this.client.post('/ingest', form, {
|
|
182
|
+
headers: form.getHeaders(),
|
|
183
|
+
});
|
|
184
|
+
return response.data;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Ingest raw text
|
|
188
|
+
*/
|
|
189
|
+
async ingestText(text, request) {
|
|
190
|
+
const form = new form_data_1.default();
|
|
191
|
+
form.append('text', text);
|
|
192
|
+
form.append('ontology', request.ontology);
|
|
193
|
+
if (request.filename) {
|
|
194
|
+
form.append('filename', request.filename);
|
|
195
|
+
}
|
|
196
|
+
if (request.force) {
|
|
197
|
+
form.append('force', 'true');
|
|
198
|
+
}
|
|
199
|
+
if (request.auto_approve) {
|
|
200
|
+
form.append('auto_approve', 'true');
|
|
201
|
+
}
|
|
202
|
+
if (request.processing_mode) {
|
|
203
|
+
form.append('processing_mode', request.processing_mode);
|
|
204
|
+
}
|
|
205
|
+
if (request.options?.target_words !== undefined) {
|
|
206
|
+
form.append('target_words', String(request.options.target_words));
|
|
207
|
+
}
|
|
208
|
+
if (request.options?.overlap_words !== undefined) {
|
|
209
|
+
form.append('overlap_words', String(request.options.overlap_words));
|
|
210
|
+
}
|
|
211
|
+
const response = await this.client.post('/ingest/text', form, {
|
|
212
|
+
headers: form.getHeaders(),
|
|
213
|
+
});
|
|
214
|
+
return response.data;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Ingest image (ADR-057)
|
|
218
|
+
*/
|
|
219
|
+
async ingestImage(filePath, request) {
|
|
220
|
+
const form = new form_data_1.default();
|
|
221
|
+
form.append('file', fs.createReadStream(filePath));
|
|
222
|
+
form.append('ontology', request.ontology);
|
|
223
|
+
if (request.filename) {
|
|
224
|
+
form.append('filename', request.filename);
|
|
225
|
+
}
|
|
226
|
+
if (request.force) {
|
|
227
|
+
form.append('force', 'true');
|
|
228
|
+
}
|
|
229
|
+
if (request.auto_approve) {
|
|
230
|
+
form.append('auto_approve', 'true');
|
|
231
|
+
}
|
|
232
|
+
if (request.vision_provider) {
|
|
233
|
+
form.append('vision_provider', request.vision_provider);
|
|
234
|
+
}
|
|
235
|
+
if (request.vision_model) {
|
|
236
|
+
form.append('vision_model', request.vision_model);
|
|
237
|
+
}
|
|
238
|
+
if (request.source_type) {
|
|
239
|
+
form.append('source_type', request.source_type);
|
|
240
|
+
}
|
|
241
|
+
if (request.source_path) {
|
|
242
|
+
form.append('source_path', request.source_path);
|
|
243
|
+
}
|
|
244
|
+
if (request.source_hostname) {
|
|
245
|
+
form.append('source_hostname', request.source_hostname);
|
|
246
|
+
}
|
|
247
|
+
const response = await this.client.post('/ingest/image', form, {
|
|
248
|
+
headers: form.getHeaders(),
|
|
249
|
+
});
|
|
250
|
+
return response.data;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Get job status
|
|
254
|
+
*/
|
|
255
|
+
async getJob(jobId) {
|
|
256
|
+
const response = await this.client.get(`/jobs/${jobId}`);
|
|
257
|
+
return response.data;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Get job status (alias for getJob)
|
|
261
|
+
*/
|
|
262
|
+
async getJobStatus(jobId) {
|
|
263
|
+
return this.getJob(jobId);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* List jobs
|
|
267
|
+
*/
|
|
268
|
+
async listJobs(status, clientId, limit = 50, offset = 0) {
|
|
269
|
+
const params = { limit, offset };
|
|
270
|
+
if (status) {
|
|
271
|
+
params.status = status;
|
|
272
|
+
}
|
|
273
|
+
if (clientId) {
|
|
274
|
+
params.client_id = clientId;
|
|
275
|
+
}
|
|
276
|
+
const response = await this.client.get('/jobs', { params });
|
|
277
|
+
return response.data;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Cancel a job
|
|
281
|
+
*/
|
|
282
|
+
async cancelJob(jobId) {
|
|
283
|
+
const response = await this.client.delete(`/jobs/${jobId}`);
|
|
284
|
+
return response.data;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Clear all jobs (nuclear option - requires confirmation)
|
|
288
|
+
*/
|
|
289
|
+
async clearAllJobs(confirm = false) {
|
|
290
|
+
const response = await this.client.delete('/jobs', {
|
|
291
|
+
params: { confirm }
|
|
292
|
+
});
|
|
293
|
+
return response.data;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Approve a job for processing (ADR-014)
|
|
297
|
+
*/
|
|
298
|
+
async approveJob(jobId) {
|
|
299
|
+
const response = await this.client.post(`/jobs/${jobId}/approve`);
|
|
300
|
+
return response.data;
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Poll job until completion
|
|
304
|
+
*
|
|
305
|
+
* @param jobId Job ID to poll
|
|
306
|
+
* @param onProgress Optional callback for progress updates
|
|
307
|
+
* @param pollInterval Poll interval in ms (default: 2000)
|
|
308
|
+
* @returns Final job status
|
|
309
|
+
*/
|
|
310
|
+
async pollJob(jobId, onProgress, pollInterval = 2000) {
|
|
311
|
+
while (true) {
|
|
312
|
+
const job = await this.getJob(jobId);
|
|
313
|
+
if (onProgress) {
|
|
314
|
+
onProgress(job);
|
|
315
|
+
}
|
|
316
|
+
// Check if job is terminal or awaiting approval
|
|
317
|
+
// Stop polling if job needs user action (approval) or is complete
|
|
318
|
+
if (['completed', 'failed', 'cancelled', 'awaiting_approval'].includes(job.status)) {
|
|
319
|
+
return job;
|
|
320
|
+
}
|
|
321
|
+
// Wait before polling again
|
|
322
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
// ========== Query Methods ==========
|
|
326
|
+
/**
|
|
327
|
+
* Search for concepts using semantic similarity
|
|
328
|
+
*/
|
|
329
|
+
async searchConcepts(request) {
|
|
330
|
+
const response = await this.client.post('/query/search', request);
|
|
331
|
+
return response.data;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Search source text using semantic similarity (ADR-068 Phase 3)
|
|
335
|
+
*/
|
|
336
|
+
async searchSources(request) {
|
|
337
|
+
const response = await this.client.post('/query/sources/search', request);
|
|
338
|
+
return response.data;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Get detailed information about a concept
|
|
342
|
+
*/
|
|
343
|
+
async getConceptDetails(conceptId, includeGrounding = false, includeDiversity = false, diversityMaxHops = 2) {
|
|
344
|
+
const response = await this.client.get(`/query/concept/${conceptId}`, {
|
|
345
|
+
params: {
|
|
346
|
+
include_grounding: includeGrounding,
|
|
347
|
+
include_diversity: includeDiversity,
|
|
348
|
+
diversity_max_hops: diversityMaxHops
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
return response.data;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Find concepts related through graph traversal
|
|
355
|
+
*/
|
|
356
|
+
async findRelatedConcepts(request) {
|
|
357
|
+
const response = await this.client.post('/query/related', request);
|
|
358
|
+
return response.data;
|
|
359
|
+
}
|
|
360
|
+
/**
|
|
361
|
+
* Find shortest paths between two concepts
|
|
362
|
+
*/
|
|
363
|
+
async findConnection(request) {
|
|
364
|
+
const response = await this.client.post('/query/connect', request);
|
|
365
|
+
return response.data;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Find shortest paths between concepts using natural language queries
|
|
369
|
+
*/
|
|
370
|
+
async findConnectionBySearch(request) {
|
|
371
|
+
const response = await this.client.post('/query/connect-by-search', request);
|
|
372
|
+
return response.data;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Get image for a source node (ADR-057)
|
|
376
|
+
* @param sourceId - Source ID from concept instance
|
|
377
|
+
* @returns Image as Buffer (binary data)
|
|
378
|
+
*/
|
|
379
|
+
async getSourceImage(sourceId) {
|
|
380
|
+
const response = await this.client.get(`/sources/${sourceId}/image`, {
|
|
381
|
+
responseType: 'arraybuffer',
|
|
382
|
+
});
|
|
383
|
+
return Buffer.from(response.data);
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Get image for a source node as base64 string (ADR-057)
|
|
387
|
+
* Useful for MCP server to return images to Claude
|
|
388
|
+
* @param sourceId - Source ID from concept instance
|
|
389
|
+
* @returns Base64-encoded image string
|
|
390
|
+
*/
|
|
391
|
+
async getSourceImageBase64(sourceId) {
|
|
392
|
+
const buffer = await this.getSourceImage(sourceId);
|
|
393
|
+
return buffer.toString('base64');
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* List source nodes with optional filtering
|
|
397
|
+
* @param options - Filter and pagination options
|
|
398
|
+
* @returns List of sources with metadata
|
|
399
|
+
*/
|
|
400
|
+
async listSources(options = {}) {
|
|
401
|
+
const params = new URLSearchParams();
|
|
402
|
+
if (options.ontology)
|
|
403
|
+
params.append('ontology', options.ontology);
|
|
404
|
+
if (options.limit)
|
|
405
|
+
params.append('limit', options.limit.toString());
|
|
406
|
+
if (options.offset)
|
|
407
|
+
params.append('offset', options.offset.toString());
|
|
408
|
+
const response = await this.client.get(`/sources?${params.toString()}`);
|
|
409
|
+
return response.data;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Get original document for a source node (ADR-081)
|
|
413
|
+
* @param sourceId - Source ID from search results or concept details
|
|
414
|
+
* @returns Document content as Buffer (binary data)
|
|
415
|
+
*/
|
|
416
|
+
async getSourceDocument(sourceId) {
|
|
417
|
+
const response = await this.client.get(`/sources/${sourceId}/document`, {
|
|
418
|
+
responseType: 'arraybuffer',
|
|
419
|
+
});
|
|
420
|
+
return Buffer.from(response.data);
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Get source metadata
|
|
424
|
+
* @param sourceId - Source ID
|
|
425
|
+
* @returns Source metadata including garage_key, content_hash, etc.
|
|
426
|
+
*/
|
|
427
|
+
async getSourceMetadata(sourceId) {
|
|
428
|
+
const response = await this.client.get(`/sources/${sourceId}`);
|
|
429
|
+
return response.data;
|
|
430
|
+
}
|
|
431
|
+
// ========== Document Methods (ADR-084) ==========
|
|
432
|
+
/**
|
|
433
|
+
* Search documents using semantic similarity
|
|
434
|
+
* Aggregates chunk-level matches to document level
|
|
435
|
+
*/
|
|
436
|
+
async searchDocuments(request) {
|
|
437
|
+
const response = await this.client.post('/query/documents/search', request);
|
|
438
|
+
return response.data;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* List documents with optional ontology filter
|
|
442
|
+
*/
|
|
443
|
+
async listDocuments(options = {}) {
|
|
444
|
+
const params = new URLSearchParams();
|
|
445
|
+
if (options.ontology)
|
|
446
|
+
params.append('ontology', options.ontology);
|
|
447
|
+
if (options.limit)
|
|
448
|
+
params.append('limit', options.limit.toString());
|
|
449
|
+
if (options.offset)
|
|
450
|
+
params.append('offset', options.offset.toString());
|
|
451
|
+
const response = await this.client.get(`/documents?${params.toString()}`);
|
|
452
|
+
return response.data;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Get document content from Garage
|
|
456
|
+
*/
|
|
457
|
+
async getDocumentContent(documentId) {
|
|
458
|
+
const response = await this.client.get(`/documents/${encodeURIComponent(documentId)}/content`);
|
|
459
|
+
return response.data;
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Get concepts extracted from a document
|
|
463
|
+
*/
|
|
464
|
+
async getDocumentConcepts(documentId) {
|
|
465
|
+
const response = await this.client.get(`/documents/${encodeURIComponent(documentId)}/concepts`);
|
|
466
|
+
return response.data;
|
|
467
|
+
}
|
|
468
|
+
// ========== Database Methods ==========
|
|
469
|
+
/**
|
|
470
|
+
* Get database statistics
|
|
471
|
+
*/
|
|
472
|
+
async getDatabaseStats() {
|
|
473
|
+
const response = await this.client.get('/database/stats');
|
|
474
|
+
return response.data;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Get database connection information
|
|
478
|
+
*/
|
|
479
|
+
async getDatabaseInfo() {
|
|
480
|
+
const response = await this.client.get('/database/info');
|
|
481
|
+
return response.data;
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Check database health
|
|
485
|
+
*/
|
|
486
|
+
async getDatabaseHealth() {
|
|
487
|
+
const response = await this.client.get('/database/health');
|
|
488
|
+
return response.data;
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Execute a custom cypher query (ADR-048)
|
|
492
|
+
* @param query - openCypher/GQL query string
|
|
493
|
+
* @param params - Optional query parameters
|
|
494
|
+
* @param namespace - Optional namespace: 'concept', 'vocab', or null for raw
|
|
495
|
+
*/
|
|
496
|
+
async executeCypherQuery(query, params, namespace) {
|
|
497
|
+
const response = await this.client.post('/database/query', {
|
|
498
|
+
query,
|
|
499
|
+
params: params || null,
|
|
500
|
+
namespace: namespace === undefined ? null : namespace
|
|
501
|
+
});
|
|
502
|
+
return response.data;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Get all graph metrics counters organized by type (ADR-079)
|
|
506
|
+
*/
|
|
507
|
+
async getDatabaseCounters() {
|
|
508
|
+
const response = await this.client.get('/database/counters');
|
|
509
|
+
return response.data;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Refresh graph metrics counters from current graph state (ADR-079)
|
|
513
|
+
*/
|
|
514
|
+
async refreshDatabaseCounters() {
|
|
515
|
+
const response = await this.client.post('/database/counters/refresh');
|
|
516
|
+
return response.data;
|
|
517
|
+
}
|
|
518
|
+
// ========== Ontology Methods ==========
|
|
519
|
+
/**
|
|
520
|
+
* List all ontologies
|
|
521
|
+
*/
|
|
522
|
+
async listOntologies() {
|
|
523
|
+
const response = await this.client.get('/ontology/');
|
|
524
|
+
return response.data;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Get ontology information
|
|
528
|
+
*/
|
|
529
|
+
async getOntologyInfo(ontologyName) {
|
|
530
|
+
const response = await this.client.get(`/ontology/${encodeURIComponent(ontologyName)}`);
|
|
531
|
+
return response.data;
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* List files in an ontology
|
|
535
|
+
*/
|
|
536
|
+
async getOntologyFiles(ontologyName) {
|
|
537
|
+
const response = await this.client.get(`/ontology/${encodeURIComponent(ontologyName)}/files`);
|
|
538
|
+
return response.data;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Delete an ontology
|
|
542
|
+
*/
|
|
543
|
+
async deleteOntology(ontologyName, force = false) {
|
|
544
|
+
const response = await this.client.delete(`/ontology/${encodeURIComponent(ontologyName)}`, {
|
|
545
|
+
params: { force }
|
|
546
|
+
});
|
|
547
|
+
return response.data;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Rename an ontology
|
|
551
|
+
*/
|
|
552
|
+
async renameOntology(oldName, newName) {
|
|
553
|
+
const response = await this.client.post(`/ontology/${encodeURIComponent(oldName)}/rename`, {
|
|
554
|
+
new_name: newName
|
|
555
|
+
});
|
|
556
|
+
return response.data;
|
|
557
|
+
}
|
|
558
|
+
// ========== Admin Methods ==========
|
|
559
|
+
/**
|
|
560
|
+
* Get system status
|
|
561
|
+
*/
|
|
562
|
+
async getSystemStatus() {
|
|
563
|
+
const response = await this.client.get('/admin/status');
|
|
564
|
+
return response.data;
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* List available backup files
|
|
568
|
+
*/
|
|
569
|
+
async listBackups() {
|
|
570
|
+
const response = await this.client.get('/admin/backups');
|
|
571
|
+
return response.data;
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Create a database backup (ADR-015 Phase 2: Streaming Download)
|
|
575
|
+
*
|
|
576
|
+
* Downloads backup as a stream and saves to specified path.
|
|
577
|
+
* Provides progress callback for tracking download.
|
|
578
|
+
*
|
|
579
|
+
* @param request Backup request (type and optional ontology)
|
|
580
|
+
* @param savePath Where to save the backup file
|
|
581
|
+
* @param onProgress Optional callback for progress updates (bytes downloaded, total bytes, percent)
|
|
582
|
+
* @returns Metadata about the downloaded backup
|
|
583
|
+
*/
|
|
584
|
+
async createBackup(request, savePath, onProgress) {
|
|
585
|
+
const response = await this.client.post('/admin/backup', request, {
|
|
586
|
+
responseType: 'stream'
|
|
587
|
+
});
|
|
588
|
+
// Extract filename from Content-Disposition header
|
|
589
|
+
const contentDisposition = response.headers['content-disposition'];
|
|
590
|
+
const filenameMatch = contentDisposition?.match(/filename=(.+)/);
|
|
591
|
+
// Default based on content type (archive is now default)
|
|
592
|
+
const contentType = response.headers['content-type'] || '';
|
|
593
|
+
const defaultFilename = contentType.includes('gzip') ? 'backup.tar.gz' : 'backup.json';
|
|
594
|
+
const filename = filenameMatch ? filenameMatch[1] : defaultFilename;
|
|
595
|
+
// Get content length if available
|
|
596
|
+
const totalBytes = parseInt(response.headers['content-length'] || '0', 10);
|
|
597
|
+
// Create write stream
|
|
598
|
+
const writer = fs.createWriteStream(savePath);
|
|
599
|
+
let downloadedBytes = 0;
|
|
600
|
+
// Pipe response to file with progress tracking
|
|
601
|
+
response.data.on('data', (chunk) => {
|
|
602
|
+
downloadedBytes += chunk.length;
|
|
603
|
+
if (onProgress && totalBytes > 0) {
|
|
604
|
+
const percent = Math.round((downloadedBytes / totalBytes) * 100);
|
|
605
|
+
onProgress(downloadedBytes, totalBytes, percent);
|
|
606
|
+
}
|
|
607
|
+
});
|
|
608
|
+
// Wait for download to complete
|
|
609
|
+
await new Promise((resolve, reject) => {
|
|
610
|
+
response.data.pipe(writer);
|
|
611
|
+
writer.on('finish', resolve);
|
|
612
|
+
writer.on('error', reject);
|
|
613
|
+
response.data.on('error', reject);
|
|
614
|
+
});
|
|
615
|
+
// Rename file to use server-provided filename if different
|
|
616
|
+
// Handle all backup formats: .json, .gexf, .tar.gz
|
|
617
|
+
const finalPath = savePath.replace(/[^/]+(\.json|\.gexf|\.tar\.gz)$/, filename);
|
|
618
|
+
if (finalPath !== savePath && fs.existsSync(savePath)) {
|
|
619
|
+
fs.renameSync(savePath, finalPath);
|
|
620
|
+
}
|
|
621
|
+
return {
|
|
622
|
+
filename,
|
|
623
|
+
path: finalPath,
|
|
624
|
+
size: downloadedBytes
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Restore a database backup (ADR-015 Phase 2: Multipart Upload)
|
|
629
|
+
*
|
|
630
|
+
* Uploads backup file as multipart/form-data and queues restore job.
|
|
631
|
+
* Server validates backup, creates checkpoint, then executes restore with progress tracking.
|
|
632
|
+
* Uses OAuth authentication (token from login).
|
|
633
|
+
*
|
|
634
|
+
* @param backupFilePath Path to backup file (.tar.gz archive or .json)
|
|
635
|
+
* @param overwrite Whether to overwrite existing data
|
|
636
|
+
* @param handleExternalDeps How to handle external dependencies ('prune', 'stitch', 'defer')
|
|
637
|
+
* @param onUploadProgress Optional callback for upload progress (bytes uploaded, total bytes, percent)
|
|
638
|
+
* @returns Job ID and initial status for polling restore progress
|
|
639
|
+
*/
|
|
640
|
+
async restoreBackup(backupFilePath, overwrite = false, handleExternalDeps = 'prune', onUploadProgress) {
|
|
641
|
+
const form = new form_data_1.default();
|
|
642
|
+
form.append('file', fs.createReadStream(backupFilePath));
|
|
643
|
+
form.append('overwrite', String(overwrite));
|
|
644
|
+
form.append('handle_external_deps', handleExternalDeps);
|
|
645
|
+
const response = await this.client.post('/admin/restore', form, {
|
|
646
|
+
headers: form.getHeaders(),
|
|
647
|
+
onUploadProgress: (progressEvent) => {
|
|
648
|
+
if (onUploadProgress && progressEvent.total) {
|
|
649
|
+
const uploaded = progressEvent.loaded;
|
|
650
|
+
const total = progressEvent.total;
|
|
651
|
+
const percent = Math.round((uploaded / total) * 100);
|
|
652
|
+
onUploadProgress(uploaded, total, percent);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
});
|
|
656
|
+
return response.data;
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Reset database (destructive - requires authentication)
|
|
660
|
+
*/
|
|
661
|
+
async resetDatabase(request) {
|
|
662
|
+
const response = await this.client.post('/admin/reset', request);
|
|
663
|
+
return response.data;
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Get job scheduler status and statistics (ADR-014)
|
|
667
|
+
*/
|
|
668
|
+
async getSchedulerStatus() {
|
|
669
|
+
const response = await this.client.get('/admin/scheduler/status');
|
|
670
|
+
return response.data;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Manually trigger job scheduler cleanup (ADR-014)
|
|
674
|
+
*/
|
|
675
|
+
async triggerSchedulerCleanup() {
|
|
676
|
+
const response = await this.client.post('/admin/scheduler/cleanup');
|
|
677
|
+
return response.data;
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Regenerate embeddings for concept nodes in the graph
|
|
681
|
+
*/
|
|
682
|
+
async regenerateConceptEmbeddings(params) {
|
|
683
|
+
const queryParams = new URLSearchParams();
|
|
684
|
+
if (params.only_missing) {
|
|
685
|
+
queryParams.append('only_missing', 'true');
|
|
686
|
+
}
|
|
687
|
+
if (params.ontology) {
|
|
688
|
+
queryParams.append('ontology', params.ontology);
|
|
689
|
+
}
|
|
690
|
+
if (params.limit) {
|
|
691
|
+
queryParams.append('limit', params.limit.toString());
|
|
692
|
+
}
|
|
693
|
+
const url = `/admin/regenerate-concept-embeddings${queryParams.toString() ? '?' + queryParams.toString() : ''}`;
|
|
694
|
+
const response = await this.client.post(url);
|
|
695
|
+
return response.data;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Unified embedding regeneration for all graph text entities (ADR-068 Phase 4).
|
|
699
|
+
*
|
|
700
|
+
* Regenerate embeddings for concepts, sources, or vocabulary (relationship types).
|
|
701
|
+
* Useful for model migrations, fixing missing/corrupted embeddings, or bulk regeneration.
|
|
702
|
+
*/
|
|
703
|
+
async regenerateEmbeddings(params) {
|
|
704
|
+
const queryParams = new URLSearchParams();
|
|
705
|
+
queryParams.append('embedding_type', params.embedding_type);
|
|
706
|
+
if (params.only_missing) {
|
|
707
|
+
queryParams.append('only_missing', 'true');
|
|
708
|
+
}
|
|
709
|
+
if (params.only_incompatible) {
|
|
710
|
+
queryParams.append('only_incompatible', 'true');
|
|
711
|
+
}
|
|
712
|
+
if (params.ontology) {
|
|
713
|
+
queryParams.append('ontology', params.ontology);
|
|
714
|
+
}
|
|
715
|
+
if (params.limit) {
|
|
716
|
+
queryParams.append('limit', params.limit.toString());
|
|
717
|
+
}
|
|
718
|
+
const url = `/admin/embedding/regenerate?${queryParams.toString()}`;
|
|
719
|
+
const response = await this.client.post(url);
|
|
720
|
+
return response.data;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Get comprehensive embedding status for all graph text entities.
|
|
724
|
+
*
|
|
725
|
+
* Shows count, percentage, compatibility verification, and hash verification
|
|
726
|
+
* for embeddings across concepts, sources, vocabulary, and images.
|
|
727
|
+
*/
|
|
728
|
+
async getEmbeddingStatus(ontology) {
|
|
729
|
+
const queryParams = new URLSearchParams();
|
|
730
|
+
if (ontology) {
|
|
731
|
+
queryParams.append('ontology', ontology);
|
|
732
|
+
}
|
|
733
|
+
const url = `/admin/embedding/status${queryParams.toString() ? '?' + queryParams.toString() : ''}`;
|
|
734
|
+
const response = await this.client.get(url);
|
|
735
|
+
return response.data;
|
|
736
|
+
}
|
|
737
|
+
// ========== RBAC Methods (ADR-028) ==========
|
|
738
|
+
/**
|
|
739
|
+
* List all registered resource types
|
|
740
|
+
*/
|
|
741
|
+
async listResources() {
|
|
742
|
+
const response = await this.client.get('/rbac/resources');
|
|
743
|
+
return response.data;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Get a specific resource type
|
|
747
|
+
*/
|
|
748
|
+
async getResource(resourceType) {
|
|
749
|
+
const response = await this.client.get(`/rbac/resources/${resourceType}`);
|
|
750
|
+
return response.data;
|
|
751
|
+
}
|
|
752
|
+
/**
|
|
753
|
+
* Register a new resource type
|
|
754
|
+
*/
|
|
755
|
+
async createResource(resource) {
|
|
756
|
+
const response = await this.client.post('/rbac/resources', resource);
|
|
757
|
+
return response.data;
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Update a resource type
|
|
761
|
+
*/
|
|
762
|
+
async updateResource(resourceType, update) {
|
|
763
|
+
const response = await this.client.put(`/rbac/resources/${resourceType}`, update);
|
|
764
|
+
return response.data;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Delete a resource type
|
|
768
|
+
*/
|
|
769
|
+
async deleteResource(resourceType) {
|
|
770
|
+
await this.client.delete(`/rbac/resources/${resourceType}`);
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* List all roles
|
|
774
|
+
*/
|
|
775
|
+
async listRoles(includeInactive = false) {
|
|
776
|
+
const response = await this.client.get('/rbac/roles', {
|
|
777
|
+
params: { include_inactive: includeInactive }
|
|
778
|
+
});
|
|
779
|
+
return response.data;
|
|
780
|
+
}
|
|
781
|
+
/**
|
|
782
|
+
* Get a specific role
|
|
783
|
+
*/
|
|
784
|
+
async getRole(roleName) {
|
|
785
|
+
const response = await this.client.get(`/rbac/roles/${roleName}`);
|
|
786
|
+
return response.data;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Create a new role
|
|
790
|
+
*/
|
|
791
|
+
async createRole(role) {
|
|
792
|
+
const response = await this.client.post('/rbac/roles', role);
|
|
793
|
+
return response.data;
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Update a role
|
|
797
|
+
*/
|
|
798
|
+
async updateRole(roleName, update) {
|
|
799
|
+
const response = await this.client.put(`/rbac/roles/${roleName}`, update);
|
|
800
|
+
return response.data;
|
|
801
|
+
}
|
|
802
|
+
/**
|
|
803
|
+
* Delete a role
|
|
804
|
+
*/
|
|
805
|
+
async deleteRole(roleName) {
|
|
806
|
+
await this.client.delete(`/rbac/roles/${roleName}`);
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* List permissions (optionally filtered)
|
|
810
|
+
*/
|
|
811
|
+
async listPermissions(roleName, resourceType) {
|
|
812
|
+
const params = {};
|
|
813
|
+
if (roleName)
|
|
814
|
+
params.role_name = roleName;
|
|
815
|
+
if (resourceType)
|
|
816
|
+
params.resource_type = resourceType;
|
|
817
|
+
const response = await this.client.get('/rbac/permissions', { params });
|
|
818
|
+
return response.data;
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Grant a permission to a role
|
|
822
|
+
*/
|
|
823
|
+
async createPermission(permission) {
|
|
824
|
+
const response = await this.client.post('/rbac/permissions', permission);
|
|
825
|
+
return response.data;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Revoke a permission from a role
|
|
829
|
+
*/
|
|
830
|
+
async deletePermission(permissionId) {
|
|
831
|
+
await this.client.delete(`/rbac/permissions/${permissionId}`);
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* List role assignments for a user
|
|
835
|
+
*/
|
|
836
|
+
async listUserRoles(userId) {
|
|
837
|
+
const response = await this.client.get(`/rbac/user-roles/${userId}`);
|
|
838
|
+
return response.data;
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Assign a role to a user
|
|
842
|
+
*/
|
|
843
|
+
async assignUserRole(assignment) {
|
|
844
|
+
const response = await this.client.post('/rbac/user-roles', assignment);
|
|
845
|
+
return response.data;
|
|
846
|
+
}
|
|
847
|
+
/**
|
|
848
|
+
* Revoke a role assignment from a user
|
|
849
|
+
*/
|
|
850
|
+
async revokeUserRole(assignmentId) {
|
|
851
|
+
await this.client.delete(`/rbac/user-roles/${assignmentId}`);
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Check if a user has a specific permission
|
|
855
|
+
*/
|
|
856
|
+
async checkPermission(request) {
|
|
857
|
+
const response = await this.client.post('/rbac/check-permission', request);
|
|
858
|
+
return response.data;
|
|
859
|
+
}
|
|
860
|
+
// ========== Vocabulary Methods (ADR-032) ==========
|
|
861
|
+
/**
|
|
862
|
+
* Get current vocabulary status
|
|
863
|
+
*/
|
|
864
|
+
async getVocabularyStatus() {
|
|
865
|
+
const response = await this.client.get('/vocabulary/status');
|
|
866
|
+
return response.data;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* List all edge types with statistics
|
|
870
|
+
*/
|
|
871
|
+
async listEdgeTypes(includeInactive = false, includeBuiltin = true) {
|
|
872
|
+
const response = await this.client.get('/vocabulary/types', {
|
|
873
|
+
params: {
|
|
874
|
+
include_inactive: includeInactive,
|
|
875
|
+
include_builtin: includeBuiltin
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
return response.data;
|
|
879
|
+
}
|
|
880
|
+
/**
|
|
881
|
+
* Manually add a new edge type (curator action)
|
|
882
|
+
*/
|
|
883
|
+
async addEdgeType(request) {
|
|
884
|
+
const response = await this.client.post('/vocabulary/types', request);
|
|
885
|
+
return response.data;
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Generate vocabulary optimization recommendations
|
|
889
|
+
*/
|
|
890
|
+
async getVocabularyRecommendations() {
|
|
891
|
+
const response = await this.client.get('/vocabulary/recommendations');
|
|
892
|
+
return response.data;
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* Execute all auto-approved recommendations
|
|
896
|
+
*/
|
|
897
|
+
async executeAutoRecommendations() {
|
|
898
|
+
const response = await this.client.post('/vocabulary/recommendations/execute');
|
|
899
|
+
return response.data;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Get detailed vocabulary analysis
|
|
903
|
+
*/
|
|
904
|
+
async getVocabularyAnalysis() {
|
|
905
|
+
const response = await this.client.get('/vocabulary/analysis');
|
|
906
|
+
return response.data;
|
|
907
|
+
}
|
|
908
|
+
/**
|
|
909
|
+
* Get vocabulary configuration
|
|
910
|
+
*/
|
|
911
|
+
async getVocabularyConfig() {
|
|
912
|
+
const response = await this.client.get('/vocabulary/config');
|
|
913
|
+
return response.data;
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Get vocabulary configuration details (admin endpoint)
|
|
917
|
+
*/
|
|
918
|
+
async getVocabularyConfigDetail() {
|
|
919
|
+
const response = await this.client.get('/admin/vocabulary/config');
|
|
920
|
+
return response.data;
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* Update vocabulary configuration (admin endpoint)
|
|
924
|
+
*/
|
|
925
|
+
async updateVocabularyConfig(config) {
|
|
926
|
+
const response = await this.client.put('/admin/vocabulary/config', config);
|
|
927
|
+
return response.data;
|
|
928
|
+
}
|
|
929
|
+
/**
|
|
930
|
+
* List aggressiveness profiles (admin endpoint)
|
|
931
|
+
*/
|
|
932
|
+
async listAggressivenessProfiles() {
|
|
933
|
+
const response = await this.client.get('/admin/vocabulary/profiles');
|
|
934
|
+
return response.data;
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Get specific aggressiveness profile (admin endpoint)
|
|
938
|
+
*/
|
|
939
|
+
async getAggressivenessProfile(profileName) {
|
|
940
|
+
const response = await this.client.get(`/admin/vocabulary/profiles/${encodeURIComponent(profileName)}`);
|
|
941
|
+
return response.data;
|
|
942
|
+
}
|
|
943
|
+
/**
|
|
944
|
+
* Create custom aggressiveness profile (admin endpoint)
|
|
945
|
+
*/
|
|
946
|
+
async createAggressivenessProfile(profile) {
|
|
947
|
+
const response = await this.client.post('/admin/vocabulary/profiles', profile);
|
|
948
|
+
return response.data;
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* Delete custom aggressiveness profile (admin endpoint)
|
|
952
|
+
*/
|
|
953
|
+
async deleteAggressivenessProfile(profileName) {
|
|
954
|
+
const response = await this.client.delete(`/admin/vocabulary/profiles/${encodeURIComponent(profileName)}`);
|
|
955
|
+
return response.data;
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Merge two edge types (curator action)
|
|
959
|
+
*/
|
|
960
|
+
async mergeEdgeTypes(request) {
|
|
961
|
+
const response = await this.client.post('/vocabulary/merge', request);
|
|
962
|
+
return response.data;
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Get category similarity scores for a relationship type (ADR-047)
|
|
966
|
+
*/
|
|
967
|
+
async getCategoryScores(relationshipType) {
|
|
968
|
+
const response = await this.client.get(`/vocabulary/category-scores/${encodeURIComponent(relationshipType)}`);
|
|
969
|
+
return response.data;
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* Refresh category assignments for vocabulary types (ADR-047)
|
|
973
|
+
*/
|
|
974
|
+
async refreshCategories(onlyComputed = true) {
|
|
975
|
+
const response = await this.client.post('/vocabulary/refresh-categories', {
|
|
976
|
+
only_computed: onlyComputed
|
|
977
|
+
});
|
|
978
|
+
return response.data;
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Generate embeddings for vocabulary types (bulk operation)
|
|
982
|
+
*/
|
|
983
|
+
async generateVocabularyEmbeddings(forceRegenerate = false, onlyMissing = true) {
|
|
984
|
+
const response = await this.client.post('/vocabulary/generate-embeddings', {
|
|
985
|
+
force_regenerate: forceRegenerate,
|
|
986
|
+
only_missing: onlyMissing
|
|
987
|
+
});
|
|
988
|
+
return response.data;
|
|
989
|
+
}
|
|
990
|
+
/**
|
|
991
|
+
* Run AITL vocabulary consolidation workflow (ADR-032)
|
|
992
|
+
*/
|
|
993
|
+
async consolidateVocabulary(request) {
|
|
994
|
+
const response = await this.client.post('/vocabulary/consolidate', {
|
|
995
|
+
target_size: request.target_size ?? 90,
|
|
996
|
+
batch_size: request.batch_size ?? 1,
|
|
997
|
+
auto_execute_threshold: request.auto_execute_threshold ?? 0.90,
|
|
998
|
+
dry_run: request.dry_run ?? false,
|
|
999
|
+
prune_unused: request.prune_unused ?? true // Default: prune unused types
|
|
1000
|
+
});
|
|
1001
|
+
return response.data;
|
|
1002
|
+
}
|
|
1003
|
+
/**
|
|
1004
|
+
* Measure epistemic status for vocabulary types (ADR-065 Phase 2)
|
|
1005
|
+
*/
|
|
1006
|
+
async measureEpistemicStatus(request) {
|
|
1007
|
+
const response = await this.client.post('/vocabulary/epistemic-status/measure', {
|
|
1008
|
+
sample_size: request.sample_size ?? 100,
|
|
1009
|
+
store: request.store ?? true,
|
|
1010
|
+
verbose: request.verbose ?? false
|
|
1011
|
+
});
|
|
1012
|
+
return response.data;
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* List vocabulary types with epistemic status (ADR-065 Phase 2)
|
|
1016
|
+
*/
|
|
1017
|
+
async listEpistemicStatus(statusFilter) {
|
|
1018
|
+
const response = await this.client.get('/vocabulary/epistemic-status', {
|
|
1019
|
+
params: statusFilter ? { status_filter: statusFilter } : {}
|
|
1020
|
+
});
|
|
1021
|
+
return response.data;
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* Get epistemic status for a specific vocabulary type (ADR-065 Phase 2)
|
|
1025
|
+
*/
|
|
1026
|
+
async getEpistemicStatus(relationshipType) {
|
|
1027
|
+
const response = await this.client.get(`/vocabulary/epistemic-status/${encodeURIComponent(relationshipType)}`);
|
|
1028
|
+
return response.data;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Sync missing edge types from graph to vocabulary (ADR-077)
|
|
1032
|
+
*/
|
|
1033
|
+
async syncVocabulary(dryRun = true) {
|
|
1034
|
+
const response = await this.client.post('/vocabulary/sync', {
|
|
1035
|
+
dry_run: dryRun
|
|
1036
|
+
});
|
|
1037
|
+
return response.data;
|
|
1038
|
+
}
|
|
1039
|
+
// ========== AI Configuration Methods (ADR-039, ADR-041) ==========
|
|
1040
|
+
/**
|
|
1041
|
+
* Get current embedding configuration (public endpoint)
|
|
1042
|
+
*/
|
|
1043
|
+
async getEmbeddingConfig() {
|
|
1044
|
+
const response = await this.client.get('/embedding/config');
|
|
1045
|
+
return response.data;
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Get detailed embedding configuration (admin endpoint)
|
|
1049
|
+
*/
|
|
1050
|
+
async getEmbeddingConfigDetail() {
|
|
1051
|
+
const response = await this.client.get('/admin/embedding/config');
|
|
1052
|
+
return response.data;
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Update embedding configuration (admin endpoint)
|
|
1056
|
+
*/
|
|
1057
|
+
async updateEmbeddingConfig(config) {
|
|
1058
|
+
const response = await this.client.post('/admin/embedding/config', config);
|
|
1059
|
+
return response.data;
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Hot reload embedding model (admin endpoint)
|
|
1063
|
+
*/
|
|
1064
|
+
async reloadEmbeddingModel() {
|
|
1065
|
+
const response = await this.client.post('/admin/embedding/config/reload');
|
|
1066
|
+
return response.data;
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* List all embedding configurations (admin endpoint)
|
|
1070
|
+
*/
|
|
1071
|
+
async listEmbeddingConfigs() {
|
|
1072
|
+
const response = await this.client.get('/admin/embedding/configs');
|
|
1073
|
+
return response.data;
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Set protection flags on an embedding config (admin endpoint)
|
|
1077
|
+
*/
|
|
1078
|
+
async protectEmbeddingConfig(configId, deleteProtected, changeProtected) {
|
|
1079
|
+
const params = {};
|
|
1080
|
+
if (deleteProtected !== undefined)
|
|
1081
|
+
params.delete_protected = deleteProtected;
|
|
1082
|
+
if (changeProtected !== undefined)
|
|
1083
|
+
params.change_protected = changeProtected;
|
|
1084
|
+
const response = await this.client.post(`/admin/embedding/config/${configId}/protect`, null, { params });
|
|
1085
|
+
return response.data;
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Delete an embedding configuration (admin endpoint)
|
|
1089
|
+
*/
|
|
1090
|
+
async deleteEmbeddingConfig(configId) {
|
|
1091
|
+
const response = await this.client.delete(`/admin/embedding/config/${configId}`);
|
|
1092
|
+
return response.data;
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Activate an embedding configuration with automatic protection management (admin endpoint)
|
|
1096
|
+
*/
|
|
1097
|
+
async activateEmbeddingConfig(configId, force) {
|
|
1098
|
+
const params = force ? { force: true } : {};
|
|
1099
|
+
const response = await this.client.post(`/admin/embedding/config/${configId}/activate`, null, { params });
|
|
1100
|
+
return response.data;
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Get current extraction configuration (public endpoint)
|
|
1104
|
+
*/
|
|
1105
|
+
async getExtractionConfig() {
|
|
1106
|
+
const response = await this.client.get('/extraction/config');
|
|
1107
|
+
return response.data;
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Get detailed extraction configuration (admin endpoint)
|
|
1111
|
+
*/
|
|
1112
|
+
async getExtractionConfigDetail() {
|
|
1113
|
+
const response = await this.client.get('/admin/extraction/config');
|
|
1114
|
+
return response.data;
|
|
1115
|
+
}
|
|
1116
|
+
/**
|
|
1117
|
+
* Update extraction configuration (admin endpoint)
|
|
1118
|
+
*/
|
|
1119
|
+
async updateExtractionConfig(config) {
|
|
1120
|
+
const response = await this.client.post('/admin/extraction/config', config);
|
|
1121
|
+
return response.data;
|
|
1122
|
+
}
|
|
1123
|
+
/**
|
|
1124
|
+
* List API keys with validation status (admin endpoint)
|
|
1125
|
+
*/
|
|
1126
|
+
async listApiKeys() {
|
|
1127
|
+
const response = await this.client.get('/admin/keys');
|
|
1128
|
+
return response.data;
|
|
1129
|
+
}
|
|
1130
|
+
/**
|
|
1131
|
+
* Set API key for a provider (admin endpoint)
|
|
1132
|
+
*/
|
|
1133
|
+
async setApiKey(provider, apiKey) {
|
|
1134
|
+
const formData = new form_data_1.default();
|
|
1135
|
+
formData.append('api_key', apiKey);
|
|
1136
|
+
const response = await this.client.post(`/admin/keys/${provider}`, formData, {
|
|
1137
|
+
headers: {
|
|
1138
|
+
'Content-Type': 'multipart/form-data'
|
|
1139
|
+
}
|
|
1140
|
+
});
|
|
1141
|
+
return response.data;
|
|
1142
|
+
}
|
|
1143
|
+
/**
|
|
1144
|
+
* Delete API key for a provider (admin endpoint)
|
|
1145
|
+
*/
|
|
1146
|
+
async deleteApiKey(provider) {
|
|
1147
|
+
const response = await this.client.delete(`/admin/keys/${provider}`);
|
|
1148
|
+
return response.data;
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Get similar edge types via embedding similarity (ADR-053)
|
|
1152
|
+
*/
|
|
1153
|
+
async getSimilarTypes(relationshipType, limit = 10, reverse = false) {
|
|
1154
|
+
const response = await this.client.get(`/vocabulary/similar/${encodeURIComponent(relationshipType)}`, { params: { limit, reverse } });
|
|
1155
|
+
return response.data;
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Get detailed vocabulary analysis (ADR-053)
|
|
1159
|
+
*/
|
|
1160
|
+
async analyzeVocabularyType(relationshipType) {
|
|
1161
|
+
const response = await this.client.get(`/vocabulary/analyze/${encodeURIComponent(relationshipType)}`);
|
|
1162
|
+
return response.data;
|
|
1163
|
+
}
|
|
1164
|
+
/**
|
|
1165
|
+
* Analyze polarity axis between two concept poles (ADR-070)
|
|
1166
|
+
*/
|
|
1167
|
+
async analyzePolarityAxis(request) {
|
|
1168
|
+
const response = await this.client.post('/query/polarity-axis', request);
|
|
1169
|
+
return response.data;
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* Submit async polarity analysis job with artifact creation (ADR-083)
|
|
1173
|
+
*/
|
|
1174
|
+
async submitPolarityJob(request) {
|
|
1175
|
+
const response = await this.client.post('/query/polarity-axis/jobs', request);
|
|
1176
|
+
return response.data;
|
|
1177
|
+
}
|
|
1178
|
+
// ============================================================================
|
|
1179
|
+
// Projection Methods (ADR-078)
|
|
1180
|
+
// ============================================================================
|
|
1181
|
+
/**
|
|
1182
|
+
* Get available projection algorithms
|
|
1183
|
+
*/
|
|
1184
|
+
async getProjectionAlgorithms() {
|
|
1185
|
+
const response = await this.client.get('/projection/algorithms');
|
|
1186
|
+
return response.data;
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* Get cached projection for an ontology
|
|
1190
|
+
*/
|
|
1191
|
+
async getProjection(ontology) {
|
|
1192
|
+
const response = await this.client.get(`/projection/${encodeURIComponent(ontology)}`);
|
|
1193
|
+
return response.data;
|
|
1194
|
+
}
|
|
1195
|
+
/**
|
|
1196
|
+
* Regenerate projection for an ontology
|
|
1197
|
+
*/
|
|
1198
|
+
async regenerateProjection(ontology, options) {
|
|
1199
|
+
const response = await this.client.post(`/projection/${encodeURIComponent(ontology)}/regenerate`, options || {});
|
|
1200
|
+
return response.data;
|
|
1201
|
+
}
|
|
1202
|
+
/**
|
|
1203
|
+
* Invalidate (delete) cached projection
|
|
1204
|
+
*/
|
|
1205
|
+
async invalidateProjection(ontology) {
|
|
1206
|
+
const response = await this.client.delete(`/projection/${encodeURIComponent(ontology)}`);
|
|
1207
|
+
return response.data;
|
|
1208
|
+
}
|
|
1209
|
+
// ============================================================================
|
|
1210
|
+
// Artifact Methods (ADR-083)
|
|
1211
|
+
// ============================================================================
|
|
1212
|
+
/**
|
|
1213
|
+
* List artifacts with optional filtering
|
|
1214
|
+
*/
|
|
1215
|
+
async listArtifacts(params) {
|
|
1216
|
+
const response = await this.client.get('/artifacts', { params });
|
|
1217
|
+
return response.data;
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Get artifact metadata by ID
|
|
1221
|
+
*/
|
|
1222
|
+
async getArtifact(artifactId) {
|
|
1223
|
+
const response = await this.client.get(`/artifacts/${artifactId}`);
|
|
1224
|
+
return response.data;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Get artifact with full payload
|
|
1228
|
+
*/
|
|
1229
|
+
async getArtifactPayload(artifactId) {
|
|
1230
|
+
const response = await this.client.get(`/artifacts/${artifactId}/payload`);
|
|
1231
|
+
return response.data;
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Create a new artifact
|
|
1235
|
+
*/
|
|
1236
|
+
async createArtifact(artifact) {
|
|
1237
|
+
const response = await this.client.post('/artifacts', artifact);
|
|
1238
|
+
return response.data;
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Delete an artifact
|
|
1242
|
+
*/
|
|
1243
|
+
async deleteArtifact(artifactId) {
|
|
1244
|
+
await this.client.delete(`/artifacts/${artifactId}`);
|
|
1245
|
+
}
|
|
1246
|
+
// ==========================================================================
|
|
1247
|
+
// Groups & Grants Methods (ADR-082)
|
|
1248
|
+
// ==========================================================================
|
|
1249
|
+
/**
|
|
1250
|
+
* List groups
|
|
1251
|
+
*/
|
|
1252
|
+
async listGroups(params) {
|
|
1253
|
+
const response = await this.client.get('/groups', { params });
|
|
1254
|
+
return response.data;
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Create a group
|
|
1258
|
+
*/
|
|
1259
|
+
async createGroup(group) {
|
|
1260
|
+
const response = await this.client.post('/groups', group);
|
|
1261
|
+
return response.data;
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* List group members
|
|
1265
|
+
*/
|
|
1266
|
+
async listGroupMembers(groupId) {
|
|
1267
|
+
const response = await this.client.get(`/groups/${groupId}/members`);
|
|
1268
|
+
return response.data;
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* Add member to group
|
|
1272
|
+
*/
|
|
1273
|
+
async addGroupMember(groupId, userId) {
|
|
1274
|
+
const response = await this.client.post(`/groups/${groupId}/members`, { user_id: userId });
|
|
1275
|
+
return response.data;
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Remove member from group
|
|
1279
|
+
*/
|
|
1280
|
+
async removeGroupMember(groupId, userId) {
|
|
1281
|
+
await this.client.delete(`/groups/${groupId}/members/${userId}`);
|
|
1282
|
+
}
|
|
1283
|
+
/**
|
|
1284
|
+
* Create a resource grant
|
|
1285
|
+
*/
|
|
1286
|
+
async createGrant(grant) {
|
|
1287
|
+
const response = await this.client.post('/grants', grant);
|
|
1288
|
+
return response.data;
|
|
1289
|
+
}
|
|
1290
|
+
/**
|
|
1291
|
+
* List grants for a resource
|
|
1292
|
+
*/
|
|
1293
|
+
async listResourceGrants(resourceType, resourceId) {
|
|
1294
|
+
const response = await this.client.get(`/resources/${resourceType}/${resourceId}/grants`);
|
|
1295
|
+
return response.data;
|
|
1296
|
+
}
|
|
1297
|
+
/**
|
|
1298
|
+
* Revoke a grant
|
|
1299
|
+
*/
|
|
1300
|
+
async revokeGrant(grantId) {
|
|
1301
|
+
await this.client.delete(`/grants/${grantId}`);
|
|
1302
|
+
}
|
|
1303
|
+
// ==========================================================================
|
|
1304
|
+
// Query Definitions Methods (ADR-083)
|
|
1305
|
+
// ==========================================================================
|
|
1306
|
+
/**
|
|
1307
|
+
* List query definitions
|
|
1308
|
+
*/
|
|
1309
|
+
async listQueryDefinitions(params) {
|
|
1310
|
+
const response = await this.client.get('/query-definitions', { params });
|
|
1311
|
+
return response.data;
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Get a query definition by ID
|
|
1315
|
+
*/
|
|
1316
|
+
async getQueryDefinition(definitionId) {
|
|
1317
|
+
const response = await this.client.get(`/query-definitions/${definitionId}`);
|
|
1318
|
+
return response.data;
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Create a query definition
|
|
1322
|
+
*/
|
|
1323
|
+
async createQueryDefinition(definition) {
|
|
1324
|
+
const response = await this.client.post('/query-definitions', definition);
|
|
1325
|
+
return response.data;
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Update a query definition
|
|
1329
|
+
*/
|
|
1330
|
+
async updateQueryDefinition(definitionId, update) {
|
|
1331
|
+
const response = await this.client.put(`/query-definitions/${definitionId}`, update);
|
|
1332
|
+
return response.data;
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* Delete a query definition
|
|
1336
|
+
*/
|
|
1337
|
+
async deleteQueryDefinition(definitionId) {
|
|
1338
|
+
await this.client.delete(`/query-definitions/${definitionId}`);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
exports.KnowledgeGraphClient = KnowledgeGraphClient;
|
|
1342
|
+
/**
|
|
1343
|
+
* Create a client from environment variables and config file
|
|
1344
|
+
* Priority: CLI flags > env vars > config file > defaults
|
|
1345
|
+
*/
|
|
1346
|
+
function createClientFromEnv() {
|
|
1347
|
+
// Lazy load config to avoid circular dependencies
|
|
1348
|
+
let config = null;
|
|
1349
|
+
try {
|
|
1350
|
+
const { getConfig } = require('../lib/config');
|
|
1351
|
+
config = getConfig();
|
|
1352
|
+
}
|
|
1353
|
+
catch (e) {
|
|
1354
|
+
// Config not available, use env vars only
|
|
1355
|
+
}
|
|
1356
|
+
return new KnowledgeGraphClient({
|
|
1357
|
+
baseUrl: process.env.KG_API_URL || config?.getApiUrl() || 'http://localhost:8000',
|
|
1358
|
+
clientId: process.env.KG_CLIENT_ID || config?.getClientId(),
|
|
1359
|
+
apiKey: process.env.KG_API_KEY || config?.getApiKey(),
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
//# sourceMappingURL=client.js.map
|