@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.
Files changed (129) hide show
  1. package/README.md +53 -70
  2. package/dist/arkServices.d.ts +3 -27
  3. package/dist/arkServices.js +31 -3
  4. package/dist/arkServices.spec.js +118 -10
  5. package/dist/commands/chat/index.js +1 -2
  6. package/dist/commands/completion/index.js +0 -2
  7. package/dist/commands/generate/generators/project.js +33 -26
  8. package/dist/commands/generate/index.js +2 -2
  9. package/dist/commands/generate/templateDiscovery.js +13 -4
  10. package/dist/commands/install/index.js +49 -58
  11. package/dist/commands/models/create.d.ts +9 -1
  12. package/dist/commands/models/create.js +97 -90
  13. package/dist/commands/models/create.spec.js +9 -37
  14. package/dist/commands/models/index.js +8 -2
  15. package/dist/commands/models/index.spec.js +1 -1
  16. package/dist/commands/status/index.d.ts +3 -1
  17. package/dist/commands/status/index.js +54 -2
  18. package/dist/components/AsyncOperation.d.ts +54 -0
  19. package/dist/components/AsyncOperation.js +110 -0
  20. package/dist/components/ChatUI.js +39 -72
  21. package/dist/components/SelectMenu.d.ts +17 -0
  22. package/dist/components/SelectMenu.js +21 -0
  23. package/dist/components/StatusMessage.d.ts +20 -0
  24. package/dist/components/StatusMessage.js +13 -0
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.js +1 -1
  27. package/dist/lib/arkApiClient.d.ts +1 -2
  28. package/dist/lib/arkApiClient.js +5 -6
  29. package/dist/lib/config.d.ts +4 -0
  30. package/dist/lib/config.js +9 -0
  31. package/dist/lib/nextSteps.js +1 -1
  32. package/dist/lib/nextSteps.spec.js +1 -1
  33. package/dist/lib/security.js +4 -0
  34. package/dist/lib/startup.js +6 -2
  35. package/dist/lib/startup.spec.js +1 -1
  36. package/dist/lib/timeout.d.ts +1 -0
  37. package/dist/lib/timeout.js +20 -0
  38. package/dist/lib/timeout.spec.d.ts +1 -0
  39. package/dist/lib/timeout.spec.js +14 -0
  40. package/dist/lib/waitForReady.d.ts +8 -0
  41. package/dist/lib/waitForReady.js +32 -0
  42. package/dist/lib/waitForReady.spec.d.ts +1 -0
  43. package/dist/lib/waitForReady.spec.js +104 -0
  44. package/dist/types/arkService.d.ts +27 -0
  45. package/dist/types/arkService.js +1 -0
  46. package/dist/ui/asyncOperations/connectingToArk.d.ts +15 -0
  47. package/dist/ui/asyncOperations/connectingToArk.js +63 -0
  48. package/package.json +7 -5
  49. package/templates/agent/agent.template.yaml +27 -0
  50. package/templates/marketplace/.editorconfig +24 -0
  51. package/templates/marketplace/.github/.keep +11 -0
  52. package/templates/marketplace/.github/workflows/.keep +16 -0
  53. package/templates/marketplace/.helmignore +23 -0
  54. package/templates/marketplace/.prettierrc.json +20 -0
  55. package/templates/marketplace/.yamllint.yml +53 -0
  56. package/templates/marketplace/README.md +197 -0
  57. package/templates/marketplace/agents/.keep +29 -0
  58. package/templates/marketplace/docs/.keep +19 -0
  59. package/templates/marketplace/mcp-servers/.keep +32 -0
  60. package/templates/marketplace/models/.keep +23 -0
  61. package/templates/marketplace/projects/.keep +43 -0
  62. package/templates/marketplace/queries/.keep +25 -0
  63. package/templates/marketplace/teams/.keep +29 -0
  64. package/templates/marketplace/tools/.keep +32 -0
  65. package/templates/marketplace/tools/examples/.keep +17 -0
  66. package/templates/mcp-server/Dockerfile +133 -0
  67. package/templates/mcp-server/Makefile +186 -0
  68. package/templates/mcp-server/README.md +178 -0
  69. package/templates/mcp-server/build.sh +76 -0
  70. package/templates/mcp-server/chart/Chart.yaml +22 -0
  71. package/templates/mcp-server/chart/templates/_helpers.tpl +62 -0
  72. package/templates/mcp-server/chart/templates/deployment.yaml +80 -0
  73. package/templates/mcp-server/chart/templates/hpa.yaml +32 -0
  74. package/templates/mcp-server/chart/templates/mcpserver.yaml +21 -0
  75. package/templates/mcp-server/chart/templates/secret.yaml +11 -0
  76. package/templates/mcp-server/chart/templates/service.yaml +15 -0
  77. package/templates/mcp-server/chart/templates/serviceaccount.yaml +13 -0
  78. package/templates/mcp-server/chart/values.yaml +84 -0
  79. package/templates/mcp-server/example-values.yaml +74 -0
  80. package/templates/mcp-server/examples/{{ .Values.mcpServerName }}-agent.yaml +33 -0
  81. package/templates/mcp-server/examples/{{ .Values.mcpServerName }}-query.yaml +24 -0
  82. package/templates/models/azure.yaml +33 -0
  83. package/templates/models/claude.yaml +28 -0
  84. package/templates/models/gemini.yaml +28 -0
  85. package/templates/models/openai.yaml +39 -0
  86. package/templates/project/.editorconfig +24 -0
  87. package/templates/project/.helmignore +24 -0
  88. package/templates/project/.prettierrc.json +16 -0
  89. package/templates/project/.yamllint.yml +50 -0
  90. package/templates/project/Chart.yaml +19 -0
  91. package/templates/project/Makefile +360 -0
  92. package/templates/project/README.md +377 -0
  93. package/templates/project/agents/.keep +11 -0
  94. package/templates/project/docs/.keep +14 -0
  95. package/templates/project/mcp-servers/.keep +34 -0
  96. package/templates/project/models/.keep +17 -0
  97. package/templates/project/queries/.keep +11 -0
  98. package/templates/project/scripts/setup.sh +108 -0
  99. package/templates/project/teams/.keep +11 -0
  100. package/templates/project/templates/00-rbac.yaml +168 -0
  101. package/templates/project/templates/01-models.yaml +11 -0
  102. package/templates/project/templates/02-mcp-servers.yaml +22 -0
  103. package/templates/project/templates/03-tools.yaml +12 -0
  104. package/templates/project/templates/04-agents.yaml +12 -0
  105. package/templates/project/templates/05-teams.yaml +11 -0
  106. package/templates/project/templates/06-queries.yaml +11 -0
  107. package/templates/project/templates/_helpers.tpl +91 -0
  108. package/templates/project/tests/e2e/.keep +10 -0
  109. package/templates/project/tests/unit/.keep +10 -0
  110. package/templates/project/tools/.keep +25 -0
  111. package/templates/project/tools/example-tool.yaml.disabled +94 -0
  112. package/templates/project/tools/examples/data-tool/Dockerfile +32 -0
  113. package/templates/project/values.yaml +141 -0
  114. package/templates/query/query.template.yaml +13 -0
  115. package/templates/team/team.template.yaml +17 -0
  116. package/templates/tool/.python-version +1 -0
  117. package/templates/tool/Dockerfile +23 -0
  118. package/templates/tool/README.md +238 -0
  119. package/templates/tool/agent.yaml +19 -0
  120. package/templates/tool/deploy.sh +10 -0
  121. package/templates/tool/deployment/deployment.yaml +31 -0
  122. package/templates/tool/deployment/kustomization.yaml +7 -0
  123. package/templates/tool/deployment/mcpserver.yaml +12 -0
  124. package/templates/tool/deployment/service.yaml +12 -0
  125. package/templates/tool/deployment/serviceaccount.yaml +8 -0
  126. package/templates/tool/deployment/values.yaml +3 -0
  127. package/templates/tool/pyproject.toml +9 -0
  128. package/templates/tool/src/main.py +36 -0
  129. package/templates/tool/uv.lock +498 -0
