@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.
Files changed (49) hide show
  1. package/README.md +2 -0
  2. package/dist/arkServices.js +13 -1
  3. package/dist/arkServices.spec.js +6 -0
  4. package/dist/commands/agents/index.d.ts +1 -1
  5. package/dist/commands/agents/index.js +4 -2
  6. package/dist/commands/completion/index.js +2 -4
  7. package/dist/commands/install/index.js +20 -10
  8. package/dist/commands/marketplace/index.js +51 -23
  9. package/dist/commands/marketplace/index.spec.d.ts +1 -0
  10. package/dist/commands/marketplace/index.spec.js +88 -0
  11. package/dist/commands/models/index.d.ts +1 -1
  12. package/dist/commands/models/index.js +4 -2
  13. package/dist/commands/query/index.d.ts +1 -1
  14. package/dist/commands/query/index.js +4 -2
  15. package/dist/commands/status/index.js +7 -2
  16. package/dist/commands/teams/index.d.ts +1 -1
  17. package/dist/commands/teams/index.js +4 -2
  18. package/dist/commands/uninstall/index.js +20 -10
  19. package/dist/lib/chatClient.d.ts +1 -0
  20. package/dist/lib/chatClient.js +4 -2
  21. package/dist/lib/config.d.ts +14 -0
  22. package/dist/lib/config.js +41 -0
  23. package/dist/lib/config.spec.js +93 -0
  24. package/dist/lib/constants.d.ts +3 -0
  25. package/dist/lib/constants.js +5 -0
  26. package/dist/lib/executeQuery.js +9 -3
  27. package/dist/lib/executeQuery.spec.js +4 -1
  28. package/dist/lib/kubectl.d.ts +1 -0
  29. package/dist/lib/kubectl.js +62 -0
  30. package/dist/lib/marketplaceFetcher.d.ts +6 -0
  31. package/dist/lib/marketplaceFetcher.js +80 -0
  32. package/dist/lib/marketplaceFetcher.spec.d.ts +1 -0
  33. package/dist/lib/marketplaceFetcher.spec.js +225 -0
  34. package/dist/marketplaceServices.d.ts +15 -6
  35. package/dist/marketplaceServices.js +38 -40
  36. package/dist/marketplaceServices.spec.d.ts +1 -0
  37. package/dist/marketplaceServices.spec.js +74 -0
  38. package/dist/types/marketplace.d.ts +37 -0
  39. package/dist/types/marketplace.js +1 -0
  40. package/dist/ui/AgentSelector.d.ts +8 -0
  41. package/dist/ui/AgentSelector.js +53 -0
  42. package/dist/ui/ModelSelector.d.ts +8 -0
  43. package/dist/ui/ModelSelector.js +53 -0
  44. package/dist/ui/TeamSelector.d.ts +8 -0
  45. package/dist/ui/TeamSelector.js +55 -0
  46. package/dist/ui/ToolSelector.d.ts +8 -0
  47. package/dist/ui/ToolSelector.js +53 -0
  48. package/package.json +1 -1
  49. package/templates/marketplace/marketplace.json.example +59 -0
@@ -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
- const MARKETPLACE_REGISTRY = 'oci://ghcr.io/mckinsey/agents-at-scale-marketplace/charts';
8
+ import { getMarketplaceServicesFromManifest, getMarketplaceAgentsFromManifest, } from './lib/marketplaceFetcher.js';
7
9
  /**
8
- * Available marketplace services
9
- * Charts are published to: oci://ghcr.io/mckinsey/agents-at-scale-marketplace/charts
10
+ * Get all marketplace services, fetching from marketplace.json
11
+ * Returns null if marketplace is unavailable
10
12
  */
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];
13
+ export async function getAllMarketplaceServices() {
14
+ return await getMarketplaceServicesFromManifest();
41
15
  }
