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.
- package/.dfx/local/network-id +4 -0
- package/.next/trace +2 -0
- package/.vercel/README.txt +11 -0
- package/.vercel/project.json +1 -0
- package/AGENTS.md +43 -0
- package/CHANGELOG.md +196 -0
- package/LICENSE +21 -0
- package/PLAN_VAULT_INTEGRATION.md +318 -0
- package/README.md +253 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-28-967Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-54-29-032Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-373Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T17-57-42-428Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-132Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-52-25-247Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-216Z.json +28 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T18-54-09-283Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-772Z.backup +1 -0
- package/backups/agentvault-backup-test-agent-2026-02-12T22-18-22-793Z.json +28 -0
- package/backups/test-backup.json +28 -0
- package/dist/cli/commands/approve.d.ts +4 -0
- package/dist/cli/commands/approve.js +232 -0
- package/dist/cli/commands/archive.d.ts +4 -0
- package/dist/cli/commands/archive.js +192 -0
- package/dist/cli/commands/backup.d.ts +4 -0
- package/dist/cli/commands/backup.js +164 -0
- package/dist/cli/commands/cloud-backup.d.ts +4 -0
- package/dist/cli/commands/cloud-backup.js +221 -0
- package/dist/cli/commands/cycles.d.ts +8 -0
- package/dist/cli/commands/cycles.js +83 -0
- package/dist/cli/commands/decrypt.d.ts +16 -0
- package/dist/cli/commands/decrypt.js +101 -0
- package/dist/cli/commands/deploy.d.ts +32 -0
- package/dist/cli/commands/deploy.js +208 -0
- package/dist/cli/commands/exec.d.ts +26 -0
- package/dist/cli/commands/exec.js +109 -0
- package/dist/cli/commands/fetch.d.ts +23 -0
- package/dist/cli/commands/fetch.js +164 -0
- package/dist/cli/commands/health.d.ts +8 -0
- package/dist/cli/commands/health.js +72 -0
- package/dist/cli/commands/identity.d.ts +8 -0
- package/dist/cli/commands/identity.js +140 -0
- package/dist/cli/commands/inference.d.ts +4 -0
- package/dist/cli/commands/inference.js +225 -0
- package/dist/cli/commands/info.d.ts +8 -0
- package/dist/cli/commands/info.js +59 -0
- package/dist/cli/commands/init.d.ts +19 -0
- package/dist/cli/commands/init.js +135 -0
- package/dist/cli/commands/instrument.d.ts +8 -0
- package/dist/cli/commands/instrument.js +35 -0
- package/dist/cli/commands/list.d.ts +36 -0
- package/dist/cli/commands/list.js +173 -0
- package/dist/cli/commands/logs.d.ts +8 -0
- package/dist/cli/commands/logs.js +96 -0
- package/dist/cli/commands/monitor.d.ts +8 -0
- package/dist/cli/commands/monitor.js +84 -0
- package/dist/cli/commands/network.d.ts +14 -0
- package/dist/cli/commands/network.js +258 -0
- package/dist/cli/commands/package.d.ts +36 -0
- package/dist/cli/commands/package.js +188 -0
- package/dist/cli/commands/profile.d.ts +8 -0
- package/dist/cli/commands/profile.js +76 -0
- package/dist/cli/commands/promote.d.ts +8 -0
- package/dist/cli/commands/promote.js +89 -0
- package/dist/cli/commands/rebuild.d.ts +21 -0
- package/dist/cli/commands/rebuild.js +140 -0
- package/dist/cli/commands/rollback.d.ts +8 -0
- package/dist/cli/commands/rollback.js +120 -0
- package/dist/cli/commands/show.d.ts +36 -0
- package/dist/cli/commands/show.js +200 -0
- package/dist/cli/commands/stats.d.ts +8 -0
- package/dist/cli/commands/stats.js +34 -0
- package/dist/cli/commands/status.d.ts +14 -0
- package/dist/cli/commands/status.js +83 -0
- package/dist/cli/commands/test.d.ts +8 -0
- package/dist/cli/commands/test.js +109 -0
- package/dist/cli/commands/tokens.d.ts +8 -0
- package/dist/cli/commands/tokens.js +62 -0
- package/dist/cli/commands/trace.d.ts +8 -0
- package/dist/cli/commands/trace.js +68 -0
- package/dist/cli/commands/wallet-export.d.ts +13 -0
- package/dist/cli/commands/wallet-export.js +140 -0
- package/dist/cli/commands/wallet-history.d.ts +10 -0
- package/dist/cli/commands/wallet-history.js +127 -0
- package/dist/cli/commands/wallet-import.d.ts +10 -0
- package/dist/cli/commands/wallet-import.js +209 -0
- package/dist/cli/commands/wallet-multi-send.d.ts +17 -0
- package/dist/cli/commands/wallet-multi-send.js +195 -0
- package/dist/cli/commands/wallet-process-queue.d.ts +19 -0
- package/dist/cli/commands/wallet-process-queue.js +209 -0
- package/dist/cli/commands/wallet-sign.d.ts +13 -0
- package/dist/cli/commands/wallet-sign.js +207 -0
- package/dist/cli/commands/wallet.d.ts +12 -0
- package/dist/cli/commands/wallet.js +794 -0
- package/dist/cli/index.d.ts +10 -0
- package/dist/cli/index.js +96 -0
- package/dist/vitest.config.d.ts +3 -0
- package/dist/vitest.config.js +14 -0
- package/fixup_1_0_OSS_release.md +136 -0
- package/fixup_REALEASE_PRD.md +136 -0
- package/package.json +79 -0
- package/pnpm-workspace.yaml +5 -0
- package/scripts/dev-dashboard.mjs +84 -0
- package/site/README.md +63 -0
- package/site/docusaurus.config.ts +148 -0
- package/site/package-lock.json +18383 -0
- package/site/package.json +47 -0
- package/site/sidebars.ts +86 -0
- package/site/static/.gitkeep +0 -0
- package/site/static/img/logo.svg +28 -0
- package/site/static/img/og-image.svg +35 -0
- package/src/archival/archive-manager.ts +372 -0
- package/src/archival/arweave-client.ts +289 -0
- package/src/archival/index.ts +8 -0
- package/src/backup/backup.ts +315 -0
- package/src/backup/index.ts +7 -0
- package/src/cloud-storage/cloud-sync.ts +461 -0
- package/src/cloud-storage/index.ts +11 -0
- package/src/cloud-storage/provider-detector.ts +198 -0
- package/src/cloud-storage/types.ts +104 -0
- package/src/debugging/index.ts +6 -0
- package/src/debugging/logs.ts +193 -0
- package/src/debugging/types.ts +100 -0
- package/src/deployment/deployer.ts +274 -0
- package/src/deployment/icpClient.ts +620 -0
- package/src/deployment/index.ts +46 -0
- package/src/deployment/promotion.ts +161 -0
- package/src/deployment/types.ts +111 -0
- package/src/icp/batch.ts +374 -0
- package/src/icp/cycles.ts +50 -0
- package/src/icp/environment.ts +215 -0
- package/src/icp/icpcli.ts +438 -0
- package/src/icp/icwasm.ts +222 -0
- package/src/icp/identity.ts +77 -0
- package/src/icp/index.ts +94 -0
- package/src/icp/optimization.ts +242 -0
- package/src/icp/tokens.ts +36 -0
- package/src/icp/tool-detector.ts +110 -0
- package/src/icp/types.ts +574 -0
- package/src/index.ts +25 -0
- package/src/inference/bittensor-client.ts +304 -0
- package/src/inference/index.ts +8 -0
- package/src/inference/inference-manager.ts +327 -0
- package/src/metrics/index.ts +7 -0
- package/src/metrics/metrics.ts +186 -0
- package/src/monitoring/alerting.ts +190 -0
- package/src/monitoring/health.ts +197 -0
- package/src/monitoring/index.ts +38 -0
- package/src/monitoring/info.ts +114 -0
- package/src/monitoring/types.ts +99 -0
- package/src/network/index.ts +5 -0
- package/src/network/network-config.ts +129 -0
- package/src/packaging/compiler.ts +647 -0
- package/src/packaging/config-persistence.ts +135 -0
- package/src/packaging/config-schemas.ts +156 -0
- package/src/packaging/detector.ts +220 -0
- package/src/packaging/index.ts +90 -0
- package/src/packaging/packager.ts +118 -0
- package/src/packaging/parsers/clawdbot.ts +278 -0
- package/src/packaging/parsers/cline.ts +223 -0
- package/src/packaging/parsers/generic.ts +266 -0
- package/src/packaging/parsers/goose.ts +214 -0
- package/src/packaging/parsers/index.ts +11 -0
- package/src/packaging/serializer.ts +260 -0
- package/src/packaging/types.ts +144 -0
- package/src/packaging/wasmedge-compiler.ts +406 -0
- package/src/security/index.ts +17 -0
- package/src/security/multisig.ts +415 -0
- package/src/security/types.ts +416 -0
- package/src/security/vetkeys.ts +655 -0
- package/src/testing/index.ts +6 -0
- package/src/testing/local-runner.ts +264 -0
- package/src/testing/types.ts +104 -0
- package/src/wallet/cbor-serializer.ts +323 -0
- package/src/wallet/chain-dispatcher.ts +313 -0
- package/src/wallet/cross-chain-aggregator.ts +346 -0
- package/src/wallet/index.ts +76 -0
- package/src/wallet/key-derivation.ts +425 -0
- package/src/wallet/providers/base-provider.ts +154 -0
- package/src/wallet/providers/cketh-provider.ts +434 -0
- package/src/wallet/providers/polkadot-provider.ts +503 -0
- package/src/wallet/providers/solana-provider.ts +490 -0
- package/src/wallet/transaction-queue.ts +284 -0
- package/src/wallet/types.ts +178 -0
- package/src/wallet/vetkeys-adapter.ts +431 -0
- package/src/wallet/wallet-manager.ts +597 -0
- package/src/wallet/wallet-storage.ts +380 -0
- 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
|
+
}
|