@rodyssey/cli 0.0.9 → 0.1.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/dist/cli.js +308 -40
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
// @bun
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __getProtoOf = Object.getPrototypeOf;
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
@@ -17,7 +17,7 @@ var __toESM = (mod, isNodeMode, target) => {
|
|
|
17
17
|
return to;
|
|
18
18
|
};
|
|
19
19
|
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
20
|
-
var __require =
|
|
20
|
+
var __require = import.meta.require;
|
|
21
21
|
|
|
22
22
|
// node_modules/commander/lib/error.js
|
|
23
23
|
var require_error = __commonJS((exports) => {
|
|
@@ -725,11 +725,11 @@ var require_suggestSimilar = __commonJS((exports) => {
|
|
|
725
725
|
|
|
726
726
|
// node_modules/commander/lib/command.js
|
|
727
727
|
var require_command = __commonJS((exports) => {
|
|
728
|
-
var EventEmitter = __require("
|
|
729
|
-
var childProcess = __require("
|
|
730
|
-
var path = __require("
|
|
731
|
-
var fs = __require("
|
|
732
|
-
var process2 = __require("
|
|
728
|
+
var EventEmitter = __require("events").EventEmitter;
|
|
729
|
+
var childProcess = __require("child_process");
|
|
730
|
+
var path = __require("path");
|
|
731
|
+
var fs = __require("fs");
|
|
732
|
+
var process2 = __require("process");
|
|
733
733
|
var { Argument, humanReadableArgName } = require_argument();
|
|
734
734
|
var { CommanderError } = require_error();
|
|
735
735
|
var { Help, stripColor } = require_help();
|
|
@@ -2070,13 +2070,13 @@ var {
|
|
|
2070
2070
|
} = import__.default;
|
|
2071
2071
|
|
|
2072
2072
|
// src/create.ts
|
|
2073
|
-
import { execSync } from "
|
|
2074
|
-
import { existsSync, rmSync } from "
|
|
2075
|
-
import path2 from "
|
|
2073
|
+
import { execSync } from "child_process";
|
|
2074
|
+
import { existsSync, rmSync } from "fs";
|
|
2075
|
+
import path2 from "path";
|
|
2076
2076
|
|
|
2077
2077
|
// src/utils.ts
|
|
2078
|
-
import { readFileSync, writeFileSync } from "
|
|
2079
|
-
import path from "
|
|
2078
|
+
import { readFileSync, writeFileSync } from "fs";
|
|
2079
|
+
import path from "path";
|
|
2080
2080
|
function replaceInFile(filePath, search, replace) {
|
|
2081
2081
|
const content = readFileSync(filePath, "utf-8");
|
|
2082
2082
|
const updated = content.replaceAll(search, replace);
|
|
@@ -2104,12 +2104,12 @@ async function create(projectName, repoUrl, templateName) {
|
|
|
2104
2104
|
const targetDir = path2.resolve(process.cwd(), projectName);
|
|
2105
2105
|
if (existsSync(targetDir)) {
|
|
2106
2106
|
console.error(`
|
|
2107
|
-
|
|
2107
|
+
\u2716 Directory "${projectName}" already exists.
|
|
2108
2108
|
`);
|
|
2109
2109
|
process.exit(1);
|
|
2110
2110
|
}
|
|
2111
2111
|
console.log(`
|
|
2112
|
-
|
|
2112
|
+
\u23F3 Cloning template "${templateName}"...
|
|
2113
2113
|
`);
|
|
2114
2114
|
try {
|
|
2115
2115
|
execSync(`git clone --depth 1 ${repoUrl} ${projectName}`, {
|
|
@@ -2118,7 +2118,7 @@ async function create(projectName, repoUrl, templateName) {
|
|
|
2118
2118
|
});
|
|
2119
2119
|
} catch {
|
|
2120
2120
|
console.error(`
|
|
2121
|
-
|
|
2121
|
+
\u2716 Failed to clone template. Make sure you have SSH access to the repo.
|
|
2122
2122
|
`);
|
|
2123
2123
|
process.exit(1);
|
|
2124
2124
|
}
|
|
@@ -2134,7 +2134,7 @@ async function create(projectName, repoUrl, templateName) {
|
|
|
2134
2134
|
}
|
|
2135
2135
|
execSync("git init", { stdio: "ignore", cwd: targetDir });
|
|
2136
2136
|
console.log(`
|
|
2137
|
-
|
|
2137
|
+
\u2705 Project "${projectName}" created successfully!
|
|
2138
2138
|
|
|
2139
2139
|
Next steps:
|
|
2140
2140
|
|
|
@@ -2144,9 +2144,271 @@ async function create(projectName, repoUrl, templateName) {
|
|
|
2144
2144
|
`);
|
|
2145
2145
|
}
|
|
2146
2146
|
|
|
2147
|
+
// src/deploy.ts
|
|
2148
|
+
var {$ } = globalThis.Bun;
|
|
2149
|
+
var {file } = globalThis.Bun;
|
|
2150
|
+
import { existsSync as existsSync2, readdirSync, statSync } from "fs";
|
|
2151
|
+
import { join } from "path";
|
|
2152
|
+
var DEVELOPMENT_URL = "https://development-cms.rodyssey.ai/api/webapps/deploy";
|
|
2153
|
+
var STAGING_URL = "https://staging-cms.rodyssey.ai/api/webapps/deploy";
|
|
2154
|
+
var PRODUCTION_URL = "https://cms.rodyssey.ai/api/webapps/deploy";
|
|
2155
|
+
var DEPLOY_URLS = {
|
|
2156
|
+
development: DEVELOPMENT_URL,
|
|
2157
|
+
staging: STAGING_URL,
|
|
2158
|
+
production: PRODUCTION_URL
|
|
2159
|
+
};
|
|
2160
|
+
var BUILD_DIR = "dist";
|
|
2161
|
+
var ZIP_FILE = "webapp-build.zip";
|
|
2162
|
+
var MAX_FILES_PER_BATCH = 5;
|
|
2163
|
+
var MAX_SIZE_PER_BATCH = 30 * 1024 * 1024;
|
|
2164
|
+
function getAllFiles(dirPath, arrayOfFiles = []) {
|
|
2165
|
+
if (!existsSync2(dirPath))
|
|
2166
|
+
return arrayOfFiles;
|
|
2167
|
+
const files = readdirSync(dirPath);
|
|
2168
|
+
files.forEach(function(f) {
|
|
2169
|
+
const fullPath = join(dirPath, f);
|
|
2170
|
+
if (statSync(fullPath).isDirectory()) {
|
|
2171
|
+
arrayOfFiles = getAllFiles(fullPath, arrayOfFiles);
|
|
2172
|
+
} else {
|
|
2173
|
+
arrayOfFiles.push(fullPath);
|
|
2174
|
+
}
|
|
2175
|
+
});
|
|
2176
|
+
return arrayOfFiles;
|
|
2177
|
+
}
|
|
2178
|
+
async function deploy(env = "development") {
|
|
2179
|
+
const DEPLOY_URL = DEPLOY_URLS[env];
|
|
2180
|
+
if (!DEPLOY_URL) {
|
|
2181
|
+
console.error(`\u274C Unknown environment "${env}". Available: ${Object.keys(DEPLOY_URLS).join(", ")}`);
|
|
2182
|
+
process.exit(1);
|
|
2183
|
+
}
|
|
2184
|
+
const ASSETS_URL = DEPLOY_URL.replace("/webapps/deploy", "/webapps/assets");
|
|
2185
|
+
console.log(`\uD83D\uDE80 Starting deployment process for [${env}] environment...
|
|
2186
|
+
`);
|
|
2187
|
+
console.log(`\uD83D\uDCCD Deploy URL: ${DEPLOY_URL}`);
|
|
2188
|
+
console.log(`\uD83D\uDCCD Assets URL: ${ASSETS_URL}
|
|
2189
|
+
`);
|
|
2190
|
+
if (!process.env.DEPLOY_TOKEN) {
|
|
2191
|
+
console.error("\u274C Error: DEPLOY_TOKEN is not set in environment variables.");
|
|
2192
|
+
console.info(`\uD83D\uDCA1 Please check your .env or .env.${env} file.`);
|
|
2193
|
+
process.exit(1);
|
|
2194
|
+
}
|
|
2195
|
+
console.log("\uD83D\uDCE6 Step 1: Building the webapp...");
|
|
2196
|
+
await $`bun run build`;
|
|
2197
|
+
console.log(`\u2705 Build completed
|
|
2198
|
+
`);
|
|
2199
|
+
const allFiles = getAllFiles(BUILD_DIR);
|
|
2200
|
+
const htmlFiles = allFiles.filter((f) => f.endsWith(".html"));
|
|
2201
|
+
const scriptFiles = allFiles.filter((f) => f.includes("/api/") || f.includes("/cron-jobs/") || f.endsWith("cron.config.json"));
|
|
2202
|
+
const heavyFiles = allFiles.filter((f) => !f.endsWith(".html") && !scriptFiles.includes(f));
|
|
2203
|
+
console.log(`\uD83D\uDCE4 Step 2: Uploading ${heavyFiles.length} heavy assets...`);
|
|
2204
|
+
if (heavyFiles.length > 0) {
|
|
2205
|
+
const batches = [];
|
|
2206
|
+
let currentBatch = [];
|
|
2207
|
+
let currentBatchSize = 0;
|
|
2208
|
+
for (const filePath of heavyFiles) {
|
|
2209
|
+
const size = statSync(filePath).size;
|
|
2210
|
+
if (currentBatch.length >= MAX_FILES_PER_BATCH || currentBatchSize + size > MAX_SIZE_PER_BATCH) {
|
|
2211
|
+
if (currentBatch.length > 0)
|
|
2212
|
+
batches.push(currentBatch);
|
|
2213
|
+
currentBatch = [];
|
|
2214
|
+
currentBatchSize = 0;
|
|
2215
|
+
}
|
|
2216
|
+
currentBatch.push(filePath);
|
|
2217
|
+
currentBatchSize += size;
|
|
2218
|
+
}
|
|
2219
|
+
if (currentBatch.length > 0)
|
|
2220
|
+
batches.push(currentBatch);
|
|
2221
|
+
console.log(`Divided into ${batches.length} batches.`);
|
|
2222
|
+
let batchIndex = 0;
|
|
2223
|
+
const uploadPromises = batches.map(async (batch) => {
|
|
2224
|
+
const formData = new FormData;
|
|
2225
|
+
for (const filePath of batch) {
|
|
2226
|
+
const relativePath = filePath.substring(BUILD_DIR.length + 1).replace(/\\/g, "/");
|
|
2227
|
+
formData.append(relativePath, file(filePath));
|
|
2228
|
+
}
|
|
2229
|
+
const response = await fetch(ASSETS_URL, {
|
|
2230
|
+
method: "POST",
|
|
2231
|
+
headers: {
|
|
2232
|
+
Authorization: `Bearer ${process.env.DEPLOY_TOKEN}`
|
|
2233
|
+
},
|
|
2234
|
+
body: formData
|
|
2235
|
+
});
|
|
2236
|
+
if (!response.ok) {
|
|
2237
|
+
const errorText = await response.text();
|
|
2238
|
+
throw new Error(`Asset upload failed: ${response.status} ${response.statusText}
|
|
2239
|
+
${errorText}`);
|
|
2240
|
+
}
|
|
2241
|
+
batchIndex++;
|
|
2242
|
+
console.log(`\u2705 Batch ${batchIndex}/${batches.length} uploaded successfully`);
|
|
2243
|
+
});
|
|
2244
|
+
await Promise.all(uploadPromises);
|
|
2245
|
+
} else {
|
|
2246
|
+
console.log("\u2705 No heavy assets to upload");
|
|
2247
|
+
}
|
|
2248
|
+
console.log();
|
|
2249
|
+
if (scriptFiles.length > 0) {
|
|
2250
|
+
console.log(`\uD83D\uDCDC Step 3: Setting up ${scriptFiles.length} scripts (APIs & Crons)...`);
|
|
2251
|
+
const scriptsPayload = { api: {}, cron: {}, cronConfig: null };
|
|
2252
|
+
for (const f of scriptFiles) {
|
|
2253
|
+
const content = await Bun.file(f).text();
|
|
2254
|
+
const relativePath = f.substring(BUILD_DIR.length + 1).replace(/\\/g, "/");
|
|
2255
|
+
if (relativePath === "cron-jobs/cron.config.json") {
|
|
2256
|
+
scriptsPayload.cronConfig = JSON.parse(content);
|
|
2257
|
+
} else if (relativePath.startsWith("api/")) {
|
|
2258
|
+
const endpoint = relativePath.substring(4, relativePath.lastIndexOf(".js"));
|
|
2259
|
+
scriptsPayload.api[endpoint] = content;
|
|
2260
|
+
} else if (relativePath.startsWith("cron-jobs/")) {
|
|
2261
|
+
const scriptName = relativePath.substring(10);
|
|
2262
|
+
scriptsPayload.cron[scriptName] = content;
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
const scriptsUrl = DEPLOY_URL.replace("/webapps/deploy", "/webapps/scripts-setup");
|
|
2266
|
+
const response = await fetch(scriptsUrl, {
|
|
2267
|
+
method: "POST",
|
|
2268
|
+
headers: {
|
|
2269
|
+
Authorization: `Bearer ${process.env.DEPLOY_TOKEN}`,
|
|
2270
|
+
"Content-Type": "application/json"
|
|
2271
|
+
},
|
|
2272
|
+
body: JSON.stringify(scriptsPayload)
|
|
2273
|
+
});
|
|
2274
|
+
if (!response.ok) {
|
|
2275
|
+
const errorText = await response.text();
|
|
2276
|
+
throw new Error(`Scripts setup failed: ${response.status} ${response.statusText}
|
|
2277
|
+
${errorText}`);
|
|
2278
|
+
}
|
|
2279
|
+
console.log(`\u2705 Scripts synced successfully`);
|
|
2280
|
+
} else {
|
|
2281
|
+
console.log(`\uD83D\uDCDC Step 3: No scripts found to sync.`);
|
|
2282
|
+
}
|
|
2283
|
+
console.log();
|
|
2284
|
+
console.log(`\uD83D\uDDDC\uFE0F Step 4: Zipping ${htmlFiles.length} HTML files...`);
|
|
2285
|
+
if (htmlFiles.length === 0) {
|
|
2286
|
+
console.warn("\u26A0\uFE0F No HTML files found to zip! Deployment might fail if CMS expects an HTML file.");
|
|
2287
|
+
}
|
|
2288
|
+
const relativeHtmlFiles = htmlFiles.map((f) => f.substring(BUILD_DIR.length + 1).replace(/\\/g, "/"));
|
|
2289
|
+
await $`cd ${BUILD_DIR} && zip ../${ZIP_FILE} ${relativeHtmlFiles}`;
|
|
2290
|
+
console.log(`\u2705 Created ${ZIP_FILE}
|
|
2291
|
+
`);
|
|
2292
|
+
console.log("\u2601\uFE0F Step 5: Deploying HTML zip to server...");
|
|
2293
|
+
const zipFile = file(ZIP_FILE);
|
|
2294
|
+
try {
|
|
2295
|
+
const response = await fetch(DEPLOY_URL, {
|
|
2296
|
+
method: "POST",
|
|
2297
|
+
headers: {
|
|
2298
|
+
Authorization: `Bearer ${process.env.DEPLOY_TOKEN}`,
|
|
2299
|
+
"Content-Type": "application/zip"
|
|
2300
|
+
},
|
|
2301
|
+
body: zipFile
|
|
2302
|
+
});
|
|
2303
|
+
if (!response.ok) {
|
|
2304
|
+
const errorText = await response.text();
|
|
2305
|
+
throw new Error(`Deploy failed: ${response.status} ${response.statusText}
|
|
2306
|
+
${errorText}`);
|
|
2307
|
+
}
|
|
2308
|
+
const result = await response.json();
|
|
2309
|
+
console.log("\u2705 Deploy completed");
|
|
2310
|
+
console.log(`
|
|
2311
|
+
\uD83D\uDCCB Deployment result:`, result);
|
|
2312
|
+
} catch (error) {
|
|
2313
|
+
console.error("\u274C Deploy failed:", error);
|
|
2314
|
+
throw error;
|
|
2315
|
+
} finally {
|
|
2316
|
+
if (existsSync2(ZIP_FILE)) {
|
|
2317
|
+
await $`rm ${ZIP_FILE}`;
|
|
2318
|
+
console.log(`
|
|
2319
|
+
\uD83E\uDDF9 Cleaned up ${ZIP_FILE}`);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
console.log(`
|
|
2323
|
+
\u2728 Deployment successful!`);
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
// src/upgrade-agent.ts
|
|
2327
|
+
import { execSync as execSync2 } from "child_process";
|
|
2328
|
+
import { existsSync as existsSync3 } from "fs";
|
|
2329
|
+
var TEMPLATES = {
|
|
2330
|
+
webapp: {
|
|
2331
|
+
name: "webapp (SPA)",
|
|
2332
|
+
repo: "https://github.com/airconcepts/webapp-template.git",
|
|
2333
|
+
remoteName: "template",
|
|
2334
|
+
checkoutFiles: ["AGENTS.md", ".agent/", "src/types/webapp.d.ts", "src/types/game-sdk.d.ts"],
|
|
2335
|
+
newFiles: [
|
|
2336
|
+
"src/exp-engine/cli.ts",
|
|
2337
|
+
"src/exp-engine/evaluate.ts",
|
|
2338
|
+
"src/exp-engine/README.md",
|
|
2339
|
+
"src/types/exp-engine.d.ts"
|
|
2340
|
+
]
|
|
2341
|
+
},
|
|
2342
|
+
"webapp-fullstack": {
|
|
2343
|
+
name: "webapp (Fullstack)",
|
|
2344
|
+
repo: "https://github.com/airconcepts/webapp-template-fullstack.git",
|
|
2345
|
+
remoteName: "template",
|
|
2346
|
+
checkoutFiles: ["AGENTS.md", ".agent/", "app/types/webapp.d.ts", "app/types/game-sdk.d.ts"],
|
|
2347
|
+
newFiles: [
|
|
2348
|
+
"app/exp-engine/cli.ts",
|
|
2349
|
+
"app/exp-engine/evaluate.ts",
|
|
2350
|
+
"app/exp-engine/README.md",
|
|
2351
|
+
"app/types/exp-engine.d.ts"
|
|
2352
|
+
]
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2355
|
+
function detectTemplate() {
|
|
2356
|
+
if (existsSync3("app")) {
|
|
2357
|
+
console.log(`\uD83D\uDD0D Detected fullstack template (found app/ directory)
|
|
2358
|
+
`);
|
|
2359
|
+
return TEMPLATES["webapp-fullstack"];
|
|
2360
|
+
}
|
|
2361
|
+
if (existsSync3("src")) {
|
|
2362
|
+
console.log(`\uD83D\uDD0D Detected SPA template (found src/ directory)
|
|
2363
|
+
`);
|
|
2364
|
+
return TEMPLATES["webapp"];
|
|
2365
|
+
}
|
|
2366
|
+
console.log(`\u26A0\uFE0F Could not detect template type, defaulting to SPA
|
|
2367
|
+
`);
|
|
2368
|
+
return TEMPLATES["webapp"];
|
|
2369
|
+
}
|
|
2370
|
+
async function upgradeAgent() {
|
|
2371
|
+
const template = detectTemplate();
|
|
2372
|
+
try {
|
|
2373
|
+
console.log(`\uD83D\uDD04 Starting Agent Upgrade for ${template.name}...`);
|
|
2374
|
+
let remoteExists = false;
|
|
2375
|
+
try {
|
|
2376
|
+
execSync2(`git remote get-url ${template.remoteName}`, { stdio: "ignore" });
|
|
2377
|
+
remoteExists = true;
|
|
2378
|
+
} catch {}
|
|
2379
|
+
if (!remoteExists) {
|
|
2380
|
+
console.log(`\u2795 Adding remote '${template.remoteName}'...`);
|
|
2381
|
+
execSync2(`git remote add ${template.remoteName} ${template.repo}`, { stdio: "inherit" });
|
|
2382
|
+
} else {
|
|
2383
|
+
console.log(`\u2139\uFE0F Remote '${template.remoteName}' already exists.`);
|
|
2384
|
+
}
|
|
2385
|
+
console.log("\u2B07\uFE0F Fetching latest changes from template...");
|
|
2386
|
+
execSync2(`git fetch ${template.remoteName}`, { stdio: "inherit" });
|
|
2387
|
+
console.log("\uD83D\uDCC2 Updating agent files...");
|
|
2388
|
+
const checkoutList = template.checkoutFiles.join(" ");
|
|
2389
|
+
execSync2(`git checkout ${template.remoteName}/main -- ${checkoutList}`, { stdio: "inherit" });
|
|
2390
|
+
for (const file2 of template.newFiles) {
|
|
2391
|
+
if (!existsSync3(file2)) {
|
|
2392
|
+
console.log(`\uD83D\uDCC2 Checking out ${file2}...`);
|
|
2393
|
+
try {
|
|
2394
|
+
execSync2(`git checkout ${template.remoteName}/main -- ${file2}`, { stdio: "inherit" });
|
|
2395
|
+
} catch {
|
|
2396
|
+
console.log(`\u26A0\uFE0F Failed to checkout ${file2}`);
|
|
2397
|
+
}
|
|
2398
|
+
} else {
|
|
2399
|
+
console.log(`\u23ED\uFE0F Skipping ${file2} (already exists)`);
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
console.log("\u2705 Agent upgrade complete! Please check git status for changes.");
|
|
2403
|
+
} catch (error) {
|
|
2404
|
+
console.error("\u274C Upgrade failed:", error);
|
|
2405
|
+
process.exit(1);
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
|
|
2147
2409
|
// src/update-game-sdk.ts
|
|
2148
|
-
import { mkdir, writeFile } from "
|
|
2149
|
-
import { dirname, join } from "
|
|
2410
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
2411
|
+
import { dirname, join as join2 } from "path";
|
|
2150
2412
|
var BASE_URL = "https://development-app.rodyssey.ai";
|
|
2151
2413
|
var FILES = [
|
|
2152
2414
|
{
|
|
@@ -2179,11 +2441,11 @@ async function downloadFile(url, path3, description) {
|
|
|
2179
2441
|
const dir = dirname(path3);
|
|
2180
2442
|
await mkdir(dir, { recursive: true });
|
|
2181
2443
|
await writeFile(path3, content, "utf-8");
|
|
2182
|
-
console.log(
|
|
2444
|
+
console.log(`\u2705 Downloaded ${description} (${content.length} bytes)
|
|
2183
2445
|
`);
|
|
2184
2446
|
return true;
|
|
2185
2447
|
} catch (error) {
|
|
2186
|
-
console.error(
|
|
2448
|
+
console.error(`\u274C Failed to download ${description}:`);
|
|
2187
2449
|
console.error(` ${error instanceof Error ? error.message : String(error)}
|
|
2188
2450
|
`);
|
|
2189
2451
|
return false;
|
|
@@ -2200,14 +2462,14 @@ async function downloadManifest() {
|
|
|
2200
2462
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
2201
2463
|
}
|
|
2202
2464
|
const manifest = await response.json();
|
|
2203
|
-
console.log(
|
|
2465
|
+
console.log(`\u2705 Manifest downloaded successfully`);
|
|
2204
2466
|
console.log(` Name: ${manifest.name}`);
|
|
2205
2467
|
console.log(` Version: ${manifest.version}`);
|
|
2206
2468
|
console.log(` Documentation files: ${manifest.documentation.length}
|
|
2207
2469
|
`);
|
|
2208
2470
|
return manifest;
|
|
2209
2471
|
} catch (error) {
|
|
2210
|
-
console.error("
|
|
2472
|
+
console.error("\u274C Failed to download manifest:");
|
|
2211
2473
|
console.error(` ${error instanceof Error ? error.message : String(error)}
|
|
2212
2474
|
`);
|
|
2213
2475
|
return null;
|
|
@@ -2220,7 +2482,7 @@ async function downloadDocumentation(manifest) {
|
|
|
2220
2482
|
let failCount = 0;
|
|
2221
2483
|
for (const doc of manifest.documentation) {
|
|
2222
2484
|
const url = `${BASE_URL}/skills/${doc.file}`;
|
|
2223
|
-
const path3 =
|
|
2485
|
+
const path3 = join2(".agent", "skills", "game-sdk", doc.file);
|
|
2224
2486
|
const description = `${doc.title} (${doc.category})`;
|
|
2225
2487
|
const success = await downloadFile(url, path3, description);
|
|
2226
2488
|
if (success) {
|
|
@@ -2231,9 +2493,9 @@ async function downloadDocumentation(manifest) {
|
|
|
2231
2493
|
}
|
|
2232
2494
|
console.log(`
|
|
2233
2495
|
\uD83D\uDCCA Documentation download summary:`);
|
|
2234
|
-
console.log(`
|
|
2496
|
+
console.log(` \u2705 Success: ${successCount}`);
|
|
2235
2497
|
if (failCount > 0) {
|
|
2236
|
-
console.log(`
|
|
2498
|
+
console.log(` \u274C Failed: ${failCount}`);
|
|
2237
2499
|
}
|
|
2238
2500
|
console.log();
|
|
2239
2501
|
return { successCount, failCount };
|
|
@@ -2246,8 +2508,8 @@ async function updateGameSdk() {
|
|
|
2246
2508
|
let totalFail = 0;
|
|
2247
2509
|
console.log(`\uD83D\uDCE6 Downloading core SDK files...
|
|
2248
2510
|
`);
|
|
2249
|
-
for (const
|
|
2250
|
-
const success = await downloadFile(
|
|
2511
|
+
for (const file2 of FILES) {
|
|
2512
|
+
const success = await downloadFile(file2.url, file2.path, file2.description);
|
|
2251
2513
|
if (success) {
|
|
2252
2514
|
totalSuccess++;
|
|
2253
2515
|
} else {
|
|
@@ -2260,27 +2522,27 @@ async function updateGameSdk() {
|
|
|
2260
2522
|
totalSuccess += successCount;
|
|
2261
2523
|
totalFail += failCount;
|
|
2262
2524
|
} else {
|
|
2263
|
-
console.log(
|
|
2525
|
+
console.log(`\u26A0\uFE0F Skipping documentation download due to manifest error
|
|
2264
2526
|
`);
|
|
2265
2527
|
}
|
|
2266
2528
|
console.log("=".repeat(60));
|
|
2267
2529
|
console.log(`\uD83C\uDF89 Download Complete!
|
|
2268
2530
|
`);
|
|
2269
2531
|
console.log(`\uD83D\uDCCA Final Summary:`);
|
|
2270
|
-
console.log(`
|
|
2532
|
+
console.log(` \u2705 Successfully downloaded: ${totalSuccess} files`);
|
|
2271
2533
|
if (totalFail > 0) {
|
|
2272
|
-
console.log(`
|
|
2534
|
+
console.log(` \u274C Failed: ${totalFail} files`);
|
|
2273
2535
|
console.log(`
|
|
2274
|
-
|
|
2536
|
+
\u26A0\uFE0F Some files failed to download. Please check the errors above.`);
|
|
2275
2537
|
process.exit(1);
|
|
2276
2538
|
} else {
|
|
2277
2539
|
console.log(`
|
|
2278
|
-
|
|
2540
|
+
\u2728 All files downloaded successfully!`);
|
|
2279
2541
|
}
|
|
2280
2542
|
}
|
|
2281
2543
|
|
|
2282
2544
|
// src/cli.ts
|
|
2283
|
-
var
|
|
2545
|
+
var TEMPLATES2 = {
|
|
2284
2546
|
webapp: {
|
|
2285
2547
|
name: "webapp",
|
|
2286
2548
|
description: "Frontend-only webapp (Vite + React Router 7)",
|
|
@@ -2293,15 +2555,15 @@ var TEMPLATES = {
|
|
|
2293
2555
|
}
|
|
2294
2556
|
};
|
|
2295
2557
|
async function selectTemplate() {
|
|
2296
|
-
const entries = Object.values(
|
|
2558
|
+
const entries = Object.values(TEMPLATES2);
|
|
2297
2559
|
console.log(`
|
|
2298
2560
|
Available templates:
|
|
2299
2561
|
`);
|
|
2300
2562
|
entries.forEach((t, i) => {
|
|
2301
|
-
console.log(` ${i + 1}. ${t.name}
|
|
2563
|
+
console.log(` ${i + 1}. ${t.name} \u2014 ${t.description}`);
|
|
2302
2564
|
});
|
|
2303
2565
|
console.log();
|
|
2304
|
-
const readline = await import("
|
|
2566
|
+
const readline = await import("readline");
|
|
2305
2567
|
const rl = readline.createInterface({
|
|
2306
2568
|
input: process.stdin,
|
|
2307
2569
|
output: process.stdout
|
|
@@ -2319,23 +2581,29 @@ Available templates:
|
|
|
2319
2581
|
});
|
|
2320
2582
|
});
|
|
2321
2583
|
}
|
|
2322
|
-
program.name("@rodyssey/cli").description("Airconcepts CLI toolkit").version("0.0
|
|
2584
|
+
program.name("@rodyssey/cli").description("Airconcepts CLI toolkit").version("0.1.0");
|
|
2323
2585
|
var app = program.command("app").description("Manage webapp projects");
|
|
2324
2586
|
app.command("create").argument("<project-name>", "Name of the project to create").option("-t, --template <template>", "Template to use (webapp | webapp-fullstack)").description("Create a new project from a template").action(async (projectName, options) => {
|
|
2325
2587
|
let templateName;
|
|
2326
2588
|
if (options.template) {
|
|
2327
|
-
if (!(options.template in
|
|
2328
|
-
console.error(`Unknown template "${options.template}". Available: ${Object.keys(
|
|
2589
|
+
if (!(options.template in TEMPLATES2)) {
|
|
2590
|
+
console.error(`Unknown template "${options.template}". Available: ${Object.keys(TEMPLATES2).join(", ")}`);
|
|
2329
2591
|
process.exit(1);
|
|
2330
2592
|
}
|
|
2331
2593
|
templateName = options.template;
|
|
2332
2594
|
} else {
|
|
2333
2595
|
templateName = await selectTemplate();
|
|
2334
2596
|
}
|
|
2335
|
-
const template =
|
|
2597
|
+
const template = TEMPLATES2[templateName];
|
|
2336
2598
|
await create(projectName, template.repo, templateName);
|
|
2337
2599
|
});
|
|
2338
2600
|
app.command("update-game-sdk").description("Download and update the GameSDK library, types, and documentation").action(async () => {
|
|
2339
2601
|
await updateGameSdk();
|
|
2340
2602
|
});
|
|
2603
|
+
app.command("deploy").description("Build and deploy the webapp to the server").option("-e, --env <environment>", "Target environment (development | staging | production)", "development").action(async (options) => {
|
|
2604
|
+
await deploy(options.env);
|
|
2605
|
+
});
|
|
2606
|
+
app.command("upgrade-agent").description("Upgrade agent files from the template repository").action(async () => {
|
|
2607
|
+
await upgradeAgent();
|
|
2608
|
+
});
|
|
2341
2609
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rodyssey/cli",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Scaffold new projects from airconcepts templates",
|
|
5
5
|
"bin": {
|
|
6
6
|
"@rodyssey/cli": "dist/cli.js"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"type": "module",
|
|
12
12
|
"module": "index.ts",
|
|
13
13
|
"scripts": {
|
|
14
|
-
"build": "bun build src/cli.ts --outdir dist --target
|
|
14
|
+
"build": "bun build src/cli.ts --outdir dist --target bun",
|
|
15
15
|
"start": "bun dist/cli.js",
|
|
16
16
|
"prepublishOnly": "bun run build"
|
|
17
17
|
},
|