@agents-at-scale/ark 0.1.35 → 0.1.36-rc1

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 (223) hide show
  1. package/dist/arkServices.d.ts +42 -0
  2. package/dist/arkServices.js +138 -0
  3. package/dist/arkServices.spec.d.ts +1 -0
  4. package/dist/arkServices.spec.js +24 -0
  5. package/dist/charts/charts.d.ts +5 -0
  6. package/dist/charts/charts.js +6 -0
  7. package/dist/charts/dependencies.d.ts +6 -0
  8. package/dist/charts/dependencies.js +50 -0
  9. package/dist/charts/types.d.ts +40 -0
  10. package/dist/charts/types.js +1 -0
  11. package/dist/commands/agents/index.d.ts +3 -0
  12. package/dist/commands/agents/index.js +65 -0
  13. package/dist/commands/agents/index.spec.d.ts +1 -0
  14. package/dist/commands/agents/index.spec.js +67 -0
  15. package/dist/commands/agents/selector.d.ts +8 -0
  16. package/dist/commands/agents/selector.js +53 -0
  17. package/dist/commands/agents.d.ts +2 -0
  18. package/dist/commands/agents.js +53 -0
  19. package/dist/commands/chat/index.d.ts +3 -0
  20. package/dist/commands/chat/index.js +29 -0
  21. package/dist/commands/chat.d.ts +2 -0
  22. package/dist/commands/chat.js +45 -0
  23. package/dist/commands/cluster/get.d.ts +2 -0
  24. package/dist/commands/cluster/get.js +39 -0
  25. package/dist/commands/cluster/get.spec.d.ts +1 -0
  26. package/dist/commands/cluster/get.spec.js +92 -0
  27. package/dist/commands/cluster/index.d.ts +2 -1
  28. package/dist/commands/cluster/index.js +3 -5
  29. package/dist/commands/cluster/index.spec.d.ts +1 -0
  30. package/dist/commands/cluster/index.spec.js +24 -0
  31. package/dist/commands/completion/index.d.ts +3 -0
  32. package/dist/commands/completion/index.js +230 -0
  33. package/dist/commands/completion/index.spec.d.ts +1 -0
  34. package/dist/commands/completion/index.spec.js +34 -0
  35. package/dist/commands/completion.js +159 -2
  36. package/dist/commands/config/index.d.ts +3 -0
  37. package/dist/commands/config/index.js +42 -0
  38. package/dist/commands/config/index.spec.d.ts +1 -0
  39. package/dist/commands/config/index.spec.js +78 -0
  40. package/dist/commands/config.d.ts +0 -3
  41. package/dist/commands/config.js +38 -321
  42. package/dist/commands/dashboard/index.d.ts +4 -0
  43. package/dist/commands/dashboard/index.js +39 -0
  44. package/dist/commands/dashboard.d.ts +3 -0
  45. package/dist/commands/dashboard.js +39 -0
  46. package/dist/commands/dev/index.d.ts +3 -0
  47. package/dist/commands/dev/index.js +9 -0
  48. package/dist/commands/dev/tool/check.d.ts +2 -0
  49. package/dist/commands/dev/tool/check.js +142 -0
  50. package/dist/commands/dev/tool/clean.d.ts +2 -0
  51. package/dist/commands/dev/tool/clean.js +153 -0
  52. package/dist/commands/dev/tool/generate.d.ts +2 -0
  53. package/dist/commands/dev/tool/generate.js +28 -0
  54. package/dist/commands/dev/tool/index.d.ts +2 -0
  55. package/dist/commands/dev/tool/index.js +14 -0
  56. package/dist/commands/dev/tool/init.d.ts +2 -0
  57. package/dist/commands/dev/tool/init.js +320 -0
  58. package/dist/commands/dev/tool/shared.d.ts +5 -0
  59. package/dist/commands/dev/tool/shared.js +258 -0
  60. package/dist/commands/dev/tool/status.d.ts +2 -0
  61. package/dist/commands/dev/tool/status.js +136 -0
  62. package/dist/commands/dev/tool-generate.spec.d.ts +1 -0
  63. package/dist/commands/dev/tool-generate.spec.js +163 -0
  64. package/dist/commands/dev/tool.d.ts +2 -0
  65. package/dist/commands/dev/tool.js +559 -0
  66. package/dist/commands/dev/tool.spec.d.ts +1 -0
  67. package/dist/commands/dev/tool.spec.js +48 -0
  68. package/dist/commands/docs/index.d.ts +4 -0
  69. package/dist/commands/docs/index.js +18 -0
  70. package/dist/commands/generate/config.js +5 -24
  71. package/dist/commands/generate/generators/mcpserver.d.ts +2 -1
  72. package/dist/commands/generate/generators/mcpserver.js +26 -5
  73. package/dist/commands/generate/generators/project.js +22 -41
  74. package/dist/commands/generate/index.d.ts +2 -1
  75. package/dist/commands/generate/index.js +1 -1
  76. package/dist/commands/install/index.d.ts +8 -0
  77. package/dist/commands/install/index.js +295 -0
  78. package/dist/commands/install/index.spec.d.ts +1 -0
  79. package/dist/commands/install/index.spec.js +143 -0
  80. package/dist/commands/install.d.ts +3 -0
  81. package/dist/commands/install.js +147 -0
  82. package/dist/commands/models/create.d.ts +1 -0
  83. package/dist/commands/models/create.js +213 -0
  84. package/dist/commands/models/create.spec.d.ts +1 -0
  85. package/dist/commands/models/create.spec.js +125 -0
  86. package/dist/commands/models/index.d.ts +3 -0
  87. package/dist/commands/models/index.js +75 -0
  88. package/dist/commands/models/index.spec.d.ts +1 -0
  89. package/dist/commands/models/index.spec.js +96 -0
  90. package/dist/commands/models/selector.d.ts +8 -0
  91. package/dist/commands/models/selector.js +53 -0
  92. package/dist/commands/query/index.d.ts +3 -0
  93. package/dist/commands/query/index.js +24 -0
  94. package/dist/commands/query/index.spec.d.ts +1 -0
  95. package/dist/commands/query/index.spec.js +53 -0
  96. package/dist/commands/routes/index.d.ts +3 -0
  97. package/dist/commands/routes/index.js +93 -0
  98. package/dist/commands/routes.d.ts +2 -0
  99. package/dist/commands/routes.js +101 -0
  100. package/dist/commands/status/index.d.ts +3 -0
  101. package/dist/commands/status/index.js +281 -0
  102. package/dist/commands/status.d.ts +3 -0
  103. package/dist/commands/status.js +33 -0
  104. package/dist/commands/targets/index.d.ts +3 -0
  105. package/dist/commands/targets/index.js +72 -0
  106. package/dist/commands/targets/index.spec.d.ts +1 -0
  107. package/dist/commands/targets/index.spec.js +154 -0
  108. package/dist/commands/targets.d.ts +2 -0
  109. package/dist/commands/targets.js +65 -0
  110. package/dist/commands/teams/index.d.ts +3 -0
  111. package/dist/commands/teams/index.js +64 -0
  112. package/dist/commands/teams/index.spec.d.ts +1 -0
  113. package/dist/commands/teams/index.spec.js +70 -0
  114. package/dist/commands/teams/selector.d.ts +8 -0
  115. package/dist/commands/teams/selector.js +55 -0
  116. package/dist/commands/tools/index.d.ts +3 -0
  117. package/dist/commands/tools/index.js +49 -0
  118. package/dist/commands/tools/index.spec.d.ts +1 -0
  119. package/dist/commands/tools/index.spec.js +70 -0
  120. package/dist/commands/tools/selector.d.ts +8 -0
  121. package/dist/commands/tools/selector.js +53 -0
  122. package/dist/commands/uninstall/index.d.ts +3 -0
  123. package/dist/commands/uninstall/index.js +101 -0
  124. package/dist/commands/uninstall/index.spec.d.ts +1 -0
  125. package/dist/commands/uninstall/index.spec.js +125 -0
  126. package/dist/commands/uninstall.d.ts +2 -0
  127. package/dist/commands/uninstall.js +83 -0
  128. package/dist/components/ChatUI.d.ts +16 -0
  129. package/dist/components/ChatUI.js +801 -0
  130. package/dist/components/StatusView.d.ts +10 -0
  131. package/dist/components/StatusView.js +39 -0
  132. package/dist/components/statusChecker.d.ts +14 -24
  133. package/dist/components/statusChecker.js +295 -129
  134. package/dist/config.d.ts +3 -22
  135. package/dist/config.js +10 -161
  136. package/dist/index.d.ts +1 -1
  137. package/dist/index.js +42 -42
  138. package/dist/lib/arkApiClient.d.ts +53 -0
  139. package/dist/lib/arkApiClient.js +102 -0
  140. package/dist/lib/arkApiProxy.d.ts +9 -0
  141. package/dist/lib/arkApiProxy.js +22 -0
  142. package/dist/lib/arkServiceProxy.d.ts +14 -0
  143. package/dist/lib/arkServiceProxy.js +95 -0
  144. package/dist/lib/arkStatus.d.ts +10 -0
  145. package/dist/lib/arkStatus.js +79 -0
  146. package/dist/lib/arkStatus.spec.d.ts +1 -0
  147. package/dist/lib/arkStatus.spec.js +49 -0
  148. package/dist/lib/chatClient.d.ts +33 -0
  149. package/dist/lib/chatClient.js +93 -0
  150. package/dist/lib/cluster.d.ts +2 -1
  151. package/dist/lib/cluster.js +37 -16
  152. package/dist/lib/cluster.spec.d.ts +1 -0
  153. package/dist/lib/cluster.spec.js +338 -0
  154. package/dist/lib/commandUtils.d.ts +4 -0
  155. package/dist/lib/commandUtils.js +18 -0
  156. package/dist/lib/commandUtils.test.d.ts +1 -0
  157. package/dist/lib/commandUtils.test.js +44 -0
  158. package/dist/lib/commands.d.ts +16 -0
  159. package/dist/lib/commands.js +29 -0
  160. package/dist/lib/commands.spec.d.ts +1 -0
  161. package/dist/lib/commands.spec.js +146 -0
  162. package/dist/lib/config.d.ts +26 -80
  163. package/dist/lib/config.js +70 -205
  164. package/dist/lib/config.spec.d.ts +1 -0
  165. package/dist/lib/config.spec.js +99 -0
  166. package/dist/lib/config.test.d.ts +1 -0
  167. package/dist/lib/config.test.js +93 -0
  168. package/dist/lib/consts.d.ts +0 -1
  169. package/dist/lib/consts.js +0 -2
  170. package/dist/lib/consts.spec.d.ts +1 -0
  171. package/dist/lib/consts.spec.js +15 -0
  172. package/dist/lib/dev/tools/analyzer.d.ts +30 -0
  173. package/dist/lib/dev/tools/analyzer.js +190 -0
  174. package/dist/lib/dev/tools/discover_tools.py +392 -0
  175. package/dist/lib/dev/tools/mcp-types.d.ts +28 -0
  176. package/dist/lib/dev/tools/mcp-types.js +86 -0
  177. package/dist/lib/dev/tools/types.d.ts +50 -0
  178. package/dist/lib/dev/tools/types.js +1 -0
  179. package/dist/lib/errors.js +1 -1
  180. package/dist/lib/errors.spec.d.ts +1 -0
  181. package/dist/lib/errors.spec.js +221 -0
  182. package/dist/lib/exec.d.ts +0 -4
  183. package/dist/lib/exec.js +0 -11
  184. package/dist/lib/executeQuery.d.ts +20 -0
  185. package/dist/lib/executeQuery.js +135 -0
  186. package/dist/lib/executeQuery.spec.d.ts +1 -0
  187. package/dist/lib/executeQuery.spec.js +170 -0
  188. package/dist/lib/nextSteps.d.ts +4 -0
  189. package/dist/lib/nextSteps.js +20 -0
  190. package/dist/lib/nextSteps.spec.d.ts +1 -0
  191. package/dist/lib/nextSteps.spec.js +59 -0
  192. package/dist/lib/output.d.ts +36 -0
  193. package/dist/lib/output.js +89 -0
  194. package/dist/lib/output.spec.d.ts +1 -0
  195. package/dist/lib/output.spec.js +123 -0
  196. package/dist/lib/portUtils.d.ts +8 -0
  197. package/dist/lib/portUtils.js +39 -0
  198. package/dist/lib/queryRunner.d.ts +22 -0
  199. package/dist/lib/queryRunner.js +142 -0
  200. package/dist/lib/startup.d.ts +9 -0
  201. package/dist/lib/startup.js +87 -0
  202. package/dist/lib/startup.spec.d.ts +1 -0
  203. package/dist/lib/startup.spec.js +152 -0
  204. package/dist/lib/types.d.ts +87 -3
  205. package/dist/lib/versions.d.ts +23 -0
  206. package/dist/lib/versions.js +51 -0
  207. package/dist/types/types.d.ts +40 -0
  208. package/dist/types/types.js +1 -0
  209. package/dist/ui/AgentSelector.d.ts +8 -0
  210. package/dist/ui/AgentSelector.js +53 -0
  211. package/dist/ui/MainMenu.d.ts +5 -1
  212. package/dist/ui/MainMenu.js +226 -91
  213. package/dist/ui/ModelSelector.d.ts +8 -0
  214. package/dist/ui/ModelSelector.js +53 -0
  215. package/dist/ui/TeamSelector.d.ts +8 -0
  216. package/dist/ui/TeamSelector.js +55 -0
  217. package/dist/ui/ToolSelector.d.ts +8 -0
  218. package/dist/ui/ToolSelector.js +53 -0
  219. package/dist/ui/statusFormatter.d.ts +22 -7
  220. package/dist/ui/statusFormatter.js +39 -39
  221. package/dist/ui/statusFormatter.spec.d.ts +1 -0
  222. package/dist/ui/statusFormatter.spec.js +58 -0
  223. package/package.json +16 -5
