@agents-at-scale/ark 0.1.36 → 0.1.38
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 +53 -70
- package/dist/arkServices.d.ts +3 -27
- package/dist/arkServices.js +31 -3
- package/dist/arkServices.spec.js +118 -10
- package/dist/commands/chat/index.js +1 -2
- package/dist/commands/completion/index.js +0 -2
- package/dist/commands/generate/generators/project.js +33 -26
- package/dist/commands/generate/index.js +2 -2
- package/dist/commands/generate/templateDiscovery.js +13 -4
- package/dist/commands/install/index.js +49 -58
- package/dist/commands/models/create.d.ts +9 -1
- package/dist/commands/models/create.js +97 -90
- package/dist/commands/models/create.spec.js +9 -37
- package/dist/commands/models/index.js +8 -2
- package/dist/commands/models/index.spec.js +1 -1
- package/dist/commands/status/index.d.ts +3 -1
- package/dist/commands/status/index.js +54 -2
- package/dist/components/AsyncOperation.d.ts +54 -0
- package/dist/components/AsyncOperation.js +110 -0
- package/dist/components/ChatUI.js +39 -72
- package/dist/components/SelectMenu.d.ts +17 -0
- package/dist/components/SelectMenu.js +21 -0
- package/dist/components/StatusMessage.d.ts +20 -0
- package/dist/components/StatusMessage.js +13 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/arkApiClient.d.ts +1 -2
- package/dist/lib/arkApiClient.js +5 -6
- package/dist/lib/config.d.ts +4 -0
- package/dist/lib/config.js +9 -0
- package/dist/lib/nextSteps.js +1 -1
- package/dist/lib/nextSteps.spec.js +1 -1
- package/dist/lib/security.js +4 -0
- package/dist/lib/startup.js +6 -2
- package/dist/lib/startup.spec.js +1 -1
- package/dist/lib/timeout.d.ts +1 -0
- package/dist/lib/timeout.js +20 -0
- package/dist/lib/timeout.spec.d.ts +1 -0
- package/dist/lib/timeout.spec.js +14 -0
- package/dist/lib/waitForReady.d.ts +8 -0
- package/dist/lib/waitForReady.js +32 -0
- package/dist/lib/waitForReady.spec.d.ts +1 -0
- package/dist/lib/waitForReady.spec.js +104 -0
- package/dist/types/arkService.d.ts +27 -0
- package/dist/types/arkService.js +1 -0
- package/dist/ui/asyncOperations/connectingToArk.d.ts +15 -0
- package/dist/ui/asyncOperations/connectingToArk.js +63 -0
- package/package.json +7 -5
- package/templates/agent/agent.template.yaml +27 -0
- package/templates/marketplace/.editorconfig +24 -0
- package/templates/marketplace/.github/.keep +11 -0
- package/templates/marketplace/.github/workflows/.keep +16 -0
- package/templates/marketplace/.helmignore +23 -0
- package/templates/marketplace/.prettierrc.json +20 -0
- package/templates/marketplace/.yamllint.yml +53 -0
- package/templates/marketplace/README.md +197 -0
- package/templates/marketplace/agents/.keep +29 -0
- package/templates/marketplace/docs/.keep +19 -0
- package/templates/marketplace/mcp-servers/.keep +32 -0
- package/templates/marketplace/models/.keep +23 -0
- package/templates/marketplace/projects/.keep +43 -0
- package/templates/marketplace/queries/.keep +25 -0
- package/templates/marketplace/teams/.keep +29 -0
- package/templates/marketplace/tools/.keep +32 -0
- package/templates/marketplace/tools/examples/.keep +17 -0
- package/templates/mcp-server/Dockerfile +133 -0
- package/templates/mcp-server/Makefile +186 -0
- package/templates/mcp-server/README.md +178 -0
- package/templates/mcp-server/build.sh +76 -0
- package/templates/mcp-server/chart/Chart.yaml +22 -0
- package/templates/mcp-server/chart/templates/_helpers.tpl +62 -0
- package/templates/mcp-server/chart/templates/deployment.yaml +80 -0
- package/templates/mcp-server/chart/templates/hpa.yaml +32 -0
- package/templates/mcp-server/chart/templates/mcpserver.yaml +21 -0
- package/templates/mcp-server/chart/templates/secret.yaml +11 -0
- package/templates/mcp-server/chart/templates/service.yaml +15 -0
- package/templates/mcp-server/chart/templates/serviceaccount.yaml +13 -0
- package/templates/mcp-server/chart/values.yaml +84 -0
- package/templates/mcp-server/example-values.yaml +74 -0
- package/templates/mcp-server/examples/{{ .Values.mcpServerName }}-agent.yaml +33 -0
- package/templates/mcp-server/examples/{{ .Values.mcpServerName }}-query.yaml +24 -0
- package/templates/models/azure.yaml +33 -0
- package/templates/models/claude.yaml +28 -0
- package/templates/models/gemini.yaml +28 -0
- package/templates/models/openai.yaml +39 -0
- package/templates/project/.editorconfig +24 -0
- package/templates/project/.helmignore +24 -0
- package/templates/project/.prettierrc.json +16 -0
- package/templates/project/.yamllint.yml +50 -0
- package/templates/project/Chart.yaml +19 -0
- package/templates/project/Makefile +360 -0
- package/templates/project/README.md +377 -0
- package/templates/project/agents/.keep +11 -0
- package/templates/project/docs/.keep +14 -0
- package/templates/project/mcp-servers/.keep +34 -0
- package/templates/project/models/.keep +17 -0
- package/templates/project/queries/.keep +11 -0
- package/templates/project/scripts/setup.sh +108 -0
- package/templates/project/teams/.keep +11 -0
- package/templates/project/templates/00-rbac.yaml +168 -0
- package/templates/project/templates/01-models.yaml +11 -0
- package/templates/project/templates/02-mcp-servers.yaml +22 -0
- package/templates/project/templates/03-tools.yaml +12 -0
- package/templates/project/templates/04-agents.yaml +12 -0
- package/templates/project/templates/05-teams.yaml +11 -0
- package/templates/project/templates/06-queries.yaml +11 -0
- package/templates/project/templates/_helpers.tpl +91 -0
- package/templates/project/tests/e2e/.keep +10 -0
- package/templates/project/tests/unit/.keep +10 -0
- package/templates/project/tools/.keep +25 -0
- package/templates/project/tools/example-tool.yaml.disabled +94 -0
- package/templates/project/tools/examples/data-tool/Dockerfile +32 -0
- package/templates/project/values.yaml +141 -0
- package/templates/query/query.template.yaml +13 -0
- package/templates/team/team.template.yaml +17 -0
- package/templates/tool/.python-version +1 -0
- package/templates/tool/Dockerfile +23 -0
- package/templates/tool/README.md +238 -0
- package/templates/tool/agent.yaml +19 -0
- package/templates/tool/deploy.sh +10 -0
- package/templates/tool/deployment/deployment.yaml +31 -0
- package/templates/tool/deployment/kustomization.yaml +7 -0
- package/templates/tool/deployment/mcpserver.yaml +12 -0
- package/templates/tool/deployment/service.yaml +12 -0
- package/templates/tool/deployment/serviceaccount.yaml +8 -0
- package/templates/tool/deployment/values.yaml +3 -0
- package/templates/tool/pyproject.toml +9 -0
- package/templates/tool/src/main.py +36 -0
- package/templates/tool/uv.lock +498 -0
package/README.md
CHANGED
|
@@ -1,95 +1,78 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
|
+
<h1 align="center"><code>ark</code></h1>
|
|
3
|
+
<h4 align="center">Ark Command Line Interface</h4>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<hr>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="#quickstart">Quickstart</a> •
|
|
9
|
+
<a href="https://mckinsey.github.io/agents-at-scale-ark/">Documentation</a>
|
|
10
|
+
</p>
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://github.com/mckinsey/agents-at-scale-ark/actions/workflows/cicd.yaml"><img src="https://github.com/mckinsey/agents-at-scale-ark/actions/workflows/cicd.yaml/badge.svg" alt="CI/CD"></a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/@agents-at-scale/ark"><img src="https://img.shields.io/npm/v/@agents-at-scale/ark.svg" alt="npm version"></a>
|
|
14
|
+
</p>
|
|
15
|
+
</div>
|
|
6
16
|
|
|
7
|
-
|
|
8
|
-
2. **Gateway setup** for service discovery:
|
|
9
|
-
```bash
|
|
10
|
-
# From agents-at-scale project root
|
|
11
|
-
make localhost-gateway-install
|
|
12
|
-
```
|
|
17
|
+
## Quickstart
|
|
13
18
|
|
|
14
|
-
|
|
19
|
+
Ensure you have [Node.js](https://nodejs.org/en/download) and [Helm](https://helm.sh/docs/intro/install/) installed. Then run the following commands to install Ark:
|
|
15
20
|
|
|
16
21
|
```bash
|
|
17
|
-
|
|
18
|
-
npm
|
|
19
|
-
npm install -g .
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Usage
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# Interactive mode (no arguments)
|
|
26
|
-
ark
|
|
22
|
+
# Install the 'ark' CLI:
|
|
23
|
+
npm install -g @agents-at-scale/ark
|
|
27
24
|
|
|
28
|
-
#
|
|
29
|
-
ark
|
|
30
|
-
ark cluster --help
|
|
25
|
+
# Install Ark:
|
|
26
|
+
ark install
|
|
31
27
|
|
|
32
|
-
#
|
|
33
|
-
ark
|
|
28
|
+
# Optionally configure a 'default' model to use for agents:
|
|
29
|
+
ark models create default
|
|
34
30
|
|
|
35
|
-
#
|
|
36
|
-
ark
|
|
31
|
+
# Run the dashboard:
|
|
32
|
+
ark dashboard
|
|
33
|
+
```
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
ark cluster get-type
|
|
40
|
-
ark cluster get-ip
|
|
41
|
-
ark cluster get-ip --verbose
|
|
42
|
-
ark cluster get-ip --context minikube
|
|
35
|
+
In most cases the default installation options will be sufficient. This will install the Ark dependencies, the controller, the APIs and the dashboard. You can optionally setup a `default` model that will be the default used by agents. You will need a Kubernetes cluster to install Ark into, you can use [Minikube](https://minikube.sigs.k8s.io/docs/start), [Kind](https://kind.sigs.k8s.io/docs/user/quick-start/), [Docker Desktop](https://docs.docker.com/desktop/kubernetes/) or similar to run a local cluster. The `install` command will warn if any required dependencies are missing.
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
ark autocomplete
|
|
46
|
-
```
|
|
37
|
+
User guides, developer guides, operations guides and API reference documentation is all available at:
|
|
47
38
|
|
|
48
|
-
|
|
39
|
+
https://mckinsey.github.io/agents-at-scale-ark/
|
|
49
40
|
|
|
50
|
-
|
|
41
|
+
The [Quickstart](https://mckinsey.github.io/agents-at-scale-ark/quickstart/) guide will walk you through the process of configuring a model, creating an agent and running basic queries.
|
|
51
42
|
|
|
52
|
-
|
|
53
|
-
2. **Kubernetes service discovery** - for internal services
|
|
54
|
-
3. **Default localhost URLs** - fallback
|
|
43
|
+
To troubleshoot an installation, run `ark status`.
|
|
55
44
|
|
|
56
|
-
|
|
45
|
+
## Configuration
|
|
57
46
|
|
|
58
|
-
|
|
47
|
+
You can customize Ark service installations using a `.arkrc.yaml` file in your home directory (`~/.arkrc.yaml`) or project directory. This allows you to override service properties like enabled status, namespace, or chart location.
|
|
59
48
|
|
|
60
|
-
|
|
49
|
+
Example `.arkrc.yaml`:
|
|
61
50
|
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
# From tools/ark-cli directory
|
|
70
|
-
npm run lint # Run linting and formatting
|
|
71
|
-
npm run lint:check # Check linting without fixing
|
|
51
|
+
```yaml
|
|
52
|
+
services:
|
|
53
|
+
localhost-gateway:
|
|
54
|
+
enabled: true
|
|
55
|
+
ark-controller:
|
|
56
|
+
namespace: custom-namespace
|
|
72
57
|
```
|
|
73
58
|
|
|
74
|
-
|
|
59
|
+
This example enables the `localhost-gateway` service (disabled by default) and changes the namespace for `ark-controller`.
|
|
75
60
|
|
|
76
|
-
|
|
61
|
+
### Installing Agents @ Scale
|
|
77
62
|
|
|
78
|
-
|
|
79
|
-
# Debug configuration discovery and service resolution
|
|
80
|
-
DEBUG=ark:config ark check status
|
|
63
|
+
To install the Agents @ Scale platform with JFrog container registry credentials:
|
|
81
64
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
65
|
+
```yaml
|
|
66
|
+
services:
|
|
67
|
+
agents-at-scale:
|
|
68
|
+
enabled: true
|
|
69
|
+
installArgs:
|
|
70
|
+
- --set
|
|
71
|
+
- containerRegistry.enabled=true
|
|
72
|
+
- --set
|
|
73
|
+
- containerRegistry.username=YOUR_USERNAME
|
|
74
|
+
- --set
|
|
75
|
+
- containerRegistry.password=YOUR_PASSWORD
|
|
89
76
|
```
|
|
90
77
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
- **Wrong URL detected**: See which discovery method is being used
|
|
94
|
-
- **Service timeouts**: Check localhost-gateway and kubernetes connectivity
|
|
95
|
-
- **Config issues**: Trace fallback logic through multiple discovery methods
|
|
78
|
+
Replace `YOUR_USERNAME` and `YOUR_PASSWORD` with your JFrog credentials.
|
package/dist/arkServices.d.ts
CHANGED
|
@@ -1,39 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Centralized ARK service definitions used by both install and status commands
|
|
3
3
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
helmReleaseName: string;
|
|
7
|
-
description: string;
|
|
8
|
-
enabled: boolean;
|
|
9
|
-
namespace?: string;
|
|
10
|
-
chartPath?: string;
|
|
11
|
-
installArgs?: string[];
|
|
12
|
-
k8sServiceName?: string;
|
|
13
|
-
k8sServicePort?: number;
|
|
14
|
-
k8sPortForwardLocalPort?: number;
|
|
15
|
-
k8sDeploymentName?: string;
|
|
16
|
-
k8sDevDeploymentName?: string;
|
|
17
|
-
}
|
|
18
|
-
export interface ServiceCollection {
|
|
19
|
-
[key: string]: ArkService;
|
|
20
|
-
}
|
|
21
|
-
export interface ArkDependency {
|
|
22
|
-
name: string;
|
|
23
|
-
command: string;
|
|
24
|
-
args: string[];
|
|
25
|
-
description: string;
|
|
26
|
-
}
|
|
27
|
-
export interface DependencyCollection {
|
|
28
|
-
[key: string]: ArkDependency;
|
|
29
|
-
}
|
|
4
|
+
import type { ArkService, ServiceCollection, ArkDependency, DependencyCollection } from './types/arkService.js';
|
|
5
|
+
export type { ArkService, ServiceCollection, ArkDependency, DependencyCollection, };
|
|
30
6
|
/**
|
|
31
7
|
* Dependencies that should be installed before ARK services
|
|
32
8
|
* Note: Dependencies will be installed in the order they are defined here
|
|
33
9
|
*/
|
|
34
10
|
export declare const arkDependencies: DependencyCollection;
|
|
35
11
|
/**
|
|
36
|
-
* Core ARK services with
|
|
12
|
+
* Core ARK services - initialized with defaults and config overrides applied
|
|
37
13
|
*/
|
|
38
14
|
export declare const arkServices: ServiceCollection;
|
|
39
15
|
/**
|
package/dist/arkServices.js
CHANGED
|
@@ -1,6 +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
5
|
const REGISTRY_BASE = 'oci://ghcr.io/mckinsey/agents-at-scale-ark/charts';
|
|
5
6
|
/**
|
|
6
7
|
* Dependencies that should be installed before ARK services
|
|
@@ -53,14 +54,15 @@ export const arkDependencies = {
|
|
|
53
54
|
},
|
|
54
55
|
};
|
|
55
56
|
/**
|
|
56
|
-
*
|
|
57
|
+
* Default ARK services with their installation and status check configurations
|
|
57
58
|
*/
|
|
58
|
-
|
|
59
|
+
const defaultArkServices = {
|
|
59
60
|
'ark-controller': {
|
|
60
61
|
name: 'ark-controller',
|
|
61
62
|
helmReleaseName: 'ark-controller',
|
|
62
63
|
description: 'Core Ark controller for managing AI resources',
|
|
63
64
|
enabled: true,
|
|
65
|
+
category: 'core',
|
|
64
66
|
namespace: 'ark-system',
|
|
65
67
|
chartPath: `${REGISTRY_BASE}/ark-controller`,
|
|
66
68
|
installArgs: ['--create-namespace', '--set', 'rbac.enable=true'],
|
|
@@ -72,7 +74,7 @@ export const arkServices = {
|
|
|
72
74
|
helmReleaseName: 'ark-api',
|
|
73
75
|
description: 'API layer for interacting with Ark resources',
|
|
74
76
|
enabled: true,
|
|
75
|
-
|
|
77
|
+
category: 'service',
|
|
76
78
|
chartPath: `${REGISTRY_BASE}/ark-api`,
|
|
77
79
|
installArgs: [],
|
|
78
80
|
k8sServiceName: 'ark-api',
|
|
@@ -86,6 +88,7 @@ export const arkServices = {
|
|
|
86
88
|
helmReleaseName: 'ark-dashboard',
|
|
87
89
|
description: 'Ark Dashboard',
|
|
88
90
|
enabled: true,
|
|
91
|
+
category: 'service',
|
|
89
92
|
// namespace: undefined - uses current context namespace
|
|
90
93
|
chartPath: `${REGISTRY_BASE}/ark-dashboard`,
|
|
91
94
|
installArgs: [],
|
|
@@ -100,6 +103,7 @@ export const arkServices = {
|
|
|
100
103
|
helmReleaseName: 'ark-api-a2a',
|
|
101
104
|
description: 'Ark API agent-to-agent communication service',
|
|
102
105
|
enabled: false, // Disabled - not currently used
|
|
106
|
+
category: 'service',
|
|
103
107
|
// namespace: undefined - uses current context namespace
|
|
104
108
|
// Note: This service might be installed as part of ark-api or separately
|
|
105
109
|
},
|
|
@@ -108,22 +112,46 @@ export const arkServices = {
|
|
|
108
112
|
helmReleaseName: 'ark-mcp',
|
|
109
113
|
description: 'Ark Model Context Protocol server',
|
|
110
114
|
enabled: true,
|
|
115
|
+
category: 'service',
|
|
111
116
|
// namespace: undefined - uses current context namespace
|
|
112
117
|
chartPath: `${REGISTRY_BASE}/ark-mcp`,
|
|
113
118
|
installArgs: [],
|
|
114
119
|
k8sDeploymentName: 'ark-mcp',
|
|
115
120
|
k8sDevDeploymentName: 'ark-mcp-devspace',
|
|
116
121
|
},
|
|
122
|
+
'agents-at-scale': {
|
|
123
|
+
name: 'agents-at-scale',
|
|
124
|
+
helmReleaseName: 'agents-at-scale',
|
|
125
|
+
description: 'Agents @ Scale Platform',
|
|
126
|
+
enabled: false,
|
|
127
|
+
category: 'service',
|
|
128
|
+
chartPath: 'oci://ghcr.io/mck-private/qb-fm-labs-legacyx/charts/legacyx',
|
|
129
|
+
installArgs: [],
|
|
130
|
+
},
|
|
117
131
|
'localhost-gateway': {
|
|
118
132
|
name: 'localhost-gateway',
|
|
119
133
|
helmReleaseName: 'localhost-gateway',
|
|
120
134
|
description: 'Gateway for local development clusters',
|
|
121
135
|
enabled: false, // Disabled - not needed for most users
|
|
136
|
+
category: 'service',
|
|
122
137
|
namespace: 'ark-system',
|
|
123
138
|
chartPath: `${REGISTRY_BASE}/localhost-gateway`,
|
|
124
139
|
installArgs: [],
|
|
125
140
|
},
|
|
126
141
|
};
|
|
142
|
+
function applyConfigOverrides(defaults) {
|
|
143
|
+
const config = loadConfig();
|
|
144
|
+
const overrides = config?.services || {};
|
|
145
|
+
const result = {};
|
|
146
|
+
for (const [key, service] of Object.entries(defaults)) {
|
|
147
|
+
result[key] = overrides[key] ? { ...service, ...overrides[key] } : service;
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Core ARK services - initialized with defaults and config overrides applied
|
|
153
|
+
*/
|
|
154
|
+
export const arkServices = applyConfigOverrides(defaultArkServices);
|
|
127
155
|
/**
|
|
128
156
|
* Get services that can be installed via Helm charts (only enabled services)
|
|
129
157
|
*/
|
package/dist/arkServices.spec.js
CHANGED
|
@@ -1,24 +1,132 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
const mockLoadConfig = jest.fn();
|
|
3
|
+
jest.unstable_mockModule('./lib/config.js', () => ({
|
|
4
|
+
loadConfig: mockLoadConfig,
|
|
5
|
+
}));
|
|
6
|
+
const { arkDependencies, arkServices: originalArkServices, getInstallableServices, } = await import('./arkServices.js');
|
|
2
7
|
describe('arkServices', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
jest.clearAllMocks();
|
|
10
|
+
});
|
|
3
11
|
it('exports arkDependencies with expected structure', () => {
|
|
4
12
|
expect(arkDependencies).toBeDefined();
|
|
5
13
|
expect(arkDependencies['cert-manager']).toBeDefined();
|
|
6
14
|
expect(arkDependencies['cert-manager'].command).toBe('helm');
|
|
7
15
|
});
|
|
8
16
|
it('exports arkServices with expected structure', () => {
|
|
9
|
-
expect(
|
|
10
|
-
expect(
|
|
11
|
-
expect(
|
|
12
|
-
|
|
13
|
-
expect(
|
|
14
|
-
expect(
|
|
15
|
-
// System services should have explicit namespace
|
|
16
|
-
expect(arkServices['localhost-gateway'].namespace).toBe('ark-system');
|
|
17
|
+
expect(originalArkServices).toBeDefined();
|
|
18
|
+
expect(originalArkServices['ark-controller']).toBeDefined();
|
|
19
|
+
expect(originalArkServices['ark-controller'].namespace).toBe('ark-system');
|
|
20
|
+
expect(originalArkServices['ark-api'].namespace).toBeUndefined();
|
|
21
|
+
expect(originalArkServices['ark-dashboard'].namespace).toBeUndefined();
|
|
22
|
+
expect(originalArkServices['localhost-gateway'].namespace).toBe('ark-system');
|
|
17
23
|
});
|
|
18
24
|
it('getInstallableServices returns services with chartPath', () => {
|
|
19
25
|
const installable = getInstallableServices();
|
|
20
26
|
expect(installable['ark-controller']).toBeDefined();
|
|
21
27
|
expect(installable['ark-api']).toBeDefined();
|
|
22
|
-
expect(installable['ark-api-a2a']).toBeUndefined();
|
|
28
|
+
expect(installable['ark-api-a2a']).toBeUndefined();
|
|
29
|
+
});
|
|
30
|
+
describe('applyConfigOverrides', () => {
|
|
31
|
+
it('applies no overrides when config has no services section', async () => {
|
|
32
|
+
mockLoadConfig.mockReturnValue({});
|
|
33
|
+
jest.resetModules();
|
|
34
|
+
const { arkServices } = await import('./arkServices.js');
|
|
35
|
+
expect(arkServices['ark-controller'].enabled).toBe(true);
|
|
36
|
+
expect(arkServices['ark-api'].enabled).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
it('applies overrides to enable a disabled service', async () => {
|
|
39
|
+
mockLoadConfig.mockReturnValue({
|
|
40
|
+
services: {
|
|
41
|
+
'localhost-gateway': { enabled: true },
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
jest.resetModules();
|
|
45
|
+
const { arkServices } = await import('./arkServices.js');
|
|
46
|
+
expect(arkServices['localhost-gateway'].enabled).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
it('applies overrides to disable an enabled service', async () => {
|
|
49
|
+
mockLoadConfig.mockReturnValue({
|
|
50
|
+
services: {
|
|
51
|
+
'ark-controller': { enabled: false },
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
jest.resetModules();
|
|
55
|
+
const { arkServices } = await import('./arkServices.js');
|
|
56
|
+
expect(arkServices['ark-controller'].enabled).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
it('applies overrides to multiple services', async () => {
|
|
59
|
+
mockLoadConfig.mockReturnValue({
|
|
60
|
+
services: {
|
|
61
|
+
'ark-controller': { enabled: false },
|
|
62
|
+
'ark-api': { enabled: false },
|
|
63
|
+
'localhost-gateway': { enabled: true },
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
jest.resetModules();
|
|
67
|
+
const { arkServices } = await import('./arkServices.js');
|
|
68
|
+
expect(arkServices['ark-controller'].enabled).toBe(false);
|
|
69
|
+
expect(arkServices['ark-api'].enabled).toBe(false);
|
|
70
|
+
expect(arkServices['localhost-gateway'].enabled).toBe(true);
|
|
71
|
+
});
|
|
72
|
+
it('applies overrides to namespace', async () => {
|
|
73
|
+
mockLoadConfig.mockReturnValue({
|
|
74
|
+
services: {
|
|
75
|
+
'ark-api': { namespace: 'custom-namespace' },
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
jest.resetModules();
|
|
79
|
+
const { arkServices } = await import('./arkServices.js');
|
|
80
|
+
expect(arkServices['ark-api'].namespace).toBe('custom-namespace');
|
|
81
|
+
});
|
|
82
|
+
it('applies overrides to chartPath', async () => {
|
|
83
|
+
mockLoadConfig.mockReturnValue({
|
|
84
|
+
services: {
|
|
85
|
+
'ark-controller': {
|
|
86
|
+
chartPath: 'oci://custom-registry/charts/ark-controller',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
jest.resetModules();
|
|
91
|
+
const { arkServices } = await import('./arkServices.js');
|
|
92
|
+
expect(arkServices['ark-controller'].chartPath).toBe('oci://custom-registry/charts/ark-controller');
|
|
93
|
+
});
|
|
94
|
+
it('applies partial overrides without affecting other properties', async () => {
|
|
95
|
+
mockLoadConfig.mockReturnValue({
|
|
96
|
+
services: {
|
|
97
|
+
'ark-controller': { enabled: false },
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
jest.resetModules();
|
|
101
|
+
const { arkServices } = await import('./arkServices.js');
|
|
102
|
+
expect(arkServices['ark-controller'].enabled).toBe(false);
|
|
103
|
+
expect(arkServices['ark-controller'].namespace).toBe('ark-system');
|
|
104
|
+
expect(arkServices['ark-controller'].category).toBe('core');
|
|
105
|
+
expect(arkServices['ark-controller'].description).toBe('Core Ark controller for managing AI resources');
|
|
106
|
+
});
|
|
107
|
+
it('applies overrides to installArgs', async () => {
|
|
108
|
+
mockLoadConfig.mockReturnValue({
|
|
109
|
+
services: {
|
|
110
|
+
'ark-controller': { installArgs: ['--set', 'custom.value=true'] },
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
jest.resetModules();
|
|
114
|
+
const { arkServices } = await import('./arkServices.js');
|
|
115
|
+
expect(arkServices['ark-controller'].installArgs).toEqual([
|
|
116
|
+
'--set',
|
|
117
|
+
'custom.value=true',
|
|
118
|
+
]);
|
|
119
|
+
});
|
|
120
|
+
it('does not affect services without overrides', async () => {
|
|
121
|
+
mockLoadConfig.mockReturnValue({
|
|
122
|
+
services: {
|
|
123
|
+
'ark-controller': { enabled: false },
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
jest.resetModules();
|
|
127
|
+
const { arkServices } = await import('./arkServices.js');
|
|
128
|
+
expect(arkServices['ark-api'].enabled).toBe(true);
|
|
129
|
+
expect(arkServices['ark-dashboard'].enabled).toBe(true);
|
|
130
|
+
});
|
|
23
131
|
});
|
|
24
132
|
});
|
|
@@ -13,14 +13,13 @@ export function createChatCommand(config) {
|
|
|
13
13
|
// Direct target argument (e.g., "agent/sample-agent")
|
|
14
14
|
const initialTargetId = targetArg;
|
|
15
15
|
// Config is passed from main
|
|
16
|
-
// Initialize proxy first - no spinner, just let ChatUI handle loading state
|
|
17
16
|
try {
|
|
18
17
|
const proxy = new ArkApiProxy();
|
|
19
18
|
const arkApiClient = await proxy.start();
|
|
20
|
-
// Pass the initialized client and config to ChatUI
|
|
21
19
|
render(_jsx(ChatUI, { initialTargetId: initialTargetId, arkApiClient: arkApiClient, arkApiProxy: proxy, config: config }));
|
|
22
20
|
}
|
|
23
21
|
catch (error) {
|
|
22
|
+
// Handle proxy startup failure or other errors
|
|
24
23
|
output.error(error instanceof Error ? error.message : 'ARK API connection failed');
|
|
25
24
|
process.exit(1);
|
|
26
25
|
}
|
|
@@ -114,7 +114,6 @@ complete -F _ark_completion ark
|
|
|
114
114
|
.description('Generate zsh completion script')
|
|
115
115
|
.action(() => {
|
|
116
116
|
// Shell script requires escaped $ characters
|
|
117
|
-
/* eslint-disable no-useless-escape */
|
|
118
117
|
console.log(`
|
|
119
118
|
#compdef ark
|
|
120
119
|
|
|
@@ -224,7 +223,6 @@ _ark() {
|
|
|
224
223
|
|
|
225
224
|
_ark
|
|
226
225
|
`.trim());
|
|
227
|
-
/* eslint-enable no-useless-escape */
|
|
228
226
|
});
|
|
229
227
|
return completion;
|
|
230
228
|
}
|
|
@@ -46,7 +46,7 @@ class ProjectGenerator {
|
|
|
46
46
|
spinner.succeed('Prerequisites validated');
|
|
47
47
|
// Get project configuration
|
|
48
48
|
spinner.start('Gathering project configuration');
|
|
49
|
-
const config = await this.getProjectConfig(name, destination, options);
|
|
49
|
+
const config = await this.getProjectConfig(name, destination, options, spinner);
|
|
50
50
|
spinner.succeed(`Project "${config.name}" configured`);
|
|
51
51
|
// Discover and configure models (only if not skipped)
|
|
52
52
|
if (config.configureModels) {
|
|
@@ -104,25 +104,28 @@ class ProjectGenerator {
|
|
|
104
104
|
console.log(chalk.cyan('💡 Tip: Install kubectl and helm later to deploy your project to a cluster'));
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
-
async getProjectConfig(name, destination, options) {
|
|
108
|
-
|
|
109
|
-
console.log(chalk.cyan('Project Configuration'));
|
|
110
|
-
console.log(chalk.gray(`${'─'.repeat(50)}\n`));
|
|
111
|
-
// Use command line options if provided, otherwise prompt
|
|
107
|
+
async getProjectConfig(name, destination, options, spinner) {
|
|
108
|
+
// Use command line options if provided
|
|
112
109
|
let projectType = options.projectType;
|
|
113
110
|
let parentDir = destination;
|
|
114
|
-
let namespace = options.namespace
|
|
111
|
+
let namespace = options.namespace;
|
|
115
112
|
// Validate project type if provided
|
|
116
113
|
if (projectType &&
|
|
117
114
|
projectType !== 'empty' &&
|
|
118
115
|
projectType !== 'with-samples') {
|
|
119
116
|
throw new Error(`Invalid project type: ${projectType}. Must be 'empty' or 'with-samples'`);
|
|
120
117
|
}
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (
|
|
118
|
+
// Default to interactive mode unless all required options are provided
|
|
119
|
+
// or explicitly set to non-interactive
|
|
120
|
+
const shouldPrompt = options.interactive !== false &&
|
|
121
|
+
(!options.projectType || !options.namespace);
|
|
122
|
+
if (shouldPrompt) {
|
|
123
|
+
// Stop spinner before showing prompts
|
|
124
|
+
spinner.stop();
|
|
125
|
+
// Show configuration header only when prompting
|
|
126
|
+
console.log(chalk.gray(`\n${'─'.repeat(50)}`));
|
|
127
|
+
console.log(chalk.cyan('Project Configuration'));
|
|
128
|
+
console.log(chalk.gray(`${'─'.repeat(50)}\n`));
|
|
126
129
|
const prompts = [];
|
|
127
130
|
if (!options.projectType) {
|
|
128
131
|
prompts.push({
|
|
@@ -160,11 +163,19 @@ class ProjectGenerator {
|
|
|
160
163
|
parentDir = answers.parentDir || parentDir;
|
|
161
164
|
namespace = answers.namespace || namespace;
|
|
162
165
|
}
|
|
166
|
+
// Restart spinner after prompts
|
|
167
|
+
spinner.start('Finalizing configuration');
|
|
163
168
|
}
|
|
164
|
-
//
|
|
169
|
+
// Use defaults for missing options
|
|
165
170
|
if (!projectType) {
|
|
166
|
-
|
|
171
|
+
projectType = GENERATOR_DEFAULTS.projectType; // 'with-samples'
|
|
167
172
|
}
|
|
173
|
+
if (!namespace) {
|
|
174
|
+
namespace = name; // Default namespace to project name
|
|
175
|
+
}
|
|
176
|
+
// Validate and normalize namespace
|
|
177
|
+
namespace = toKebabCase(namespace);
|
|
178
|
+
validateNameStrict(namespace, 'namespace');
|
|
168
179
|
const projectPath = path.join(parentDir, name);
|
|
169
180
|
// Check if directory exists
|
|
170
181
|
if (fs.existsSync(projectPath)) {
|
|
@@ -329,7 +340,10 @@ class ProjectGenerator {
|
|
|
329
340
|
return descriptions[name] || `Model: ${name}`;
|
|
330
341
|
}
|
|
331
342
|
async configureGit(config) {
|
|
332
|
-
|
|
343
|
+
// If git setup is explicitly skipped, don't do anything
|
|
344
|
+
if (!config.initGit) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
333
347
|
// Check if git is available
|
|
334
348
|
const gitAvailable = await this.isGitAvailable();
|
|
335
349
|
if (!gitAvailable) {
|
|
@@ -337,7 +351,7 @@ class ProjectGenerator {
|
|
|
337
351
|
config.initGit = false;
|
|
338
352
|
return;
|
|
339
353
|
}
|
|
340
|
-
// Check if git is configured
|
|
354
|
+
// Check if git is configured (only if we're initializing git)
|
|
341
355
|
try {
|
|
342
356
|
await execa('git', ['config', 'user.name'], { stdio: 'pipe' });
|
|
343
357
|
await execa('git', ['config', 'user.email'], { stdio: 'pipe' });
|
|
@@ -345,16 +359,9 @@ class ProjectGenerator {
|
|
|
345
359
|
catch {
|
|
346
360
|
console.log(chalk.yellow('⚠️ Git user not configured. Run: git config --global user.name "Your Name" && git config --global user.email "your.email@example.com"'));
|
|
347
361
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
name: 'initGit',
|
|
352
|
-
message: 'Initialize git repository with initial commit?',
|
|
353
|
-
default: true,
|
|
354
|
-
},
|
|
355
|
-
]);
|
|
356
|
-
config.initGit = gitAnswers.initGit;
|
|
357
|
-
config.createCommit = gitAnswers.initGit; // Always create commit if initializing git
|
|
362
|
+
// Since initGit is already true from command line options or defaults,
|
|
363
|
+
// we can proceed without prompting
|
|
364
|
+
config.createCommit = true; // Always create commit if initializing git
|
|
358
365
|
}
|
|
359
366
|
async generateProject(config) {
|
|
360
367
|
console.log(chalk.cyan(CLI_CONFIG.messages.generatingProject));
|
|
@@ -214,9 +214,9 @@ ${chalk.cyan('Use Cases:')}
|
|
|
214
214
|
: 'Working directory (default: current directory)', type === 'project' || type === 'marketplace'
|
|
215
215
|
? getDefaultDestination()
|
|
216
216
|
: undefined)
|
|
217
|
-
.option('-
|
|
217
|
+
.option('--no-interactive', type === 'marketplace'
|
|
218
218
|
? 'Not supported for marketplace'
|
|
219
|
-
: '
|
|
219
|
+
: 'Skip interactive prompts and use defaults (prompts by default)');
|
|
220
220
|
if (helpText?.examples) {
|
|
221
221
|
subCommand.addHelpText('after', helpText.examples);
|
|
222
222
|
}
|
|
@@ -3,11 +3,20 @@ import path from 'path';
|
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
export class TemplateDiscovery {
|
|
5
5
|
constructor() {
|
|
6
|
-
// Get the path to the templates directory
|
|
7
|
-
//
|
|
6
|
+
// Get the path to the templates directory
|
|
7
|
+
// This handles both development and production scenarios
|
|
8
8
|
const currentFile = fileURLToPath(import.meta.url);
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
// Try production path first (templates included in npm package)
|
|
10
|
+
const packageRoot = path.resolve(path.dirname(currentFile), '../../../');
|
|
11
|
+
const productionTemplatesPath = path.join(packageRoot, 'templates');
|
|
12
|
+
if (fs.existsSync(productionTemplatesPath)) {
|
|
13
|
+
this.templatesPath = productionTemplatesPath;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
// Fall back to development path (relative to ARK project root)
|
|
17
|
+
const arkRoot = path.resolve(path.dirname(currentFile), '../../../../../');
|
|
18
|
+
this.templatesPath = path.join(arkRoot, 'templates');
|
|
19
|
+
}
|
|
11
20
|
}
|
|
12
21
|
/**
|
|
13
22
|
* Discover all available templates in the templates directory
|