@codemieai/cdk 0.1.288 → 0.1.290
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/cli/index.js +249 -28
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -78,6 +78,9 @@ The `.env` file is already added to `.gitignore` and should never be committed t
|
|
|
78
78
|
## Quick Start
|
|
79
79
|
|
|
80
80
|
```bash
|
|
81
|
+
# Initialize a new Codemie IaC project (creates .env and codemie.yaml via wizard)
|
|
82
|
+
codemie init
|
|
83
|
+
|
|
81
84
|
# Full validation with API connectivity check (default, recommended)
|
|
82
85
|
npm run validate
|
|
83
86
|
|
|
@@ -104,6 +107,22 @@ npm run <command> --config codemie/iac.json
|
|
|
104
107
|
```
|
|
105
108
|
**Note:** All commands work identically whether you use monolithic configuration or modular imports - the `$import` directives are automatically resolved during config loading.
|
|
106
109
|
|
|
110
|
+
### Project Initialization (`codemie init`)
|
|
111
|
+
|
|
112
|
+
Use the interactive wizard to scaffold a project:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
codemie init
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
What it does:
|
|
119
|
+
- Creates a `.env` template (with a safety prompt if it already exists)
|
|
120
|
+
- Generates a minimal `codemie.yaml` using your project name and description
|
|
121
|
+
- Saves an optional `appConfig` file when you pick non-default paths for config/state/backups
|
|
122
|
+
- Prints next steps to validate and deploy
|
|
123
|
+
|
|
124
|
+
If `.env` or `codemie.yaml` already exist, the wizard asks before overwriting and will keep your files if you decline.
|
|
125
|
+
|
|
107
126
|
**Config file structure:**
|
|
108
127
|
```json
|
|
109
128
|
{
|
package/dist/cli/index.js
CHANGED
|
@@ -9,10 +9,11 @@ import * as crypto from 'crypto';
|
|
|
9
9
|
import * as yaml3 from 'yaml';
|
|
10
10
|
import { CodeMieClient, DataSourceType } from 'codemie-sdk';
|
|
11
11
|
import pLimit from 'p-limit';
|
|
12
|
+
import * as readline from 'readline';
|
|
12
13
|
|
|
13
14
|
// package.json
|
|
14
15
|
var package_default = {
|
|
15
|
-
version: "0.1.
|
|
16
|
+
version: "0.1.290"};
|
|
16
17
|
var appConfigSchema = z.object({
|
|
17
18
|
rootDir: z.string(),
|
|
18
19
|
codemieConfig: z.string(),
|
|
@@ -1275,28 +1276,28 @@ Import chain: ${[...visitedFiles].join(" \u2192 ")} \u2192 ${normalizedPath}`
|
|
|
1275
1276
|
* @param rootConfig - Root config object (constant reference for resolving paths like "imported.integrations.xxx")
|
|
1276
1277
|
* @param path - Current path in config tree (for error messages, e.g., "resources.assistants[0].toolkits")
|
|
1277
1278
|
*/
|
|
1278
|
-
resolveReferencesRecursive(current, rootConfig,
|
|
1279
|
+
resolveReferencesRecursive(current, rootConfig, path15 = "") {
|
|
1279
1280
|
if (!current || typeof current !== "object") {
|
|
1280
1281
|
return;
|
|
1281
1282
|
}
|
|
1282
1283
|
if (Array.isArray(current)) {
|
|
1283
|
-
this.resolveArrayReferences(current, rootConfig,
|
|
1284
|
+
this.resolveArrayReferences(current, rootConfig, path15);
|
|
1284
1285
|
return;
|
|
1285
1286
|
}
|
|
1286
1287
|
if ("$ref" in current && typeof current.$ref === "string") {
|
|
1287
|
-
this.resolveObjectReference(current, rootConfig,
|
|
1288
|
+
this.resolveObjectReference(current, rootConfig, path15);
|
|
1288
1289
|
return;
|
|
1289
1290
|
}
|
|
1290
|
-
this.resolveObjectProperties(current, rootConfig,
|
|
1291
|
+
this.resolveObjectProperties(current, rootConfig, path15);
|
|
1291
1292
|
}
|
|
1292
1293
|
/**
|
|
1293
1294
|
* Resolve $ref items in arrays and flatten if they point to arrays
|
|
1294
1295
|
* Example: [{ $ref: "context_definitions.repos" }] where repos is [item1, item2]
|
|
1295
1296
|
* becomes [item1, item2]
|
|
1296
1297
|
*/
|
|
1297
|
-
resolveArrayReferences(arr, rootConfig,
|
|
1298
|
+
resolveArrayReferences(arr, rootConfig, path15) {
|
|
1298
1299
|
const result = arr.flatMap((item, i) => {
|
|
1299
|
-
const contextPath = `${
|
|
1300
|
+
const contextPath = `${path15}[${i}]`;
|
|
1300
1301
|
if (!this.isRefObject(item) || item.$ref.startsWith("#")) {
|
|
1301
1302
|
this.resolveReferencesRecursive(item, rootConfig, contextPath);
|
|
1302
1303
|
return [item];
|
|
@@ -1314,9 +1315,9 @@ Import chain: ${[...visitedFiles].join(" \u2192 ")} \u2192 ${normalizedPath}`
|
|
|
1314
1315
|
* Resolve object reference: { $ref: "path" }
|
|
1315
1316
|
* Replaces object with resolved data (in-place mutation)
|
|
1316
1317
|
*/
|
|
1317
|
-
resolveObjectReference(current, rootConfig,
|
|
1318
|
+
resolveObjectReference(current, rootConfig, path15) {
|
|
1318
1319
|
const refPath = current.$ref;
|
|
1319
|
-
const contextPath =
|
|
1320
|
+
const contextPath = path15 || "root";
|
|
1320
1321
|
if (refPath.startsWith("#")) {
|
|
1321
1322
|
return;
|
|
1322
1323
|
}
|
|
@@ -1326,24 +1327,24 @@ Import chain: ${[...visitedFiles].join(" \u2192 ")} \u2192 ${normalizedPath}`
|
|
|
1326
1327
|
delete current[key];
|
|
1327
1328
|
}
|
|
1328
1329
|
Object.assign(current, filteredResolved);
|
|
1329
|
-
this.resolveReferencesRecursive(current, rootConfig,
|
|
1330
|
+
this.resolveReferencesRecursive(current, rootConfig, path15);
|
|
1330
1331
|
}
|
|
1331
1332
|
/**
|
|
1332
1333
|
* Resolve object properties recursively
|
|
1333
1334
|
* Handles both nested objects and "$ref:path" string references
|
|
1334
1335
|
*/
|
|
1335
|
-
resolveObjectProperties(current, rootConfig,
|
|
1336
|
+
resolveObjectProperties(current, rootConfig, path15) {
|
|
1336
1337
|
for (const [key, value] of Object.entries(current)) {
|
|
1337
1338
|
if (typeof value === "string" && value.startsWith("$ref:")) {
|
|
1338
1339
|
const refPath = value.slice(5);
|
|
1339
1340
|
if (refPath.startsWith("#")) {
|
|
1340
1341
|
continue;
|
|
1341
1342
|
}
|
|
1342
|
-
const contextPath =
|
|
1343
|
+
const contextPath = path15 ? `${path15}.${key}` : key;
|
|
1343
1344
|
const resolved = this.resolveReference(rootConfig, refPath, contextPath);
|
|
1344
1345
|
current[key] = resolved;
|
|
1345
1346
|
} else {
|
|
1346
|
-
this.resolveReferencesRecursive(value, rootConfig,
|
|
1347
|
+
this.resolveReferencesRecursive(value, rootConfig, path15 ? `${path15}.${key}` : key);
|
|
1347
1348
|
}
|
|
1348
1349
|
}
|
|
1349
1350
|
}
|
|
@@ -1499,8 +1500,8 @@ async function withRetry(fn, operation, maxAttempts = RATE_LIMITING.RETRY_ATTEMP
|
|
|
1499
1500
|
}
|
|
1500
1501
|
const delayMs = RATE_LIMITING.RETRY_DELAY_MS * 2 ** (attempt - 1);
|
|
1501
1502
|
logger.warn(` \u26A0\uFE0F Retry ${attempt}/${maxAttempts} for ${operation} after ${delayMs}ms...`);
|
|
1502
|
-
await new Promise((
|
|
1503
|
-
const timerId = setTimeout(
|
|
1503
|
+
await new Promise((resolve6) => {
|
|
1504
|
+
const timerId = setTimeout(resolve6, delayMs);
|
|
1504
1505
|
timerId.unref();
|
|
1505
1506
|
});
|
|
1506
1507
|
}
|
|
@@ -2853,13 +2854,13 @@ async function destroyResources(options) {
|
|
|
2853
2854
|
if (force) {
|
|
2854
2855
|
logger.info("\u{1F680} --force flag detected, skipping confirmation\n");
|
|
2855
2856
|
} else {
|
|
2856
|
-
const
|
|
2857
|
-
const rl =
|
|
2857
|
+
const readline2 = await import('readline');
|
|
2858
|
+
const rl = readline2.createInterface({
|
|
2858
2859
|
input: process.stdin,
|
|
2859
2860
|
output: process.stdout
|
|
2860
2861
|
});
|
|
2861
|
-
const answer = await new Promise((
|
|
2862
|
-
rl.question('Type "destroy" to confirm deletion: ',
|
|
2862
|
+
const answer = await new Promise((resolve6) => {
|
|
2863
|
+
rl.question('Type "destroy" to confirm deletion: ', resolve6);
|
|
2863
2864
|
});
|
|
2864
2865
|
rl.close();
|
|
2865
2866
|
if (answer.trim().toLowerCase() !== "destroy") {
|
|
@@ -2904,6 +2905,222 @@ async function main3(options) {
|
|
|
2904
2905
|
process.exit(1);
|
|
2905
2906
|
}
|
|
2906
2907
|
}
|
|
2908
|
+
async function promptUser(question, defaultValue) {
|
|
2909
|
+
const rl = readline.createInterface({
|
|
2910
|
+
input: process.stdin,
|
|
2911
|
+
output: process.stdout
|
|
2912
|
+
});
|
|
2913
|
+
const displayQuestion = defaultValue ? `${question} (${defaultValue}): ` : `${question}: `;
|
|
2914
|
+
const answer = await new Promise((resolve6) => {
|
|
2915
|
+
rl.question(displayQuestion, resolve6);
|
|
2916
|
+
});
|
|
2917
|
+
rl.close();
|
|
2918
|
+
const trimmedAnswer = answer.trim();
|
|
2919
|
+
return trimmedAnswer || defaultValue || "";
|
|
2920
|
+
}
|
|
2921
|
+
async function confirmOverwrite(filename) {
|
|
2922
|
+
const answer = await promptUser(`File '${filename}' already exists. Overwrite? (y/n)`);
|
|
2923
|
+
return answer.toLowerCase() === "y";
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
// src/lib/initHelpers.ts
|
|
2927
|
+
function fileExists(filePath) {
|
|
2928
|
+
return fs2.existsSync(filePath);
|
|
2929
|
+
}
|
|
2930
|
+
function generateEnvTemplate() {
|
|
2931
|
+
return `# Codemie API Configuration
|
|
2932
|
+
# Replace these placeholder values with your actual Codemie instance details
|
|
2933
|
+
# DO NOT commit this file to Git!
|
|
2934
|
+
|
|
2935
|
+
# Codemie API endpoint URL
|
|
2936
|
+
CODEMIE_API_URL=https://your-instance.codemie.ai/api
|
|
2937
|
+
|
|
2938
|
+
# Keycloak authentication server URL
|
|
2939
|
+
CODEMIE_AUTH_URL=https://your-keycloak.auth.com
|
|
2940
|
+
|
|
2941
|
+
# Keycloak realm name
|
|
2942
|
+
CODEMIE_REALM=codemie
|
|
2943
|
+
|
|
2944
|
+
# Service account client ID
|
|
2945
|
+
CODEMIE_CLIENT_ID=your-client-id
|
|
2946
|
+
|
|
2947
|
+
# Service account client secret (keep this secure!)
|
|
2948
|
+
CODEMIE_CLIENT_SECRET=your-client-secret
|
|
2949
|
+
`;
|
|
2950
|
+
}
|
|
2951
|
+
function generateMinimalCodemieYaml(projectName, projectDescription) {
|
|
2952
|
+
return `# Codemie Infrastructure as Code Configuration
|
|
2953
|
+
# For detailed examples and documentation, see:
|
|
2954
|
+
# - examples/assistant-examples.yaml
|
|
2955
|
+
# - examples/datasource-examples.yaml
|
|
2956
|
+
# - examples/workflow-examples.yaml
|
|
2957
|
+
# - examples/toolkit-examples.yaml
|
|
2958
|
+
# - examples/modular-config-example/
|
|
2959
|
+
|
|
2960
|
+
version: "1"
|
|
2961
|
+
|
|
2962
|
+
# Project identification
|
|
2963
|
+
project:
|
|
2964
|
+
name: ${projectName}
|
|
2965
|
+
description: ${projectDescription}
|
|
2966
|
+
|
|
2967
|
+
# Environment configuration (uses variables from .env file)
|
|
2968
|
+
environment:
|
|
2969
|
+
codemie_api_url: \${CODEMIE_API_URL}
|
|
2970
|
+
auth_server_url: \${CODEMIE_AUTH_URL}
|
|
2971
|
+
auth_realm_name: \${CODEMIE_REALM}
|
|
2972
|
+
client_id: \${CODEMIE_CLIENT_ID}
|
|
2973
|
+
client_secret: \${CODEMIE_CLIENT_SECRET}
|
|
2974
|
+
|
|
2975
|
+
# Imported resources from existing Codemie platform
|
|
2976
|
+
# Reference existing assistants, datasources, and integrations to use in your IaC configurations
|
|
2977
|
+
imported:
|
|
2978
|
+
assistants: []
|
|
2979
|
+
datasources: []
|
|
2980
|
+
integrations: []
|
|
2981
|
+
|
|
2982
|
+
# Resources to be managed by IaC
|
|
2983
|
+
# Add your assistants, datasources, and workflows here
|
|
2984
|
+
resources:
|
|
2985
|
+
assistants: []
|
|
2986
|
+
datasources: []
|
|
2987
|
+
workflows: []
|
|
2988
|
+
`;
|
|
2989
|
+
}
|
|
2990
|
+
async function promptAppConfig() {
|
|
2991
|
+
const rootDir = await promptUser("Root directory", defaultConfig.rootDir);
|
|
2992
|
+
const codemieConfig = await promptUser("Codemie config file path", defaultConfig.codemieConfig);
|
|
2993
|
+
const codemieState = await promptUser("Codemie state file path", defaultConfig.codemieState);
|
|
2994
|
+
const backupsDirectory = await promptUser("Backups directory", defaultConfig.backupsDirectory);
|
|
2995
|
+
return {
|
|
2996
|
+
rootDir,
|
|
2997
|
+
codemieConfig,
|
|
2998
|
+
codemieState,
|
|
2999
|
+
backupsDirectory
|
|
3000
|
+
};
|
|
3001
|
+
}
|
|
3002
|
+
function compareConfigWithDefaults(userConfig) {
|
|
3003
|
+
return userConfig.rootDir !== defaultConfig.rootDir || userConfig.codemieConfig !== defaultConfig.codemieConfig || userConfig.codemieState !== defaultConfig.codemieState || userConfig.backupsDirectory !== defaultConfig.backupsDirectory;
|
|
3004
|
+
}
|
|
3005
|
+
async function saveConfigFile(config, defaultFilename = "config.json") {
|
|
3006
|
+
const configFilename = await promptUser(`Enter config file path`, defaultFilename);
|
|
3007
|
+
const configPath = path6.resolve(process.cwd(), configFilename);
|
|
3008
|
+
if (fileExists(configPath)) {
|
|
3009
|
+
const shouldOverwrite = await confirmOverwrite(configFilename);
|
|
3010
|
+
if (!shouldOverwrite) {
|
|
3011
|
+
throw new Error(`Cancelled: Configuration file not saved.`);
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
fs2.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
3015
|
+
return configFilename;
|
|
3016
|
+
}
|
|
3017
|
+
function suggestConfigUsage(configFileName) {
|
|
3018
|
+
logger.info("\n\u{1F4CB} To use this configuration with other commands, add the `-c` flag:\n");
|
|
3019
|
+
logger.info(` codemie deploy -c ${configFileName}`);
|
|
3020
|
+
logger.info(` codemie validate -c ${configFileName}`);
|
|
3021
|
+
logger.info(` codemie preview -c ${configFileName}`);
|
|
3022
|
+
logger.info(` codemie backup -c ${configFileName}`);
|
|
3023
|
+
logger.info(` codemie destroy -c ${configFileName}
|
|
3024
|
+
`);
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
// src/init.ts
|
|
3028
|
+
async function initProject(options) {
|
|
3029
|
+
logger.info("\u{1F680} Initialize Codemie IaC Project\n\n");
|
|
3030
|
+
try {
|
|
3031
|
+
const { appConfig } = options;
|
|
3032
|
+
const envPath = path6.resolve(appConfig.rootDir, ".env");
|
|
3033
|
+
const configPath = path6.resolve(appConfig.rootDir, appConfig.codemieConfig);
|
|
3034
|
+
logger.info("This wizard will create the following files:");
|
|
3035
|
+
logger.info(` \u{1F4C4} .env - Environment variables with API credentials`);
|
|
3036
|
+
logger.info(` \u{1F4C4} ${appConfig.codemieConfig} - Codemie IaC configuration
|
|
3037
|
+
|
|
3038
|
+
`);
|
|
3039
|
+
logger.info("\u{1F4DD} Project Information\n");
|
|
3040
|
+
const projectName = await promptUser("Project name", "my-codemie-project");
|
|
3041
|
+
const projectDescription = await promptUser(
|
|
3042
|
+
"Project description",
|
|
3043
|
+
"AI assistants and workflows managed with Codemie IaC"
|
|
3044
|
+
);
|
|
3045
|
+
logger.info("\n\u{1F4CB} Application Configuration\n");
|
|
3046
|
+
logger.info("Configure where Codemie IaC will store files and state:\n");
|
|
3047
|
+
const userAppConfig = await promptAppConfig();
|
|
3048
|
+
let configFileName;
|
|
3049
|
+
if (compareConfigWithDefaults(userAppConfig)) {
|
|
3050
|
+
try {
|
|
3051
|
+
configFileName = await saveConfigFile(userAppConfig);
|
|
3052
|
+
logger.info(`\u2713 Configuration saved to ${configFileName}
|
|
3053
|
+
`);
|
|
3054
|
+
} catch (error) {
|
|
3055
|
+
logger.warn(`
|
|
3056
|
+
\u26A0\uFE0F ${error instanceof Error ? error.message : String(error)}`);
|
|
3057
|
+
logger.warn("Continuing with project initialization...\n");
|
|
3058
|
+
}
|
|
3059
|
+
} else {
|
|
3060
|
+
logger.info("\u2713 Using default configuration\n");
|
|
3061
|
+
}
|
|
3062
|
+
let shouldCreateEnv = true;
|
|
3063
|
+
if (fileExists(envPath)) {
|
|
3064
|
+
logger.warn(`\u26A0\uFE0F File '.env' already exists`);
|
|
3065
|
+
shouldCreateEnv = await confirmOverwrite(".env");
|
|
3066
|
+
if (!shouldCreateEnv) {
|
|
3067
|
+
logger.info(" Keeping existing .env file\n");
|
|
3068
|
+
}
|
|
3069
|
+
}
|
|
3070
|
+
let shouldCreateConfig = true;
|
|
3071
|
+
if (fileExists(configPath)) {
|
|
3072
|
+
logger.warn(`\u26A0\uFE0F File '${appConfig.codemieConfig}' already exists`);
|
|
3073
|
+
shouldCreateConfig = await confirmOverwrite(appConfig.codemieConfig);
|
|
3074
|
+
if (!shouldCreateConfig) {
|
|
3075
|
+
logger.info(` Keeping existing ${appConfig.codemieConfig} file
|
|
3076
|
+
`);
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
if (!shouldCreateEnv && !shouldCreateConfig) {
|
|
3080
|
+
logger.info("\u2713 No files created (all existing files kept)\n");
|
|
3081
|
+
return;
|
|
3082
|
+
}
|
|
3083
|
+
logger.info("\n\u{1F4C1} Creating configuration files...\n");
|
|
3084
|
+
if (shouldCreateEnv) {
|
|
3085
|
+
const envContent = generateEnvTemplate();
|
|
3086
|
+
fs2.writeFileSync(envPath, envContent, "utf-8");
|
|
3087
|
+
logger.info(`\u2713 Created .env`);
|
|
3088
|
+
logger.warn(` \u26A0\uFE0F Remember to fill in your actual credentials!`);
|
|
3089
|
+
logger.warn(` \u26A0\uFE0F DO NOT commit .env to Git!
|
|
3090
|
+
`);
|
|
3091
|
+
}
|
|
3092
|
+
if (shouldCreateConfig) {
|
|
3093
|
+
const configContent = generateMinimalCodemieYaml(projectName, projectDescription);
|
|
3094
|
+
fs2.writeFileSync(configPath, configContent, "utf-8");
|
|
3095
|
+
logger.info(`\u2713 Created ${appConfig.codemieConfig}`);
|
|
3096
|
+
logger.info(` See examples/ directory for detailed configuration examples
|
|
3097
|
+
|
|
3098
|
+
`);
|
|
3099
|
+
}
|
|
3100
|
+
logger.info("\u{1F389} Initialization complete!\n");
|
|
3101
|
+
logger.info("Next steps:");
|
|
3102
|
+
logger.info(" 1. Edit .env and add your Codemie API credentials");
|
|
3103
|
+
logger.info(` 2. Edit ${appConfig.codemieConfig} and add your resources`);
|
|
3104
|
+
logger.info(' 3. Run "codemie validate" to check your configuration');
|
|
3105
|
+
logger.info(' 4. Run "codemie deploy" to deploy your resources\n');
|
|
3106
|
+
if (configFileName) {
|
|
3107
|
+
suggestConfigUsage(configFileName);
|
|
3108
|
+
}
|
|
3109
|
+
logger.info("\u{1F4DA} For examples and documentation, see:");
|
|
3110
|
+
logger.info(" \u2022 examples/assistant-examples.yaml");
|
|
3111
|
+
logger.info(" \u2022 examples/datasource-examples.yaml");
|
|
3112
|
+
logger.info(" \u2022 examples/workflow-examples.yaml");
|
|
3113
|
+
logger.info(" \u2022 examples/modular-config-example/\n");
|
|
3114
|
+
} catch (error) {
|
|
3115
|
+
logger.error(`
|
|
3116
|
+
\u274C Initialization failed: ${error instanceof Error ? error.message : String(error)}
|
|
3117
|
+
`);
|
|
3118
|
+
process.exit(1);
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
async function main4(options) {
|
|
3122
|
+
await initProject(options);
|
|
3123
|
+
}
|
|
2907
3124
|
async function previewResource(resource, resourceType, getState, checkExists, calculateChecksums) {
|
|
2908
3125
|
const existingState = getState(resource.name);
|
|
2909
3126
|
if (existingState) {
|
|
@@ -3094,7 +3311,7 @@ async function previewChanges(appConfig, existingClient) {
|
|
|
3094
3311
|
}
|
|
3095
3312
|
};
|
|
3096
3313
|
}
|
|
3097
|
-
async function
|
|
3314
|
+
async function main5(options) {
|
|
3098
3315
|
logger.info("\u{1F4CB} Generating deployment preview...\n");
|
|
3099
3316
|
try {
|
|
3100
3317
|
const { appConfig } = options;
|
|
@@ -3202,10 +3419,10 @@ var DependencyValidator = class {
|
|
|
3202
3419
|
const errors = [];
|
|
3203
3420
|
const visited = /* @__PURE__ */ new Set();
|
|
3204
3421
|
const recursionStack = /* @__PURE__ */ new Set();
|
|
3205
|
-
const dfs = (name,
|
|
3422
|
+
const dfs = (name, path15) => {
|
|
3206
3423
|
if (recursionStack.has(name)) {
|
|
3207
|
-
const cycleStart =
|
|
3208
|
-
const cycle = [...
|
|
3424
|
+
const cycleStart = path15.indexOf(name);
|
|
3425
|
+
const cycle = [...path15.slice(cycleStart), name];
|
|
3209
3426
|
errors.push(`Cyclic dependency detected: ${cycle.join(" \u2192 ")}`);
|
|
3210
3427
|
return true;
|
|
3211
3428
|
}
|
|
@@ -3214,14 +3431,14 @@ var DependencyValidator = class {
|
|
|
3214
3431
|
}
|
|
3215
3432
|
visited.add(name);
|
|
3216
3433
|
recursionStack.add(name);
|
|
3217
|
-
|
|
3434
|
+
path15.push(name);
|
|
3218
3435
|
const assistant = assistantMap.get(name);
|
|
3219
3436
|
const subAssistantRefs = assistant?.sub_assistants || [];
|
|
3220
3437
|
for (const subRef of subAssistantRefs) {
|
|
3221
3438
|
if (!assistantMap.has(subRef)) {
|
|
3222
3439
|
continue;
|
|
3223
3440
|
}
|
|
3224
|
-
if (dfs(subRef, [...
|
|
3441
|
+
if (dfs(subRef, [...path15])) {
|
|
3225
3442
|
return true;
|
|
3226
3443
|
}
|
|
3227
3444
|
}
|
|
@@ -3409,7 +3626,7 @@ async function validateConfig(options) {
|
|
|
3409
3626
|
}
|
|
3410
3627
|
return { success: errors.length === 0, errors };
|
|
3411
3628
|
}
|
|
3412
|
-
async function
|
|
3629
|
+
async function main6(options) {
|
|
3413
3630
|
const { checkApi = false, appConfig } = options;
|
|
3414
3631
|
logger.info("\u{1F50D} Validating configuration...");
|
|
3415
3632
|
if (checkApi) {
|
|
@@ -3454,6 +3671,10 @@ async function main5(options) {
|
|
|
3454
3671
|
|
|
3455
3672
|
// src/cli/index.ts
|
|
3456
3673
|
program.name("codemie").description("Infrastructure as Code for Codemie platform").version(package_default.version);
|
|
3674
|
+
program.command("init").description("Initialize a new Codemie IaC project").action(() => {
|
|
3675
|
+
const appConfig = loadAppConfig();
|
|
3676
|
+
void main4({ appConfig });
|
|
3677
|
+
});
|
|
3457
3678
|
program.command("deploy").description("Deploy resources to Codemie platform").option("-p, --prune", "Delete orphaned resources").option("-c, --config <path>", "Configuration file").action((options) => {
|
|
3458
3679
|
const configPath = options.config ? path6__default.resolve(options.config) : void 0;
|
|
3459
3680
|
const appConfig = loadAppConfig(configPath);
|
|
@@ -3472,11 +3693,11 @@ program.command("destroy").description("Destroy all IaC-managed resources").opti
|
|
|
3472
3693
|
program.command("preview").description("Preview changes without applying them").option("-c, --config <path>", "Configuration file").action((options) => {
|
|
3473
3694
|
const appConfigPath = options.config ? path6__default.resolve(options.config) : void 0;
|
|
3474
3695
|
const appConfig = loadAppConfig(appConfigPath);
|
|
3475
|
-
void
|
|
3696
|
+
void main5({ appConfig });
|
|
3476
3697
|
});
|
|
3477
3698
|
program.command("validate").description("Validate configuration").option("-a, --check-api", "Check for API conflicts").option("-c, --config <path>", "Configuration file").action((options) => {
|
|
3478
3699
|
const configPath = options.config ? path6__default.resolve(options.config) : void 0;
|
|
3479
3700
|
const appConfig = loadAppConfig(configPath);
|
|
3480
|
-
void
|
|
3701
|
+
void main6({ appConfig, checkApi: options.checkApi });
|
|
3481
3702
|
});
|
|
3482
3703
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codemieai/cdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.290",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Infrastructure as Code solution for managing Codemie AI assistants, datasources, and workflows through declarative YAML configuration",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"format:check": "biome format ./src",
|
|
33
33
|
"lint": "npm-run-all types:check biome:check format:check",
|
|
34
34
|
"lint:check": "npm-run-all types:check biome:check",
|
|
35
|
-
"lint:fix": "npm-run-all types:check
|
|
35
|
+
"lint:fix": "npm-run-all types:check biome format",
|
|
36
36
|
"test": "jest --silent --passWithNoTests",
|
|
37
37
|
"test:ci": "jest --silent --coverage --ci",
|
|
38
38
|
"test:coverage": "jest --silent --coverage",
|