@agents-at-scale/ark 0.1.42 → 0.1.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.
Files changed (36) hide show
  1. package/dist/arkServices.js +0 -9
  2. package/dist/commands/completion/index.js +38 -3
  3. package/dist/commands/evaluation/index.spec.js +1 -6
  4. package/dist/commands/generate/generators/team.js +4 -1
  5. package/dist/commands/install/index.js +27 -0
  6. package/dist/commands/marketplace/index.d.ts +4 -0
  7. package/dist/commands/marketplace/index.js +50 -0
  8. package/dist/commands/models/create.js +1 -1
  9. package/dist/commands/models/create.spec.js +6 -2
  10. package/dist/commands/models/providers/azure.spec.js +3 -1
  11. package/dist/commands/queries/delete.d.ts +7 -0
  12. package/dist/commands/queries/delete.js +24 -0
  13. package/dist/commands/queries/delete.spec.d.ts +1 -0
  14. package/dist/commands/queries/delete.spec.js +74 -0
  15. package/dist/commands/queries/index.js +42 -4
  16. package/dist/commands/queries/list.d.ts +6 -0
  17. package/dist/commands/queries/list.js +66 -0
  18. package/dist/commands/queries/list.spec.d.ts +1 -0
  19. package/dist/commands/queries/list.spec.js +170 -0
  20. package/dist/commands/queries/validation.d.ts +2 -0
  21. package/dist/commands/queries/validation.js +10 -0
  22. package/dist/commands/queries/validation.spec.d.ts +1 -0
  23. package/dist/commands/queries/validation.spec.js +27 -0
  24. package/dist/commands/uninstall/index.js +27 -0
  25. package/dist/components/ChatUI.js +2 -2
  26. package/dist/index.js +2 -0
  27. package/dist/lib/arkApiClient.js +2 -0
  28. package/dist/lib/executeQuery.d.ts +0 -4
  29. package/dist/lib/executeQuery.js +98 -104
  30. package/dist/lib/executeQuery.spec.js +176 -99
  31. package/dist/lib/kubectl.d.ts +7 -0
  32. package/dist/lib/kubectl.js +27 -0
  33. package/dist/lib/kubectl.spec.js +89 -1
  34. package/dist/marketplaceServices.d.ts +15 -0
  35. package/dist/marketplaceServices.js +51 -0
  36. package/package.json +1 -1
@@ -10,17 +10,26 @@ const mockSpinner = {
10
10
  warn: jest.fn(),
11
11
  stop: jest.fn(),
12
12
  text: '',
13
+ isSpinning: false,
13
14
  };
14
15
  const mockOra = jest.fn(() => mockSpinner);
15
16
  jest.unstable_mockModule('ora', () => ({
16
17
  default: mockOra,
17
18
  }));