@@ -1,82 +1,28 @@
1
- /**
2
- * Configuration management for ARK CLI
3
- */
4
- export interface ArkConfig {
5
- defaultProjectType: 'empty' | 'with-samples';
6
- defaultDestination: string;
7
- skipGitByDefault: boolean;
8
- skipModelsbyDefault: boolean;
9
- preferredEditor: string;
10
- colorOutput: boolean;
11
- verboseOutput: boolean;
12
- defaultModelProvider: 'azure' | 'openai' | 'claude' | 'gemini' | 'custom';
13
- templateDirectory?: string;
14
- customTemplates: Record<string, string>;
15
- parallelOperations: boolean;
16
- maxConcurrentFiles: number;
17
- fileWatchingEnabled: boolean;
18
- telemetryEnabled: boolean;
19
- errorReporting: boolean;
1
+ import type { ClusterInfo } from './cluster.js';
2
+ export interface ChatConfig {
3
+ streaming?: boolean;
4
+ outputFormat?: 'text' | 'markdown';
20
5
  }
21
- export declare const DEFAULT_CONFIG: ArkConfig;
22
- export declare class ConfigManager {
23
- private configPath;
24
- private config;
25
- constructor();
26
- /**
27
- * Get the path to the configuration file
28
- */
29
- private getConfigPath;
30
- /**
31
- * Load configuration from file or create with defaults
32
- */
33
- private loadConfig;
34
- /**
35
- * Save configuration to file
36
- */
37
- private saveConfig;
38
- /**
39
- * Get the current configuration
40
- */
41
- getConfig(): ArkConfig;
42
- /**
43
- * Update configuration
44
- */
45
- updateConfig(updates: Partial<ArkConfig>): void;
46
- /**
47
- * Reset configuration to defaults
48
- */
49
- resetConfig(): void;
50
- /**
51
- * Get a specific configuration value
52
- */
53
- get<K extends keyof ArkConfig>(key: K): ArkConfig[K];
54
- /**
55
- * Set a specific configuration value
56
- */
57
- set<K extends keyof ArkConfig>(key: K, value: ArkConfig[K]): void;
58
- /**
59
- * Validate configuration values
60
- */
61
- validateConfig(): void;
62
- /**
63
- * Get environment variable overrides
64
- */
65
- getEnvironmentOverrides(): Partial<ArkConfig>;
66
- /**
67
- * Get merged configuration with environment overrides
68
- */
69
- getMergedConfig(): ArkConfig;
70
- /**
71
- * Export configuration for backup
72
- */
73
- exportConfig(): string;
74
- /**
75
- * Import configuration from backup
76
- */
77
- importConfig(configJson: string): void;
78
- /**
79
- * Get configuration file path for CLI display
80
- */
81
- getConfigFilePath(): string;
6
+ export interface ArkConfig {
7
+ chat?: ChatConfig;
8
+ clusterInfo?: ClusterInfo;
82
9
  }
10
+ /**
11
+ * Load configuration from multiple sources with proper precedence:
12
+ * 1. Defaults
13
+ * 2. ~/.arkrc.yaml (user config)
14
+ * 3. .arkrc.yaml (project config)
15
+ * 4. Environment variables (override all)
16
+ */
17
+ export declare function loadConfig(): ArkConfig;
18
+ /**
19
+ * Get the paths checked for config files
20
+ */
21
+ export declare function getConfigPaths(): {
22
+ user: string;
23
+ project: string;
24
+ };
25
+ /**
26
+ * Format config as YAML for display
27
+ */
28
+ export declare function formatConfig(config: ArkConfig): string;
@@ -1,223 +1,88 @@
1
- /**
2
- * Configuration management for ARK CLI
3
- */
4
1
  import fs from 'fs';
5
2
  import path from 'path';
6
3
  import os from 'os';
7
- import { SecurityUtils } from './security.js';
8
- import { ValidationError } from './errors.js';
9
- export const DEFAULT_CONFIG = {
10
- defaultProjectType: 'with-samples',
11
- defaultDestination: process.cwd(),
12
- skipGitByDefault: false,
13
- skipModelsbyDefault: false,
14
- preferredEditor: process.env.EDITOR || 'code',
15
- colorOutput: true,
16
- verboseOutput: false,
17
- defaultModelProvider: 'azure',
18
- customTemplates: {},
19
- parallelOperations: true,
20
- maxConcurrentFiles: 10,
21
- fileWatchingEnabled: false,
22
- telemetryEnabled: false,
23
- errorReporting: false,
24
- };
25
- export class ConfigManager {
26
- constructor() {
27
- this.configPath = this.getConfigPath();
28
- this.config = this.loadConfig();
29
- }
30
- /**
31
- * Get the path to the configuration file
32
- */
33
- getConfigPath() {
34
- const configDir = process.env.ARK_CONFIG_DIR || path.join(os.homedir(), '.config', 'ark');
35
- // Ensure config directory exists
36
- if (!fs.existsSync(configDir)) {
37
- fs.mkdirSync(configDir, { recursive: true, mode: 0o755 });
38
- }
39
- return path.join(configDir, 'config.json');
40
- }
41
- /**
42
- * Load configuration from file or create with defaults
43
- */
44
- loadConfig() {
4
+ import yaml from 'yaml';
5
+ /**
6
+ * Load configuration from multiple sources with proper precedence:
7
+ * 1. Defaults
8
+ * 2. ~/.arkrc.yaml (user config)
9
+ * 3. .arkrc.yaml (project config)
10
+ * 4. Environment variables (override all)
11
+ */
12
+ export function loadConfig() {
13
+ // Start with defaults
14
+ const config = {
15
+ chat: {
16
+ streaming: true,
17
+ outputFormat: 'text',
18
+ },
19
+ };
20
+ // Load user config from home directory
21
+ const userConfigPath = path.join(os.homedir(), '.arkrc.yaml');
22
+ if (fs.existsSync(userConfigPath)) {
45
23
  try {
46
- if (fs.existsSync(this.configPath)) {
47
- const configContent = fs.readFileSync(this.configPath, 'utf-8');
48
- const userConfig = JSON.parse(configContent);
49
- // Merge with defaults to ensure all properties exist
50
- return { ...DEFAULT_CONFIG, ...userConfig };
51
- }
24
+ const userConfig = yaml.parse(fs.readFileSync(userConfigPath, 'utf-8'));
25
+ mergeConfig(config, userConfig);
52
26
  }
53
- catch (error) {
54
- console.warn(`Warning: Failed to load config from ${this.configPath}: ${error}`);
27
+ catch (e) {
28
+ const message = e instanceof Error ? e.message : 'Unknown error';
29
+ throw new Error(`Invalid YAML in ${userConfigPath}: ${message}`);
55
30
  }
56
- // Return defaults and save them
57
- this.saveConfig(DEFAULT_CONFIG);
58
- return { ...DEFAULT_CONFIG };
59
31
  }
60
- /**
61
- * Save configuration to file
62
- */
63
- saveConfig(config) {
32
+ // Load project config from current directory
33
+ const projectConfigPath = path.join(process.cwd(), '.arkrc.yaml');
34
+ if (fs.existsSync(projectConfigPath)) {
64
35
  try {
65
- const configContent = JSON.stringify(config, null, 2);
66
- SecurityUtils.validatePath(this.configPath, 'config file');
67
- fs.writeFileSync(this.configPath, configContent, {
68
- mode: 0o600, // Owner read/write only
69
- flag: 'w',
70
- });
36
+ const projectConfig = yaml.parse(fs.readFileSync(projectConfigPath, 'utf-8'));
37
+ mergeConfig(config, projectConfig);
71
38
  }
72
- catch (error) {
73
- throw new ValidationError(`Failed to save configuration: ${error}`, 'config', [
74
- 'Check file permissions',
75
- 'Ensure config directory exists',
76
- 'Verify disk space',
77
- ]);
39
+ catch (e) {
40
+ const message = e instanceof Error ? e.message : 'Unknown error';
41
+ throw new Error(`Invalid YAML in ${projectConfigPath}: ${message}`);
78
42
  }
79
43
  }
80
- /**
81
- * Get the current configuration
82
- */
83
- getConfig() {
84
- return { ...this.config };
85
- }
86
- /**
87
- * Update configuration
88
- */
89
- updateConfig(updates) {
90
- this.config = { ...this.config, ...updates };
91
- this.saveConfig(this.config);
92
- }
93
- /**
94
- * Reset configuration to defaults
95
- */
96
- resetConfig() {
97
- this.config = { ...DEFAULT_CONFIG };
98
- this.saveConfig(this.config);
44
+ // Apply environment variable overrides
45
+ if (process.env.ARK_CHAT_STREAMING !== undefined) {
46
+ config.chat = config.chat || {};
47
+ config.chat.streaming =
48
+ process.env.ARK_CHAT_STREAMING === '1' ||
49
+ process.env.ARK_CHAT_STREAMING === 'true';
99
50
  }
100
- /**
101
- * Get a specific configuration value
102
- */
103
- get(key) {
104
- return this.config[key];
105
- }
106
- /**
107
- * Set a specific configuration value
108
- */
109
- set(key, value) {
110
- this.config[key] = value;
111
- this.saveConfig(this.config);
112
- }
113
- /**
114
- * Validate configuration values
115
- */
116
- validateConfig() {
117
- const config = this.config;
118
- // Validate project type
119
- if (!['empty', 'with-samples'].includes(config.defaultProjectType)) {
120
- throw new ValidationError(`Invalid defaultProjectType: ${config.defaultProjectType}`, 'defaultProjectType', ['Must be "empty" or "with-samples"']);
121
- }
122
- // Validate model provider
123
- const validProviders = ['azure', 'openai', 'claude', 'gemini', 'custom'];
124
- if (!validProviders.includes(config.defaultModelProvider)) {
125
- throw new ValidationError(`Invalid defaultModelProvider: ${config.defaultModelProvider}`, 'defaultModelProvider', [`Must be one of: ${validProviders.join(', ')}`]);
126
- }
127
- // Validate numeric values
128
- if (config.maxConcurrentFiles < 1 || config.maxConcurrentFiles > 100) {
129
- throw new ValidationError(`Invalid maxConcurrentFiles: ${config.maxConcurrentFiles}`, 'maxConcurrentFiles', ['Must be between 1 and 100']);
130
- }
131
- // Validate paths
132
- if (config.defaultDestination) {
133
- SecurityUtils.validatePath(config.defaultDestination, 'default destination');
134
- }
135
- if (config.templateDirectory) {
136
- SecurityUtils.validatePath(config.templateDirectory, 'template directory');
137
- }
138
- }
139
- /**
140
- * Get environment variable overrides
141
- */
142
- getEnvironmentOverrides() {
143
- const overrides = {};
144
- // Check for environment variable overrides
145
- if (process.env.ARK_DEFAULT_PROJECT_TYPE) {
146
- const projectType = process.env.ARK_DEFAULT_PROJECT_TYPE;
147
- if (['empty', 'with-samples'].includes(projectType)) {
148
- overrides.defaultProjectType = projectType;
149
- }
150
- }
151
- if (process.env.ARK_DEFAULT_DESTINATION) {
152
- overrides.defaultDestination = process.env.ARK_DEFAULT_DESTINATION;
51
+ if (process.env.ARK_CHAT_OUTPUT_FORMAT !== undefined) {
52
+ config.chat = config.chat || {};
53
+ const format = process.env.ARK_CHAT_OUTPUT_FORMAT.toLowerCase();
54
+ if (format === 'markdown' || format === 'text') {
55
+ config.chat.outputFormat = format;
153
56
  }
154
- if (process.env.ARK_SKIP_GIT) {
155
- overrides.skipGitByDefault = process.env.ARK_SKIP_GIT === 'true';
156
- }
157
- if (process.env.ARK_SKIP_MODELS) {
158
- overrides.skipModelsbyDefault = process.env.ARK_SKIP_MODELS === 'true';
159
- }
160
- if (process.env.ARK_COLOR_OUTPUT) {
161
- overrides.colorOutput = process.env.ARK_COLOR_OUTPUT !== 'false';
162
- }
163
- if (process.env.ARK_VERBOSE) {
164
- overrides.verboseOutput = process.env.ARK_VERBOSE === 'true';
165
- }
166
- if (process.env.ARK_DEFAULT_MODEL_PROVIDER) {
167
- const provider = process.env.ARK_DEFAULT_MODEL_PROVIDER;
168
- const validProviders = [
169
- 'azure',
170
- 'openai',
171
- 'claude',
172
- 'gemini',
173
- 'custom',
174
- ];
175
- if (validProviders.includes(provider)) {
176
- overrides.defaultModelProvider =
177
- provider;
178
- }
179
- }
180
- return overrides;
181
57
  }
182
- /**
183
- * Get merged configuration with environment overrides
184
- */
185
- getMergedConfig() {
186
- const envOverrides = this.getEnvironmentOverrides();
187
- return { ...this.config, ...envOverrides };
188
- }
189
- /**
190
- * Export configuration for backup
191
- */
192
- exportConfig() {
193
- return JSON.stringify(this.config, null, 2);
194
- }
195
- /**
196
- * Import configuration from backup
197
- */
198
- importConfig(configJson) {
199
- try {
200
- const importedConfig = JSON.parse(configJson);
201
- // Validate the imported config
202
- const tempManager = new ConfigManager();
203
- tempManager.config = { ...DEFAULT_CONFIG, ...importedConfig };
204
- tempManager.validateConfig();
205
- // If validation passes, update our config
206
- this.config = tempManager.config;
207
- this.saveConfig(this.config);
58
+ return config;
59
+ }
60
+ /**
61
+ * Merge source config into target config (mutates target)
62
+ */
63
+ function mergeConfig(target, source) {
64
+ if (source.chat) {
65
+ target.chat = target.chat || {};
66
+ if (source.chat.streaming !== undefined) {
67
+ target.chat.streaming = source.chat.streaming;
208
68
  }
209
- catch (error) {
210
- throw new ValidationError(`Failed to import configuration: ${error}`, 'config', [
211
- 'Check JSON syntax',
212
- 'Ensure all required fields are present',
213
- 'Verify configuration values are valid',
214
- ]);
69
+ if (source.chat.outputFormat !== undefined) {
70
+ target.chat.outputFormat = source.chat.outputFormat;
215
71
  }
216
72
  }
217
- /**
218
- * Get configuration file path for CLI display
219
- */
220
- getConfigFilePath() {
221
- return this.configPath;
222
- }
73
+ }
74
+ /**
75
+ * Get the paths checked for config files
76
+ */
77
+ export function getConfigPaths() {
78
+ return {
79
+ user: path.join(os.homedir(), '.arkrc.yaml'),
80
+ project: path.join(process.cwd(), '.arkrc.yaml'),
81
+ };
82
+ }
83
+ /**
84
+ * Format config as YAML for display
85
+ */
86
+ export function formatConfig(config) {
87
+ return yaml.stringify(config);
223
88
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,99 @@
1
+ import { jest } from '@jest/globals';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ const mockFs = {
5
+ existsSync: jest.fn(),
6
+ readFileSync: jest.fn(),
7
+ };
8
+ jest.unstable_mockModule('fs', () => ({
9
+ default: mockFs,
10
+ ...mockFs,
11
+ }));
12
+ const mockYaml = {
13
+ parse: jest.fn(),
14
+ stringify: jest.fn(),
15
+ };
16
+ jest.unstable_mockModule('yaml', () => ({
17
+ default: mockYaml,
18
+ ...mockYaml,
19
+ }));
20
+ const { loadConfig, getConfigPaths, formatConfig } = await import('./config.js');
21
+ describe('config', () => {
22
+ const originalEnv = process.env;
23
+ beforeEach(() => {
24
+ jest.clearAllMocks();
25
+ process.env = { ...originalEnv };
26
+ });
27
+ afterEach(() => {
28
+ process.env = originalEnv;
29
+ });
30
+ it('returns default config when no files exist', () => {
31
+ mockFs.existsSync.mockReturnValue(false);
32
+ const config = loadConfig();
33
+ expect(config).toEqual({
34
+ chat: {
35
+ streaming: true,
36
+ outputFormat: 'text',
37
+ },
38
+ });
39
+ });
40
+ it('loads and merges configs in order: defaults, user, project', () => {
41
+ mockFs.existsSync.mockReturnValue(true);
42
+ mockFs.readFileSync
43
+ .mockReturnValueOnce('user yaml')
44
+ .mockReturnValueOnce('project yaml');
45
+ mockYaml.parse
46
+ .mockReturnValueOnce({
47
+ chat: {
48
+ streaming: false,
49
+ outputFormat: 'markdown',
50
+ },
51
+ })
52
+ .mockReturnValueOnce({
53
+ chat: {
54
+ streaming: true,
55
+ },
56
+ });
57
+ const config = loadConfig();
58
+ expect(config.chat?.streaming).toBe(true);
59
+ expect(config.chat?.outputFormat).toBe('markdown');
60
+ });
61
+ it('environment variables override all configs', () => {
62
+ mockFs.existsSync.mockReturnValue(false);
63
+ process.env.ARK_CHAT_STREAMING = '1';
64
+ process.env.ARK_CHAT_OUTPUT_FORMAT = 'MARKDOWN';
65
+ const config = loadConfig();
66
+ expect(config.chat?.streaming).toBe(true);
67
+ expect(config.chat?.outputFormat).toBe('markdown');
68
+ });
69
+ it('throws error for invalid YAML', () => {
70
+ const userConfigPath = path.join(os.homedir(), '.arkrc.yaml');
71
+ mockFs.existsSync.mockImplementation((path) => path === userConfigPath);
72
+ mockFs.readFileSync.mockReturnValue('invalid yaml');
73
+ mockYaml.parse.mockImplementation(() => {
74
+ throw new Error('YAML parse error');
75
+ });
76
+ expect(() => loadConfig()).toThrow(`Invalid YAML in ${userConfigPath}: YAML parse error`);
77
+ });
78
+ it('handles non-Error exceptions', () => {
79
+ const userConfigPath = path.join(os.homedir(), '.arkrc.yaml');
80
+ mockFs.existsSync.mockImplementation((path) => path === userConfigPath);
81
+ mockFs.readFileSync.mockReturnValue('invalid yaml');
82
+ mockYaml.parse.mockImplementation(() => {
83
+ throw 'string error';
84
+ });
85
+ expect(() => loadConfig()).toThrow(`Invalid YAML in ${userConfigPath}: Unknown error`);
86
+ });
87
+ it('getConfigPaths returns correct paths', () => {
88
+ const paths = getConfigPaths();
89
+ expect(paths.user).toBe(path.join(os.homedir(), '.arkrc.yaml'));
90
+ expect(paths.project).toBe(path.join(process.cwd(), '.arkrc.yaml'));
91
+ });
92
+ it('formatConfig uses yaml.stringify', () => {
93
+ const config = { chat: { streaming: true, outputFormat: 'text' } };
94
+ mockYaml.stringify.mockReturnValue('formatted');
95
+ const result = formatConfig(config);
96
+ expect(mockYaml.stringify).toHaveBeenCalledWith(config);
97
+ expect(result).toBe('formatted');
98
+ });
99
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,93 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
2
+ import { loadConfig } from './config.js';
3
+ import fs from 'fs';
4
+ import path from 'path';
5
+ import os from 'os';
6
+ describe('Config', () => {
7
+ const originalEnv = process.env;
8
+ const testProjectConfig = path.join(process.cwd(), '.arkrc.yaml');
9
+ const testUserConfig = path.join(os.homedir(), '.arkrc.yaml');
10
+ beforeEach(() => {
11
+ // Reset environment
12
+ process.env = { ...originalEnv };
13
+ // Clean up any existing test configs
14
+ if (fs.existsSync(testProjectConfig)) {
15
+ fs.unlinkSync(testProjectConfig);
16
+ }
17
+ if (fs.existsSync(testUserConfig)) {
18
+ fs.unlinkSync(testUserConfig);
19
+ }
20
+ });
21
+ afterEach(() => {
22
+ // Restore environment
23
+ process.env = originalEnv;
24
+ // Clean up test configs
25
+ if (fs.existsSync(testProjectConfig)) {
26
+ fs.unlinkSync(testProjectConfig);
27
+ }
28
+ if (fs.existsSync(testUserConfig)) {
29
+ fs.unlinkSync(testUserConfig);
30
+ }
31
+ });
32
+ it('should load default config when no files or env vars exist', () => {
33
+ const config = loadConfig();
34
+ expect(config.chat?.streaming).toBe(true);
35
+ expect(config.chat?.outputFormat).toBe('text');
36
+ });
37
+ it('should override defaults with environment variables', () => {
38
+ process.env.ARK_CHAT_STREAMING = '0';
39
+ process.env.ARK_CHAT_OUTPUT_FORMAT = 'markdown';
40
+ const config = loadConfig();
41
+ expect(config.chat?.streaming).toBe(false);
42
+ expect(config.chat?.outputFormat).toBe('markdown');
43
+ });
44
+ it('should accept "1" and "true" for streaming', () => {
45
+ process.env.ARK_CHAT_STREAMING = '1';
46
+ let config = loadConfig();
47
+ expect(config.chat?.streaming).toBe(true);
48
+ process.env.ARK_CHAT_STREAMING = 'true';
49
+ config = loadConfig();
50
+ expect(config.chat?.streaming).toBe(true);
51
+ });
52
+ it('should load project config file', () => {
53
+ const configContent = `
54
+ chat:
55
+ streaming: false
56
+ outputFormat: markdown
57
+ `;
58
+ fs.writeFileSync(testProjectConfig, configContent);
59
+ const config = loadConfig();
60
+ expect(config.chat?.streaming).toBe(false);
61
+ expect(config.chat?.outputFormat).toBe('markdown');
62
+ });
63
+ it('should prioritize env vars over config files', () => {
64
+ const configContent = `
65
+ chat:
66
+ streaming: false
67
+ outputFormat: markdown
68
+ `;
69
+ fs.writeFileSync(testProjectConfig, configContent);
70
+ process.env.ARK_CHAT_STREAMING = '1';
71
+ process.env.ARK_CHAT_OUTPUT_FORMAT = 'text';
72
+ const config = loadConfig();
73
+ expect(config.chat?.streaming).toBe(true);
74
+ expect(config.chat?.outputFormat).toBe('text');
75
+ });
76
+ it('should handle invalid config files gracefully', () => {
77
+ fs.writeFileSync(testProjectConfig, 'invalid: yaml: content: {{{');
78
+ // Should fall back to defaults without throwing
79
+ const config = loadConfig();
80
+ expect(config.chat?.streaming).toBe(true);
81
+ expect(config.chat?.outputFormat).toBe('text');
82
+ });
83
+ it('should handle partial configs', () => {
84
+ const configContent = `
85
+ chat:
86
+ streaming: false
87
+ `;
88
+ fs.writeFileSync(testProjectConfig, configContent);
89
+ const config = loadConfig();
90
+ expect(config.chat?.streaming).toBe(false);
91
+ expect(config.chat?.outputFormat).toBe('text'); // Should use default
92
+ });
93
+ });
@@ -7,4 +7,3 @@ export declare const DEFAULT_ARK_DASHBOARD_URL = "http://localhost:3000";
7
7
  export declare const DEFAULT_ARK_A2A_URL = "http://localhost:8080";
8
8
  export declare const DEFAULT_ARK_MEMORY_URL = "http://localhost:8081";
9
9
  export declare const DEFAULT_ARK_OTEL_URL = "http://localhost:4318";
10
- export declare const ARK_REPO_ERROR_MESSAGE = "Error: This command must be run inside the ARK repository.";
@@ -11,5 +11,3 @@ export const DEFAULT_ARK_DASHBOARD_URL = 'http://localhost:3000';
11
11
  export const DEFAULT_ARK_A2A_URL = 'http://localhost:8080';
12
12
  export const DEFAULT_ARK_MEMORY_URL = 'http://localhost:8081';
13
13
  export const DEFAULT_ARK_OTEL_URL = 'http://localhost:4318';
14
- // Error message for different ARK repo
15
- export const ARK_REPO_ERROR_MESSAGE = 'Error: This command must be run inside the ARK repository.';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,15 @@
1
+ import { describe, it, expect } from '@jest/globals';
2
+ import { DEFAULT_ADDRESS_ARK_API, DEFAULT_TIMEOUT_MS, DEFAULT_CONNECTION_TEST_TIMEOUT_MS, CONFIG_DIR_NAME, CONFIG_FILE_NAME, DEFAULT_ARK_DASHBOARD_URL, DEFAULT_ARK_A2A_URL, DEFAULT_ARK_MEMORY_URL, DEFAULT_ARK_OTEL_URL, } from './consts.js';
3
+ describe('Constants', () => {
4
+ it('defines correct default values', () => {
5
+ expect(DEFAULT_ADDRESS_ARK_API).toBe('http://localhost:8000');
6
+ expect(DEFAULT_TIMEOUT_MS).toBe(30000);
7
+ expect(DEFAULT_CONNECTION_TEST_TIMEOUT_MS).toBe(5000);
8
+ expect(CONFIG_DIR_NAME).toBe('ark');
9
+ expect(CONFIG_FILE_NAME).toBe('ark-cli.json');
10
+ expect(DEFAULT_ARK_DASHBOARD_URL).toBe('http://localhost:3000');
11
+ expect(DEFAULT_ARK_A2A_URL).toBe('http://localhost:8080');
12
+ expect(DEFAULT_ARK_MEMORY_URL).toBe('http://localhost:8081');
13
+ expect(DEFAULT_ARK_OTEL_URL).toBe('http://localhost:4318');
14
+ });
15
+ });
@@ -0,0 +1,30 @@
1
+ import { ArkDevToolStatus, DiscoveryResult, ProjectDiscoveryResult } from './types.js';
2
+ export declare class ArkDevToolAnalyzer {
3
+ private discoverToolsScript;
4
+ constructor();
5
+ /**
6
+ * Analyze a tool directory and return its status
7
+ */
8
+ analyzeToolDirectory(toolPath: string): Promise<ArkDevToolStatus>;
9
+ /**
10
+ * Get project information by checking for Python project files
11
+ */
12
+ private getProjectInfo;
13
+ /**
14
+ * Discover project configuration
15
+ */
16
+ discoverProject(targetPath: string): Promise<ProjectDiscoveryResult | undefined>;
17
+ /**
18
+ * Discover tools using the Python script
19
+ */
20
+ discoverTools(targetPath: string): Promise<DiscoveryResult | undefined>;
21
+ /**
22
+ * Recursively find all MCP tools in a project
23
+ * This is a naive implementation that searches all Python files in the project tree
24
+ */
25
+ findProjectTools(projectRoot: string): Promise<any>;
26
+ /**
27
+ * Extract all tools from discovery result
28
+ */
29
+ private extractTools;
30
+ }