@agents-at-scale/ark 0.1.45 → 0.1.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/arkServices.js +13 -1
- 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/completion/index.js +2 -4
- 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/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 +4 -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/lib/chatClient.d.ts +1 -0
- package/dist/lib/chatClient.js +4 -2
- package/dist/lib/config.d.ts +14 -0
- package/dist/lib/config.js +41 -0
- package/dist/lib/config.spec.js +93 -0
- package/dist/lib/constants.d.ts +3 -0
- package/dist/lib/constants.js +5 -0
- package/dist/lib/executeQuery.js +9 -3
- package/dist/lib/executeQuery.spec.js +4 -1
- package/dist/lib/kubectl.d.ts +1 -0
- package/dist/lib/kubectl.js +62 -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/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/AgentSelector.d.ts +8 -0
- package/dist/ui/AgentSelector.js +53 -0
- package/dist/ui/ModelSelector.d.ts +8 -0
- package/dist/ui/ModelSelector.js +53 -0
- package/dist/ui/TeamSelector.d.ts +8 -0
- package/dist/ui/TeamSelector.js +55 -0
- package/dist/ui/ToolSelector.d.ts +8 -0
- package/dist/ui/ToolSelector.js +53 -0
- package/package.json +1 -1
- package/templates/marketplace/marketplace.json.example +59 -0
package/README.md
CHANGED
package/dist/arkServices.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Centralized ARK service definitions used by both install and status commands
|
|
3
3
|
*/
|
|
4
|
-
import { loadConfig } from './lib/config.js';
|
|
4
|
+
import { loadConfig, getMarketplaceRegistry } from './lib/config.js';
|
|
5
5
|
const REGISTRY_BASE = 'oci://ghcr.io/mckinsey/agents-at-scale-ark/charts';
|
|
6
6
|
/**
|
|
7
7
|
* Dependencies that should be installed before ARK services
|
|
@@ -153,6 +153,18 @@ const defaultArkServices = {
|
|
|
153
153
|
chartPath: `${REGISTRY_BASE}/localhost-gateway`,
|
|
154
154
|
installArgs: [],
|
|
155
155
|
},
|
|
156
|
+
'noah': {
|
|
157
|
+
name: 'noah',
|
|
158
|
+
helmReleaseName: 'noah',
|
|
159
|
+
description: 'Runtime administration agent with cluster privileges',
|
|
160
|
+
enabled: true,
|
|
161
|
+
category: 'service',
|
|
162
|
+
chartPath: `${getMarketplaceRegistry()}/noah`,
|
|
163
|
+
installArgs: [],
|
|
164
|
+
k8sServiceName: 'noah-mcp',
|
|
165
|
+
k8sServicePort: 8639,
|
|
166
|
+
k8sDeploymentName: 'noah-mcp',
|
|
167
|
+
},
|
|
156
168
|
};
|
|
157
169
|
function applyConfigOverrides(defaults) {
|
|
158
170
|
const config = loadConfig();
|
package/dist/arkServices.spec.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { jest } from '@jest/globals';
|
|
2
2
|
const mockLoadConfig = jest.fn();
|
|
3
|
+
const mockGetMarketplaceRegistry = jest.fn();
|
|
3
4
|
jest.unstable_mockModule('./lib/config.js', () => ({
|
|
4
5
|
loadConfig: mockLoadConfig,
|
|
6
|
+
getMarketplaceRegistry: mockGetMarketplaceRegistry,
|
|
5
7
|
}));
|
|
8
|
+
mockLoadConfig.mockReturnValue({});
|
|
9
|
+
mockGetMarketplaceRegistry.mockReturnValue('oci://test-registry/charts');
|
|
6
10
|
const { arkDependencies, arkServices: originalArkServices, getInstallableServices, } = await import('./arkServices.js');
|
|
7
11
|
describe('arkServices', () => {
|
|
8
12
|
beforeEach(() => {
|
|
9
13
|
jest.clearAllMocks();
|
|
14
|
+
mockLoadConfig.mockReturnValue({});
|
|
15
|
+
mockGetMarketplaceRegistry.mockReturnValue('oci://test-registry/charts');
|
|
10
16
|
});
|
|
11
17
|
it('exports arkDependencies with expected structure', () => {
|
|
12
18
|
expect(arkDependencies).toBeDefined();
|
|
@@ -30,7 +30,7 @@ async function listAgents(options) {
|
|
|
30
30
|
process.exit(1);
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
export function createAgentsCommand(
|
|
33
|
+
export function createAgentsCommand(config) {
|
|
34
34
|
const agentsCommand = new Command('agents');
|
|
35
35
|
agentsCommand
|
|
36
36
|
.description('list available agents')
|
|
@@ -54,11 +54,13 @@ export function createAgentsCommand(_) {
|
|
|
54
54
|
.description('Query an agent')
|
|
55
55
|
.argument('<name>', 'Agent name')
|
|
56
56
|
.argument('<message>', 'Message to send')
|
|
57
|
-
.
|
|
57
|
+
.option('--timeout <timeout>', 'Query timeout (e.g., 30s, 5m, 1h)')
|
|
58
|
+
.action(async (name, message, options) => {
|
|
58
59
|
await executeQuery({
|
|
59
60
|
targetType: 'agent',
|
|
60
61
|
targetName: name,
|
|
61
62
|
message,
|
|
63
|
+
timeout: options.timeout || config.queryTimeout,
|
|
62
64
|
});
|
|
63
65
|
});
|
|
64
66
|
return agentsCommand;
|
|
@@ -85,14 +85,12 @@ _ark_completion() {
|
|
|
85
85
|
return 0
|
|
86
86
|
;;
|
|
87
87
|
install)
|
|
88
|
-
|
|
89
|
-
opts="marketplace/services/phoenix marketplace/services/langfuse"
|
|
88
|
+
opts="marketplace/services/phoenix marketplace/services/langfuse marketplace/agents/noah"
|
|
90
89
|
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
91
90
|
return 0
|
|
92
91
|
;;
|
|
93
92
|
uninstall)
|
|
94
|
-
|
|
95
|
-
opts="marketplace/services/phoenix marketplace/services/langfuse"
|
|
93
|
+
opts="marketplace/services/phoenix marketplace/services/langfuse marketplace/agents/noah"
|
|
96
94
|
COMPREPLY=( $(compgen -W "\${opts}" -- \${cur}) )
|
|
97
95
|
return 0
|
|
98
96
|
;;
|
|
@@ -5,7 +5,7 @@ import inquirer from 'inquirer';
|
|
|
5
5
|
import { showNoClusterError } from '../../lib/startup.js';
|
|
6
6
|
import output from '../../lib/output.js';
|
|
7
7
|
import { getInstallableServices, arkDependencies, arkServices, } from '../../arkServices.js';
|
|
8
|
-
import { isMarketplaceService,
|
|
8
|
+
import { isMarketplaceService, getMarketplaceItem, getAllMarketplaceServices, getAllMarketplaceAgents, } from '../../marketplaceServices.js';
|
|
9
9
|
import { printNextSteps } from '../../lib/nextSteps.js';
|
|
10
10
|
import ora from 'ora';
|
|
11
11
|
import { waitForServicesReady, } from '../../lib/waitForReady.js';
|
|
@@ -42,20 +42,30 @@ export async function installArk(config, serviceName, options = {}) {
|
|
|
42
42
|
console.log(); // Add blank line after cluster info
|
|
43
43
|
// If a specific service is requested, install only that service
|
|
44
44
|
if (serviceName) {
|
|
45
|
-
// Check if it's a marketplace
|
|
45
|
+
// Check if it's a marketplace item
|
|
46
46
|
if (isMarketplaceService(serviceName)) {
|
|
47
|
-
const
|
|
48
|
-
const service = getMarketplaceService(marketplaceServiceName);
|
|
47
|
+
const service = await getMarketplaceItem(serviceName);
|
|
49
48
|
if (!service) {
|
|
50
|
-
output.error(`marketplace
|
|
51
|
-
output.info('available marketplace
|
|
52
|
-
const marketplaceServices = getAllMarketplaceServices();
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
output.error(`marketplace item '${serviceName}' not found`);
|
|
50
|
+
output.info('available marketplace items:');
|
|
51
|
+
const marketplaceServices = await getAllMarketplaceServices();
|
|
52
|
+
if (marketplaceServices) {
|
|
53
|
+
for (const name of Object.keys(marketplaceServices)) {
|
|
54
|
+
output.info(` marketplace/services/${name}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const marketplaceAgents = await getAllMarketplaceAgents();
|
|
58
|
+
if (marketplaceAgents) {
|
|
59
|
+
for (const name of Object.keys(marketplaceAgents)) {
|
|
60
|
+
output.info(` marketplace/agents/${name}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!marketplaceServices && !marketplaceAgents) {
|
|
64
|
+
output.warning('Marketplace unavailable');
|
|
55
65
|
}
|
|
56
66
|
process.exit(1);
|
|
57
67
|
}
|
|
58
|
-
output.info(`installing marketplace
|
|
68
|
+
output.info(`installing marketplace item ${service.name}...`);
|
|
59
69
|
try {
|
|
60
70
|
await installService(service, options.verbose);
|
|
61
71
|
output.success(`${service.name} installed successfully`);
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import {
|
|
3
|
+
import { getMarketplaceRepoUrl, getMarketplaceRegistry, } from '../../lib/config.js';
|
|
4
|
+
import { getAllMarketplaceServices, getAllMarketplaceAgents, } from '../../marketplaceServices.js';
|
|
5
|
+
import { fetchMarketplaceManifest } from '../../lib/marketplaceFetcher.js';
|
|
4
6
|
function createMarketplaceCommand(_config) {
|
|
7
|
+
const repoUrl = getMarketplaceRepoUrl();
|
|
8
|
+
const registry = getMarketplaceRegistry();
|
|
5
9
|
const marketplace = new Command('marketplace');
|
|
6
10
|
marketplace
|
|
7
11
|
.description('Manage marketplace services')
|
|
@@ -9,39 +13,63 @@ function createMarketplaceCommand(_config) {
|
|
|
9
13
|
${chalk.blue('🏪 ARK Marketplace')}
|
|
10
14
|
Install community-contributed services from the ARK Marketplace.
|
|
11
15
|
|
|
12
|
-
Repository: ${chalk.cyan(
|
|
13
|
-
Registry: ${chalk.cyan(
|
|
16
|
+
Repository: ${chalk.cyan(repoUrl)}
|
|
17
|
+
Registry: ${chalk.cyan(registry.replace('oci://', ''))}
|
|
14
18
|
`)
|
|
15
19
|
.addHelpText('after', `
|
|
16
20
|
${chalk.cyan('Examples:')}
|
|
17
|
-
${chalk.yellow('ark marketplace list')} # List available services
|
|
18
|
-
${chalk.yellow('ark install marketplace/services/phoenix')} # Install Phoenix
|
|
21
|
+
${chalk.yellow('ark marketplace list')} # List available services and agents
|
|
22
|
+
${chalk.yellow('ark install marketplace/services/phoenix')} # Install Phoenix service
|
|
23
|
+
${chalk.yellow('ark install marketplace/agents/noah')} # Install Noah agent
|
|
19
24
|
${chalk.yellow('ark uninstall marketplace/services/phoenix')} # Uninstall Phoenix
|
|
20
|
-
|
|
21
|
-
${chalk.cyan('Available Services:')}
|
|
22
|
-
• phoenix - AI/ML observability and evaluation platform
|
|
23
|
-
• langfuse - Open-source LLM observability and analytics
|
|
24
25
|
`);
|
|
25
26
|
// List command
|
|
26
27
|
const list = new Command('list');
|
|
27
28
|
list
|
|
28
29
|
.alias('ls')
|
|
29
|
-
.description('List available marketplace services')
|
|
30
|
-
.action(() => {
|
|
31
|
-
const services = getAllMarketplaceServices();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
console.log(
|
|
39
|
-
|
|
40
|
-
console.log(` ${chalk.dim(namespaceInfo)}`);
|
|
30
|
+
.description('List available marketplace services and agents')
|
|
31
|
+
.action(async () => {
|
|
32
|
+
const services = await getAllMarketplaceServices();
|
|
33
|
+
const agents = await getAllMarketplaceAgents();
|
|
34
|
+
const manifest = await fetchMarketplaceManifest();
|
|
35
|
+
console.log(chalk.blue('\n🏪 ARK Marketplace\n'));
|
|
36
|
+
if (!manifest) {
|
|
37
|
+
console.log(chalk.yellow('⚠️ Marketplace unavailable\n'));
|
|
38
|
+
console.log(chalk.gray('Could not fetch marketplace.json from repository.\n'));
|
|
39
|
+
console.log(chalk.cyan(`Repository: ${repoUrl}`));
|
|
40
|
+
console.log(chalk.cyan(`Registry: ${registry}`));
|
|
41
41
|
console.log();
|
|
42
|
+
return;
|
|
42
43
|
}
|
|
43
|
-
console.log(chalk.
|
|
44
|
-
|
|
44
|
+
console.log(chalk.dim(`Using marketplace.json (version: ${manifest.version})\n`));
|
|
45
|
+
if (services && Object.keys(services).length > 0) {
|
|
46
|
+
console.log(chalk.bold('Services:'));
|
|
47
|
+
console.log(chalk.gray('Install with: ark install marketplace/services/<name>\n'));
|
|
48
|
+
for (const [key, service] of Object.entries(services)) {
|
|
49
|
+
const icon = '📦';
|
|
50
|
+
const serviceName = `marketplace/services/${key.padEnd(12)}`;
|
|
51
|
+
const serviceDesc = service.description;
|
|
52
|
+
console.log(`${icon} ${chalk.green(serviceName)} ${chalk.gray(serviceDesc)}`);
|
|
53
|
+
const namespaceInfo = `namespace: ${service.namespace || 'default'}`;
|
|
54
|
+
console.log(` ${chalk.dim(namespaceInfo)}`);
|
|
55
|
+
console.log();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (agents && Object.keys(agents).length > 0) {
|
|
59
|
+
console.log(chalk.bold('Agents:'));
|
|
60
|
+
console.log(chalk.gray('Install with: ark install marketplace/agents/<name>\n'));
|
|
61
|
+
for (const [key, agent] of Object.entries(agents)) {
|
|
62
|
+
const icon = '🤖';
|
|
63
|
+
const agentName = `marketplace/agents/${key.padEnd(12)}`;
|
|
64
|
+
const agentDesc = agent.description;
|
|
65
|
+
console.log(`${icon} ${chalk.green(agentName)} ${chalk.gray(agentDesc)}`);
|
|
66
|
+
const namespaceInfo = `namespace: ${agent.namespace || 'default'}`;
|
|
67
|
+
console.log(` ${chalk.dim(namespaceInfo)}`);
|
|
68
|
+
console.log();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
console.log(chalk.cyan(`Repository: ${repoUrl}`));
|
|
72
|
+
console.log(chalk.cyan(`Registry: ${registry}`));
|
|
45
73
|
console.log();
|
|
46
74
|
});
|
|
47
75
|
marketplace.addCommand(list);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
const mockGetAllMarketplaceServices = jest.fn();
|
|
4
|
+
const mockGetAllMarketplaceAgents = jest.fn();
|
|
5
|
+
const mockFetchMarketplaceManifest = jest.fn();
|
|
6
|
+
const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation(() => { });
|
|
7
|
+
jest.unstable_mockModule('../../marketplaceServices.js', () => ({
|
|
8
|
+
getAllMarketplaceServices: mockGetAllMarketplaceServices,
|
|
9
|
+
getAllMarketplaceAgents: mockGetAllMarketplaceAgents,
|
|
10
|
+
}));
|
|
11
|
+
jest.unstable_mockModule('../../lib/marketplaceFetcher.js', () => ({
|
|
12
|
+
fetchMarketplaceManifest: mockFetchMarketplaceManifest,
|
|
13
|
+
}));
|
|
14
|
+
const { createMarketplaceCommand } = await import('./index.js');
|
|
15
|
+
describe('marketplace command', () => {
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
jest.clearAllMocks();
|
|
18
|
+
});
|
|
19
|
+
it('creates marketplace command with correct structure', () => {
|
|
20
|
+
const command = createMarketplaceCommand({});
|
|
21
|
+
expect(command).toBeInstanceOf(Command);
|
|
22
|
+
expect(command.name()).toBe('marketplace');
|
|
23
|
+
});
|
|
24
|
+
it('lists services and agents from manifest', async () => {
|
|
25
|
+
const mockServices = {
|
|
26
|
+
'test-service': {
|
|
27
|
+
name: 'test-service',
|
|
28
|
+
helmReleaseName: 'test-service',
|
|
29
|
+
description: 'Test service description',
|
|
30
|
+
enabled: true,
|
|
31
|
+
category: 'marketplace',
|
|
32
|
+
namespace: 'test-ns',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
const mockAgents = {
|
|
36
|
+
'test-agent': {
|
|
37
|
+
name: 'test-agent',
|
|
38
|
+
helmReleaseName: 'test-agent',
|
|
39
|
+
description: 'Test agent description',
|
|
40
|
+
enabled: true,
|
|
41
|
+
category: 'marketplace',
|
|
42
|
+
namespace: 'test-ns',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const mockManifest = {
|
|
46
|
+
version: '1.0.0',
|
|
47
|
+
marketplace: 'ARK Marketplace',
|
|
48
|
+
items: [
|
|
49
|
+
{
|
|
50
|
+
name: 'test-service',
|
|
51
|
+
description: 'Test service',
|
|
52
|
+
type: 'service',
|
|
53
|
+
ark: {
|
|
54
|
+
chartPath: 'oci://registry/test-service',
|
|
55
|
+
namespace: 'test',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'test-agent',
|
|
60
|
+
description: 'Test agent',
|
|
61
|
+
type: 'agent',
|
|
62
|
+
ark: {
|
|
63
|
+
chartPath: 'oci://registry/test-agent',
|
|
64
|
+
namespace: 'test',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
mockGetAllMarketplaceServices.mockResolvedValue(mockServices);
|
|
70
|
+
mockGetAllMarketplaceAgents.mockResolvedValue(mockAgents);
|
|
71
|
+
mockFetchMarketplaceManifest.mockResolvedValue(mockManifest);
|
|
72
|
+
const command = createMarketplaceCommand({});
|
|
73
|
+
await command.parseAsync(['node', 'test', 'list']);
|
|
74
|
+
expect(mockGetAllMarketplaceServices).toHaveBeenCalled();
|
|
75
|
+
expect(mockGetAllMarketplaceAgents).toHaveBeenCalled();
|
|
76
|
+
expect(mockConsoleLog).toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
it('shows unavailable message when marketplace unavailable', async () => {
|
|
79
|
+
mockGetAllMarketplaceServices.mockResolvedValue(null);
|
|
80
|
+
mockGetAllMarketplaceAgents.mockResolvedValue(null);
|
|
81
|
+
mockFetchMarketplaceManifest.mockResolvedValue(null);
|
|
82
|
+
const command = createMarketplaceCommand({});
|
|
83
|
+
await command.parseAsync(['node', 'test', 'list']);
|
|
84
|
+
expect(mockConsoleLog).toHaveBeenCalled();
|
|
85
|
+
const logCalls = mockConsoleLog.mock.calls.map((c) => c[0]).join(' ');
|
|
86
|
+
expect(logCalls).toContain('unavailable');
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -31,7 +31,7 @@ async function listModels(options) {
|
|
|
31
31
|
process.exit(1);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
export function createModelsCommand(
|
|
34
|
+
export function createModelsCommand(config) {
|
|
35
35
|
const modelsCommand = new Command('models');
|
|
36
36
|
modelsCommand
|
|
37
37
|
.description('List available models')
|
|
@@ -69,11 +69,13 @@ export function createModelsCommand(_) {
|
|
|
69
69
|
.description('Query a model')
|
|
70
70
|
.argument('<name>', 'Model name (e.g., default)')
|
|
71
71
|
.argument('<message>', 'Message to send')
|
|
72
|
-
.
|
|
72
|
+
.option('--timeout <timeout>', 'Query timeout (e.g., 30s, 5m, 1h)')
|
|
73
|
+
.action(async (name, message, options) => {
|
|
73
74
|
await executeQuery({
|
|
74
75
|
targetType: 'model',
|
|
75
76
|
targetName: name,
|
|
76
77
|
message,
|
|
78
|
+
timeout: options.timeout || config.queryTimeout,
|
|
77
79
|
});
|
|
78
80
|
});
|
|
79
81
|
modelsCommand.addCommand(queryCommand);
|
|
@@ -2,13 +2,14 @@ import { Command } from 'commander';
|
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { executeQuery, parseTarget } from '../../lib/executeQuery.js';
|
|
4
4
|
import { ExitCodes } from '../../lib/errors.js';
|
|
5
|
-
export function createQueryCommand(
|
|
5
|
+
export function createQueryCommand(config) {
|
|
6
6
|
const queryCommand = new Command('query');
|
|
7
7
|
queryCommand
|
|
8
8
|
.description('Execute a single query against a model or agent')
|
|
9
9
|
.argument('<target>', 'Query target (e.g., model/default, agent/my-agent)')
|
|
10
10
|
.argument('<message>', 'Message to send')
|
|
11
|
-
.option('-o, --output <format>', 'Output format: yaml, json, or
|
|
11
|
+
.option('-o, --output <format>', 'Output format: yaml, json, name or events (shows structured event data)')
|
|
12
|
+
.option('--timeout <timeout>', 'Query timeout (e.g., 30s, 5m, 1h)')
|
|
12
13
|
.option('--session-id <sessionId>', 'Session ID to associate with the query for conversation continuity')
|
|
13
14
|
.action(async (target, message, options) => {
|
|
14
15
|
const parsed = parseTarget(target);
|
|
@@ -21,6 +22,7 @@ export function createQueryCommand(_) {
|
|
|
21
22
|
targetName: parsed.name,
|
|
22
23
|
message,
|
|
23
24
|
outputFormat: options.output,
|
|
25
|
+
timeout: options.timeout || config.queryTimeout,
|
|
24
26
|
sessionId: options.sessionId,
|
|
25
27
|
});
|
|
26
28
|
});
|
|
@@ -327,7 +327,12 @@ export function createStatusCommand() {
|
|
|
327
327
|
statusCommand
|
|
328
328
|
.description('Check ARK system status')
|
|
329
329
|
.argument('[services...]', 'specific services to check (optional)')
|
|
330
|
-
.option('--wait-for-ready
|
|
331
|
-
.action((services, options) =>
|
|
330
|
+
.option('--wait-for-ready [timeout]', 'wait for services to be ready, e.g, 30s, 2m, 1h (default: 30m)')
|
|
331
|
+
.action((services, options) => {
|
|
332
|
+
if (options.waitForReady === true) {
|
|
333
|
+
options.waitForReady = '30m';
|
|
334
|
+
}
|
|
335
|
+
checkStatus(services, options);
|
|
336
|
+
});
|
|
332
337
|
return statusCommand;
|
|
333
338
|
}
|
|
@@ -29,7 +29,7 @@ async function listTeams(options) {
|
|
|
29
29
|
process.exit(1);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
export function createTeamsCommand(
|
|
32
|
+
export function createTeamsCommand(config) {
|
|
33
33
|
const teamsCommand = new Command('teams');
|
|
34
34
|
teamsCommand
|
|
35
35
|
.description('List available teams')
|
|
@@ -52,11 +52,13 @@ export function createTeamsCommand(_) {
|
|
|
52
52
|
.description('Query a team')
|
|
53
53
|
.argument('<name>', 'Team name')
|
|
54
54
|
.argument('<message>', 'Message to send')
|
|
55
|
-
.
|
|
55
|
+
.option('--timeout <timeout>', 'Query timeout (e.g., 30s, 5m, 1h)')
|
|
56
|
+
.action(async (name, message, options) => {
|
|
56
57
|
await executeQuery({
|
|
57
58
|
targetType: 'team',
|
|
58
59
|
targetName: name,
|
|
59
60
|
message,
|
|
61
|
+
timeout: options.timeout || config.queryTimeout,
|
|
60
62
|
});
|
|
61
63
|
});
|
|
62
64
|
teamsCommand.addCommand(queryCommand);
|
|
@@ -5,7 +5,7 @@ import inquirer from 'inquirer';
|
|
|
5
5
|
import { showNoClusterError } from '../../lib/startup.js';
|
|
6
6
|
import output from '../../lib/output.js';
|
|
7
7
|
import { getInstallableServices } from '../../arkServices.js';
|
|
8
|
-
import { isMarketplaceService,
|
|
8
|
+
import { isMarketplaceService, getMarketplaceItem, getAllMarketplaceServices, getAllMarketplaceAgents, } from '../../marketplaceServices.js';
|
|
9
9
|
async function uninstallService(service, verbose = false) {
|
|
10
10
|
const helmArgs = ['uninstall', service.helmReleaseName, '--ignore-not-found'];
|
|
11
11
|
// Only add namespace flag if service has explicit namespace
|
|
@@ -26,20 +26,30 @@ async function uninstallArk(config, serviceName, options = {}) {
|
|
|
26
26
|
console.log(); // Add blank line after cluster info
|
|
27
27
|
// If a specific service is requested, uninstall only that service
|
|
28
28
|
if (serviceName) {
|
|
29
|
-
// Check if it's a marketplace
|
|
29
|
+
// Check if it's a marketplace item
|
|
30
30
|
if (isMarketplaceService(serviceName)) {
|
|
31
|
-
const
|
|
32
|
-
const service = getMarketplaceService(marketplaceServiceName);
|
|
31
|
+
const service = await getMarketplaceItem(serviceName);
|
|
33
32
|
if (!service) {
|
|
34
|
-
output.error(`marketplace
|
|
35
|
-
output.info('available marketplace
|
|
36
|
-
const marketplaceServices = getAllMarketplaceServices();
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
output.error(`marketplace item '${serviceName}' not found`);
|
|
34
|
+
output.info('available marketplace items:');
|
|
35
|
+
const marketplaceServices = await getAllMarketplaceServices();
|
|
36
|
+
if (marketplaceServices) {
|
|
37
|
+
for (const name of Object.keys(marketplaceServices)) {
|
|
38
|
+
output.info(` marketplace/services/${name}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const marketplaceAgents = await getAllMarketplaceAgents();
|
|
42
|
+
if (marketplaceAgents) {
|
|
43
|
+
for (const name of Object.keys(marketplaceAgents)) {
|
|
44
|
+
output.info(` marketplace/agents/${name}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!marketplaceServices && !marketplaceAgents) {
|
|
48
|
+
output.warning('Marketplace unavailable');
|
|
39
49
|
}
|
|
40
50
|
process.exit(1);
|
|
41
51
|
}
|
|
42
|
-
output.info(`uninstalling marketplace
|
|
52
|
+
output.info(`uninstalling marketplace item ${service.name}...`);
|
|
43
53
|
try {
|
|
44
54
|
await uninstallService(service, options.verbose);
|
|
45
55
|
output.success(`${service.name} uninstalled successfully`);
|
package/dist/lib/chatClient.d.ts
CHANGED
package/dist/lib/chatClient.js
CHANGED
|
@@ -17,12 +17,14 @@ export class ChatClient {
|
|
|
17
17
|
signal: signal,
|
|
18
18
|
};
|
|
19
19
|
// Build metadata object - only add if we have something to include
|
|
20
|
-
if (config.sessionId || config.a2aContextId) {
|
|
20
|
+
if (config.sessionId || config.a2aContextId || config.queryTimeout) {
|
|
21
21
|
params.metadata = {};
|
|
22
|
-
// Add sessionId directly to metadata (goes to spec, not annotations)
|
|
23
22
|
if (config.sessionId) {
|
|
24
23
|
params.metadata.sessionId = config.sessionId;
|
|
25
24
|
}
|
|
25
|
+
if (config.queryTimeout) {
|
|
26
|
+
params.metadata.timeout = config.queryTimeout;
|
|
27
|
+
}
|
|
26
28
|
// Add A2A context ID to queryAnnotations (goes to annotations)
|
|
27
29
|
if (config.a2aContextId) {
|
|
28
30
|
const queryAnnotations = {
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -4,11 +4,17 @@ export interface ChatConfig {
|
|
|
4
4
|
streaming?: boolean;
|
|
5
5
|
outputFormat?: 'text' | 'markdown';
|
|
6
6
|
}
|
|
7
|
+
export interface MarketplaceConfig {
|
|
8
|
+
repoUrl?: string;
|
|
9
|
+
registry?: string;
|
|
10
|
+
}
|
|
7
11
|
export interface ArkConfig {
|
|
8
12
|
chat?: ChatConfig;
|
|
13
|
+
marketplace?: MarketplaceConfig;
|
|
9
14
|
services?: {
|
|
10
15
|
[serviceName: string]: Partial<ArkService>;
|
|
11
16
|
};
|
|
17
|
+
queryTimeout?: string;
|
|
12
18
|
clusterInfo?: ClusterInfo;
|
|
13
19
|
}
|
|
14
20
|
/**
|
|
@@ -30,3 +36,11 @@ export declare function getConfigPaths(): {
|
|
|
30
36
|
* Format config as YAML for display
|
|
31
37
|
*/
|
|
32
38
|
export declare function formatConfig(config: ArkConfig): string;
|
|
39
|
+
/**
|
|
40
|
+
* Get marketplace repository URL from config
|
|
41
|
+
*/
|
|
42
|
+
export declare function getMarketplaceRepoUrl(): string;
|
|
43
|
+
/**
|
|
44
|
+
* Get marketplace registry from config
|
|
45
|
+
*/
|
|
46
|
+
export declare function getMarketplaceRegistry(): string;
|
package/dist/lib/config.js
CHANGED
|
@@ -16,6 +16,10 @@ export function loadConfig() {
|
|
|
16
16
|
streaming: true,
|
|
17
17
|
outputFormat: 'text',
|
|
18
18
|
},
|
|
19
|
+
marketplace: {
|
|
20
|
+
repoUrl: 'https://github.com/mckinsey/agents-at-scale-marketplace',
|
|
21
|
+
registry: 'oci://ghcr.io/mckinsey/agents-at-scale-marketplace/charts',
|
|
22
|
+
},
|
|
19
23
|
};
|
|
20
24
|
// Load user config from home directory
|
|
21
25
|
const userConfigPath = path.join(os.homedir(), '.arkrc.yaml');
|
|
@@ -55,6 +59,17 @@ export function loadConfig() {
|
|
|
55
59
|
config.chat.outputFormat = format;
|
|
56
60
|
}
|
|
57
61
|
}
|
|
62
|
+
if (process.env.ARK_QUERY_TIMEOUT !== undefined) {
|
|
63
|
+
config.queryTimeout = process.env.ARK_QUERY_TIMEOUT;
|
|
64
|
+
}
|
|
65
|
+
if (process.env.ARK_MARKETPLACE_REPO_URL !== undefined) {
|
|
66
|
+
config.marketplace = config.marketplace || {};
|
|
67
|
+
config.marketplace.repoUrl = process.env.ARK_MARKETPLACE_REPO_URL;
|
|
68
|
+
}
|
|
69
|
+
if (process.env.ARK_MARKETPLACE_REGISTRY !== undefined) {
|
|
70
|
+
config.marketplace = config.marketplace || {};
|
|
71
|
+
config.marketplace.registry = process.env.ARK_MARKETPLACE_REGISTRY;
|
|
72
|
+
}
|
|
58
73
|
return config;
|
|
59
74
|
}
|
|
60
75
|
/**
|
|
@@ -70,6 +85,15 @@ function mergeConfig(target, source) {
|
|
|
70
85
|
target.chat.outputFormat = source.chat.outputFormat;
|
|
71
86
|
}
|
|
72
87
|
}
|
|
88
|
+
if (source.marketplace) {
|
|
89
|
+
target.marketplace = target.marketplace || {};
|
|
90
|
+
if (source.marketplace.repoUrl !== undefined) {
|
|
91
|
+
target.marketplace.repoUrl = source.marketplace.repoUrl;
|
|
92
|
+
}
|
|
93
|
+
if (source.marketplace.registry !== undefined) {
|
|
94
|
+
target.marketplace.registry = source.marketplace.registry;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
73
97
|
if (source.services) {
|
|
74
98
|
target.services = target.services || {};
|
|
75
99
|
for (const [serviceName, overrides] of Object.entries(source.services)) {
|
|
@@ -79,6 +103,9 @@ function mergeConfig(target, source) {
|
|
|
79
103
|
};
|
|
80
104
|
}
|
|
81
105
|
}
|
|
106
|
+
if (source.queryTimeout !== undefined) {
|
|
107
|
+
target.queryTimeout = source.queryTimeout;
|
|
108
|
+
}
|
|
82
109
|
}
|
|
83
110
|
/**
|
|
84
111
|
* Get the paths checked for config files
|
|
@@ -95,3 +122,17 @@ export function getConfigPaths() {
|
|
|
95
122
|
export function formatConfig(config) {
|
|
96
123
|
return yaml.stringify(config);
|
|
97
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Get marketplace repository URL from config
|
|
127
|
+
*/
|
|
128
|
+
export function getMarketplaceRepoUrl() {
|
|
129
|
+
const config = loadConfig();
|
|
130
|
+
return config.marketplace.repoUrl;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Get marketplace registry from config
|
|
134
|
+
*/
|
|
135
|
+
export function getMarketplaceRegistry() {
|
|
136
|
+
const config = loadConfig();
|
|
137
|
+
return config.marketplace.registry;
|
|
138
|
+
}
|