18
- const mockOutput = {
19
- warning: jest.fn(),
20
- error: jest.fn(),
19
+ let mockSendMessage = jest.fn();
20
+ const mockChatClient = jest.fn(() => ({
21
+ sendMessage: mockSendMessage,
22
+ }));
23
+ let mockArkApiProxyInstance = {
24
+ start: jest.fn(),
25
+ stop: jest.fn(),
21
26
  };
22
- jest.unstable_mockModule('./output.js', () => ({
23
- default: mockOutput,
27
+ const mockArkApiProxy = jest.fn(() => mockArkApiProxyInstance);
28
+ jest.unstable_mockModule('./arkApiProxy.js', () => ({
29
+ ArkApiProxy: mockArkApiProxy,
30
+ }));
31
+ jest.unstable_mockModule('./chatClient.js', () => ({
32
+ ChatClient: mockChatClient,
24
33
  }));
25
34
  const mockExit = jest.spyOn(process, 'exit').mockImplementation((() => {
26
35
  throw new Error('process.exit called');
@@ -29,12 +38,25 @@ const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { });
29
38
  const mockConsoleError = jest
30
39
  .spyOn(console, 'error')
31
40
  .mockImplementation(() => { });
41
+ const mockStdoutWrite = jest
42
+ .spyOn(process.stdout, 'write')
43
+ .mockImplementation(() => true);
32
44
  const { executeQuery, parseTarget } = await import('./executeQuery.js');
33
45
  const { ExitCodes } = await import('./errors.js');
34
46
  describe('executeQuery', () => {
35
47
  beforeEach(() => {
36
48
  jest.clearAllMocks();
37
49
  mockSpinner.start.mockReturnValue(mockSpinner);
50
+ mockSpinner.isSpinning = false;
51
+ mockSendMessage = jest.fn();
52
+ mockChatClient.mockReturnValue({ sendMessage: mockSendMessage });
53
+ const startMock = jest.fn();
54
+ startMock.mockResolvedValue({});
55
+ mockArkApiProxyInstance = {
56
+ start: startMock,
57
+ stop: jest.fn(),
58
+ };
59
+ mockArkApiProxy.mockReturnValue(mockArkApiProxyInstance);
38
60
  });
39
61
  describe('parseTarget', () => {
40
62
  it('should parse valid target strings', () => {
@@ -57,24 +79,107 @@ describe('executeQuery', () => {
57
79
  expect(parseTarget('model/default/extra')).toBeNull();
58
80
  });
59
81
  });
60
- describe('executeQuery', () => {
61
- it('should create and apply a query manifest', async () => {
62
- const mockQueryResponse = {
63
- status: {
64
- phase: 'done',
65
- responses: [{ content: 'Test response' }],
66
- },
67
- };
82
+ describe('executeQuery with streaming', () => {
83
+ it('should execute query with streaming and display chunks', async () => {
84
+ mockSendMessage.mockImplementation(async (targetId, messages, options, callback) => {
85
+ callback('Hello', undefined, { agent: 'test-agent' });
86
+ callback(' world', undefined, { agent: 'test-agent' });
87
+ });
88
+ await executeQuery({
89
+ targetType: 'model',
90
+ targetName: 'default',
91
+ message: 'Hello',
92
+ });
93
+ expect(mockArkApiProxy).toHaveBeenCalled();
94
+ expect(mockArkApiProxyInstance.start).toHaveBeenCalled();
95
+ expect(mockChatClient).toHaveBeenCalled();
96
+ expect(mockSendMessage).toHaveBeenCalledWith('model/default', [{ role: 'user', content: 'Hello' }], { streamingEnabled: true }, expect.any(Function));
97
+ expect(mockSpinner.stop).toHaveBeenCalled();
98
+ expect(mockArkApiProxyInstance.stop).toHaveBeenCalled();
99
+ expect(mockStdoutWrite).toHaveBeenCalled();
100
+ });
101
+ it('should display agent names with correct formatting', async () => {
102
+ mockSendMessage.mockImplementation(async (targetId, messages, options, callback) => {
103
+ callback('Response 1', undefined, { agent: 'agent-1' });
104
+ callback('Response 2', undefined, { agent: 'agent-2' });
105
+ });
106
+ await executeQuery({
107
+ targetType: 'agent',
108
+ targetName: 'test-agent',
109
+ message: 'Hello',
110
+ });
111
+ expect(mockStdoutWrite).toHaveBeenCalled();
112
+ const calls = mockStdoutWrite.mock.calls.map((call) => String(call[0]));
113
+ expect(calls.some((call) => call.includes('agent-1'))).toBe(true);
114
+ expect(calls.some((call) => call.includes('agent-2'))).toBe(true);
115
+ });
116
+ it('should display team names with diamond prefix', async () => {
117
+ mockSendMessage.mockImplementation(async (targetId, messages, options, callback) => {
118
+ callback('Team response', undefined, { team: 'my-team' });
119
+ });
120
+ await executeQuery({
121
+ targetType: 'team',
122
+ targetName: 'my-team',
123
+ message: 'Hello',
124
+ });
125
+ const calls = mockStdoutWrite.mock.calls.map((call) => String(call[0]));
126
+ expect(calls.some((call) => call.includes('◆'))).toBe(true);
127
+ expect(calls.some((call) => call.includes('my-team'))).toBe(true);
128
+ });
129
+ it('should display tool calls', async () => {
130
+ mockSendMessage.mockImplementation(async (targetId, messages, options, callback) => {
131
+ callback('', [{ id: 1, function: { name: 'get_weather' } }], {
132
+ agent: 'weather-agent',
133
+ });
134
+ callback('The weather is sunny', undefined, {
135
+ agent: 'weather-agent',
136
+ });
137
+ });
138
+ await executeQuery({
139
+ targetType: 'agent',
140
+ targetName: 'weather-agent',
141
+ message: 'What is the weather?',
142
+ });
143
+ const calls = mockStdoutWrite.mock.calls.map((call) => String(call[0]));
144
+ expect(calls.some((call) => call.includes('get_weather'))).toBe(true);
145
+ expect(calls.some((call) => call.includes('The weather is sunny'))).toBe(true);
146
+ });
147
+ it('should handle errors and exit with CliError', async () => {
148
+ mockSpinner.isSpinning = true;
149
+ const startMock = jest.fn();
150
+ startMock.mockRejectedValue(new Error('Connection failed'));
151
+ mockArkApiProxyInstance.start = startMock;
152
+ await expect(executeQuery({
153
+ targetType: 'model',
154
+ targetName: 'default',
155
+ message: 'Hello',
156
+ })).rejects.toThrow('process.exit called');
157
+ expect(mockSpinner.stop).toHaveBeenCalled();
158
+ expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('Connection failed'));
159
+ expect(mockExit).toHaveBeenCalledWith(ExitCodes.CliError);
160
+ expect(mockArkApiProxyInstance.stop).toHaveBeenCalled();
161
+ });
162
+ it('should stop spinner when first output arrives', async () => {
163
+ mockSpinner.isSpinning = true;
164
+ mockSendMessage.mockImplementation(async (targetId, messages, options, callback) => {
165
+ callback('First chunk', undefined, { agent: 'test-agent' });
166
+ });
167
+ await executeQuery({
168
+ targetType: 'model',
169
+ targetName: 'default',
170
+ message: 'Hello',
171
+ });
172
+ expect(mockSpinner.stop).toHaveBeenCalled();
173
+ });
174
+ });
175
+ describe('executeQuery with output format', () => {
176
+ it('should create query and output name format', async () => {
68
177
  mockExeca.mockImplementation(async (command, args) => {
69
178
  if (args.includes('apply')) {
70
179
  return { stdout: '', stderr: '', exitCode: 0 };
71
180
  }
72
- if (args.includes('get') && args.includes('queries')) {
73
- return {
74
- stdout: JSON.stringify(mockQueryResponse),
75
- stderr: '',
76
- exitCode: 0,
77
- };
181
+ if (args.includes('wait')) {
182
+ return { stdout: '', stderr: '', exitCode: 0 };
78
183
  }
79
184
  return { stdout: '', stderr: '', exitCode: 0 };
80
185
  });
@@ -82,83 +187,67 @@ describe('executeQuery', () => {
82
187
  targetType: 'model',
83
188
  targetName: 'default',
84
189
  message: 'Hello',
190
+ outputFormat: 'name',
85
191
  });
86
- expect(mockSpinner.start).toHaveBeenCalled();
87
- expect(mockSpinner.stop).toHaveBeenCalled();
88
- expect(mockConsoleLog).toHaveBeenCalledWith('Test response');
192
+ expect(mockExeca).toHaveBeenCalledWith('kubectl', expect.arrayContaining(['apply', '-f', '-']), expect.any(Object));
193
+ expect(mockExeca).toHaveBeenCalledWith('kubectl', expect.arrayContaining(['wait', '--for=condition=Completed']), expect.any(Object));
194
+ expect(mockConsoleLog).toHaveBeenCalledWith(expect.stringMatching(/cli-query-\d+/));
89
195
  });
90
- it('should handle query error phase and exit with code 2', async () => {
91
- const mockQueryResponse = {
92
- status: {
93
- phase: 'error',
94
- responses: [{ content: 'Query failed with test error' }],
95
- },
196
+ it('should output json format', async () => {
197
+ const mockQuery = {
198
+ apiVersion: 'ark.mckinsey.com/v1alpha1',
199
+ kind: 'Query',
200
+ metadata: { name: 'test-query' },
96
201
  };
97
202
  mockExeca.mockImplementation(async (command, args) => {
98
203
  if (args.includes('apply')) {
99
204
  return { stdout: '', stderr: '', exitCode: 0 };
100
205
  }
101
- if (args.includes('get') && args.includes('queries')) {
102
- return {
103
- stdout: JSON.stringify(mockQueryResponse),
104
- stderr: '',
105
- exitCode: 0,
106
- };
206
+ if (args.includes('wait')) {
207
+ return { stdout: '', stderr: '', exitCode: 0 };
208
+ }
209
+ if (args.includes('get') && args.includes('-o')) {
210
+ return { stdout: JSON.stringify(mockQuery), stderr: '', exitCode: 0 };
107
211
  }
108
212
  return { stdout: '', stderr: '', exitCode: 0 };
109
213
  });
110
- try {
111
- await executeQuery({
112
- targetType: 'model',
113
- targetName: 'default',
114
- message: 'Hello',
115
- });
116
- }
117
- catch (error) {
118
- expect(error.message).toBe('process.exit called');
119
- }
120
- expect(mockSpinner.stop).toHaveBeenCalled();
121
- expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('Query failed with test error'));
122
- expect(mockExit).toHaveBeenCalledWith(ExitCodes.OperationError);
214
+ await executeQuery({
215
+ targetType: 'model',
216
+ targetName: 'default',
217
+ message: 'Hello',
218
+ outputFormat: 'json',
219
+ });
220
+ expect(mockConsoleLog).toHaveBeenCalledWith(JSON.stringify(mockQuery));
123
221
  });
124
- it('should handle query canceled phase and exit with code 2', async () => {
125
- const mockQueryResponse = {
126
- status: {
127
- phase: 'canceled',
128
- message: 'Query was canceled',
129
- },
130
- };
222
+ it('should output yaml format', async () => {
223
+ const mockYaml = 'apiVersion: ark.mckinsey.com/v1alpha1\nkind: Query';
131
224
  mockExeca.mockImplementation(async (command, args) => {
132
225
  if (args.includes('apply')) {
133
226
  return { stdout: '', stderr: '', exitCode: 0 };
134
227
  }
135
- if (args.includes('get') && args.includes('queries')) {
136
- return {
137
- stdout: JSON.stringify(mockQueryResponse),
138
- stderr: '',
139
- exitCode: 0,
140
- };
228
+ if (args.includes('wait')) {
229
+ return { stdout: '', stderr: '', exitCode: 0 };
230
+ }
231
+ if (args.includes('get') && args.includes('yaml')) {
232
+ return { stdout: mockYaml, stderr: '', exitCode: 0 };
141
233
  }
142
234
  return { stdout: '', stderr: '', exitCode: 0 };
143
235
  });
144
- try {
145
- await executeQuery({
146
- targetType: 'agent',
147
- targetName: 'test-agent',
148
- message: 'Hello',
149
- });
150
- }
151
- catch (error) {
152
- expect(error.message).toBe('process.exit called');
153
- }
154
- expect(mockSpinner.warn).toHaveBeenCalledWith('Query canceled');
155
- expect(mockOutput.warning).toHaveBeenCalledWith('Query was canceled');
156
- expect(mockExit).toHaveBeenCalledWith(ExitCodes.OperationError);
236
+ await executeQuery({
237
+ targetType: 'model',
238
+ targetName: 'default',
239
+ message: 'Hello',
240
+ outputFormat: 'yaml',
241
+ });
242
+ expect(mockConsoleLog).toHaveBeenCalledWith(mockYaml);
157
243
  });
158
- it('should handle kubectl apply failures with exit code 1', async () => {
244
+ it('should reject invalid output format', async () => {
159
245
  mockExeca.mockImplementation(async (command, args) => {
160
246
  if (args.includes('apply')) {
161
- throw new Error('Failed to apply');
247
+ return { stdout: '', stderr: '', exitCode: 0 };
248
+ }
249
+ if (args.includes('wait')) {
250
+ return { stdout: '', stderr: '', exitCode: 0 };
162
251
  }
163
252
  return { stdout: '', stderr: '', exitCode: 0 };
164
253
  });
@@ -166,38 +255,26 @@ describe('executeQuery', () => {
166
255
  targetType: 'model',
167
256
  targetName: 'default',
168
257
  message: 'Hello',
258
+ outputFormat: 'invalid',
169
259
  })).rejects.toThrow('process.exit called');
170
- expect(mockSpinner.stop).toHaveBeenCalled();
171
- expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('Failed to apply'));
260
+ expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('Invalid output format'));
172
261
  expect(mockExit).toHaveBeenCalledWith(ExitCodes.CliError);
173
262
  });
174
- it('should handle query timeout and exit with code 3', async () => {
263
+ it('should handle kubectl errors', async () => {
175
264
  mockExeca.mockImplementation(async (command, args) => {
176
265
  if (args.includes('apply')) {
177
- return { stdout: '', stderr: '', exitCode: 0 };
178
- }
179
- if (args.includes('wait')) {
180
- // Simulate kubectl wait timeout
181
- const error = new Error('timed out waiting for the condition');
182
- throw error;
266
+ throw new Error('kubectl apply failed');
183
267
  }
184
268
  return { stdout: '', stderr: '', exitCode: 0 };
185
269
  });
186
- try {
187
- await executeQuery({
188
- targetType: 'model',
189
- targetName: 'default',
190
- message: 'Hello',
191
- timeout: '100ms',
192
- watchTimeout: '200ms',
193
- });
194
- }
195
- catch (error) {
196
- expect(error.message).toBe('process.exit called');
197
- }
198
- expect(mockSpinner.stop).toHaveBeenCalled();
199
- expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('Query did not complete within 200ms'));
200
- expect(mockExit).toHaveBeenCalledWith(ExitCodes.Timeout);
270
+ await expect(executeQuery({
271
+ targetType: 'model',
272
+ targetName: 'default',
273
+ message: 'Hello',
274
+ outputFormat: 'name',
275
+ })).rejects.toThrow('process.exit called');
276
+ expect(mockConsoleError).toHaveBeenCalledWith(expect.stringContaining('kubectl apply failed'));
277
+ expect(mockExit).toHaveBeenCalledWith(ExitCodes.CliError);
201
278
  });
202
279
  });
203
280
  });
@@ -5,4 +5,11 @@ interface K8sResource {
5
5
  };
6
6
  }
7
7
  export declare function getResource<T extends K8sResource>(resourceType: string, name: string): Promise<T>;
8
+ export declare function listResources<T extends K8sResource>(resourceType: string, options?: {
9
+ sortBy?: string;
10
+ }): Promise<T[]>;
11
+ export declare function deleteResource(resourceType: string, name?: string, options?: {
12
+ all?: boolean;
13
+ }): Promise<void>;
14
+ export declare function replaceResource<T extends K8sResource>(resource: T): Promise<T>;
8
15
  export {};
@@ -18,3 +18,30 @@ export async function getResource(resourceType, name) {
18
18
  const result = await execa('kubectl', ['get', resourceType, name, '-o', 'json'], { stdio: 'pipe' });
19
19
  return JSON.parse(result.stdout);
20
20
  }
21
+ export async function listResources(resourceType, options) {
22
+ const args = ['get', resourceType];
23
+ if (options?.sortBy) {
24
+ args.push(`--sort-by=${options.sortBy}`);
25
+ }
26
+ args.push('-o', 'json');
27
+ const result = await execa('kubectl', args, { stdio: 'pipe' });
28
+ const data = JSON.parse(result.stdout);
29
+ return data.items || [];
30
+ }
31
+ export async function deleteResource(resourceType, name, options) {
32
+ const args = ['delete', resourceType];
33
+ if (options?.all) {
34
+ args.push('--all');
35
+ }
36
+ else if (name) {
37
+ args.push(name);
38
+ }
39
+ await execa('kubectl', args, { stdio: 'pipe' });
40
+ }
41
+ export async function replaceResource(resource) {
42
+ const result = await execa('kubectl', ['replace', '-f', '-', '-o', 'json'], {
43
+ input: JSON.stringify(resource),
44
+ stdio: ['pipe', 'pipe', 'pipe'],
45
+ });
46
+ return JSON.parse(result.stdout);
47
+ }
@@ -3,7 +3,7 @@ const mockExeca = jest.fn();
3
3
  jest.unstable_mockModule('execa', () => ({
4
4
  execa: mockExeca,
5
5
  }));
6
- const { getResource } = await import('./kubectl.js');
6
+ const { getResource, listResources, deleteResource } = await import('./kubectl.js');
7
7
  describe('kubectl', () => {
8
8
  beforeEach(() => {
9
9
  jest.clearAllMocks();
@@ -85,4 +85,92 @@ describe('kubectl', () => {
85
85
  expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'agents', 'test-agent', '-o', 'json'], { stdio: 'pipe' });
86
86
  });
87
87
  });
88
+ describe('listResources', () => {
89
+ it('should list all resources of a given type', async () => {
90
+ const mockResources = [
91
+ {
92
+ metadata: {
93
+ name: 'query-1',
94
+ creationTimestamp: '2024-01-01T00:00:00Z',
95
+ },
96
+ spec: {
97
+ value: 'test1',
98
+ },
99
+ },
100
+ {
101
+ metadata: {
102
+ name: 'query-2',
103
+ creationTimestamp: '2024-01-02T00:00:00Z',
104
+ },
105
+ spec: {
106
+ value: 'test2',
107
+ },
108
+ },
109
+ ];
110
+ mockExeca.mockResolvedValue({
111
+ stdout: JSON.stringify({ items: mockResources }),
112
+ });
113
+ const result = await listResources('queries');
114
+ expect(result).toEqual(mockResources);
115
+ expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', '-o', 'json'], { stdio: 'pipe' });
116
+ });
117
+ it('should return an empty array when no resources exist', async () => {
118
+ mockExeca.mockResolvedValue({
119
+ stdout: JSON.stringify({ items: [] }),
120
+ });
121
+ const result = await listResources('queries');
122
+ expect(result).toEqual([]);
123
+ expect(mockExeca).toHaveBeenCalledWith('kubectl', ['get', 'queries', '-o', 'json'], { stdio: 'pipe' });
124
+ });
125
+ it('should list resources with custom sort option', async () => {
126
+ const mockResources = [
127
+ {
128
+ metadata: {
129
+ name: 'query-1',
130
+ creationTimestamp: '2024-01-01T00:00:00Z',
131
+ },
132
+ },
133
+ {
134
+ metadata: {
135
+ name: 'query-2',
136
+ creationTimestamp: '2024-01-02T00:00:00Z',
137
+ },
138
+ },
139
+ ];
140
+ mockExeca.mockResolvedValue({
141
+ stdout: JSON.stringify({ items: mockResources }),
142
+ });
143
+ const result = await listResources('queries', {
144
+ sortBy: '.metadata.creationTimestamp',
145
+ });
146
+ expect(result).toEqual(mockResources);
147
+ expect(mockExeca).toHaveBeenCalledWith('kubectl', [
148
+ 'get',
149
+ 'queries',
150
+ '--sort-by=.metadata.creationTimestamp',
151
+ '-o',
152
+ 'json',
153
+ ], { stdio: 'pipe' });
154
+ });
155
+ it('should handle kubectl errors when listing resources', async () => {
156
+ mockExeca.mockRejectedValue(new Error('kubectl connection error'));
157
+ await expect(listResources('queries')).rejects.toThrow('kubectl connection error');
158
+ });
159
+ });
160
+ describe('deleteResource', () => {
161
+ it('should delete a resource by name', async () => {
162
+ mockExeca.mockResolvedValue({
163
+ stdout: '',
164
+ });
165
+ await deleteResource('queries', 'test-query');
166
+ expect(mockExeca).toHaveBeenCalledWith('kubectl', ['delete', 'queries', 'test-query'], { stdio: 'pipe' });
167
+ });
168
+ it('should delete all resources of a type when all option is true', async () => {
169
+ mockExeca.mockResolvedValue({
170
+ stdout: '',
171
+ });
172
+ await deleteResource('queries', undefined, { all: true });
173
+ expect(mockExeca).toHaveBeenCalledWith('kubectl', ['delete', 'queries', '--all'], { stdio: 'pipe' });
174
+ });
175
+ });
88
176
  });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Marketplace service definitions for external ARK marketplace resources
3
+ * Repository: https://github.com/mckinsey/agents-at-scale-marketplace
4
+ * Charts are installed from the public OCI registry
5
+ */
6
+ import type { ArkService, ServiceCollection } from './types/arkService.js';
7
+ /**
8
+ * Available marketplace services
9
+ * Charts are published to: oci://ghcr.io/mckinsey/agents-at-scale-marketplace/charts
10
+ */
11
+ export declare const marketplaceServices: ServiceCollection;
12
+ export declare function getMarketplaceService(name: string): ArkService | undefined;
13
+ export declare function getAllMarketplaceServices(): ServiceCollection;
14
+ export declare function isMarketplaceService(name: string): boolean;
15
+ export declare function extractMarketplaceServiceName(path: string): string;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Marketplace service definitions for external ARK marketplace resources
3
+ * Repository: https://github.com/mckinsey/agents-at-scale-marketplace
4
+ * Charts are installed from the public OCI registry
5
+ */
6
+ const MARKETPLACE_REGISTRY = 'oci://ghcr.io/mckinsey/agents-at-scale-marketplace/charts';
7
+ /**
8
+ * Available marketplace services
9
+ * Charts are published to: oci://ghcr.io/mckinsey/agents-at-scale-marketplace/charts
10
+ */
11
+ export const marketplaceServices = {
12
+ phoenix: {
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];
41
+ }
42
+ export function getAllMarketplaceServices() {
43
+ return marketplaceServices;
44
+ }
45
+ export function isMarketplaceService(name) {
46
+ return name.startsWith('marketplace/services/');
47
+ }
48
+ export function extractMarketplaceServiceName(path) {
49
+ // Extract service name from marketplace/services/phoenix
50
+ return path.replace(/^marketplace\/services\//, '');
51
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-at-scale/ark",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "description": "Ark CLI - Interactive terminal interface for ARK agents",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",