42
- export function getAllMarketplaceServices() {
43
- return marketplaceServices;
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
- export function isMarketplaceService(name) {
46
- return name.startsWith('marketplace/services/');
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 extractMarketplaceServiceName(path) {
49
- // Extract service name from marketplace/services/phoenix
50
- return path.replace(/^marketplace\/services\//, '');
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 {};
@@ -0,0 +1,8 @@
1
+ import { Agent, ArkApiClient } from '../lib/arkApiClient.js';
2
+ interface AgentSelectorProps {
3
+ arkApiClient: ArkApiClient;
4
+ onSelect: (agent: Agent) => void;
5
+ onExit: () => void;
6
+ }
7
+ export declare function AgentSelector({ arkApiClient, onSelect, onExit, }: AgentSelectorProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import { Box, Text, useInput } from 'ink';
4
+ export function AgentSelector({ arkApiClient, onSelect, onExit, }) {
5
+ const [selectedIndex, setSelectedIndex] = useState(0);
6
+ const [agents, setAgents] = useState([]);
7
+ const [loading, setLoading] = useState(true);
8
+ const [error, setError] = useState(null);
9
+ useEffect(() => {
10
+ arkApiClient
11
+ .getAgents()
12
+ .then((fetchedAgents) => {
13
+ setAgents(fetchedAgents);
14
+ setLoading(false);
15
+ })
16
+ .catch((err) => {
17
+ setError(err.message || 'Failed to fetch agents');
18
+ setLoading(false);
19
+ });
20
+ }, [arkApiClient]);
21
+ useInput((input, key) => {
22
+ if (key.escape) {
23
+ onExit();
24
+ }
25
+ else if (key.upArrow || input === 'k') {
26
+ setSelectedIndex((prev) => (prev === 0 ? agents.length - 1 : prev - 1));
27
+ }
28
+ else if (key.downArrow || input === 'j') {
29
+ setSelectedIndex((prev) => (prev === agents.length - 1 ? 0 : prev + 1));
30
+ }
31
+ else if (key.return) {
32
+ onSelect(agents[selectedIndex]);
33
+ }
34
+ else {
35
+ // Handle number keys for quick selection
36
+ const num = parseInt(input, 10);
37
+ if (!isNaN(num) && num >= 1 && num <= agents.length) {
38
+ onSelect(agents[num - 1]);
39
+ }
40
+ }
41
+ });
42
+ if (loading) {
43
+ return (_jsx(Box, { children: _jsx(Text, { children: "Loading agents..." }) }));
44
+ }
45
+ if (error) {
46
+ return (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) }));
47
+ }
48
+ if (agents.length === 0) {
49
+ return (_jsx(Box, { children: _jsx(Text, { children: "No agents available" }) }));
50
+ }
51
+ const selectedAgent = agents[selectedIndex];
52
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Select Agent" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose an agent to start a conversation with" }) }), _jsx(Box, { flexDirection: "column", children: agents.map((agent, index) => (_jsx(Box, { marginBottom: 0, children: _jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", agent.name] }) }, agent.name))) }), selectedAgent.description && (_jsx(Box, { marginTop: 1, paddingLeft: 2, children: _jsx(Text, { dimColor: true, wrap: "wrap", children: selectedAgent.description }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter to confirm \u00B7 Number to select \u00B7 Esc to exit" }) })] }));
53
+ }
@@ -0,0 +1,8 @@
1
+ import { Model, ArkApiClient } from '../lib/arkApiClient.js';
2
+ interface ModelSelectorProps {
3
+ arkApiClient: ArkApiClient;
4
+ onSelect: (model: Model) => void;
5
+ onExit: () => void;
6
+ }
7
+ export declare function ModelSelector({ arkApiClient, onSelect, onExit, }: ModelSelectorProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import { Box, Text, useInput } from 'ink';
4
+ export function ModelSelector({ arkApiClient, onSelect, onExit, }) {
5
+ const [selectedIndex, setSelectedIndex] = useState(0);
6
+ const [models, setModels] = useState([]);
7
+ const [loading, setLoading] = useState(true);
8
+ const [error, setError] = useState(null);
9
+ useEffect(() => {
10
+ arkApiClient
11
+ .getModels()
12
+ .then((fetchedModels) => {
13
+ setModels(fetchedModels);
14
+ setLoading(false);
15
+ })
16
+ .catch((err) => {
17
+ setError(err.message || 'Failed to fetch models');
18
+ setLoading(false);
19
+ });
20
+ }, [arkApiClient]);
21
+ useInput((input, key) => {
22
+ if (key.escape) {
23
+ onExit();
24
+ }
25
+ else if (key.upArrow || input === 'k') {
26
+ setSelectedIndex((prev) => (prev === 0 ? models.length - 1 : prev - 1));
27
+ }
28
+ else if (key.downArrow || input === 'j') {
29
+ setSelectedIndex((prev) => (prev === models.length - 1 ? 0 : prev + 1));
30
+ }
31
+ else if (key.return) {
32
+ onSelect(models[selectedIndex]);
33
+ }
34
+ else {
35
+ // Handle number keys for quick selection
36
+ const num = parseInt(input, 10);
37
+ if (!isNaN(num) && num >= 1 && num <= models.length) {
38
+ onSelect(models[num - 1]);
39
+ }
40
+ }
41
+ });
42
+ if (loading) {
43
+ return (_jsx(Box, { children: _jsx(Text, { children: "Loading models..." }) }));
44
+ }
45
+ if (error) {
46
+ return (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) }));
47
+ }
48
+ if (models.length === 0) {
49
+ return (_jsx(Box, { children: _jsx(Text, { children: "No models available" }) }));
50
+ }
51
+ const selectedModel = models[selectedIndex];
52
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Select Model" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose a model to start a conversation with" }) }), _jsx(Box, { flexDirection: "column", children: models.map((model, index) => (_jsx(Box, { marginBottom: 0, children: _jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", model.name, model.type ? ` (${model.type})` : ''] }) }, model.name))) }), selectedModel && selectedModel.model && (_jsx(Box, { marginTop: 1, paddingLeft: 2, children: _jsxs(Text, { dimColor: true, wrap: "wrap", children: ["Model: ", selectedModel.model] }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter to confirm \u00B7 Number to select \u00B7 Esc to exit" }) })] }));
53
+ }
@@ -0,0 +1,8 @@
1
+ import { Team, ArkApiClient } from '../lib/arkApiClient.js';
2
+ interface TeamSelectorProps {
3
+ arkApiClient: ArkApiClient;
4
+ onSelect: (team: Team) => void;
5
+ onExit: () => void;
6
+ }
7
+ export declare function TeamSelector({ arkApiClient, onSelect, onExit, }: TeamSelectorProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,55 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import { Box, Text, useInput } from 'ink';
4
+ export function TeamSelector({ arkApiClient, onSelect, onExit, }) {
5
+ const [selectedIndex, setSelectedIndex] = useState(0);
6
+ const [teams, setTeams] = useState([]);
7
+ const [loading, setLoading] = useState(true);
8
+ const [error, setError] = useState(null);
9
+ useEffect(() => {
10
+ arkApiClient
11
+ .getTeams()
12
+ .then((fetchedTeams) => {
13
+ setTeams(fetchedTeams);
14
+ setLoading(false);
15
+ })
16
+ .catch((err) => {
17
+ setError(err.message || 'Failed to fetch teams');
18
+ setLoading(false);
19
+ });
20
+ }, [arkApiClient]);
21
+ useInput((input, key) => {
22
+ if (key.escape) {
23
+ onExit();
24
+ }
25
+ else if (key.upArrow || input === 'k') {
26
+ setSelectedIndex((prev) => (prev === 0 ? teams.length - 1 : prev - 1));
27
+ }
28
+ else if (key.downArrow || input === 'j') {
29
+ setSelectedIndex((prev) => (prev === teams.length - 1 ? 0 : prev + 1));
30
+ }
31
+ else if (key.return) {
32
+ onSelect(teams[selectedIndex]);
33
+ }
34
+ else {
35
+ // Handle number keys for quick selection
36
+ const num = parseInt(input, 10);
37
+ if (!isNaN(num) && num >= 1 && num <= teams.length) {
38
+ onSelect(teams[num - 1]);
39
+ }
40
+ }
41
+ });
42
+ if (loading) {
43
+ return (_jsx(Box, { children: _jsx(Text, { children: "Loading teams..." }) }));
44
+ }
45
+ if (error) {
46
+ return (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) }));
47
+ }
48
+ if (teams.length === 0) {
49
+ return (_jsx(Box, { children: _jsx(Text, { children: "No teams available" }) }));
50
+ }
51
+ const selectedTeam = teams[selectedIndex];
52
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Select Team" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose a team to start a conversation with" }) }), _jsx(Box, { flexDirection: "column", children: teams.map((team, index) => (_jsx(Box, { marginBottom: 0, children: _jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", team.name, team.strategy ? ` (${team.strategy})` : ''] }) }, team.name))) }), selectedTeam &&
53
+ (selectedTeam.description || selectedTeam.members_count) && (_jsx(Box, { marginTop: 1, paddingLeft: 2, children: _jsx(Text, { dimColor: true, wrap: "wrap", children: selectedTeam.description ||
54
+ `Members: ${selectedTeam.members_count}` }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter to confirm \u00B7 Number to select \u00B7 Esc to exit" }) })] }));
55
+ }
@@ -0,0 +1,8 @@
1
+ import { Tool, ArkApiClient } from '../lib/arkApiClient.js';
2
+ interface ToolSelectorProps {
3
+ arkApiClient: ArkApiClient;
4
+ onSelect: (tool: Tool) => void;
5
+ onExit: () => void;
6
+ }
7
+ export declare function ToolSelector({ arkApiClient, onSelect, onExit, }: ToolSelectorProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState, useEffect } from 'react';
3
+ import { Box, Text, useInput } from 'ink';
4
+ export function ToolSelector({ arkApiClient, onSelect, onExit, }) {
5
+ const [selectedIndex, setSelectedIndex] = useState(0);
6
+ const [tools, setTools] = useState([]);
7
+ const [loading, setLoading] = useState(true);
8
+ const [error, setError] = useState(null);
9
+ useEffect(() => {
10
+ arkApiClient
11
+ .getTools()
12
+ .then((fetchedTools) => {
13
+ setTools(fetchedTools);
14
+ setLoading(false);
15
+ })
16
+ .catch((err) => {
17
+ setError(err.message || 'Failed to fetch tools');
18
+ setLoading(false);
19
+ });
20
+ }, [arkApiClient]);
21
+ useInput((input, key) => {
22
+ if (key.escape) {
23
+ onExit();
24
+ }
25
+ else if (key.upArrow || input === 'k') {
26
+ setSelectedIndex((prev) => (prev === 0 ? tools.length - 1 : prev - 1));
27
+ }
28
+ else if (key.downArrow || input === 'j') {
29
+ setSelectedIndex((prev) => (prev === tools.length - 1 ? 0 : prev + 1));
30
+ }
31
+ else if (key.return) {
32
+ onSelect(tools[selectedIndex]);
33
+ }
34
+ else {
35
+ // Handle number keys for quick selection
36
+ const num = parseInt(input, 10);
37
+ if (!isNaN(num) && num >= 1 && num <= tools.length) {
38
+ onSelect(tools[num - 1]);
39
+ }
40
+ }
41
+ });
42
+ if (loading) {
43
+ return (_jsx(Box, { children: _jsx(Text, { children: "Loading tools..." }) }));
44
+ }
45
+ if (error) {
46
+ return (_jsx(Box, { children: _jsxs(Text, { color: "red", children: ["Error: ", error] }) }));
47
+ }
48
+ if (tools.length === 0) {
49
+ return (_jsx(Box, { children: _jsx(Text, { children: "No tools available" }) }));
50
+ }
51
+ const selectedTool = tools[selectedIndex];
52
+ return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, children: [_jsx(Box, { marginBottom: 1, children: _jsx(Text, { bold: true, children: "Select Tool" }) }), _jsx(Box, { marginBottom: 1, children: _jsx(Text, { dimColor: true, children: "Choose a tool to start a conversation with" }) }), _jsx(Box, { flexDirection: "column", children: tools.map((tool, index) => (_jsx(Box, { marginBottom: 0, children: _jsxs(Text, { color: index === selectedIndex ? 'green' : undefined, children: [index === selectedIndex ? '❯ ' : ' ', index + 1, ". ", tool.name] }) }, tool.name))) }), selectedTool && selectedTool.description && (_jsx(Box, { marginTop: 1, paddingLeft: 2, children: _jsx(Text, { dimColor: true, wrap: "wrap", children: selectedTool.description }) })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { dimColor: true, children: "Enter to confirm \u00B7 Number to select \u00B7 Esc to exit" }) })] }));
53
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agents-at-scale/ark",
3
- "version": "0.1.45",
3
+ "version": "0.1.47",
4
4
  "description": "Ark CLI - Interactive terminal interface for ARK agents",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -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
+