package/README.md CHANGED
@@ -1,95 +1,78 @@
1
- # ARK CLI
1
+ <div align="center">
2
+ <h1 align="center"><code>ark</code></h1>
3
+ <h4 align="center">Ark Command Line Interface</h4>
2
4
 
3
- Interactive terminal interface for ARK agents.
5
+ <hr>
4
6
 
5
- ## Prerequisites
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
- 1. **ARK system deployed** in your Kubernetes cluster
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
- ## Installation
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
- cd tools/ark-cli
18
- npm run build
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
- # Show help
29
- ark --help
30
- ark cluster --help
25
+ # Install Ark:
26
+ ark install
31
27
 
32
- # Check system status
33
- ark check status
28
+ # Optionally configure a 'default' model to use for agents:
29
+ ark models create default
34
30
 
35
- # Generate (project, agent, team, etc)
36
- ark generate
31
+ # Run the dashboard:
32
+ ark dashboard
33
+ ```
37
34
 
38
- # Cluster operations
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
- # Show shell autocomplete options.
45
- ark autocomplete
46
- ```
37
+ User guides, developer guides, operations guides and API reference documentation is all available at:
47
38
 
48
- ## Configuration
39
+ https://mckinsey.github.io/agents-at-scale-ark/
49
40
 
50
- ARK CLI automatically detects services via:
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
- 1. **localhost-gateway** (when running) - `*.127.0.0.1.nip.io:8080`
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
- Settings stored in `~/.config/ark-cli/config.json`
45
+ ## Configuration
57
46
 
