agentvault 1.0.0

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 (188) hide show
  1. package/.dfx/local/network-id +4 -0
  2. package/.next/trace +2 -0
  3. package/.vercel/README.txt +11 -0
  4. package/.vercel/project.json +1 -0
  5. package/AGENTS.md +43 -0
  6. package/CHANGELOG.md +196 -0
  7. package/LICENSE +21 -0
  8. package/PLAN_VAULT_INTEGRATION.md +318 -0
  9. package/README.md +253 -0
  10. package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +28 -0
  11. package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +1 -0
  12. package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +28 -0
  13. package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +1 -0
  14. package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +28 -0
  15. package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +1 -0
  16. package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +28 -0
  17. package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +1 -0
  18. package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +1 -0
  19. package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +28 -0
  20. package/backups/test-backup.json +28 -0
  21. package/dist/cli/commands/approve.d.ts +4 -0
  22. package/dist/cli/commands/approve.js +232 -0
  23. package/dist/cli/commands/archive.d.ts +4 -0
  24. package/dist/cli/commands/archive.js +192 -0
  25. package/dist/cli/commands/backup.d.ts +4 -0
  26. package/dist/cli/commands/backup.js +164 -0
  27. package/dist/cli/commands/cloud-backup.d.ts +4 -0
  28. package/dist/cli/commands/cloud-backup.js +221 -0
  29. package/dist/cli/commands/cycles.d.ts +8 -0
  30. package/dist/cli/commands/cycles.js +83 -0
  31. package/dist/cli/commands/decrypt.d.ts +16 -0
  32. package/dist/cli/commands/decrypt.js +101 -0
  33. package/dist/cli/commands/deploy.d.ts +32 -0
  34. package/dist/cli/commands/deploy.js +208 -0
  35. package/dist/cli/commands/exec.d.ts +26 -0
  36. package/dist/cli/commands/exec.js +109 -0
  37. package/dist/cli/commands/fetch.d.ts +23 -0
  38. package/dist/cli/commands/fetch.js +164 -0
  39. package/dist/cli/commands/health.d.ts +8 -0
  40. package/dist/cli/commands/health.js +72 -0
  41. package/dist/cli/commands/identity.d.ts +8 -0
  42. package/dist/cli/commands/identity.js +140 -0
  43. package/dist/cli/commands/inference.d.ts +4 -0
  44. package/dist/cli/commands/inference.js +225 -0
  45. package/dist/cli/commands/info.d.ts +8 -0
  46. package/dist/cli/commands/info.js +59 -0
  47. package/dist/cli/commands/init.d.ts +19 -0
  48. package/dist/cli/commands/init.js +135 -0
  49. package/dist/cli/commands/instrument.d.ts +8 -0
  50. package/dist/cli/commands/instrument.js +35 -0
  51. package/dist/cli/commands/list.d.ts +36 -0
  52. package/dist/cli/commands/list.js +173 -0
  53. package/dist/cli/commands/logs.d.ts +8 -0
  54. package/dist/cli/commands/logs.js +96 -0
  55. package/dist/cli/commands/monitor.d.ts +8 -0
  56. package/dist/cli/commands/monitor.js +84 -0
  57. package/dist/cli/commands/network.d.ts +14 -0
  58. package/dist/cli/commands/network.js +258 -0
  59. package/dist/cli/commands/package.d.ts +36 -0
  60. package/dist/cli/commands/package.js +188 -0
  61. package/dist/cli/commands/profile.d.ts +8 -0
  62. package/dist/cli/commands/profile.js +76 -0
  63. package/dist/cli/commands/promote.d.ts +8 -0
  64. package/dist/cli/commands/promote.js +89 -0
  65. package/dist/cli/commands/rebuild.d.ts +21 -0
  66. package/dist/cli/commands/rebuild.js +140 -0
  67. package/dist/cli/commands/rollback.d.ts +8 -0
  68. package/dist/cli/commands/rollback.js +120 -0
  69. package/dist/cli/commands/show.d.ts +36 -0
  70. package/dist/cli/commands/show.js +200 -0
  71. package/dist/cli/commands/stats.d.ts +8 -0
  72. package/dist/cli/commands/stats.js +34 -0
  73. package/dist/cli/commands/status.d.ts +14 -0
  74. package/dist/cli/commands/status.js +83 -0
  75. package/dist/cli/commands/test.d.ts +8 -0
  76. package/dist/cli/commands/test.js +109 -0
  77. package/dist/cli/commands/tokens.d.ts +8 -0
  78. package/dist/cli/commands/tokens.js +62 -0
  79. package/dist/cli/commands/trace.d.ts +8 -0
  80. package/dist/cli/commands/trace.js +68 -0
  81. package/dist/cli/commands/wallet-export.d.ts +13 -0
  82. package/dist/cli/commands/wallet-export.js +140 -0
  83. package/dist/cli/commands/wallet-history.d.ts +10 -0
  84. package/dist/cli/commands/wallet-history.js +127 -0
  85. package/dist/cli/commands/wallet-import.d.ts +10 -0
  86. package/dist/cli/commands/wallet-import.js +209 -0
  87. package/dist/cli/commands/wallet-multi-send.d.ts +17 -0
  88. package/dist/cli/commands/wallet-multi-send.js +195 -0
  89. package/dist/cli/commands/wallet-process-queue.d.ts +19 -0
  90. package/dist/cli/commands/wallet-process-queue.js +209 -0
  91. package/dist/cli/commands/wallet-sign.d.ts +13 -0
  92. package/dist/cli/commands/wallet-sign.js +207 -0
  93. package/dist/cli/commands/wallet.d.ts +12 -0
  94. package/dist/cli/commands/wallet.js +794 -0
  95. package/dist/cli/index.d.ts +10 -0
  96. package/dist/cli/index.js +96 -0
  97. package/dist/vitest.config.d.ts +3 -0
  98. package/dist/vitest.config.js +14 -0
  99. package/fixup_1_0_OSS_release.md +136 -0
  100. package/fixup_REALEASE_PRD.md +136 -0
  101. package/package.json +79 -0
  102. package/pnpm-workspace.yaml +5 -0
  103. package/scripts/dev-dashboard.mjs +84 -0
  104. package/site/README.md +63 -0
  105. package/site/docusaurus.config.ts +148 -0
  106. package/site/package-lock.json +18383 -0
  107. package/site/package.json +47 -0
  108. package/site/sidebars.ts +86 -0
  109. package/site/static/.gitkeep +0 -0
  110. package/site/static/img/logo.svg +28 -0
  111. package/site/static/img/og-image.svg +35 -0
  112. package/src/archival/archive-manager.ts +372 -0
  113. package/src/archival/arweave-client.ts +289 -0
  114. package/src/archival/index.ts +8 -0
  115. package/src/backup/backup.ts +315 -0
  116. package/src/backup/index.ts +7 -0
  117. package/src/cloud-storage/cloud-sync.ts +461 -0
  118. package/src/cloud-storage/index.ts +11 -0
  119. package/src/cloud-storage/provider-detector.ts +198 -0
  120. package/src/cloud-storage/types.ts +104 -0
  121. package/src/debugging/index.ts +6 -0
  122. package/src/debugging/logs.ts +193 -0
  123. package/src/debugging/types.ts +100 -0
  124. package/src/deployment/deployer.ts +274 -0
  125. package/src/deployment/icpClient.ts +620 -0
  126. package/src/deployment/index.ts +46 -0
  127. package/src/deployment/promotion.ts +161 -0
  128. package/src/deployment/types.ts +111 -0
  129. package/src/icp/batch.ts +374 -0
  130. package/src/icp/cycles.ts +50 -0
  131. package/src/icp/environment.ts +215 -0
  132. package/src/icp/icpcli.ts +438 -0
  133. package/src/icp/icwasm.ts +222 -0
  134. package/src/icp/identity.ts +77 -0
  135. package/src/icp/index.ts +94 -0
  136. package/src/icp/optimization.ts +242 -0
  137. package/src/icp/tokens.ts +36 -0
  138. package/src/icp/tool-detector.ts +110 -0
  139. package/src/icp/types.ts +574 -0
  140. package/src/index.ts +25 -0
  141. package/src/inference/bittensor-client.ts +304 -0
  142. package/src/inference/index.ts +8 -0
  143. package/src/inference/inference-manager.ts +327 -0
  144. package/src/metrics/index.ts +7 -0
  145. package/src/metrics/metrics.ts +186 -0
  146. package/src/monitoring/alerting.ts +190 -0
  147. package/src/monitoring/health.ts +197 -0
  148. package/src/monitoring/index.ts +38 -0
  149. package/src/monitoring/info.ts +114 -0
  150. package/src/monitoring/types.ts +99 -0
  151. package/src/network/index.ts +5 -0
  152. package/src/network/network-config.ts +129 -0
  153. package/src/packaging/compiler.ts +647 -0
  154. package/src/packaging/config-persistence.ts +135 -0
  155. package/src/packaging/config-schemas.ts +156 -0
  156. package/src/packaging/detector.ts +220 -0
  157. package/src/packaging/index.ts +90 -0
  158. package/src/packaging/packager.ts +118 -0
  159. package/src/packaging/parsers/clawdbot.ts +278 -0
  160. package/src/packaging/parsers/cline.ts +223 -0
  161. package/src/packaging/parsers/generic.ts +266 -0
  162. package/src/packaging/parsers/goose.ts +214 -0
  163. package/src/packaging/parsers/index.ts +11 -0
  164. package/src/packaging/serializer.ts +260 -0
  165. package/src/packaging/types.ts +144 -0
  166. package/src/packaging/wasmedge-compiler.ts +406 -0
  167. package/src/security/index.ts +17 -0
  168. package/src/security/multisig.ts +415 -0
  169. package/src/security/types.ts +416 -0
  170. package/src/security/vetkeys.ts +655 -0
  171. package/src/testing/index.ts +6 -0
  172. package/src/testing/local-runner.ts +264 -0
  173. package/src/testing/types.ts +104 -0
  174. package/src/wallet/cbor-serializer.ts +323 -0
  175. package/src/wallet/chain-dispatcher.ts +313 -0
  176. package/src/wallet/cross-chain-aggregator.ts +346 -0
  177. package/src/wallet/index.ts +76 -0
  178. package/src/wallet/key-derivation.ts +425 -0
  179. package/src/wallet/providers/base-provider.ts +154 -0
  180. package/src/wallet/providers/cketh-provider.ts +434 -0
  181. package/src/wallet/providers/polkadot-provider.ts +503 -0
  182. package/src/wallet/providers/solana-provider.ts +490 -0
  183. package/src/wallet/transaction-queue.ts +284 -0
  184. package/src/wallet/types.ts +178 -0
  185. package/src/wallet/vetkeys-adapter.ts +431 -0
  186. package/src/wallet/wallet-manager.ts +597 -0
  187. package/src/wallet/wallet-storage.ts +380 -0
  188. package/vercel.json +8 -0
