langmart-gateway-type3 3.0.41 → 3.0.43
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/.env.example +3 -3
- package/README.md +38 -38
- package/dist/automation-tools.d.ts +18 -57
- package/dist/automation-tools.d.ts.map +1 -1
- package/dist/automation-tools.js +348 -497
- package/dist/automation-tools.js.map +1 -1
- package/dist/gateway-server.d.ts +52 -26
- package/dist/gateway-server.d.ts.map +1 -1
- package/dist/gateway-server.js +423 -145
- package/dist/gateway-server.js.map +1 -1
- package/dist/headless-session.d.ts +22 -2
- package/dist/headless-session.d.ts.map +1 -1
- package/dist/headless-session.js +209 -7
- package/dist/headless-session.js.map +1 -1
- package/dist/index-server.d.ts.map +1 -1
- package/dist/index-server.js +11 -21
- package/dist/index-server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -20
- package/dist/index.js.map +1 -1
- package/dist/{marketplace-tools.d.ts → registry-tools.d.ts} +30 -8
- package/dist/registry-tools.d.ts.map +1 -0
- package/dist/{marketplace-tools.js → registry-tools.js} +565 -144
- package/dist/registry-tools.js.map +1 -0
- package/package.json +8 -7
- package/scripts/install.ps1 +14 -14
- package/scripts/install.sh +9 -9
- package/scripts/start.ps1 +5 -5
- package/scripts/start.sh +4 -4
- package/dist/marketplace-tools.d.ts.map +0 -1
- package/dist/marketplace-tools.js.map +0 -1
|
@@ -3,27 +3,27 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.RegistryTools = void 0;
|
|
7
7
|
const debug_utils_1 = require("./debug-utils");
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Registry Tools - Built-in MCP Tools for LangMart Self-Hosted Gateway CLI
|
|
10
10
|
*
|
|
11
|
-
* Provides AI assistant with tools to manage
|
|
11
|
+
* Provides AI assistant with tools to manage registry connections,
|
|
12
12
|
* providers, and models through natural language conversation.
|
|
13
13
|
*
|
|
14
|
-
* These tools call LangMart
|
|
14
|
+
* These tools call LangMart Registry API endpoints.
|
|
15
15
|
*/
|
|
16
16
|
const axios_1 = __importDefault(require("axios"));
|
|
17
|
-
class
|
|
18
|
-
constructor(
|
|
17
|
+
class RegistryTools {
|
|
18
|
+
constructor(registryUrl, apiKey, managementUrl = 'http://localhost:8083', keyVault) {
|
|
19
19
|
this.connectionMap = new Map(); // sequence number → UUID mapping
|
|
20
20
|
this.providerMap = new Map(); // sequence number → UUID mapping
|
|
21
|
-
this.
|
|
21
|
+
this.registryUrl = registryUrl;
|
|
22
22
|
this.apiKey = apiKey;
|
|
23
23
|
this.managementUrl = managementUrl;
|
|
24
24
|
this.keyVault = keyVault;
|
|
25
25
|
this.client = axios_1.default.create({
|
|
26
|
-
baseURL:
|
|
26
|
+
baseURL: registryUrl,
|
|
27
27
|
timeout: 30000,
|
|
28
28
|
maxRedirects: 0, // Don't follow redirects
|
|
29
29
|
validateStatus: (status) => status < 500, // Accept any non-5xx response
|
|
@@ -32,16 +32,16 @@ class MarketplaceTools {
|
|
|
32
32
|
'Content-Type': 'application/json'
|
|
33
33
|
}
|
|
34
34
|
});
|
|
35
|
-
(0, debug_utils_1.debugLog)(`[
|
|
35
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Initialized with baseURL: ${registryUrl}`);
|
|
36
36
|
}
|
|
37
|
-
static getInstance(
|
|
38
|
-
if (!
|
|
39
|
-
|
|
37
|
+
static getInstance(registryUrl, apiKey, managementUrl, keyVault) {
|
|
38
|
+
if (!RegistryTools.instance && registryUrl && apiKey && keyVault) {
|
|
39
|
+
RegistryTools.instance = new RegistryTools(registryUrl, apiKey, managementUrl || 'http://localhost:8083', keyVault);
|
|
40
40
|
}
|
|
41
|
-
if (!
|
|
42
|
-
throw new Error('
|
|
41
|
+
if (!RegistryTools.instance) {
|
|
42
|
+
throw new Error('RegistryTools not initialized. Provide registryUrl, apiKey, and keyVault.');
|
|
43
43
|
}
|
|
44
|
-
return
|
|
44
|
+
return RegistryTools.instance;
|
|
45
45
|
}
|
|
46
46
|
/**
|
|
47
47
|
* Get tool definitions for AI
|
|
@@ -51,8 +51,8 @@ class MarketplaceTools {
|
|
|
51
51
|
{
|
|
52
52
|
type: 'function',
|
|
53
53
|
function: {
|
|
54
|
-
name: '
|
|
55
|
-
description: 'List all user connections from the
|
|
54
|
+
name: 'registry_connections_list',
|
|
55
|
+
description: 'List all user connections from the registry. Shows provider, endpoint type, gateway type (Managed/Self-hosted), and status for each connection. Connections are numbered [1], [2], [3], etc. in order of creation. No parameters required - call this tool directly when user asks to list, show, or see connections. You can use the connection numbers in subsequent tool calls (e.g., registry_connections_test with connection_id "1").',
|
|
56
56
|
parameters: {
|
|
57
57
|
type: 'object',
|
|
58
58
|
properties: {},
|
|
@@ -63,8 +63,8 @@ class MarketplaceTools {
|
|
|
63
63
|
{
|
|
64
64
|
type: 'function',
|
|
65
65
|
function: {
|
|
66
|
-
name: '
|
|
67
|
-
description: 'Add a new connection to the
|
|
66
|
+
name: 'registry_connections_add',
|
|
67
|
+
description: 'Add a new connection to the registry. Creates a connection to an LLM provider (OpenAI, Anthropic, Groq, Ollama, etc.) with specified API key and gateway type. The endpoint_type (protocol translator) is automatically determined from the provider - do NOT ask the user for it. Ask the user for: display name, provider name (must match a provider from registry_providers_list), API key, endpoint URL, and gateway type. Registry-Managed Compute (Type 2): registry stores encrypted API keys and manages gateway - convenient but requires trust. Provider API must be accessible from registry network (cloud). Self-Hosted Compute (Type 3): you run local gateway and store API keys in local vault - full control over credentials. Provider API must be accessible from YOUR network (can access localhost/private IPs). Both types work with ANY provider. IMPORTANT: After adding the connection, show the tool result directly to the user with the connection details and ask what they want to do next (test, discover models, update, or remove). DO NOT automatically call registry_providers_list or registry_models_discover - let the user decide.',
|
|
68
68
|
parameters: {
|
|
69
69
|
type: 'object',
|
|
70
70
|
properties: {
|
|
@@ -74,7 +74,7 @@ class MarketplaceTools {
|
|
|
74
74
|
},
|
|
75
75
|
provider_name: {
|
|
76
76
|
type: 'string',
|
|
77
|
-
description: 'Provider key from
|
|
77
|
+
description: 'Provider key from registry_providers_list: "anthropic", "openai", "groq", "google", "ollama", etc. IMPORTANT: Use registry_providers_list first to see available providers and their keys.'
|
|
78
78
|
},
|
|
79
79
|
endpoint_url: {
|
|
80
80
|
type: 'string',
|
|
@@ -86,7 +86,7 @@ class MarketplaceTools {
|
|
|
86
86
|
},
|
|
87
87
|
gateway_type: {
|
|
88
88
|
type: 'number',
|
|
89
|
-
description: 'Gateway type: 2 (
|
|
89
|
+
description: 'Gateway type: 2 (Registry-Managed Compute - registry stores API keys, provider must be reachable from registry network), 3 (Self-Hosted Compute - you store API keys locally, provider must be reachable from YOUR network, can access localhost). Both work with ANY provider (OpenAI, Anthropic, Groq, Ollama, etc.)'
|
|
90
90
|
}
|
|
91
91
|
},
|
|
92
92
|
required: ['name', 'provider_name', 'endpoint_url', 'api_key', 'gateway_type']
|
|
@@ -96,8 +96,8 @@ class MarketplaceTools {
|
|
|
96
96
|
{
|
|
97
97
|
type: 'function',
|
|
98
98
|
function: {
|
|
99
|
-
name: '
|
|
100
|
-
description: 'Remove a connection from the
|
|
99
|
+
name: 'registry_connections_remove',
|
|
100
|
+
description: 'Remove a connection from the registry (soft delete). IMPORTANT: You can use EITHER a sequence number (1, 2, 3) OR a UUID. If the user says "remove 1" or "remove connection 1", use connection_id: "1" - the tool will automatically resolve it. If the user does not provide any identifier, ask which connection they want to remove.',
|
|
101
101
|
parameters: {
|
|
102
102
|
type: 'object',
|
|
103
103
|
properties: {
|
|
@@ -113,8 +113,8 @@ class MarketplaceTools {
|
|
|
113
113
|
{
|
|
114
114
|
type: 'function',
|
|
115
115
|
function: {
|
|
116
|
-
name: '
|
|
117
|
-
description: 'Test a connection to verify API key and endpoint are working. Works for BOTH
|
|
116
|
+
name: 'registry_connections_test',
|
|
117
|
+
description: 'Test a connection to verify API key and endpoint are working. Works for BOTH Registry-Managed Compute and Self-Hosted Compute connections. For Self-Hosted connections, the test is automatically routed to your local gateway instance. IMPORTANT: You can use EITHER a sequence number (1, 2, 3) OR a UUID. If the user says "test 1" or "test connection 1", use connection_id: "1" - the tool will automatically resolve it. If user provides just "test connection" without any number, ask which connection they want to test.',
|
|
118
118
|
parameters: {
|
|
119
119
|
type: 'object',
|
|
120
120
|
properties: {
|
|
@@ -130,7 +130,7 @@ class MarketplaceTools {
|
|
|
130
130
|
{
|
|
131
131
|
type: 'function',
|
|
132
132
|
function: {
|
|
133
|
-
name: '
|
|
133
|
+
name: 'registry_connections_update_key',
|
|
134
134
|
description: 'Update the API key for an existing connection. IMPORTANT: You can use EITHER a sequence number (1, 2, 3) OR a UUID for the connection. If the user says "update key for connection 1", use connection_id: "1" - the tool will automatically resolve it. Always ask the user for the new API key if not provided.',
|
|
135
135
|
parameters: {
|
|
136
136
|
type: 'object',
|
|
@@ -151,8 +151,8 @@ class MarketplaceTools {
|
|
|
151
151
|
{
|
|
152
152
|
type: 'function',
|
|
153
153
|
function: {
|
|
154
|
-
name: '
|
|
155
|
-
description: 'List all available LLM providers in the
|
|
154
|
+
name: 'registry_providers_list',
|
|
155
|
+
description: 'List all available LLM providers in the registry. Shows provider names, base URLs, and active status. No parameters required - call this tool directly when user asks to list, show, or see available providers. IMPORTANT: After displaying the provider list, ALWAYS ask the user: "Would you like to add a connection to any of these providers?" Explain that they will need: (1) Provider API key from the provider, (2) Display name for the connection, (3) Gateway type: Registry-Managed Compute (provider must be internet-accessible from registry) or Self-Hosted Compute (provider can be on your local network, including localhost). Then use registry_connections_add to create the connection. Wait for user response.',
|
|
156
156
|
parameters: {
|
|
157
157
|
type: 'object',
|
|
158
158
|
properties: {},
|
|
@@ -163,14 +163,14 @@ class MarketplaceTools {
|
|
|
163
163
|
{
|
|
164
164
|
type: 'function',
|
|
165
165
|
function: {
|
|
166
|
-
name: '
|
|
167
|
-
description: 'Discover and store models from a provider. Fetches available models from the provider API and adds them to the
|
|
166
|
+
name: 'registry_models_discover',
|
|
167
|
+
description: 'Discover and store models from a provider. Fetches available models from the provider API and adds them to the registry. IMPORTANT: This requires detailed provider information. If the user wants to discover models from an existing connection, first call registry_connections_list to get the connection details (provider, endpoint_url, endpoint_type, gateway_type), then ask the user for their API key. If user wants to discover from a new provider, ask them for: provider name, API key, endpoint URL, endpoint type, and gateway type (2 for Registry-Managed Compute - provider must be internet-accessible, 3 for Self-Hosted Compute - provider can be on local network).',
|
|
168
168
|
parameters: {
|
|
169
169
|
type: 'object',
|
|
170
170
|
properties: {
|
|
171
171
|
provider: {
|
|
172
172
|
type: 'string',
|
|
173
|
-
description: 'Provider key (e.g., "groq", "openai", "anthropic"). Use
|
|
173
|
+
description: 'Provider key (e.g., "groq", "openai", "anthropic"). Use registry_providers_list to see available providers.'
|
|
174
174
|
},
|
|
175
175
|
apiKey: {
|
|
176
176
|
type: 'string',
|
|
@@ -178,7 +178,7 @@ class MarketplaceTools {
|
|
|
178
178
|
},
|
|
179
179
|
gatewayType: {
|
|
180
180
|
type: 'number',
|
|
181
|
-
description: 'Gateway type: 2 (
|
|
181
|
+
description: 'Gateway type: 2 (Registry-Managed Compute - provider must be internet-accessible from registry), 3 (Self-Hosted Compute - provider can be on local network, localhost accessible). Both work with ANY provider.'
|
|
182
182
|
},
|
|
183
183
|
endpointUrl: {
|
|
184
184
|
type: 'string',
|
|
@@ -196,7 +196,7 @@ class MarketplaceTools {
|
|
|
196
196
|
{
|
|
197
197
|
type: 'function',
|
|
198
198
|
function: {
|
|
199
|
-
name: '
|
|
199
|
+
name: 'registry_models_list',
|
|
200
200
|
description: 'List and filter available models for the user with pagination. Shows model names, providers, context windows, pricing, and capabilities. Supports filtering by publication status (public/private), price range, provider, keyword search, capabilities, and context window.\n\n**Filter behavior (same as UI tab filter):**\n- Space-separated keywords use AND condition (all must match)\n- Matches against model_id and model_name\n- Example: "groq llama" matches models containing BOTH "groq" AND "llama"\n\nUse filters when user asks for specific model types (e.g., "cheap models", "vision models", "Groq models", "published models", "private models", "models with 100k+ context"). Pagination defaults to 10 models per page - use offset to get next pages. HELPFUL TIP: After showing models, explain that they can use these models for chat by selecting them with Tab or /model command.',
|
|
201
201
|
parameters: {
|
|
202
202
|
type: 'object',
|
|
@@ -215,11 +215,11 @@ class MarketplaceTools {
|
|
|
215
215
|
},
|
|
216
216
|
access_level: {
|
|
217
217
|
type: 'string',
|
|
218
|
-
description: 'Filter by publication status. Options: "public" (published models available to all
|
|
218
|
+
description: 'Filter by publication status. Options: "public" (published models available to all registry users), "private" (unpublished models only visible to owner). Omit to see all models (both public and private). Example: use "public" to list only published models.'
|
|
219
219
|
},
|
|
220
220
|
provider: {
|
|
221
221
|
type: 'string',
|
|
222
|
-
description: 'Filter by provider name (case-insensitive). Example: "groq", "openai", "anthropic", "google". Use
|
|
222
|
+
description: 'Filter by provider name (case-insensitive). Example: "groq", "openai", "anthropic", "google". Use registry_providers_list to see available providers.'
|
|
223
223
|
},
|
|
224
224
|
max_input_price: {
|
|
225
225
|
type: 'number',
|
|
@@ -269,14 +269,14 @@ class MarketplaceTools {
|
|
|
269
269
|
{
|
|
270
270
|
type: 'function',
|
|
271
271
|
function: {
|
|
272
|
-
name: '
|
|
272
|
+
name: 'registry_models_update_capabilities',
|
|
273
273
|
description: 'Update capability flags for a model. Allows setting vision support, reasoning capability, tool/function calling, image generation, video generation, audio processing, and embedding capabilities. Use when user wants to update or configure what their model can do. Each capability is a boolean flag. IMPORTANT: Only the model owner can update capabilities.',
|
|
274
274
|
parameters: {
|
|
275
275
|
type: 'object',
|
|
276
276
|
properties: {
|
|
277
277
|
model_id: {
|
|
278
278
|
type: 'string',
|
|
279
|
-
description: 'Model ID (e.g., "groq/llama-3.3-70b-versatile"). Use
|
|
279
|
+
description: 'Model ID (e.g., "groq/llama-3.3-70b-versatile"). Use registry_models_list to get model IDs.'
|
|
280
280
|
},
|
|
281
281
|
supports_vision: {
|
|
282
282
|
type: 'boolean',
|
|
@@ -314,14 +314,14 @@ class MarketplaceTools {
|
|
|
314
314
|
{
|
|
315
315
|
type: 'function',
|
|
316
316
|
function: {
|
|
317
|
-
name: '
|
|
317
|
+
name: 'registry_models_get',
|
|
318
318
|
description: 'Get detailed information about a specific model including pricing and capabilities. Returns model name, display name, provider, context window, input/output pricing per million tokens, and all capability flags (vision, reasoning, tool_use, etc.). Use when user asks for details about a specific model, its price, or what it can do.',
|
|
319
319
|
parameters: {
|
|
320
320
|
type: 'object',
|
|
321
321
|
properties: {
|
|
322
322
|
model_id: {
|
|
323
323
|
type: 'string',
|
|
324
|
-
description: 'Model identifier (e.g., "groq/llama-3.3-70b-versatile", "google/gemini-2.5-flash"). Use
|
|
324
|
+
description: 'Model identifier (e.g., "groq/llama-3.3-70b-versatile", "google/gemini-2.5-flash"). Use registry_models_list to find available model IDs.'
|
|
325
325
|
}
|
|
326
326
|
},
|
|
327
327
|
required: ['model_id']
|
|
@@ -331,7 +331,7 @@ class MarketplaceTools {
|
|
|
331
331
|
{
|
|
332
332
|
type: 'function',
|
|
333
333
|
function: {
|
|
334
|
-
name: '
|
|
334
|
+
name: 'registry_request_logs_list',
|
|
335
335
|
description: 'Query user\'s request logs with pagination and filtering. Shows recent API requests including method, endpoint, status code, model used, IP address, and timestamp. Use this to debug issues, view usage history, or find specific requests. Each log has an x-request-id for tracking. Supports filtering by status code, endpoint path, and model name. Call when user asks to see logs, requests, history, or wants to debug an issue.',
|
|
336
336
|
parameters: {
|
|
337
337
|
type: 'object',
|
|
@@ -364,14 +364,14 @@ class MarketplaceTools {
|
|
|
364
364
|
{
|
|
365
365
|
type: 'function',
|
|
366
366
|
function: {
|
|
367
|
-
name: '
|
|
368
|
-
description: 'Get detailed log entry by ID including full request/response bodies, headers, status codes, and timing information. Useful for debugging specific failed requests. The log ID can be found from
|
|
367
|
+
name: 'registry_request_logs_get',
|
|
368
|
+
description: 'Get detailed log entry by ID including full request/response bodies, headers, status codes, and timing information. Useful for debugging specific failed requests. The log ID can be found from request_logs_list or from the x-request-id response header. Sensitive data (API keys, auth tokens) are automatically redacted. Body content is truncated by default for readability - use show_full_body to see complete content.',
|
|
369
369
|
parameters: {
|
|
370
370
|
type: 'object',
|
|
371
371
|
properties: {
|
|
372
372
|
log_id: {
|
|
373
373
|
type: 'string',
|
|
374
|
-
description: 'Log ID (UUID) from
|
|
374
|
+
description: 'Log ID (UUID) from request_logs_list or x-request-id header'
|
|
375
375
|
},
|
|
376
376
|
show_full_body: {
|
|
377
377
|
type: 'boolean',
|
|
@@ -385,7 +385,7 @@ class MarketplaceTools {
|
|
|
385
385
|
{
|
|
386
386
|
type: 'function',
|
|
387
387
|
function: {
|
|
388
|
-
name: '
|
|
388
|
+
name: 'registry_request_logs_stats',
|
|
389
389
|
description: 'Get aggregated statistics about user\'s API usage. Shows total requests, success rate, top models used, top endpoints, and daily request counts. Use this for usage analytics, monitoring, or understanding request patterns. No parameters required.',
|
|
390
390
|
parameters: {
|
|
391
391
|
type: 'object',
|
|
@@ -406,7 +406,7 @@ class MarketplaceTools {
|
|
|
406
406
|
{
|
|
407
407
|
type: 'function',
|
|
408
408
|
function: {
|
|
409
|
-
name: '
|
|
409
|
+
name: 'registry_vault_status',
|
|
410
410
|
description: 'Get comprehensive vault status showing LocalVault (persistent encrypted storage) and KeyVault (in-memory protection). Returns pre-formatted text with box-drawing characters. IMPORTANT: Display the output exactly as received - do not summarize or reformat. Use when user asks about vault, credentials, or security.',
|
|
411
411
|
parameters: {
|
|
412
412
|
type: 'object',
|
|
@@ -418,7 +418,7 @@ class MarketplaceTools {
|
|
|
418
418
|
{
|
|
419
419
|
type: 'function',
|
|
420
420
|
function: {
|
|
421
|
-
name: '
|
|
421
|
+
name: 'registry_vault_localvault',
|
|
422
422
|
description: 'List all credentials in LocalVault (persistent encrypted storage at ~/.langmart/keystore.enc). Returns pre-formatted text. IMPORTANT: Display output exactly as received - do not summarize. Use when user asks about stored credentials.',
|
|
423
423
|
parameters: {
|
|
424
424
|
type: 'object',
|
|
@@ -430,7 +430,7 @@ class MarketplaceTools {
|
|
|
430
430
|
{
|
|
431
431
|
type: 'function',
|
|
432
432
|
function: {
|
|
433
|
-
name: '
|
|
433
|
+
name: 'registry_vault_keyvault',
|
|
434
434
|
description: 'Show KeyVault status (in-memory chat protection that redacts API keys from LLM messages). Returns pre-formatted text. IMPORTANT: Display output exactly as received. Use when user asks about key protection or redaction.',
|
|
435
435
|
parameters: {
|
|
436
436
|
type: 'object',
|
|
@@ -442,8 +442,8 @@ class MarketplaceTools {
|
|
|
442
442
|
{
|
|
443
443
|
type: 'function',
|
|
444
444
|
function: {
|
|
445
|
-
name: '
|
|
446
|
-
description: 'Set or update sales quota limits for a connection. Quota applies to ALL models under the connection and tracks total consumption (owner usage + published model sales). Daily quota resets at midnight UTC, monthly resets on 1st. When quota exceeded, all models auto-disable. Can enable/disable enforcement. Use connection_id from
|
|
445
|
+
name: 'registry_connections_quota_manage',
|
|
446
|
+
description: 'Set or update sales quota limits for a connection. Quota applies to ALL models under the connection and tracks total consumption (owner usage + published model sales). Daily quota resets at midnight UTC, monthly resets on 1st. When quota exceeded, all models auto-disable. Can enable/disable enforcement. Use connection_id from registry_connections_list.',
|
|
447
447
|
parameters: {
|
|
448
448
|
type: 'object',
|
|
449
449
|
properties: {
|
|
@@ -471,8 +471,8 @@ class MarketplaceTools {
|
|
|
471
471
|
{
|
|
472
472
|
type: 'function',
|
|
473
473
|
function: {
|
|
474
|
-
name: '
|
|
475
|
-
description: 'Get current quota status and usage for a specific connection. Shows daily/monthly limits, current consumption, percentage used, quota exceeded status, affected models count, and usage history (last 30 days). Use connection_id from
|
|
474
|
+
name: 'registry_connections_quota_get',
|
|
475
|
+
description: 'Get current quota status and usage for a specific connection. Shows daily/monthly limits, current consumption, percentage used, quota exceeded status, affected models count, and usage history (last 30 days). Use connection_id from registry_connections_list.',
|
|
476
476
|
parameters: {
|
|
477
477
|
type: 'object',
|
|
478
478
|
properties: {
|
|
@@ -488,7 +488,7 @@ class MarketplaceTools {
|
|
|
488
488
|
{
|
|
489
489
|
type: 'function',
|
|
490
490
|
function: {
|
|
491
|
-
name: '
|
|
491
|
+
name: 'registry_connections_quota_list',
|
|
492
492
|
description: 'List quota status for all connections owned by the user. Shows quota settings, current usage, and enforcement status for each connection. Useful for getting an overview of quota usage across all provider connections.',
|
|
493
493
|
parameters: {
|
|
494
494
|
type: 'object',
|
|
@@ -500,14 +500,14 @@ class MarketplaceTools {
|
|
|
500
500
|
{
|
|
501
501
|
type: 'function',
|
|
502
502
|
function: {
|
|
503
|
-
name: '
|
|
504
|
-
description: 'Update pricing for one or multiple models using filter-based selection. Supports both single model updates and bulk operations.\n\n**TWO PRICING METHODS:**\n1. Exact Price: Set specific prices with input_tokens_per_1k and output_tokens_per_1k\n2. Percentage Adjustment: Increase/decrease current prices by percentage\n\n**TWO TARGET MODES:**\n1. Single Model: Provide model_id to update one model\n2. Bulk Mode: Provide filter (space-separated keywords) to update multiple models using AND-condition matching\n\n**PERCENTAGE EXAMPLES:**\n- "increase all groq models by 10%" → filter="groq", increase_percentage=10\n- "decrease all llama models by 15%" → filter="llama", decrease_percentage=15\n- "increase my published models by 20%" → filter="", source_access_level="public", increase_percentage=20\n- "increase all image models by 10%" → filter="image", increase_percentage=10\n\n**BULK UPDATE WORKFLOW:**\n- Default (auto_confirm: false): Shows matched models, asks for confirmation\n- With auto_confirm: true: Immediately updates all matched models\n- Use source_access_level to pre-filter by publication status\n\n**ENHANCED FILTER LOGIC:**\n- Space-separated keywords use AND condition (all must match)\n- Matches against model_id, model_name, provider name, AND capabilities\n- Capability keywords: image, vision, tool, reasoning, audio, video, embedding\n- Example: "groq llama" matches models with BOTH keywords\n- Example: "image" matches all models with vision or image generation capability\n- Example: "google tool" matches Google models with tool use capability\n\nOnly model owners can update pricing. Use
|
|
503
|
+
name: 'registry_models_update_pricing',
|
|
504
|
+
description: 'Update pricing for one or multiple models using filter-based selection. Supports both single model updates and bulk operations.\n\n**TWO PRICING METHODS:**\n1. Exact Price: Set specific prices with input_tokens_per_1k and output_tokens_per_1k\n2. Percentage Adjustment: Increase/decrease current prices by percentage\n\n**TWO TARGET MODES:**\n1. Single Model: Provide model_id to update one model\n2. Bulk Mode: Provide filter (space-separated keywords) to update multiple models using AND-condition matching\n\n**PERCENTAGE EXAMPLES:**\n- "increase all groq models by 10%" → filter="groq", increase_percentage=10\n- "decrease all llama models by 15%" → filter="llama", decrease_percentage=15\n- "increase my published models by 20%" → filter="", source_access_level="public", increase_percentage=20\n- "increase all image models by 10%" → filter="image", increase_percentage=10\n\n**BULK UPDATE WORKFLOW:**\n- Default (auto_confirm: false): Shows matched models, asks for confirmation\n- With auto_confirm: true: Immediately updates all matched models\n- Use source_access_level to pre-filter by publication status\n\n**ENHANCED FILTER LOGIC:**\n- Space-separated keywords use AND condition (all must match)\n- Matches against model_id, model_name, provider name, AND capabilities\n- Capability keywords: image, vision, tool, reasoning, audio, video, embedding\n- Example: "groq llama" matches models with BOTH keywords\n- Example: "image" matches all models with vision or image generation capability\n- Example: "google tool" matches Google models with tool use capability\n\nOnly model owners can update pricing. Use registry_models_list to find model IDs.',
|
|
505
505
|
parameters: {
|
|
506
506
|
type: 'object',
|
|
507
507
|
properties: {
|
|
508
508
|
model_id: {
|
|
509
509
|
type: 'string',
|
|
510
|
-
description: 'Single model UUID from
|
|
510
|
+
description: 'Single model UUID from registry_models_list (the id field, NOT model_id field). Mutually exclusive with filter. Use for single model updates.'
|
|
511
511
|
},
|
|
512
512
|
filter: {
|
|
513
513
|
type: 'string',
|
|
@@ -554,36 +554,109 @@ class MarketplaceTools {
|
|
|
554
554
|
{
|
|
555
555
|
type: 'function',
|
|
556
556
|
function: {
|
|
557
|
-
name: '
|
|
558
|
-
description: '
|
|
557
|
+
name: 'registry_models_update_billing',
|
|
558
|
+
description: 'Update billing settings for organization models (org admin only). Sets how model usage costs are handled within the organization.\n\n**Billing modes:**\n- "org_pays": Organization pays for all usage (members use for free)\n- "member_pays": Members pay from their own credits (org can set fee %)\n\n**Org fee:**\n- Only applies when billing_mode is "member_pays"\n- Percentage (0-100) added to model cost as org fee\n- Example: 10 = 10% fee on top of model cost\n\n**Pricing (optional):**\n- Override default model pricing if needed\n- Set input_per_1k and output_per_1k in USD\n\n**Requirements:**\n- Must be org admin or owner\n- Model must be organization-level (not private/public)',
|
|
559
559
|
parameters: {
|
|
560
560
|
type: 'object',
|
|
561
561
|
properties: {
|
|
562
562
|
model_id: {
|
|
563
563
|
type: 'string',
|
|
564
|
-
description: '
|
|
564
|
+
description: 'Model UUID from registry_models_list (the "id" field). Required.'
|
|
565
565
|
},
|
|
566
|
-
|
|
566
|
+
billing_mode: {
|
|
567
567
|
type: 'string',
|
|
568
|
-
|
|
568
|
+
enum: ['org_pays', 'member_pays'],
|
|
569
|
+
description: 'How usage costs are handled: "org_pays" (org covers all costs) or "member_pays" (member pays from their credits)'
|
|
569
570
|
},
|
|
570
|
-
|
|
571
|
+
org_fee_percentage: {
|
|
572
|
+
type: 'number',
|
|
573
|
+
description: 'Fee percentage for member_pays mode (0-100). Ignored for org_pays mode.'
|
|
574
|
+
},
|
|
575
|
+
input_per_1k: {
|
|
576
|
+
type: 'number',
|
|
577
|
+
description: 'Optional: Override price per 1000 input tokens in USD'
|
|
578
|
+
},
|
|
579
|
+
output_per_1k: {
|
|
580
|
+
type: 'number',
|
|
581
|
+
description: 'Optional: Override price per 1000 output tokens in USD'
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
required: ['model_id', 'billing_mode']
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
type: 'function',
|
|
590
|
+
function: {
|
|
591
|
+
name: 'registry_models_update_visibility',
|
|
592
|
+
description: 'Update visibility for organization models (org admin only). Controls whether org members can see and use the model.\n\n**Visibility:**\n- true: Model is visible and usable by org members\n- false: Model is hidden from org members (admin can still see)\n\n**Requirements:**\n- Must be org admin or owner\n- Model must be organization-level (not private/public)\n\n**Note:** For individual (private) models, owners always have full access. This tool is only for org admins to control org-wide model visibility.',
|
|
593
|
+
parameters: {
|
|
594
|
+
type: 'object',
|
|
595
|
+
properties: {
|
|
596
|
+
model_id: {
|
|
571
597
|
type: 'string',
|
|
572
|
-
description: '
|
|
573
|
-
enum: ['public', 'private', 'disabled']
|
|
598
|
+
description: 'Model UUID from registry_models_list (the "id" field). Required.'
|
|
574
599
|
},
|
|
575
|
-
|
|
600
|
+
is_available: {
|
|
576
601
|
type: 'boolean',
|
|
577
|
-
description: '
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
602
|
+
description: 'true = visible to org members, false = hidden from org members'
|
|
603
|
+
}
|
|
604
|
+
},
|
|
605
|
+
required: ['model_id', 'is_available']
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
},
|
|
609
|
+
// ========================================================================
|
|
610
|
+
// WORKFLOW QUERY TOOLS - For agents to query workflow execution state
|
|
611
|
+
// ========================================================================
|
|
612
|
+
{
|
|
613
|
+
type: 'function',
|
|
614
|
+
function: {
|
|
615
|
+
name: 'workflow_get_status',
|
|
616
|
+
description: 'Get the overall status of a workflow execution by trace ID. Returns the workflow name, overall status (pending/running/completed/failed), start time, completion time, and progress summary. Use this to check if the workflow is still running or has completed.',
|
|
617
|
+
parameters: {
|
|
618
|
+
type: 'object',
|
|
619
|
+
properties: {
|
|
620
|
+
trace_id: {
|
|
621
|
+
type: 'string',
|
|
622
|
+
description: 'The trace ID of the workflow execution. This is provided in your system prompt as "Trace ID".'
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
required: ['trace_id']
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
type: 'function',
|
|
631
|
+
function: {
|
|
632
|
+
name: 'workflow_list_instances',
|
|
633
|
+
description: 'List all agent instances in a workflow execution. Shows each agent\'s name, role (START/AGENT/END), execution order, status, and any error messages. Use this to see what other agents are in your workflow and their current status.',
|
|
634
|
+
parameters: {
|
|
635
|
+
type: 'object',
|
|
636
|
+
properties: {
|
|
637
|
+
trace_id: {
|
|
638
|
+
type: 'string',
|
|
639
|
+
description: 'The trace ID of the workflow execution. This is provided in your system prompt as "Trace ID".'
|
|
640
|
+
}
|
|
641
|
+
},
|
|
642
|
+
required: ['trace_id']
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
type: 'function',
|
|
648
|
+
function: {
|
|
649
|
+
name: 'workflow_get_instance_output',
|
|
650
|
+
description: 'Get the output from a specific agent instance in the workflow. Returns the agent\'s response/output from its most recent session. Use this to retrieve results from agents that have already completed.',
|
|
651
|
+
parameters: {
|
|
652
|
+
type: 'object',
|
|
653
|
+
properties: {
|
|
654
|
+
instance_id: {
|
|
581
655
|
type: 'string',
|
|
582
|
-
description: '
|
|
583
|
-
enum: ['public', 'private', 'disabled']
|
|
656
|
+
description: 'The instance ID of the agent. Get instance IDs from workflow_list_instances.'
|
|
584
657
|
}
|
|
585
658
|
},
|
|
586
|
-
required: ['
|
|
659
|
+
required: ['instance_id']
|
|
587
660
|
}
|
|
588
661
|
}
|
|
589
662
|
}
|
|
@@ -610,53 +683,62 @@ class MarketplaceTools {
|
|
|
610
683
|
return tools.map(formatTool).join('\n\n');
|
|
611
684
|
}
|
|
612
685
|
/**
|
|
613
|
-
* Execute a
|
|
686
|
+
* Execute a registry tool
|
|
614
687
|
*/
|
|
615
688
|
async executeTool(toolName, args) {
|
|
616
689
|
try {
|
|
617
690
|
switch (toolName) {
|
|
618
|
-
case '
|
|
691
|
+
case 'registry_connections_list':
|
|
619
692
|
return await this.listConnections();
|
|
620
|
-
case '
|
|
693
|
+
case 'registry_connections_add':
|
|
621
694
|
return await this.addConnection(args);
|
|
622
|
-
case '
|
|
695
|
+
case 'registry_connections_remove':
|
|
623
696
|
return await this.removeConnection(args.connection_id);
|
|
624
|
-
case '
|
|
697
|
+
case 'registry_connections_test':
|
|
625
698
|
return await this.testConnection(args.connection_id);
|
|
626
|
-
case '
|
|
699
|
+
case 'registry_connections_update_key':
|
|
627
700
|
return await this.updateConnectionKey(args.connection_id, args.api_key);
|
|
628
|
-
case '
|
|
701
|
+
case 'registry_providers_list':
|
|
629
702
|
return await this.listProviders();
|
|
630
|
-
case '
|
|
703
|
+
case 'registry_models_discover':
|
|
631
704
|
return await this.discoverModels(args);
|
|
632
|
-
case '
|
|
705
|
+
case 'registry_models_list':
|
|
633
706
|
return await this.listModels(args);
|
|
634
|
-
case '
|
|
707
|
+
case 'registry_models_update_capabilities':
|
|
635
708
|
return await this.updateModelCapabilities(args);
|
|
636
|
-
case '
|
|
709
|
+
case 'registry_models_get':
|
|
637
710
|
return await this.getModelInfo(args.model_id);
|
|
638
|
-
case '
|
|
711
|
+
case 'registry_request_logs_list':
|
|
639
712
|
return await this.listRequestLogs(args);
|
|
640
|
-
case '
|
|
713
|
+
case 'registry_request_logs_get':
|
|
641
714
|
return await this.getRequestLog(args.log_id, args.show_full_body);
|
|
642
|
-
case '
|
|
715
|
+
case 'registry_request_logs_stats':
|
|
643
716
|
return await this.getRequestLogStats(args);
|
|
644
|
-
case '
|
|
717
|
+
case 'registry_vault_status':
|
|
645
718
|
return await this.getVaultStatus();
|
|
646
|
-
case '
|
|
719
|
+
case 'registry_vault_localvault':
|
|
647
720
|
return await this.getLocalVaultList();
|
|
648
|
-
case '
|
|
721
|
+
case 'registry_vault_keyvault':
|
|
649
722
|
return await this.getKeyVaultStatus();
|
|
650
|
-
case '
|
|
723
|
+
case 'registry_connections_quota_manage':
|
|
651
724
|
return await this.manageConnectionQuota(args);
|
|
652
|
-
case '
|
|
725
|
+
case 'registry_connections_quota_get':
|
|
653
726
|
return await this.getConnectionQuota(args.connection_id);
|
|
654
|
-
case '
|
|
727
|
+
case 'registry_connections_quota_list':
|
|
655
728
|
return await this.listConnectionQuotas();
|
|
656
|
-
case '
|
|
729
|
+
case 'registry_models_update_pricing':
|
|
657
730
|
return await this.updateModelPricing(args);
|
|
658
|
-
case '
|
|
659
|
-
return await this.
|
|
731
|
+
case 'registry_models_update_billing':
|
|
732
|
+
return await this.updateModelBilling(args);
|
|
733
|
+
case 'registry_models_update_visibility':
|
|
734
|
+
return await this.updateModelVisibility(args);
|
|
735
|
+
// Workflow query tools
|
|
736
|
+
case 'workflow_get_status':
|
|
737
|
+
return await this.getWorkflowStatus(args.trace_id);
|
|
738
|
+
case 'workflow_list_instances':
|
|
739
|
+
return await this.listWorkflowInstances(args.trace_id);
|
|
740
|
+
case 'workflow_get_instance_output':
|
|
741
|
+
return await this.getInstanceOutput(args.instance_id);
|
|
660
742
|
default:
|
|
661
743
|
return {
|
|
662
744
|
success: false,
|
|
@@ -707,15 +789,15 @@ class MarketplaceTools {
|
|
|
707
789
|
// ========================================================================
|
|
708
790
|
async listConnections() {
|
|
709
791
|
try {
|
|
710
|
-
(0, debug_utils_1.debugLog)(`[
|
|
792
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Listing connections from: ${this.registryUrl}/api/connections`);
|
|
711
793
|
const response = await this.client.get('/api/connections');
|
|
712
|
-
(0, debug_utils_1.debugLog)(`[
|
|
713
|
-
(0, debug_utils_1.debugLog)(`[
|
|
794
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] List response status: ${response.status}`);
|
|
795
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] List response data keys:`, Object.keys(response.data || {}));
|
|
714
796
|
const connections = response.data.connections || [];
|
|
715
797
|
if (connections.length === 0) {
|
|
716
798
|
return {
|
|
717
799
|
success: true,
|
|
718
|
-
output: 'No connections found. Use
|
|
800
|
+
output: 'No connections found. Use registry.connections.add to create one.'
|
|
719
801
|
};
|
|
720
802
|
}
|
|
721
803
|
// Sort by created_at to maintain consistent ordering
|
|
@@ -747,9 +829,9 @@ class MarketplaceTools {
|
|
|
747
829
|
` ➕ Add a New Connection\n` +
|
|
748
830
|
` Create connection to LLM provider (OpenAI, Groq, etc.)\n\n` +
|
|
749
831
|
` 🔍 Discover Models\n` +
|
|
750
|
-
` Fetch available models from provider API and add to
|
|
832
|
+
` Fetch available models from provider API and add to registry\n\n` +
|
|
751
833
|
` 🔑 Update API Key\n` +
|
|
752
|
-
` Change API key for existing connection (
|
|
834
|
+
` Change API key for existing connection (Registry-Managed only)\n\n` +
|
|
753
835
|
` 📊 Manage Quota\n` +
|
|
754
836
|
` Set usage limits for connection (daily/monthly spending caps)\n\n` +
|
|
755
837
|
` 📈 View Quota Status\n` +
|
|
@@ -759,23 +841,23 @@ class MarketplaceTools {
|
|
|
759
841
|
` 🧪 Test Connection\n` +
|
|
760
842
|
` Verify connection works by discovering models\n\n` +
|
|
761
843
|
` 🗑️ Delete Connection\n` +
|
|
762
|
-
` Remove connection and all its models from
|
|
844
|
+
` Remove connection and all its models from registry\n\n` +
|
|
763
845
|
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`
|
|
764
846
|
};
|
|
765
847
|
}
|
|
766
848
|
catch (error) {
|
|
767
|
-
console.error(`[
|
|
768
|
-
console.error(`[
|
|
769
|
-
console.error(`[
|
|
770
|
-
console.error(`[
|
|
771
|
-
console.error(`[
|
|
849
|
+
console.error(`[RegistryTools] List connections error:`);
|
|
850
|
+
console.error(`[RegistryTools] Error code:`, error.code);
|
|
851
|
+
console.error(`[RegistryTools] Error message:`, error.message);
|
|
852
|
+
console.error(`[RegistryTools] Response status:`, error.response?.status);
|
|
853
|
+
console.error(`[RegistryTools] Response data:`, error.response?.data);
|
|
772
854
|
// Socket hang up / connection reset errors
|
|
773
855
|
if (error.code === 'ECONNRESET' || error.code === 'EPIPE' ||
|
|
774
856
|
error.message?.toLowerCase().includes('socket hang up')) {
|
|
775
857
|
return {
|
|
776
858
|
success: false,
|
|
777
859
|
error: `🔌 Connection lost while listing connections\n\n` +
|
|
778
|
-
`The
|
|
860
|
+
`The registry API connection was interrupted.\n` +
|
|
779
861
|
`This may happen if:\n` +
|
|
780
862
|
` • The gateway is restarting\n` +
|
|
781
863
|
` • Network is unstable\n` +
|
|
@@ -796,7 +878,7 @@ class MarketplaceTools {
|
|
|
796
878
|
const response = await this.client.post('/api/connections', args);
|
|
797
879
|
const conn = response.data.connection;
|
|
798
880
|
// Build detailed connection info
|
|
799
|
-
const gatewayTypeLabel = conn.gateway_type === 2 ? '
|
|
881
|
+
const gatewayTypeLabel = conn.gateway_type === 2 ? 'Registry-Managed Compute' : 'Self-Hosted Compute';
|
|
800
882
|
return {
|
|
801
883
|
success: true,
|
|
802
884
|
output: `✅ Connection added successfully!\n\n` +
|
|
@@ -813,13 +895,13 @@ class MarketplaceTools {
|
|
|
813
895
|
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n` +
|
|
814
896
|
`💡 What would you like to do next?\n\n` +
|
|
815
897
|
` 1️⃣ Test this connection\n` +
|
|
816
|
-
` Use:
|
|
898
|
+
` Use: registry.connections.test\n\n` +
|
|
817
899
|
` 2️⃣ Discover available models\n` +
|
|
818
|
-
` Use:
|
|
900
|
+
` Use: registry.models.discover\n\n` +
|
|
819
901
|
` 3️⃣ Update the API key\n` +
|
|
820
|
-
` Use:
|
|
902
|
+
` Use: registry.connections.updateKey\n\n` +
|
|
821
903
|
` 4️⃣ Remove this connection\n` +
|
|
822
|
-
` Use:
|
|
904
|
+
` Use: registry.connections.remove\n\n` +
|
|
823
905
|
`IMPORTANT: Show this output to the user and ask what they'd like to do next. DO NOT automatically call other tools.`
|
|
824
906
|
};
|
|
825
907
|
}
|
|
@@ -852,11 +934,11 @@ class MarketplaceTools {
|
|
|
852
934
|
// Resolve sequence number to UUID if needed
|
|
853
935
|
const resolvedId = this.resolveConnectionId(connectionId);
|
|
854
936
|
const testUrl = `/api/connections/${resolvedId}/test`;
|
|
855
|
-
(0, debug_utils_1.debugLog)(`[
|
|
856
|
-
(0, debug_utils_1.debugLog)(`[
|
|
937
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Testing connection: ${connectionId} (resolved to: ${resolvedId})`);
|
|
938
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Full URL: ${this.registryUrl}${testUrl}`);
|
|
857
939
|
const response = await this.client.post(testUrl);
|
|
858
|
-
(0, debug_utils_1.debugLog)(`[
|
|
859
|
-
(0, debug_utils_1.debugLog)(`[
|
|
940
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Response status: ${response.status}`);
|
|
941
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Response data:`, response.data);
|
|
860
942
|
const data = response.data;
|
|
861
943
|
// Check for non-2xx responses (axios doesn't throw for < 500)
|
|
862
944
|
if (response.status >= 400 || data.success === false) {
|
|
@@ -866,7 +948,7 @@ class MarketplaceTools {
|
|
|
866
948
|
success: false,
|
|
867
949
|
error: `❌ Connection not found\n\n` +
|
|
868
950
|
`Connection: ${connectionId} (resolved to: ${resolvedId})\n\n` +
|
|
869
|
-
`💡 Use
|
|
951
|
+
`💡 Use registry.connections.list to see available connections.`
|
|
870
952
|
};
|
|
871
953
|
}
|
|
872
954
|
// Handle other 4xx errors using the standardized error format
|
|
@@ -890,7 +972,7 @@ class MarketplaceTools {
|
|
|
890
972
|
`Status: ${errorData.status} (Authentication Failed)\n` +
|
|
891
973
|
(errorData.details ? `Details: ${errorData.details}\n` : '') +
|
|
892
974
|
`\n💡 Check your API key and update it if needed using:\n` +
|
|
893
|
-
`
|
|
975
|
+
` registry.connections.updateKey`
|
|
894
976
|
};
|
|
895
977
|
}
|
|
896
978
|
if (errorData.code === 'type3_gateway_unavailable') {
|
|
@@ -930,18 +1012,18 @@ class MarketplaceTools {
|
|
|
930
1012
|
};
|
|
931
1013
|
}
|
|
932
1014
|
catch (error) {
|
|
933
|
-
console.error(`[
|
|
934
|
-
console.error(`[
|
|
935
|
-
console.error(`[
|
|
936
|
-
console.error(`[
|
|
937
|
-
console.error(`[
|
|
1015
|
+
console.error(`[RegistryTools] Test connection error for ${connectionId}:`);
|
|
1016
|
+
console.error(`[RegistryTools] Error code:`, error.code);
|
|
1017
|
+
console.error(`[RegistryTools] Error message:`, error.message);
|
|
1018
|
+
console.error(`[RegistryTools] Response status:`, error.response?.status);
|
|
1019
|
+
console.error(`[RegistryTools] Response data:`, error.response?.data);
|
|
938
1020
|
// Socket hang up / connection reset errors
|
|
939
1021
|
if (error.code === 'ECONNRESET' || error.code === 'EPIPE' ||
|
|
940
1022
|
error.message?.toLowerCase().includes('socket hang up')) {
|
|
941
1023
|
return {
|
|
942
1024
|
success: false,
|
|
943
1025
|
error: `🔌 Connection lost during test\n\n` +
|
|
944
|
-
`The
|
|
1026
|
+
`The registry API connection was interrupted.\n` +
|
|
945
1027
|
`This may happen if:\n` +
|
|
946
1028
|
` • The gateway is restarting\n` +
|
|
947
1029
|
` • Network is unstable\n` +
|
|
@@ -955,9 +1037,9 @@ class MarketplaceTools {
|
|
|
955
1037
|
if (error.code === 'ECONNREFUSED') {
|
|
956
1038
|
return {
|
|
957
1039
|
success: false,
|
|
958
|
-
error: `🔌 Cannot connect to
|
|
959
|
-
`The
|
|
960
|
-
`💡 Ensure the LangMart
|
|
1040
|
+
error: `🔌 Cannot connect to registry API\n\n` +
|
|
1041
|
+
`The registry API is not reachable at ${this.registryUrl}\n\n` +
|
|
1042
|
+
`💡 Ensure the LangMart Registry is running on the correct port.`
|
|
961
1043
|
};
|
|
962
1044
|
}
|
|
963
1045
|
// Generic error fallback
|
|
@@ -994,7 +1076,7 @@ class MarketplaceTools {
|
|
|
994
1076
|
if (providers.length === 0) {
|
|
995
1077
|
return {
|
|
996
1078
|
success: true,
|
|
997
|
-
output: 'No providers found in
|
|
1079
|
+
output: 'No providers found in registry.'
|
|
998
1080
|
};
|
|
999
1081
|
}
|
|
1000
1082
|
const output = providers.map((p, idx) => `${idx + 1}. ${p.name} (${p.key})\n` +
|
|
@@ -1039,7 +1121,7 @@ class MarketplaceTools {
|
|
|
1039
1121
|
`Stored: ${data.stored} models\n` +
|
|
1040
1122
|
`Failed: ${data.failed} models\n` +
|
|
1041
1123
|
`Source: ${data.source}\n\n` +
|
|
1042
|
-
`Use
|
|
1124
|
+
`Use registry.models.list to see all available models.`
|
|
1043
1125
|
};
|
|
1044
1126
|
}
|
|
1045
1127
|
catch (error) {
|
|
@@ -1064,7 +1146,7 @@ class MarketplaceTools {
|
|
|
1064
1146
|
if (models.length === 0) {
|
|
1065
1147
|
return {
|
|
1066
1148
|
success: true,
|
|
1067
|
-
output: 'No models found. Use
|
|
1149
|
+
output: 'No models found. Use registry.models.discover to discover models from your connections.'
|
|
1068
1150
|
};
|
|
1069
1151
|
}
|
|
1070
1152
|
// Pagination parameters
|
|
@@ -1264,7 +1346,7 @@ class MarketplaceTools {
|
|
|
1264
1346
|
output: `No models match the specified filters.\n\n` +
|
|
1265
1347
|
`Active Filters:\n ${activeFilters.join('\n ')}\n` +
|
|
1266
1348
|
`Sorted By: ${sortLabel}\n\n` +
|
|
1267
|
-
`Try relaxing the filters or use
|
|
1349
|
+
`Try relaxing the filters or use registry.models.discover to add more models.`
|
|
1268
1350
|
};
|
|
1269
1351
|
}
|
|
1270
1352
|
// Apply pagination
|
|
@@ -1381,7 +1463,7 @@ class MarketplaceTools {
|
|
|
1381
1463
|
if (error.response?.status === 404) {
|
|
1382
1464
|
return {
|
|
1383
1465
|
success: false,
|
|
1384
|
-
error: `Model "${modelId}" not found. Use
|
|
1466
|
+
error: `Model "${modelId}" not found. Use registry.models.list to see available models.`
|
|
1385
1467
|
};
|
|
1386
1468
|
}
|
|
1387
1469
|
return {
|
|
@@ -1753,7 +1835,7 @@ class MarketplaceTools {
|
|
|
1753
1835
|
const provider = providers[i];
|
|
1754
1836
|
if (provider.connection_id === '__gateway_auth__') {
|
|
1755
1837
|
lines.push(` ${i + 1}. 🔐 Gateway Authentication`);
|
|
1756
|
-
lines.push(` Type:
|
|
1838
|
+
lines.push(` Type: Registry API Key`);
|
|
1757
1839
|
lines.push(` Status: ✅ Encrypted & Stored`);
|
|
1758
1840
|
}
|
|
1759
1841
|
else {
|
|
@@ -1766,7 +1848,7 @@ class MarketplaceTools {
|
|
|
1766
1848
|
}
|
|
1767
1849
|
if (provider.gateway_type) {
|
|
1768
1850
|
const gatewayName = provider.gateway_type === 2
|
|
1769
|
-
? '
|
|
1851
|
+
? 'Registry-Managed Compute'
|
|
1770
1852
|
: 'Self-Hosted Compute';
|
|
1771
1853
|
lines.push(` Gateway: ${gatewayName}`);
|
|
1772
1854
|
}
|
|
@@ -1860,8 +1942,8 @@ class MarketplaceTools {
|
|
|
1860
1942
|
const provider = providers[i];
|
|
1861
1943
|
if (provider.connection_id === '__gateway_auth__') {
|
|
1862
1944
|
lines.push(` ${i + 1}. 🔐 Gateway Authentication`);
|
|
1863
|
-
lines.push(` Type:
|
|
1864
|
-
lines.push(` Purpose: Authenticate with
|
|
1945
|
+
lines.push(` Type: Registry API Key`);
|
|
1946
|
+
lines.push(` Purpose: Authenticate with registry`);
|
|
1865
1947
|
lines.push(` Status: ✅ Encrypted & Stored`);
|
|
1866
1948
|
}
|
|
1867
1949
|
else {
|
|
@@ -1874,7 +1956,7 @@ class MarketplaceTools {
|
|
|
1874
1956
|
}
|
|
1875
1957
|
if (provider.gateway_type) {
|
|
1876
1958
|
const gatewayName = provider.gateway_type === 2
|
|
1877
|
-
? '
|
|
1959
|
+
? 'Registry-Managed Compute'
|
|
1878
1960
|
: 'Self-Hosted Compute';
|
|
1879
1961
|
lines.push(` Gateway: ${gatewayName}`);
|
|
1880
1962
|
}
|
|
@@ -2151,7 +2233,7 @@ class MarketplaceTools {
|
|
|
2151
2233
|
if (connections.length === 0) {
|
|
2152
2234
|
return {
|
|
2153
2235
|
success: true,
|
|
2154
|
-
output: 'No connections found. Use
|
|
2236
|
+
output: 'No connections found. Use registry.connections.add to create one.'
|
|
2155
2237
|
};
|
|
2156
2238
|
}
|
|
2157
2239
|
// Sort by created_at to maintain consistent ordering
|
|
@@ -2199,7 +2281,7 @@ class MarketplaceTools {
|
|
|
2199
2281
|
}
|
|
2200
2282
|
}
|
|
2201
2283
|
output += `\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
2202
|
-
output += `💡 Use
|
|
2284
|
+
output += `💡 Use registry.connections.quota.get to see detailed history for a specific connection\n`;
|
|
2203
2285
|
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`;
|
|
2204
2286
|
return {
|
|
2205
2287
|
success: true,
|
|
@@ -2802,7 +2884,7 @@ class MarketplaceTools {
|
|
|
2802
2884
|
switch (access_level) {
|
|
2803
2885
|
case 'public':
|
|
2804
2886
|
statusEmoji = '🌍';
|
|
2805
|
-
accessDescription = 'Public - Available to all
|
|
2887
|
+
accessDescription = 'Public - Available to all registry users';
|
|
2806
2888
|
break;
|
|
2807
2889
|
case 'private':
|
|
2808
2890
|
statusEmoji = '🔒';
|
|
@@ -2825,7 +2907,7 @@ class MarketplaceTools {
|
|
|
2825
2907
|
` Description: ${accessDescription}\n\n` +
|
|
2826
2908
|
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n` +
|
|
2827
2909
|
(access_level === 'organization'
|
|
2828
|
-
? `ℹ️ Your model is now listed in the
|
|
2910
|
+
? `ℹ️ Your model is now listed in the registry and available for\n` +
|
|
2829
2911
|
` other users to consume. You'll earn revenue when others use it.\n\n`
|
|
2830
2912
|
: access_level === 'private'
|
|
2831
2913
|
? `ℹ️ Your model is now private and only accessible to you.\n\n`
|
|
@@ -2840,7 +2922,346 @@ class MarketplaceTools {
|
|
|
2840
2922
|
};
|
|
2841
2923
|
}
|
|
2842
2924
|
}
|
|
2925
|
+
/**
|
|
2926
|
+
* Update billing settings for organization models (org admin only)
|
|
2927
|
+
* Calls /api/admin/models/:id/billing
|
|
2928
|
+
*/
|
|
2929
|
+
async updateModelBilling(args) {
|
|
2930
|
+
try {
|
|
2931
|
+
const { model_id, billing_mode, org_fee_percentage, input_per_1k, output_per_1k } = args;
|
|
2932
|
+
if (!model_id) {
|
|
2933
|
+
return {
|
|
2934
|
+
success: false,
|
|
2935
|
+
error: 'model_id is required'
|
|
2936
|
+
};
|
|
2937
|
+
}
|
|
2938
|
+
if (!billing_mode || !['org_pays', 'member_pays'].includes(billing_mode)) {
|
|
2939
|
+
return {
|
|
2940
|
+
success: false,
|
|
2941
|
+
error: 'billing_mode is required and must be "org_pays" or "member_pays"'
|
|
2942
|
+
};
|
|
2943
|
+
}
|
|
2944
|
+
// Build request body
|
|
2945
|
+
const body = {
|
|
2946
|
+
billing_mode
|
|
2947
|
+
};
|
|
2948
|
+
if (org_fee_percentage !== undefined) {
|
|
2949
|
+
body.org_fee_percentage = org_fee_percentage;
|
|
2950
|
+
}
|
|
2951
|
+
if (input_per_1k !== undefined) {
|
|
2952
|
+
body.price_per_1k_input_tokens = input_per_1k;
|
|
2953
|
+
}
|
|
2954
|
+
if (output_per_1k !== undefined) {
|
|
2955
|
+
body.price_per_1k_output_tokens = output_per_1k;
|
|
2956
|
+
}
|
|
2957
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Updating billing for model: ${model_id}`, body);
|
|
2958
|
+
const response = await this.client.patch(`/api/admin/models/${encodeURIComponent(model_id)}/billing`, body);
|
|
2959
|
+
if (!response.data.success) {
|
|
2960
|
+
return {
|
|
2961
|
+
success: false,
|
|
2962
|
+
error: response.data.error?.message || 'Failed to update billing settings'
|
|
2963
|
+
};
|
|
2964
|
+
}
|
|
2965
|
+
const result = response.data.data;
|
|
2966
|
+
// Format output
|
|
2967
|
+
const billingModeLabel = result.billing.mode === 'org_pays'
|
|
2968
|
+
? '🏢 Organization Pays'
|
|
2969
|
+
: '👤 Member Pays';
|
|
2970
|
+
let output = `✅ Billing settings updated successfully!\n\n` +
|
|
2971
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` +
|
|
2972
|
+
`💰 Model Billing Settings:\n` +
|
|
2973
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` +
|
|
2974
|
+
` Model ID: ${result.model_id}\n\n` +
|
|
2975
|
+
` Billing Mode: ${billingModeLabel}\n`;
|
|
2976
|
+
if (result.billing.mode === 'member_pays' && result.billing.org_fee_percentage > 0) {
|
|
2977
|
+
output += ` Org Fee: ${result.billing.org_fee_percentage}%\n`;
|
|
2978
|
+
}
|
|
2979
|
+
if (result.pricing) {
|
|
2980
|
+
output += `\n Pricing:\n` +
|
|
2981
|
+
` Input: $${result.pricing.input_per_1k.toFixed(6)}/1K tokens\n` +
|
|
2982
|
+
` Output: $${result.pricing.output_per_1k.toFixed(6)}/1K tokens\n`;
|
|
2983
|
+
}
|
|
2984
|
+
output += `\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n` +
|
|
2985
|
+
`Updated: ${new Date(result.updated_at).toLocaleString()}`;
|
|
2986
|
+
return {
|
|
2987
|
+
success: true,
|
|
2988
|
+
output
|
|
2989
|
+
};
|
|
2990
|
+
}
|
|
2991
|
+
catch (error) {
|
|
2992
|
+
// Handle specific error codes
|
|
2993
|
+
const errorCode = error.response?.data?.error?.code;
|
|
2994
|
+
const errorMsg = error.response?.data?.error?.message || error.message;
|
|
2995
|
+
if (errorCode === 'ADMIN_MODEL_004') {
|
|
2996
|
+
return {
|
|
2997
|
+
success: false,
|
|
2998
|
+
error: 'This tool only works on organization-level models. For private models, owners already have full access.'
|
|
2999
|
+
};
|
|
3000
|
+
}
|
|
3001
|
+
if (errorCode === 'ADMIN_MODEL_006' || errorCode === 'ADMIN_MODEL_005') {
|
|
3002
|
+
return {
|
|
3003
|
+
success: false,
|
|
3004
|
+
error: 'Only organization admins and owners can update billing settings.'
|
|
3005
|
+
};
|
|
3006
|
+
}
|
|
3007
|
+
return {
|
|
3008
|
+
success: false,
|
|
3009
|
+
error: errorMsg
|
|
3010
|
+
};
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
/**
|
|
3014
|
+
* Update visibility for organization models (org admin only)
|
|
3015
|
+
* Calls /api/admin/models/:id/visibility
|
|
3016
|
+
*/
|
|
3017
|
+
async updateModelVisibility(args) {
|
|
3018
|
+
try {
|
|
3019
|
+
const { model_id, is_available } = args;
|
|
3020
|
+
if (!model_id) {
|
|
3021
|
+
return {
|
|
3022
|
+
success: false,
|
|
3023
|
+
error: 'model_id is required'
|
|
3024
|
+
};
|
|
3025
|
+
}
|
|
3026
|
+
if (typeof is_available !== 'boolean') {
|
|
3027
|
+
return {
|
|
3028
|
+
success: false,
|
|
3029
|
+
error: 'is_available is required and must be true or false'
|
|
3030
|
+
};
|
|
3031
|
+
}
|
|
3032
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Updating visibility for model: ${model_id} to ${is_available}`);
|
|
3033
|
+
const response = await this.client.patch(`/api/admin/models/${encodeURIComponent(model_id)}/visibility`, {
|
|
3034
|
+
is_available
|
|
3035
|
+
});
|
|
3036
|
+
if (!response.data.success) {
|
|
3037
|
+
return {
|
|
3038
|
+
success: false,
|
|
3039
|
+
error: response.data.error?.message || 'Failed to update visibility'
|
|
3040
|
+
};
|
|
3041
|
+
}
|
|
3042
|
+
const result = response.data.data;
|
|
3043
|
+
// Format output
|
|
3044
|
+
const visibilityLabel = result.is_available
|
|
3045
|
+
? '👁️ Visible - Org members can see and use this model'
|
|
3046
|
+
: '🙈 Hidden - Only org admins can see this model';
|
|
3047
|
+
const output = `✅ Visibility updated successfully!\n\n` +
|
|
3048
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` +
|
|
3049
|
+
`👁️ Model Visibility Settings:\n` +
|
|
3050
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` +
|
|
3051
|
+
` Model ID: ${result.model_id}\n\n` +
|
|
3052
|
+
` Visibility: ${visibilityLabel}\n\n` +
|
|
3053
|
+
`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n` +
|
|
3054
|
+
`Updated: ${new Date(result.updated_at).toLocaleString()}`;
|
|
3055
|
+
return {
|
|
3056
|
+
success: true,
|
|
3057
|
+
output
|
|
3058
|
+
};
|
|
3059
|
+
}
|
|
3060
|
+
catch (error) {
|
|
3061
|
+
// Handle specific error codes
|
|
3062
|
+
const errorCode = error.response?.data?.error?.code;
|
|
3063
|
+
const errorMsg = error.response?.data?.error?.message || error.message;
|
|
3064
|
+
if (errorCode === 'ADMIN_MODEL_VIS_003') {
|
|
3065
|
+
return {
|
|
3066
|
+
success: false,
|
|
3067
|
+
error: 'This tool only works on organization-level models. For private models, owners always have full access and visibility.'
|
|
3068
|
+
};
|
|
3069
|
+
}
|
|
3070
|
+
if (errorCode === 'ADMIN_MODEL_VIS_005' || errorCode === 'ADMIN_MODEL_VIS_004') {
|
|
3071
|
+
return {
|
|
3072
|
+
success: false,
|
|
3073
|
+
error: 'Only organization admins and owners can update model visibility.'
|
|
3074
|
+
};
|
|
3075
|
+
}
|
|
3076
|
+
return {
|
|
3077
|
+
success: false,
|
|
3078
|
+
error: errorMsg
|
|
3079
|
+
};
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
// ========================================================================
|
|
3083
|
+
// WORKFLOW QUERY TOOL IMPLEMENTATIONS
|
|
3084
|
+
// ========================================================================
|
|
3085
|
+
/**
|
|
3086
|
+
* Get overall status of a workflow execution
|
|
3087
|
+
*/
|
|
3088
|
+
async getWorkflowStatus(traceId) {
|
|
3089
|
+
try {
|
|
3090
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Getting workflow status for trace: ${traceId}`);
|
|
3091
|
+
const response = await this.client.get(`/api/agents/executions/${traceId}/trace`);
|
|
3092
|
+
if (!response.data.success) {
|
|
3093
|
+
return {
|
|
3094
|
+
success: false,
|
|
3095
|
+
error: response.data.error || 'Failed to get workflow status'
|
|
3096
|
+
};
|
|
3097
|
+
}
|
|
3098
|
+
const { workflowName, status, startedAt, completedAt, instances } = response.data;
|
|
3099
|
+
// Calculate progress
|
|
3100
|
+
const total = instances?.length || 0;
|
|
3101
|
+
const completed = instances?.filter((i) => i.status === 'completed').length || 0;
|
|
3102
|
+
const failed = instances?.filter((i) => i.status === 'failed').length || 0;
|
|
3103
|
+
const running = instances?.filter((i) => i.status === 'active' || i.status === 'running').length || 0;
|
|
3104
|
+
let statusEmoji = '⏳';
|
|
3105
|
+
if (status === 'completed')
|
|
3106
|
+
statusEmoji = '✅';
|
|
3107
|
+
else if (status === 'failed')
|
|
3108
|
+
statusEmoji = '❌';
|
|
3109
|
+
else if (status === 'running')
|
|
3110
|
+
statusEmoji = '🔄';
|
|
3111
|
+
let output = `${statusEmoji} Workflow Execution Status\n`;
|
|
3112
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n`;
|
|
3113
|
+
output += ` Workflow: ${workflowName || 'Unnamed Workflow'}\n`;
|
|
3114
|
+
output += ` Trace ID: ${traceId}\n`;
|
|
3115
|
+
output += ` Status: ${status?.toUpperCase() || 'UNKNOWN'}\n\n`;
|
|
3116
|
+
output += ` Progress: ${completed}/${total} agents completed\n`;
|
|
3117
|
+
if (running > 0)
|
|
3118
|
+
output += ` Running: ${running} agent(s)\n`;
|
|
3119
|
+
if (failed > 0)
|
|
3120
|
+
output += ` Failed: ${failed} agent(s)\n`;
|
|
3121
|
+
output += `\n`;
|
|
3122
|
+
if (startedAt)
|
|
3123
|
+
output += ` Started: ${new Date(startedAt).toLocaleString()}\n`;
|
|
3124
|
+
if (completedAt)
|
|
3125
|
+
output += ` Completed: ${new Date(completedAt).toLocaleString()}\n`;
|
|
3126
|
+
return {
|
|
3127
|
+
success: true,
|
|
3128
|
+
output
|
|
3129
|
+
};
|
|
3130
|
+
}
|
|
3131
|
+
catch (error) {
|
|
3132
|
+
return {
|
|
3133
|
+
success: false,
|
|
3134
|
+
error: error.response?.data?.error || error.message
|
|
3135
|
+
};
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
/**
|
|
3139
|
+
* List all instances in a workflow execution
|
|
3140
|
+
*/
|
|
3141
|
+
async listWorkflowInstances(traceId) {
|
|
3142
|
+
try {
|
|
3143
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Listing workflow instances for trace: ${traceId}`);
|
|
3144
|
+
const response = await this.client.get(`/api/agents/executions/${traceId}/trace`);
|
|
3145
|
+
if (!response.data.success) {
|
|
3146
|
+
return {
|
|
3147
|
+
success: false,
|
|
3148
|
+
error: response.data.error || 'Failed to list workflow instances'
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
const { workflowName, instances } = response.data;
|
|
3152
|
+
if (!instances || instances.length === 0) {
|
|
3153
|
+
return {
|
|
3154
|
+
success: true,
|
|
3155
|
+
output: 'No instances found for this workflow execution.'
|
|
3156
|
+
};
|
|
3157
|
+
}
|
|
3158
|
+
let output = `📋 Workflow Instances\n`;
|
|
3159
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
3160
|
+
output += ` Workflow: ${workflowName || 'Unnamed Workflow'}\n`;
|
|
3161
|
+
output += ` Total Agents: ${instances.length}\n\n`;
|
|
3162
|
+
for (const instance of instances) {
|
|
3163
|
+
let statusEmoji = '⏳';
|
|
3164
|
+
if (instance.status === 'completed')
|
|
3165
|
+
statusEmoji = '✅';
|
|
3166
|
+
else if (instance.status === 'failed')
|
|
3167
|
+
statusEmoji = '❌';
|
|
3168
|
+
else if (instance.status === 'active' || instance.status === 'running')
|
|
3169
|
+
statusEmoji = '🔄';
|
|
3170
|
+
let roleEmoji = '🤖';
|
|
3171
|
+
if (instance.nodeType === 'START')
|
|
3172
|
+
roleEmoji = '🚀';
|
|
3173
|
+
else if (instance.nodeType === 'END')
|
|
3174
|
+
roleEmoji = '🏁';
|
|
3175
|
+
output += `${roleEmoji} [${instance.executionOrder}] ${instance.definitionName || instance.name}\n`;
|
|
3176
|
+
output += ` ID: ${instance.id}\n`;
|
|
3177
|
+
output += ` Role: ${instance.nodeType}\n`;
|
|
3178
|
+
output += ` Status: ${statusEmoji} ${instance.status?.toUpperCase() || 'PENDING'}\n`;
|
|
3179
|
+
if (instance.errorMessage) {
|
|
3180
|
+
output += ` Error: ${instance.errorMessage}\n`;
|
|
3181
|
+
}
|
|
3182
|
+
output += `\n`;
|
|
3183
|
+
}
|
|
3184
|
+
return {
|
|
3185
|
+
success: true,
|
|
3186
|
+
output
|
|
3187
|
+
};
|
|
3188
|
+
}
|
|
3189
|
+
catch (error) {
|
|
3190
|
+
return {
|
|
3191
|
+
success: false,
|
|
3192
|
+
error: error.response?.data?.error || error.message
|
|
3193
|
+
};
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
/**
|
|
3197
|
+
* Get output from a specific agent instance
|
|
3198
|
+
*/
|
|
3199
|
+
async getInstanceOutput(instanceId) {
|
|
3200
|
+
try {
|
|
3201
|
+
(0, debug_utils_1.debugLog)(`[RegistryTools] Getting instance output for: ${instanceId}`);
|
|
3202
|
+
// Get the instance trace which includes sessions
|
|
3203
|
+
const traceResponse = await this.client.get(`/api/agents/instances/${instanceId}/trace`);
|
|
3204
|
+
if (!traceResponse.data?.success) {
|
|
3205
|
+
return {
|
|
3206
|
+
success: false,
|
|
3207
|
+
error: traceResponse.data?.error || 'Instance not found'
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
const instance = traceResponse.data.instance;
|
|
3211
|
+
const sessions = traceResponse.data.sessions || [];
|
|
3212
|
+
if (sessions.length === 0) {
|
|
3213
|
+
return {
|
|
3214
|
+
success: true,
|
|
3215
|
+
output: `📦 Instance Output\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n` +
|
|
3216
|
+
` Instance: ${instance.name || instanceId}\n` +
|
|
3217
|
+
` Status: No sessions found - agent has not run yet.\n`
|
|
3218
|
+
};
|
|
3219
|
+
}
|
|
3220
|
+
const latestSession = sessions[0];
|
|
3221
|
+
let statusEmoji = '⏳';
|
|
3222
|
+
if (latestSession.status === 'completed')
|
|
3223
|
+
statusEmoji = '✅';
|
|
3224
|
+
else if (latestSession.status === 'failed')
|
|
3225
|
+
statusEmoji = '❌';
|
|
3226
|
+
else if (latestSession.status === 'active')
|
|
3227
|
+
statusEmoji = '🔄';
|
|
3228
|
+
let output = `📦 Instance Output\n`;
|
|
3229
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n`;
|
|
3230
|
+
output += ` Instance: ${instance.name || instanceId}\n`;
|
|
3231
|
+
output += ` Definition: ${instance.definition_name || 'Unknown'}\n`;
|
|
3232
|
+
output += ` Status: ${statusEmoji} ${latestSession.status?.toUpperCase() || 'UNKNOWN'}\n\n`;
|
|
3233
|
+
if (latestSession.error_message) {
|
|
3234
|
+
output += ` ❌ Error: ${latestSession.error_message}\n\n`;
|
|
3235
|
+
}
|
|
3236
|
+
// Try to get the assistant's response from the session
|
|
3237
|
+
if (latestSession.response) {
|
|
3238
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
3239
|
+
output += `Response:\n`;
|
|
3240
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n`;
|
|
3241
|
+
output += latestSession.response;
|
|
3242
|
+
}
|
|
3243
|
+
else if (latestSession.metadata?.output) {
|
|
3244
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
3245
|
+
output += `Output:\n`;
|
|
3246
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n`;
|
|
3247
|
+
output += JSON.stringify(latestSession.metadata.output, null, 2);
|
|
3248
|
+
}
|
|
3249
|
+
else {
|
|
3250
|
+
output += ` No output available yet.\n`;
|
|
3251
|
+
}
|
|
3252
|
+
return {
|
|
3253
|
+
success: true,
|
|
3254
|
+
output
|
|
3255
|
+
};
|
|
3256
|
+
}
|
|
3257
|
+
catch (error) {
|
|
3258
|
+
return {
|
|
3259
|
+
success: false,
|
|
3260
|
+
error: error.response?.data?.error || error.message
|
|
3261
|
+
};
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
2843
3264
|
}
|
|
2844
|
-
exports.
|
|
2845
|
-
|
|
2846
|
-
//# sourceMappingURL=
|
|
3265
|
+
exports.RegistryTools = RegistryTools;
|
|
3266
|
+
RegistryTools.instance = null;
|
|
3267
|
+
//# sourceMappingURL=registry-tools.js.map
|