58
- ## Development
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
- **Note:** All make commands must be run from the repository root directory.
49
+ Example `.arkrc.yaml`:
61
50
 
62
- ```bash
63
- # From repository root
64
- make ark-cli-install # Build and install globally
65
- make ark-cli-build # Build only
66
- make clean # Clean build artifacts and stamp files
67
- make ark-cli-uninstall # Remove global installation
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
- ## Troubleshooting
59
+ This example enables the `localhost-gateway` service (disabled by default) and changes the namespace for `ark-controller`.
75
60
 
76
- Enable debug logging to see detailed configuration discovery and service resolution:
61
+ ### Installing Agents @ Scale
77
62
 
78
- ```bash
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
- # Debug all ARK CLI components
83
- DEBUG=ark:* ark check status
84
-
85
- # Keep debug enabled for multiple commands
86
- export DEBUG=ark:config
87
- ark check status
88
- ark dashboard
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
- **Common debug scenarios:**
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.
@@ -1,39 +1,15 @@
1
1
  /**
2
2
  * Centralized ARK service definitions used by both install and status commands
3
3
  */
4
- export interface ArkService {
5
- name: string;
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 their installation and status check configurations
12
+ * Core ARK services - initialized with defaults and config overrides applied
37
13
  */
38
14
  export declare const arkServices: ServiceCollection;
39
15
  /**
@@ -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
- * Core ARK services with their installation and status check configurations
57
+ * Default ARK services with their installation and status check configurations
57
58
  */
58
- export const arkServices = {
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
- // namespace: undefined - uses current context namespace
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
  */
@@ -1,24 +1,132 @@
1
- import { arkDependencies, arkServices, getInstallableServices, } from './arkServices.js';
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(arkServices).toBeDefined();
10
- expect(arkServices['ark-controller']).toBeDefined();
11
- expect(arkServices['ark-controller'].namespace).toBe('ark-system');
12
- // User services should have undefined namespace (use current context)
13
- expect(arkServices['ark-api'].namespace).toBeUndefined();
14
- expect(arkServices['ark-dashboard'].namespace).toBeUndefined();
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(); // no chartPath
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
- console.log(chalk.gray(`\n${'─'.repeat(50)}`));
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 || name;
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
- // Validate and normalize namespace
122
- namespace = toKebabCase(namespace);
123
- validateNameStrict(namespace, 'namespace');
124
- // Only prompt if in interactive mode and missing required options
125
- if (options.interactive || !options.projectType || !options.namespace) {
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
- // Ensure projectType has a value
169
+ // Use defaults for missing options
165
170
  if (!projectType) {
166
- throw new Error('Project type is required. Use --project-type <empty|with-samples> or run in interactive mode.');
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
- console.log(chalk.cyan('📋 Git Repository Configuration\n'));
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
- const gitAnswers = await inquirer.prompt([
349
- {
350
- type: 'confirm',
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('-i, --interactive', type === 'marketplace'
217
+ .option('--no-interactive', type === 'marketplace'
218
218
  ? 'Not supported for marketplace'
219
- : 'Force additional configuration prompts (generators prompt by default when info is missing)', false);
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 relative to the ark CLI
7
- // Navigate from tools/ark-cli/src/commands/generate/templateDiscovery.js to agents-at-scale/templates
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
- const arkRoot = path.resolve(path.dirname(currentFile), '../../../../../');
10
- this.templatesPath = path.join(arkRoot, 'templates');
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