@agents-at-scale/ark 0.1.46 → 0.1.49
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/.arkrc.template.yaml +51 -0
- package/README.md +4 -0
- package/dist/arkServices.js +22 -8
- package/dist/arkServices.spec.js +6 -0
- package/dist/commands/agents/index.d.ts +1 -1
- package/dist/commands/agents/index.js +4 -2
- package/dist/commands/chat/index.js +1 -1
- package/dist/commands/completion/index.js +19 -5
- package/dist/commands/dashboard/index.d.ts +2 -2
- package/dist/commands/dashboard/index.js +5 -4
- package/dist/commands/export/index.d.ts +3 -0
- package/dist/commands/export/index.js +73 -0
- package/dist/commands/export/index.spec.d.ts +1 -0
- package/dist/commands/export/index.spec.js +145 -0
- package/dist/commands/import/index.d.ts +3 -0
- package/dist/commands/import/index.js +27 -0
- package/dist/commands/import/index.spec.d.ts +1 -0
- package/dist/commands/import/index.spec.js +46 -0
- package/dist/commands/install/index.js +20 -10
- package/dist/commands/marketplace/index.js +51 -23
- package/dist/commands/marketplace/index.spec.d.ts +1 -0
- package/dist/commands/marketplace/index.spec.js +88 -0
- package/dist/commands/memory/index.js +9 -4
- package/dist/commands/models/index.d.ts +1 -1
- package/dist/commands/models/index.js +4 -2
- package/dist/commands/query/index.d.ts +1 -1
- package/dist/commands/query/index.js +6 -2
- package/dist/commands/status/index.js +7 -2
- package/dist/commands/teams/index.d.ts +1 -1
- package/dist/commands/teams/index.js +4 -2
- package/dist/commands/uninstall/index.js +20 -10
- package/dist/index.js +4 -0
- package/dist/lib/arkApiProxy.d.ts +1 -1
- package/dist/lib/arkApiProxy.js +2 -2
- package/dist/lib/arkServiceProxy.d.ts +3 -1
- package/dist/lib/arkServiceProxy.js +34 -1
- package/dist/lib/arkServiceProxy.spec.d.ts +1 -0
- package/dist/lib/arkServiceProxy.spec.js +100 -0
- package/dist/lib/chatClient.d.ts +2 -0
- package/dist/lib/chatClient.js +10 -2
- package/dist/lib/config.d.ts +17 -1
- package/dist/lib/config.js +62 -7
- package/dist/lib/config.spec.js +103 -0
- package/dist/lib/constants.d.ts +3 -0
- package/dist/lib/constants.js +5 -0
- package/dist/lib/executeQuery.d.ts +1 -0
- package/dist/lib/executeQuery.js +21 -4
- package/dist/lib/executeQuery.spec.js +4 -1
- package/dist/lib/kubectl.d.ts +3 -0
- package/dist/lib/kubectl.js +68 -0
- package/dist/lib/kubectl.spec.js +16 -0
- package/dist/lib/marketplaceFetcher.d.ts +6 -0
- package/dist/lib/marketplaceFetcher.js +80 -0
- package/dist/lib/marketplaceFetcher.spec.d.ts +1 -0
- package/dist/lib/marketplaceFetcher.spec.js +225 -0
- package/dist/lib/types.d.ts +1 -0
- package/dist/marketplaceServices.d.ts +15 -6
- package/dist/marketplaceServices.js +38 -40
- package/dist/marketplaceServices.spec.d.ts +1 -0
- package/dist/marketplaceServices.spec.js +74 -0
- package/dist/types/marketplace.d.ts +37 -0
- package/dist/types/marketplace.js +1 -0
- package/dist/ui/MainMenu.js +6 -2
- package/package.json +4 -2
- package/templates/marketplace/marketplace.json.example +59 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
const mockAxiosGet = jest.fn();
|
|
3
|
+
jest.unstable_mockModule('axios', () => ({
|
|
4
|
+
default: {
|
|
5
|
+
get: mockAxiosGet,
|
|
6
|
+
isAxiosError: (error) => {
|
|
7
|
+
return (typeof error === 'object' &&
|
|
8
|
+
error !== null &&
|
|
9
|
+
'isAxiosError' in error &&
|
|
10
|
+
error.isAxiosError === true);
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
}));
|
|
14
|
+
const mockGetMarketplaceRepoUrl = jest.fn();
|
|
15
|
+
const mockGetMarketplaceRegistry = jest.fn();
|
|
16
|
+
jest.unstable_mockModule('./config.js', () => ({
|
|
17
|
+
getMarketplaceRepoUrl: mockGetMarketplaceRepoUrl,
|
|
18
|
+
getMarketplaceRegistry: mockGetMarketplaceRegistry,
|
|
19
|
+
}));
|
|
20
|
+
const { fetchMarketplaceManifest, mapMarketplaceItemToArkService, getMarketplaceServicesFromManifest, } = await import('./marketplaceFetcher.js');
|
|
21
|
+
describe('marketplaceFetcher', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
mockAxiosGet.mockClear();
|
|
25
|
+
mockGetMarketplaceRepoUrl.mockReturnValue('https://test-repo.example.com/marketplace');
|
|
26
|
+
mockGetMarketplaceRegistry.mockReturnValue('oci://test-registry.example.com/charts');
|
|
27
|
+
});
|
|
28
|
+
describe('fetchMarketplaceManifest', () => {
|
|
29
|
+
it('fetches and returns manifest successfully', async () => {
|
|
30
|
+
const mockManifest = {
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
marketplace: 'ARK Marketplace',
|
|
33
|
+
items: [
|
|
34
|
+
{
|
|
35
|
+
name: 'test-service',
|
|
36
|
+
description: 'Test service',
|
|
37
|
+
ark: {
|
|
38
|
+
chartPath: 'oci://registry/test-service',
|
|
39
|
+
namespace: 'test',
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
mockAxiosGet.mockResolvedValue({
|
|
45
|
+
data: mockManifest,
|
|
46
|
+
status: 200,
|
|
47
|
+
statusText: 'OK',
|
|
48
|
+
headers: {},
|
|
49
|
+
config: {},
|
|
50
|
+
});
|
|
51
|
+
const result = await fetchMarketplaceManifest();
|
|
52
|
+
expect(result).toEqual(mockManifest);
|
|
53
|
+
expect(mockAxiosGet).toHaveBeenCalledWith(expect.stringContaining('marketplace.json'), expect.objectContaining({
|
|
54
|
+
timeout: 10000,
|
|
55
|
+
headers: { Accept: 'application/json' },
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
it('returns null on network error', async () => {
|
|
59
|
+
const networkError = new Error('Network error');
|
|
60
|
+
networkError.code = 'ENOTFOUND';
|
|
61
|
+
networkError.isAxiosError = true;
|
|
62
|
+
mockAxiosGet.mockRejectedValue(networkError);
|
|
63
|
+
const result = await fetchMarketplaceManifest();
|
|
64
|
+
expect(result).toBeNull();
|
|
65
|
+
});
|
|
66
|
+
it('returns null on connection refused', async () => {
|
|
67
|
+
const connectionError = Object.assign(new Error('Connection refused'), {
|
|
68
|
+
code: 'ECONNREFUSED',
|
|
69
|
+
isAxiosError: true,
|
|
70
|
+
});
|
|
71
|
+
mockAxiosGet.mockRejectedValue(connectionError);
|
|
72
|
+
const result = await fetchMarketplaceManifest();
|
|
73
|
+
expect(result).toBeNull();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('mapMarketplaceItemToArkService', () => {
|
|
77
|
+
it('maps marketplace item to ARK service correctly', () => {
|
|
78
|
+
const item = {
|
|
79
|
+
name: 'test-service',
|
|
80
|
+
description: 'Test description',
|
|
81
|
+
ark: {
|
|
82
|
+
chartPath: 'oci://registry/test',
|
|
83
|
+
namespace: 'test-ns',
|
|
84
|
+
helmReleaseName: 'test-release',
|
|
85
|
+
installArgs: ['--create-namespace'],
|
|
86
|
+
k8sServiceName: 'test-svc',
|
|
87
|
+
k8sServicePort: 8080,
|
|
88
|
+
k8sDeploymentName: 'test-deploy',
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
const result = mapMarketplaceItemToArkService(item);
|
|
92
|
+
expect(result).toEqual({
|
|
93
|
+
name: 'test-service',
|
|
94
|
+
helmReleaseName: 'test-release',
|
|
95
|
+
description: 'Test description',
|
|
96
|
+
enabled: true,
|
|
97
|
+
category: 'marketplace',
|
|
98
|
+
namespace: 'test-ns',
|
|
99
|
+
chartPath: 'oci://registry/test',
|
|
100
|
+
installArgs: ['--create-namespace'],
|
|
101
|
+
k8sServiceName: 'test-svc',
|
|
102
|
+
k8sServicePort: 8080,
|
|
103
|
+
k8sDeploymentName: 'test-deploy',
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
it('uses defaults when ark fields are missing', () => {
|
|
107
|
+
const item = {
|
|
108
|
+
name: 'simple-service',
|
|
109
|
+
description: 'Simple service',
|
|
110
|
+
ark: {},
|
|
111
|
+
};
|
|
112
|
+
const result = mapMarketplaceItemToArkService(item);
|
|
113
|
+
expect(result.name).toBe('simple-service');
|
|
114
|
+
expect(result.helmReleaseName).toBe('simple-service');
|
|
115
|
+
expect(result.namespace).toBe('simple-service');
|
|
116
|
+
expect(result.chartPath).toContain('simple-service');
|
|
117
|
+
});
|
|
118
|
+
it('sanitizes service name', () => {
|
|
119
|
+
const item = {
|
|
120
|
+
name: 'Test Service 123!',
|
|
121
|
+
description: 'Test',
|
|
122
|
+
ark: {},
|
|
123
|
+
};
|
|
124
|
+
const result = mapMarketplaceItemToArkService(item);
|
|
125
|
+
expect(result.name).toBe('test-service-123');
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
describe('getMarketplaceServicesFromManifest', () => {
|
|
129
|
+
it('converts manifest items to service collection', async () => {
|
|
130
|
+
const mockManifest = {
|
|
131
|
+
version: '1.0.0',
|
|
132
|
+
marketplace: 'ARK Marketplace',
|
|
133
|
+
items: [
|
|
134
|
+
{
|
|
135
|
+
name: 'service1',
|
|
136
|
+
description: 'Service 1',
|
|
137
|
+
type: 'service',
|
|
138
|
+
ark: {
|
|
139
|
+
chartPath: 'oci://registry/service1',
|
|
140
|
+
namespace: 'ns1',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: 'service2',
|
|
145
|
+
description: 'Service 2',
|
|
146
|
+
type: 'service',
|
|
147
|
+
ark: {
|
|
148
|
+
chartPath: 'oci://registry/service2',
|
|
149
|
+
namespace: 'ns2',
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
};
|
|
154
|
+
mockAxiosGet.mockResolvedValue({
|
|
155
|
+
data: mockManifest,
|
|
156
|
+
status: 200,
|
|
157
|
+
statusText: 'OK',
|
|
158
|
+
headers: {},
|
|
159
|
+
config: {},
|
|
160
|
+
});
|
|
161
|
+
const result = await getMarketplaceServicesFromManifest();
|
|
162
|
+
expect(result).not.toBeNull();
|
|
163
|
+
expect(result?.['service1']).toBeDefined();
|
|
164
|
+
expect(result?.['service2']).toBeDefined();
|
|
165
|
+
expect(result?.['service1']?.description).toBe('Service 1');
|
|
166
|
+
expect(result?.['service2']?.description).toBe('Service 2');
|
|
167
|
+
});
|
|
168
|
+
it('filters out items without ark field', async () => {
|
|
169
|
+
const mockManifest = {
|
|
170
|
+
version: '1.0.0',
|
|
171
|
+
marketplace: 'ARK Marketplace',
|
|
172
|
+
items: [
|
|
173
|
+
{
|
|
174
|
+
name: 'service1',
|
|
175
|
+
description: 'Service 1',
|
|
176
|
+
type: 'service',
|
|
177
|
+
ark: {
|
|
178
|
+
chartPath: 'oci://registry/service1',
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: 'service2',
|
|
183
|
+
description: 'Service 2',
|
|
184
|
+
type: 'service',
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
};
|
|
188
|
+
mockAxiosGet.mockResolvedValue({
|
|
189
|
+
data: mockManifest,
|
|
190
|
+
status: 200,
|
|
191
|
+
statusText: 'OK',
|
|
192
|
+
headers: {},
|
|
193
|
+
config: {},
|
|
194
|
+
});
|
|
195
|
+
const result = await getMarketplaceServicesFromManifest();
|
|
196
|
+
expect(result).not.toBeNull();
|
|
197
|
+
expect(result?.['service1']).toBeDefined();
|
|
198
|
+
expect(result?.['service2']).toBeUndefined();
|
|
199
|
+
});
|
|
200
|
+
it('returns null when manifest fetch fails', async () => {
|
|
201
|
+
const networkError = new Error('Network error');
|
|
202
|
+
networkError.code = 'ENOTFOUND';
|
|
203
|
+
networkError.isAxiosError = true;
|
|
204
|
+
mockAxiosGet.mockRejectedValue(networkError);
|
|
205
|
+
const result = await getMarketplaceServicesFromManifest();
|
|
206
|
+
expect(result).toBeNull();
|
|
207
|
+
});
|
|
208
|
+
it('returns null when manifest has no items', async () => {
|
|
209
|
+
const mockManifest = {
|
|
210
|
+
version: '1.0.0',
|
|
211
|
+
marketplace: 'ARK Marketplace',
|
|
212
|
+
items: [],
|
|
213
|
+
};
|
|
214
|
+
mockAxiosGet.mockResolvedValue({
|
|
215
|
+
data: mockManifest,
|
|
216
|
+
status: 200,
|
|
217
|
+
statusText: 'OK',
|
|
218
|
+
headers: {},
|
|
219
|
+
config: {},
|
|
220
|
+
});
|
|
221
|
+
const result = await getMarketplaceServicesFromManifest();
|
|
222
|
+
expect(result).toBeNull();
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
});
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -2,14 +2,23 @@
|
|
|
2
2
|
* Marketplace service definitions for external ARK marketplace resources
|
|
3
3
|
* Repository: https://github.com/mckinsey/agents-at-scale-marketplace
|
|
4
4
|
* Charts are installed from the public OCI registry
|
|
5
|
+
*
|
|
6
|
+
* Supports Anthropic Marketplace JSON format for dynamic enumeration
|
|
5
7
|
*/
|
|
6
8
|
import type { ArkService, ServiceCollection } from './types/arkService.js';
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* Get all marketplace services, fetching from marketplace.json
|
|
11
|
+
* Returns null if marketplace is unavailable
|
|
10
12
|
*/
|
|
11
|
-
export declare
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
export declare function getAllMarketplaceServices(): Promise<ServiceCollection | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Get all marketplace agents, fetching from marketplace.json
|
|
16
|
+
* Returns null if marketplace is unavailable
|
|
17
|
+
*/
|
|
18
|
+
export declare function getAllMarketplaceAgents(): Promise<ServiceCollection | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Get a marketplace item by path (supports both services and agents)
|
|
21
|
+
* Returns null if marketplace is unavailable
|
|
22
|
+
*/
|
|
23
|
+
export declare function getMarketplaceItem(path: string): Promise<ArkService | undefined | null>;
|
|
14
24
|
export declare function isMarketplaceService(name: string): boolean;
|
|
15
|
-
export declare function extractMarketplaceServiceName(path: string): string;
|
|
@@ -2,50 +2,48 @@
|
|
|
2
2
|
* Marketplace service definitions for external ARK marketplace resources
|
|
3
3
|
* Repository: https://github.com/mckinsey/agents-at-scale-marketplace
|
|
4
4
|
* Charts are installed from the public OCI registry
|
|
5
|
+
*
|
|
6
|
+
* Supports Anthropic Marketplace JSON format for dynamic enumeration
|
|
5
7
|
*/
|
|
6
|
-
|
|
8
|
+
import { getMarketplaceServicesFromManifest, getMarketplaceAgentsFromManifest, } from './lib/marketplaceFetcher.js';
|
|
7
9
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
+
* Get all marketplace services, fetching from marketplace.json
|
|
11
|
+
* Returns null if marketplace is unavailable
|
|
10
12
|
*/
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
name: 'phoenix',
|
|
14
|
-
helmReleaseName: 'phoenix',
|
|
15
|
-
description: 'AI/ML observability and evaluation platform with OpenTelemetry integration',
|
|
16
|
-
enabled: true,
|
|
17
|
-
category: 'marketplace',
|
|
18
|
-
namespace: 'phoenix',
|
|
19
|
-
chartPath: `${MARKETPLACE_REGISTRY}/phoenix`,
|
|
20
|
-
installArgs: ['--create-namespace'],
|
|
21
|
-
k8sServiceName: 'phoenix',
|
|
22
|
-
k8sServicePort: 6006,
|
|
23
|
-
k8sDeploymentName: 'phoenix',
|
|
24
|
-
},
|
|
25
|
-
langfuse: {
|
|
26
|
-
name: 'langfuse',
|
|
27
|
-
helmReleaseName: 'langfuse',
|
|
28
|
-
description: 'Open-source LLM observability and analytics platform with session tracking',
|
|
29
|
-
enabled: true,
|
|
30
|
-
category: 'marketplace',
|
|
31
|
-
namespace: 'telemetry',
|
|
32
|
-
chartPath: `${MARKETPLACE_REGISTRY}/langfuse`,
|
|
33
|
-
installArgs: ['--create-namespace'],
|
|
34
|
-
k8sServiceName: 'langfuse',
|
|
35
|
-
k8sServicePort: 3000,
|
|
36
|
-
k8sDeploymentName: 'langfuse-web',
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
export function getMarketplaceService(name) {
|
|
40
|
-
return marketplaceServices[name];
|
|
13
|
+
export async function getAllMarketplaceServices() {
|
|
14
|
+
return await getMarketplaceServicesFromManifest();
|
|
41
15
|
}
|
|
42
|
-
|
|
43
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Get all marketplace agents, fetching from marketplace.json
|
|
18
|
+
* Returns null if marketplace is unavailable
|
|
19
|
+
*/
|
|
20
|
+
export async function getAllMarketplaceAgents() {
|
|
21
|
+
return await getMarketplaceAgentsFromManifest();
|
|
44
22
|
}
|
|
45
|
-
|
|
46
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Get a marketplace item by path (supports both services and agents)
|
|
25
|
+
* Returns null if marketplace is unavailable
|
|
26
|
+
*/
|
|
27
|
+
export async function getMarketplaceItem(path) {
|
|
28
|
+
if (path.startsWith('marketplace/services/')) {
|
|
29
|
+
const name = path.replace(/^marketplace\/services\//, '');
|
|
30
|
+
const services = await getAllMarketplaceServices();
|
|
31
|
+
if (!services) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return services[name];
|
|
35
|
+
}
|
|
36
|
+
if (path.startsWith('marketplace/agents/')) {
|
|
37
|
+
const name = path.replace(/^marketplace\/agents\//, '');
|
|
38
|
+
const agents = await getAllMarketplaceAgents();
|
|
39
|
+
if (!agents) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
return agents[name];
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
47
45
|
}
|
|
48
|
-
export function
|
|
49
|
-
|
|
50
|
-
|
|
46
|
+
export function isMarketplaceService(name) {
|
|
47
|
+
return (name.startsWith('marketplace/services/') ||
|
|
48
|
+
name.startsWith('marketplace/agents/'));
|
|
51
49
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
const mockGetMarketplaceServicesFromManifest = jest.fn();
|
|
3
|
+
const mockGetMarketplaceAgentsFromManifest = jest.fn();
|
|
4
|
+
const mockFetchMarketplaceManifest = jest.fn();
|
|
5
|
+
jest.unstable_mockModule('./lib/marketplaceFetcher.js', () => ({
|
|
6
|
+
getMarketplaceServicesFromManifest: mockGetMarketplaceServicesFromManifest,
|
|
7
|
+
getMarketplaceAgentsFromManifest: mockGetMarketplaceAgentsFromManifest,
|
|
8
|
+
fetchMarketplaceManifest: mockFetchMarketplaceManifest,
|
|
9
|
+
}));
|
|
10
|
+
const { getAllMarketplaceServices, getAllMarketplaceAgents, getMarketplaceItem, } = await import('./marketplaceServices.js');
|
|
11
|
+
describe('marketplaceServices', () => {
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
jest.clearAllMocks();
|
|
14
|
+
mockGetMarketplaceServicesFromManifest.mockClear();
|
|
15
|
+
});
|
|
16
|
+
describe('getAllMarketplaceServices', () => {
|
|
17
|
+
it('returns manifest services when available', async () => {
|
|
18
|
+
const mockServices = {
|
|
19
|
+
'new-service': {
|
|
20
|
+
name: 'new-service',
|
|
21
|
+
helmReleaseName: 'new-service',
|
|
22
|
+
description: 'New service',
|
|
23
|
+
enabled: true,
|
|
24
|
+
category: 'marketplace',
|
|
25
|
+
namespace: 'new-ns',
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
mockGetMarketplaceServicesFromManifest.mockResolvedValue(mockServices);
|
|
29
|
+
const result = await getAllMarketplaceServices();
|
|
30
|
+
expect(result).toEqual(mockServices);
|
|
31
|
+
expect(mockGetMarketplaceServicesFromManifest).toHaveBeenCalled();
|
|
32
|
+
});
|
|
33
|
+
it('returns null when manifest unavailable', async () => {
|
|
34
|
+
mockGetMarketplaceServicesFromManifest.mockResolvedValue(null);
|
|
35
|
+
const result = await getAllMarketplaceServices();
|
|
36
|
+
expect(result).toBeNull();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
describe('getMarketplaceItem', () => {
|
|
40
|
+
it('returns service by path from manifest', async () => {
|
|
41
|
+
const mockServices = {
|
|
42
|
+
'test-service': {
|
|
43
|
+
name: 'test-service',
|
|
44
|
+
helmReleaseName: 'test-service',
|
|
45
|
+
description: 'Test',
|
|
46
|
+
enabled: true,
|
|
47
|
+
category: 'marketplace',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
mockGetMarketplaceServicesFromManifest.mockResolvedValue(mockServices);
|
|
51
|
+
const result = await getMarketplaceItem('marketplace/services/test-service');
|
|
52
|
+
expect(result).toEqual(mockServices['test-service']);
|
|
53
|
+
});
|
|
54
|
+
it('returns undefined for non-existent service', async () => {
|
|
55
|
+
const mockServices = {
|
|
56
|
+
'test-service': {
|
|
57
|
+
name: 'test-service',
|
|
58
|
+
helmReleaseName: 'test-service',
|
|
59
|
+
description: 'Test',
|
|
60
|
+
enabled: true,
|
|
61
|
+
category: 'marketplace',
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
mockGetMarketplaceServicesFromManifest.mockResolvedValue(mockServices);
|
|
65
|
+
const result = await getMarketplaceItem('marketplace/services/non-existent');
|
|
66
|
+
expect(result).toBeUndefined();
|
|
67
|
+
});
|
|
68
|
+
it('returns null when marketplace unavailable', async () => {
|
|
69
|
+
mockGetMarketplaceServicesFromManifest.mockResolvedValue(null);
|
|
70
|
+
const result = await getMarketplaceItem('marketplace/services/phoenix');
|
|
71
|
+
expect(result).toBeNull();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface AnthropicMarketplaceItem {
|
|
2
|
+
name: string;
|
|
3
|
+
displayName?: string;
|
|
4
|
+
description: string;
|
|
5
|
+
type?: 'service' | 'agent';
|
|
6
|
+
version?: string;
|
|
7
|
+
author?: string;
|
|
8
|
+
homepage?: string;
|
|
9
|
+
repository?: string;
|
|
10
|
+
license?: string;
|
|
11
|
+
tags?: string[];
|
|
12
|
+
category?: string;
|
|
13
|
+
icon?: string;
|
|
14
|
+
screenshots?: string[];
|
|
15
|
+
documentation?: string;
|
|
16
|
+
support?: {
|
|
17
|
+
email?: string;
|
|
18
|
+
url?: string;
|
|
19
|
+
};
|
|
20
|
+
metadata?: Record<string, unknown>;
|
|
21
|
+
ark?: {
|
|
22
|
+
chartPath?: string;
|
|
23
|
+
namespace?: string;
|
|
24
|
+
helmReleaseName?: string;
|
|
25
|
+
installArgs?: string[];
|
|
26
|
+
k8sServiceName?: string;
|
|
27
|
+
k8sServicePort?: number;
|
|
28
|
+
k8sPortForwardLocalPort?: number;
|
|
29
|
+
k8sDeploymentName?: string;
|
|
30
|
+
k8sDevDeploymentName?: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export interface AnthropicMarketplaceManifest {
|
|
34
|
+
version: string;
|
|
35
|
+
marketplace: string;
|
|
36
|
+
items: AnthropicMarketplaceItem[];
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/ui/MainMenu.js
CHANGED
|
@@ -155,9 +155,11 @@ const MainMenu = ({ config }) => {
|
|
|
155
155
|
// Import and start ChatUI in the same process
|
|
156
156
|
const { render } = await import('ink');
|
|
157
157
|
const { ArkApiProxy } = await import('../lib/arkApiProxy.js');
|
|
158
|
+
const { loadConfig } = await import('../lib/config.js');
|
|
158
159
|
const ChatUI = (await import('../components/ChatUI.js')).default;
|
|
159
160
|
try {
|
|
160
|
-
const
|
|
161
|
+
const config = loadConfig();
|
|
162
|
+
const proxy = new ArkApiProxy(undefined, config.services?.reusePortForwards ?? false);
|
|
161
163
|
const arkApiClient = await proxy.start();
|
|
162
164
|
// Render ChatUI as a new Ink app
|
|
163
165
|
render(_jsx(ChatUI, { arkApiClient: arkApiClient, arkApiProxy: proxy }));
|
|
@@ -211,7 +213,9 @@ const MainMenu = ({ config }) => {
|
|
|
211
213
|
// Unmount fullscreen app and clear screen.
|
|
212
214
|
await unmountInkApp();
|
|
213
215
|
const { openDashboard } = await import('../commands/dashboard/index.js');
|
|
214
|
-
await
|
|
216
|
+
const { loadConfig } = await import('../lib/config.js');
|
|
217
|
+
const config = loadConfig();
|
|
218
|
+
await openDashboard(config);
|
|
215
219
|
break;
|
|
216
220
|
}
|
|
217
221
|
case 'status': {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agents-at-scale/ark",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.49",
|
|
4
4
|
"description": "Ark CLI - Interactive terminal interface for ARK agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
|
-
"templates"
|
|
12
|
+
"templates",
|
|
13
|
+
".arkrc.template.yaml"
|
|
13
14
|
],
|
|
14
15
|
"scripts": {
|
|
15
16
|
"build": "npm run copy-templates && tsc && chmod +x dist/index.js",
|
|
@@ -48,6 +49,7 @@
|
|
|
48
49
|
"commander": "^12.1.0",
|
|
49
50
|
"debug": "^4.4.1",
|
|
50
51
|
"execa": "^9.6.0",
|
|
52
|
+
"find-process": "^1.4.7",
|
|
51
53
|
"ink": "^6.0.1",
|
|
52
54
|
"ink-select-input": "^6.2.0",
|
|
53
55
|
"ink-spinner": "^5.0.0",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"marketplace": "ARK Marketplace",
|
|
4
|
+
"items": [
|
|
5
|
+
{
|
|
6
|
+
"name": "phoenix",
|
|
7
|
+
"displayName": "Phoenix",
|
|
8
|
+
"description": "AI/ML observability and evaluation platform with OpenTelemetry integration",
|
|
9
|
+
"version": "0.1.5",
|
|
10
|
+
"author": "ARK Marketplace",
|
|
11
|
+
"homepage": "https://github.com/mckinsey/agents-at-scale-marketplace",
|
|
12
|
+
"repository": "https://github.com/mckinsey/agents-at-scale-marketplace",
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"tags": ["observability", "evaluation", "telemetry", "monitoring"],
|
|
15
|
+
"category": "observability",
|
|
16
|
+
"icon": "https://example.com/phoenix-icon.png",
|
|
17
|
+
"documentation": "https://mckinsey.github.io/agents-at-scale-marketplace/services/phoenix/",
|
|
18
|
+
"support": {
|
|
19
|
+
"url": "https://github.com/mckinsey/agents-at-scale-marketplace/issues"
|
|
20
|
+
},
|
|
21
|
+
"ark": {
|
|
22
|
+
"chartPath": "oci://ghcr.io/mckinsey/agents-at-scale-marketplace/charts/phoenix",
|
|
23
|
+
"namespace": "phoenix",
|
|
24
|
+
"helmReleaseName": "phoenix",
|
|
25
|
+
"installArgs": ["--create-namespace"],
|
|
26
|
+
"k8sServiceName": "phoenix",
|
|
27
|
+
"k8sServicePort": 6006,
|
|
28
|
+
"k8sDeploymentName": "phoenix"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "langfuse",
|
|
33
|
+
"displayName": "Langfuse",
|
|
34
|
+
"description": "Open-source LLM observability and analytics platform with session tracking",
|
|
35
|
+
"version": "0.1.4",
|
|
36
|
+
"author": "ARK Marketplace",
|
|
37
|
+
"homepage": "https://github.com/mckinsey/agents-at-scale-marketplace",
|
|
38
|
+
"repository": "https://github.com/mckinsey/agents-at-scale-marketplace",
|
|
39
|
+
"license": "Apache-2.0",
|
|
40
|
+
"tags": ["observability", "analytics", "llm", "tracking"],
|
|
41
|
+
"category": "observability",
|
|
42
|
+
"icon": "https://example.com/langfuse-icon.png",
|
|
43
|
+
"documentation": "https://mckinsey.github.io/agents-at-scale-marketplace/services/langfuse/",
|
|
44
|
+
"support": {
|
|
45
|
+
"url": "https://github.com/mckinsey/agents-at-scale-marketplace/issues"
|
|
46
|
+
},
|
|
47
|
+
"ark": {
|
|
48
|
+
"chartPath": "oci://ghcr.io/mckinsey/agents-at-scale-marketplace/charts/langfuse",
|
|
49
|
+
"namespace": "telemetry",
|
|
50
|
+
"helmReleaseName": "langfuse",
|
|
51
|
+
"installArgs": ["--create-namespace"],
|
|
52
|
+
"k8sServiceName": "langfuse",
|
|
53
|
+
"k8sServicePort": 3000,
|
|
54
|
+
"k8sDeploymentName": "langfuse-web"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
|