@@ -0,0 +1,278 @@
1
+ /**
2
+ * Clawdbot Configuration Parser
3
+ *
4
+ * Parses Clawdbot agent configuration from .clawdbot directory.
5
+ * Reads JSON files and constructs full configuration object.
6
+ */
7
+
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import type {
11
+ ClawdbotConfig,
12
+ ConfigLocation,
13
+ ConfigValidationResult,
14
+ } from '../config-schemas.js';
15
+ import {
16
+ DEFAULT_CLAWDBOT_SETTINGS,
17
+ type ClawdbotProject,
18
+ type ClawdbotTask,
19
+ type ClawdbotSettings,
20
+ } from '../config-schemas.js';
21
+
22
+ /**
23
+ * Find Clawdbot directory or configuration file
24
+ */
25
+ function findClawdbotConfig(sourcePath: string): ConfigLocation | null {
26
+ const absolutePath = path.resolve(sourcePath);
27
+
28
+ // Check for .clawdbot directory
29
+ const clawdbotDir = path.join(absolutePath, '.clawdbot');
30
+ if (fs.existsSync(clawdbotDir)) {
31
+ return {
32
+ path: clawdbotDir,
33
+ type: 'directory',
34
+ };
35
+ }
36
+
37
+ // Check for clawdbot.json or clawdbot.config.json
38
+ const configFiles = ['clawdbot.json', 'clawdbot.config.json'];
39
+ for (const file of configFiles) {
40
+ const filePath = path.join(absolutePath, file);
41
+ if (fs.existsSync(filePath)) {
42
+ return {
43
+ path: filePath,
44
+ type: 'json',
45
+ };
46
+ }
47
+ }
48
+
49
+ return null;
50
+ }
51
+
52
+ /**
53
+ * Read and parse .clawdbot directory structure
54
+ */
55
+ function readClawdbotDirectory(dirPath: string): ClawdbotConfig {
56
+ try {
57
+ // Read projects
58
+ const projectsPath = path.join(dirPath, 'projects.json');
59
+ let projects: ClawdbotProject[] = [];
60
+ if (fs.existsSync(projectsPath)) {
61
+ const projectsContent = fs.readFileSync(projectsPath, 'utf-8');
62
+ projects = JSON.parse(projectsContent);
63
+ }
64
+
65
+ // Read tasks
66
+ const tasksPath = path.join(dirPath, 'tasks.json');
67
+ let tasks: ClawdbotTask[] = [];
68
+ if (fs.existsSync(tasksPath)) {
69
+ const tasksContent = fs.readFileSync(tasksPath, 'utf-8');
70
+ tasks = JSON.parse(tasksContent);
71
+ }
72
+
73
+ // Read context
74
+ const contextPath = path.join(dirPath, 'context.json');
75
+ let context: Record<string, unknown> = {};
76
+ if (fs.existsSync(contextPath)) {
77
+ const contextContent = fs.readFileSync(contextPath, 'utf-8');
78
+ context = JSON.parse(contextContent);
79
+ }
80
+
81
+ // Read settings
82
+ const settingsPath = path.join(dirPath, 'settings.json');
83
+ let settings: ClawdbotSettings = { ...DEFAULT_CLAWDBOT_SETTINGS };
84
+ if (fs.existsSync(settingsPath)) {
85
+ const settingsContent = fs.readFileSync(settingsPath, 'utf-8');
86
+ const parsedSettings = JSON.parse(settingsContent);
87
+ settings = { ...DEFAULT_CLAWDBOT_SETTINGS, ...parsedSettings };
88
+ }
89
+
90
+ // Read main config file if exists
91
+ let name = 'clawdbot-agent';
92
+ let version = '1.0.0';
93
+ let description = '';
94
+
95
+ const configPath = path.join(dirPath, 'config.json');
96
+ if (fs.existsSync(configPath)) {
97
+ const configContent = fs.readFileSync(configPath, 'utf-8');
98
+ const configFile = JSON.parse(configContent);
99
+ name = configFile.name || name;
100
+ version = configFile.version || version;
101
+ description = configFile.description || description;
102
+ }
103
+
104
+ const parsedConfig: ClawdbotConfig = {
105
+ type: 'clawdbot',
106
+ name,
107
+ version,
108
+ description,
109
+ projects,
110
+ tasks,
111
+ context,
112
+ settings,
113
+ };
114
+
115
+ return parsedConfig;
116
+ } catch (error) {
117
+ const message = error instanceof Error ? error.message : 'Unknown error';
118
+ throw new Error(`Failed to parse Clawdbot config: ${message}`);
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Validate Clawdbot configuration
124
+ */
125
+ function validateClawdbotConfig(config: ClawdbotConfig): ConfigValidationResult {
126
+ const errors: string[] = [];
127
+ const warnings: string[] = [];
128
+
129
+ // Validate name
130
+ if (!config.name || config.name.trim() === '') {
131
+ errors.push('Agent name is required');
132
+ }
133
+
134
+ // Validate version format
135
+ if (config.version) {
136
+ const versionRegex = /^\d+\.\d+\.\d+$/;
137
+ if (!versionRegex.test(config.version)) {
138
+ errors.push(`Invalid version format: ${config.version}. Expected: X.Y.Z`);
139
+ }
140
+ }
141
+
142
+ // Validate settings
143
+ if (config.settings) {
144
+ // Validate temperature (must be between 0 and 2)
145
+ if (config.settings.temperature !== undefined) {
146
+ if (config.settings.temperature < 0 || config.settings.temperature > 2) {
147
+ errors.push(`Temperature must be between 0 and 2, got: ${config.settings.temperature}`);
148
+ }
149
+ }
150
+
151
+ // Validate maxTokens (must be positive)
152
+ if (config.settings.maxTokens !== undefined) {
153
+ if (config.settings.maxTokens <= 0) {
154
+ errors.push(`maxTokens must be positive, got: ${config.settings.maxTokens}`);
155
+ }
156
+ }
157
+ }
158
+
159
+ // Validate projects
160
+ if (config.projects && config.projects.length === 0) {
161
+ warnings.push('No projects defined in configuration');
162
+ }
163
+
164
+ // Validate tasks
165
+ if (config.tasks && config.tasks.length === 0) {
166
+ warnings.push('No tasks defined in configuration');
167
+ }
168
+
169
+ return {
170
+ valid: errors.length === 0,
171
+ errors,
172
+ warnings,
173
+ };
174
+ }
175
+
176
+ /**
177
+ * Parse Clawdbot agent configuration
178
+ *
179
+ * This function reads .clawdbot directory or clawdbot.json file
180
+ * and returns a fully validated configuration object.
181
+ */
182
+ export async function parseClawdbotConfig(
183
+ sourcePath: string,
184
+ verbose: boolean = false
185
+ ): Promise<ClawdbotConfig> {
186
+ if (verbose) {
187
+ console.log(`[Clawdbot] Parsing configuration from: ${sourcePath}`);
188
+ }
189
+
190
+ const configLocation = findClawdbotConfig(sourcePath);
191
+
192
+ if (configLocation === null) {
193
+ throw new Error(
194
+ 'No Clawdbot configuration found. ' +
195
+ 'Expected .clawdbot directory or clawdbot.json file in the agent source path.'
196
+ );
197
+ }
198
+
199
+ let config: ClawdbotConfig;
200
+
201
+ if (configLocation.type === 'json') {
202
+ if (verbose) {
203
+ console.log(`[Clawdbot] Found JSON config: ${configLocation.path}`);
204
+ }
205
+ const content = fs.readFileSync(configLocation.path, 'utf-8');
206
+ const parsed = JSON.parse(content);
207
+ const settings = { ...DEFAULT_CLAWDBOT_SETTINGS, ...parsed.settings };
208
+ config = {
209
+ type: 'clawdbot',
210
+ name: parsed.name || 'clawdbot-agent',
211
+ version: parsed.version || '1.0.0',
212
+ description: parsed.description || '',
213
+ settings,
214
+ projects: parsed.projects || [],
215
+ tasks: parsed.tasks || [],
216
+ context: parsed.context || {},
217
+ };
218
+ } else {
219
+ if (verbose) {
220
+ console.log(`[Clawdbot] Found directory: ${configLocation.path}`);
221
+ }
222
+ config = readClawdbotDirectory(configLocation.path);
223
+ if (verbose) {
224
+ console.log(`[Clawdbot] Parsed projects: ${config.projects?.length || 0}`);
225
+ console.log(`[Clawdbot] Parsed tasks: ${config.tasks?.length || 0}`);
226
+ console.log(`[Clawdbot] Parsed context keys: ${Object.keys(config.context || {}).length}`);
227
+ if (config.settings) {
228
+ console.log(`[Clawdbot] Model: ${config.settings.model}`);
229
+ console.log(`[Clawdbot] Temperature: ${config.settings.temperature}`);
230
+ console.log(`[Clawdbot] Max Tokens: ${config.settings.maxTokens}`);
231
+ }
232
+ }
233
+ }
234
+
235
+ const validation = validateClawdbotConfig(config);
236
+
237
+ if (verbose || !validation.valid) {
238
+ if (validation.errors.length > 0) {
239
+ console.error('[Clawdbot] Validation errors:');
240
+ validation.errors.forEach((error) => console.error(` - ${error}`));
241
+ }
242
+ if (validation.warnings.length > 0) {
243
+ console.warn('[Clawdbot] Warnings:');
244
+ validation.warnings.forEach((warning) => console.warn(` - ${warning}`));
245
+ }
246
+ }
247
+
248
+ if (!validation.valid) {
249
+ throw new Error(
250
+ `Clawdbot configuration validation failed: ${validation.errors.join('; ')}`
251
+ );
252
+ }
253
+
254
+ return config;
255
+ }
256
+
257
+ /**
258
+ * Find all Clawdbot configurations in a directory
259
+ */
260
+ export async function findClawdbotConfigs(dir: string): Promise<string[]> {
261
+ const results: string[] = [];
262
+
263
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
264
+ for (const entry of entries) {
265
+ const entryPath = path.join(dir, entry.name);
266
+
267
+ if (entry.isDirectory()) {
268
+ try {
269
+ await parseClawdbotConfig(entryPath);
270
+ results.push(entry.name);
271
+ } catch {
272
+ // Skip directories that aren't valid Clawdbot configs
273
+ }
274
+ }
275
+ }
276
+
277
+ return results;
278
+ }
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Cline Configuration Parser
3
+ *
4
+ * Parses Cline agent configuration from JSON files.
5
+ * Reads cline.json, cline.config.json, or .cline file and constructs configuration object.
6
+ */
7
+
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import type {
11
+ ClineConfig,
12
+ ConfigLocation,
13
+ ConfigValidationResult,
14
+ } from '../config-schemas.js';
15
+ import {
16
+ DEFAULT_CLINE_CONFIG,
17
+ } from '../config-schemas.js';
18
+
19
+ /**
20
+ * Find Cline configuration file
21
+ */
22
+ function findClineConfig(sourcePath: string): ConfigLocation | null {
23
+ const absolutePath = path.resolve(sourcePath);
24
+
25
+ // Check for JSON config files
26
+ const configFiles = ['cline.json', 'cline.config.json', '.cline'];
27
+ for (const file of configFiles) {
28
+ const filePath = path.join(absolutePath, file);
29
+ if (fs.existsSync(filePath)) {
30
+ return {
31
+ path: filePath,
32
+ type: 'json',
33
+ };
34
+ }
35
+ }
36
+
37
+ return null;
38
+ }
39
+
40
+ /**
41
+ * Validate Cline configuration
42
+ */
43
+ function validateClineConfig(config: ClineConfig): ConfigValidationResult {
44
+ const errors: string[] = [];
45
+ const warnings: string[] = [];
46
+
47
+ // Validate name
48
+ if (!config.name || config.name.trim() === '') {
49
+ errors.push('Agent name is required');
50
+ }
51
+
52
+ // Validate mode
53
+ if (config.mode && !['auto', 'request'].includes(config.mode)) {
54
+ errors.push(`Invalid mode: ${config.mode}. Must be 'auto' or 'request'`);
55
+ }
56
+
57
+ // Validate claudeVersion format if specified
58
+ if (config.claudeVersion) {
59
+ // Basic version format validation
60
+ const versionRegex = /^\d+\.\d+/;
61
+ if (!versionRegex.test(config.claudeVersion)) {
62
+ warnings.push(`Unusual claudeVersion format: ${config.claudeVersion}`);
63
+ }
64
+ }
65
+
66
+ // Validate version format
67
+ if (config.version) {
68
+ const versionRegex = /^\d+\.\d+\.\d+$/;
69
+ if (!versionRegex.test(config.version)) {
70
+ errors.push(`Invalid version format: ${config.version}. Expected: X.Y.Z`);
71
+ }
72
+ }
73
+
74
+ // Validate working directory exists (if specified)
75
+ if (config.workingDirectory) {
76
+ const workingDirPath = path.resolve(process.cwd(), config.workingDirectory);
77
+ if (!fs.existsSync(workingDirPath)) {
78
+ warnings.push(`Working directory does not exist: ${config.workingDirectory}`);
79
+ }
80
+ }
81
+
82
+ // Validate allowedCommands format if specified
83
+ if (config.allowedCommands) {
84
+ if (!Array.isArray(config.allowedCommands)) {
85
+ errors.push('allowedCommands must be an array');
86
+ } else {
87
+ for (const cmd of config.allowedCommands) {
88
+ if (typeof cmd !== 'string' || cmd.trim() === '') {
89
+ errors.push(`Invalid command in allowedCommands: ${cmd}`);
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ // Warn if no allowedCommands defined in auto mode
96
+ if (config.mode === 'auto' && (!config.allowedCommands || config.allowedCommands.length === 0)) {
97
+ warnings.push('Auto mode without allowedCommands may execute dangerous commands');
98
+ }
99
+
100
+ return {
101
+ valid: errors.length === 0,
102
+ errors,
103
+ warnings,
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Parse Cline agent configuration
109
+ *
110
+ * This function reads cline.json, cline.config.json, or .cline file
111
+ * and returns a fully validated configuration object.
112
+ *
113
+ * @param sourcePath - Path to agent source directory
114
+ * @param verbose - Enable verbose logging
115
+ * @returns Parsed and validated Cline configuration
116
+ */
117
+ export async function parseClineConfig(
118
+ sourcePath: string,
119
+ verbose: boolean = false
120
+ ): Promise<ClineConfig> {
121
+ if (verbose) {
122
+ console.log(`[Cline] Parsing configuration from: ${sourcePath}`);
123
+ }
124
+
125
+ const configLocation = findClineConfig(sourcePath);
126
+
127
+ if (configLocation === null) {
128
+ throw new Error(
129
+ 'No Cline configuration found. ' +
130
+ 'Expected cline.json, cline.config.json, or .cline file in the agent source path.'
131
+ );
132
+ }
133
+
134
+ if (verbose) {
135
+ console.log(`[Cline] Found JSON config: ${configLocation.path}`);
136
+ }
137
+
138
+ let config: ClineConfig;
139
+
140
+ try {
141
+ const content = fs.readFileSync(configLocation.path, 'utf-8');
142
+ const parsed = JSON.parse(content);
143
+
144
+ // Merge with defaults
145
+ config = {
146
+ type: 'cline',
147
+ name: parsed.name || DEFAULT_CLINE_CONFIG.name,
148
+ version: parsed.version || DEFAULT_CLINE_CONFIG.version,
149
+ description: parsed.description || DEFAULT_CLINE_CONFIG.description,
150
+ mode: parsed.mode || DEFAULT_CLINE_CONFIG.mode,
151
+ claudeVersion: parsed.claudeVersion,
152
+ workingDirectory: parsed.workingDirectory || DEFAULT_CLINE_CONFIG.workingDirectory,
153
+ autoConfirm: parsed.autoConfirm !== undefined ? parsed.autoConfirm : DEFAULT_CLINE_CONFIG.autoConfirm,
154
+ useReadline: parsed.useReadline !== undefined ? parsed.useReadline : DEFAULT_CLINE_CONFIG.useReadline,
155
+ allowedCommands: parsed.allowedCommands || [],
156
+ };
157
+
158
+ if (verbose) {
159
+ console.log(`[Cline] Parsed name: ${config.name}`);
160
+ console.log(`[Cline] Parsed version: ${config.version}`);
161
+ console.log(`[Cline] Parsed mode: ${config.mode}`);
162
+ console.log(`[Cline] Parsed claudeVersion: ${config.claudeVersion || 'default'}`);
163
+ console.log(`[Cline] Parsed workingDirectory: ${config.workingDirectory}`);
164
+ console.log(`[Cline] Parsed autoConfirm: ${config.autoConfirm}`);
165
+ console.log(`[Cline] Parsed useReadline: ${config.useReadline}`);
166
+ console.log(`[Cline] Parsed allowedCommands: ${config.allowedCommands?.length || 0}`);
167
+ }
168
+ } catch (error) {
169
+ const message = error instanceof Error ? error.message : 'Unknown error';
170
+ throw new Error(`Failed to parse Cline config: ${message}`);
171
+ }
172
+
173
+ // Validate configuration
174
+ const validation = validateClineConfig(config);
175
+
176
+ if (!validation.valid) {
177
+ const errorMessage = `Cline configuration validation failed:\n${validation.errors.map(e => ` - ${e}`).join('\n')}`;
178
+ throw new Error(errorMessage);
179
+ }
180
+
181
+ // Display warnings if verbose
182
+ if (verbose && validation.warnings.length > 0) {
183
+ console.log(`[Cline] Warnings:`);
184
+ for (const warning of validation.warnings) {
185
+ console.log(`[Cline] - ${warning}`);
186
+ }
187
+ }
188
+
189
+ return config;
190
+ }
191
+
192
+ /**
193
+ * Find all Cline configurations in a directory tree
194
+ *
195
+ * @param rootPath - Root directory to search
196
+ * @returns Array of paths to Cline configuration files
197
+ */
198
+ export function findClineConfigs(rootPath: string): string[] {
199
+ const configs: string[] = [];
200
+
201
+ function searchDirectory(dirPath: string): void {
202
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
203
+
204
+ for (const entry of entries) {
205
+ const fullPath = path.join(dirPath, entry.name);
206
+
207
+ if (entry.isDirectory()) {
208
+ // Skip node_modules and .git
209
+ if (entry.name !== 'node_modules' && entry.name !== '.git') {
210
+ searchDirectory(fullPath);
211
+ }
212
+ } else if (entry.isFile()) {
213
+ // Check for Cline config files
214
+ if (entry.name === 'cline.json' || entry.name === 'cline.config.json' || entry.name === '.cline') {
215
+ configs.push(fullPath);
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ searchDirectory(rootPath);
222
+ return configs;
223
+ }