@rodyssey/cli 0.0.8 → 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 +313 -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
|
{
|
|
@@ -2154,6 +2416,11 @@ var FILES = [
|
|
|
2154
2416
|
path: "public/game-sdk.js",
|
|
2155
2417
|
description: "GameSDK JavaScript library"
|
|
2156
2418
|
},
|
|
2419
|
+
{
|
|
2420
|
+
url: `${BASE_URL}/game-sdk-reactions.js`,
|
|
2421
|
+
path: "public/game-sdk-reactions.js",
|
|
2422
|
+
description: "GameSDK Reactions JavaScript library"
|
|
2423
|
+
},
|
|
2157
2424
|
{
|
|
2158
2425
|
url: `${BASE_URL}/game-sdk.d.ts`,
|
|
2159
2426
|
path: "src/types/game-sdk.d.ts",
|
|
@@ -2174,11 +2441,11 @@ async function downloadFile(url, path3, description) {
|
|
|
2174
2441
|
const dir = dirname(path3);
|
|
2175
2442
|
await mkdir(dir, { recursive: true });
|
|
2176
2443
|
await writeFile(path3, content, "utf-8");
|
|
2177
|
-
console.log(
|
|
2444
|
+
console.log(`\u2705 Downloaded ${description} (${content.length} bytes)
|
|
2178
2445
|
`);
|
|
2179
2446
|
return true;
|
|
2180
2447
|
} catch (error) {
|
|
2181
|
-
console.error(
|
|
2448
|
+
console.error(`\u274C Failed to download ${description}:`);
|
|
2182
2449
|
console.error(` ${error instanceof Error ? error.message : String(error)}
|
|
2183
2450
|
`);
|
|
2184
2451
|
return false;
|
|
@@ -2195,14 +2462,14 @@ async function downloadManifest() {
|
|
|
2195
2462
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
2196
2463
|
}
|
|
2197
2464
|
const manifest = await response.json();
|
|
2198
|
-
console.log(
|
|
2465
|
+
console.log(`\u2705 Manifest downloaded successfully`);
|
|
2199
2466
|
console.log(` Name: ${manifest.name}`);
|
|
2200
2467
|
console.log(` Version: ${manifest.version}`);
|
|
2201
2468
|
console.log(` Documentation files: ${manifest.documentation.length}
|
|
2202
2469
|
`);
|
|
2203
2470
|
return manifest;
|
|
2204
2471
|
} catch (error) {
|
|
2205
|
-
console.error("
|
|
2472
|
+
console.error("\u274C Failed to download manifest:");
|
|
2206
2473
|
console.error(` ${error instanceof Error ? error.message : String(error)}
|
|
2207
2474
|
`);
|
|
2208
2475
|
return null;
|
|
@@ -2215,7 +2482,7 @@ async function downloadDocumentation(manifest) {
|
|
|
2215
2482
|
let failCount = 0;
|
|
2216
2483
|
for (const doc of manifest.documentation) {
|
|
2217
2484
|
const url = `${BASE_URL}/skills/${doc.file}`;
|
|
2218
|
-
const path3 =
|
|
2485
|
+
const path3 = join2(".agent", "skills", "game-sdk", doc.file);
|
|
2219
2486
|
const description = `${doc.title} (${doc.category})`;
|
|
2220
2487
|
const success = await downloadFile(url, path3, description);
|
|
2221
2488
|
if (success) {
|
|
@@ -2226,9 +2493,9 @@ async function downloadDocumentation(manifest) {
|
|
|
2226
2493
|
}
|
|
2227
2494
|
console.log(`
|
|
2228
2495
|
\uD83D\uDCCA Documentation download summary:`);
|
|
2229
|
-
console.log(`
|
|
2496
|
+
console.log(` \u2705 Success: ${successCount}`);
|
|
2230
2497
|
if (failCount > 0) {
|
|
2231
|
-
console.log(`
|
|
2498
|
+
console.log(` \u274C Failed: ${failCount}`);
|
|
2232
2499
|
}
|
|
2233
2500
|
console.log();
|
|
2234
2501
|
return { successCount, failCount };
|
|
@@ -2241,8 +2508,8 @@ async function updateGameSdk() {
|
|
|
2241
2508
|
let totalFail = 0;
|
|
2242
2509
|
console.log(`\uD83D\uDCE6 Downloading core SDK files...
|
|
2243
2510
|
`);
|
|
2244
|
-
for (const
|
|
2245
|
-
const success = await downloadFile(
|
|
2511
|
+
for (const file2 of FILES) {
|
|
2512
|
+
const success = await downloadFile(file2.url, file2.path, file2.description);
|
|
2246
2513
|
if (success) {
|
|
2247
2514
|
totalSuccess++;
|
|
2248
2515
|
} else {
|
|
@@ -2255,27 +2522,27 @@ async function updateGameSdk() {
|
|
|
2255
2522
|
totalSuccess += successCount;
|
|
2256
2523
|
totalFail += failCount;
|
|
2257
2524
|
} else {
|
|
2258
|
-
console.log(
|
|
2525
|
+
console.log(`\u26A0\uFE0F Skipping documentation download due to manifest error
|
|
2259
2526
|
`);
|
|
2260
2527
|
}
|
|
2261
2528
|
console.log("=".repeat(60));
|
|
2262
2529
|
console.log(`\uD83C\uDF89 Download Complete!
|
|
2263
2530
|
`);
|
|
2264
2531
|
console.log(`\uD83D\uDCCA Final Summary:`);
|
|
2265
|
-
console.log(`
|
|
2532
|
+
console.log(` \u2705 Successfully downloaded: ${totalSuccess} files`);
|
|
2266
2533
|
if (totalFail > 0) {
|
|
2267
|
-
console.log(`
|
|
2534
|
+
console.log(` \u274C Failed: ${totalFail} files`);
|
|
2268
2535
|
console.log(`
|
|
2269
|
-
|
|
2536
|
+
\u26A0\uFE0F Some files failed to download. Please check the errors above.`);
|
|
2270
2537
|
process.exit(1);
|
|
2271
2538
|
} else {
|
|
2272
2539
|
console.log(`
|
|
2273
|
-
|
|
2540
|
+
\u2728 All files downloaded successfully!`);
|
|
2274
2541
|
}
|
|
2275
2542
|
}
|
|
2276
2543
|
|
|
2277
2544
|
// src/cli.ts
|
|
2278
|
-
var
|
|
2545
|
+
var TEMPLATES2 = {
|
|
2279
2546
|
webapp: {
|
|
2280
2547
|
name: "webapp",
|
|
2281
2548
|
description: "Frontend-only webapp (Vite + React Router 7)",
|
|
@@ -2288,15 +2555,15 @@ var TEMPLATES = {
|
|
|
2288
2555
|
}
|
|
2289
2556
|
};
|
|
2290
2557
|
async function selectTemplate() {
|
|
2291
|
-
const entries = Object.values(
|
|
2558
|
+
const entries = Object.values(TEMPLATES2);
|
|
2292
2559
|
console.log(`
|
|
2293
2560
|
Available templates:
|
|
2294
2561
|
`);
|
|
2295
2562
|
entries.forEach((t, i) => {
|
|
2296
|
-
console.log(` ${i + 1}. ${t.name}
|
|
2563
|
+
console.log(` ${i + 1}. ${t.name} \u2014 ${t.description}`);
|
|
2297
2564
|
});
|
|
2298
2565
|
console.log();
|
|
2299
|
-
const readline = await import("
|
|
2566
|
+
const readline = await import("readline");
|
|
2300
2567
|
const rl = readline.createInterface({
|
|
2301
2568
|
input: process.stdin,
|
|
2302
2569
|
output: process.stdout
|
|
@@ -2314,23 +2581,29 @@ Available templates:
|
|
|
2314
2581
|
});
|
|
2315
2582
|
});
|
|
2316
2583
|
}
|
|
2317
|
-
program.name("@rodyssey/cli").description("Airconcepts CLI toolkit").version("0.0
|
|
2584
|
+
program.name("@rodyssey/cli").description("Airconcepts CLI toolkit").version("0.1.0");
|
|
2318
2585
|
var app = program.command("app").description("Manage webapp projects");
|
|
2319
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) => {
|
|
2320
2587
|
let templateName;
|
|
2321
2588
|
if (options.template) {
|
|
2322
|
-
if (!(options.template in
|
|
2323
|
-
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(", ")}`);
|
|
2324
2591
|
process.exit(1);
|
|
2325
2592
|
}
|
|
2326
2593
|
templateName = options.template;
|
|
2327
2594
|
} else {
|
|
2328
2595
|
templateName = await selectTemplate();
|
|
2329
2596
|
}
|
|
2330
|
-
const template =
|
|
2597
|
+
const template = TEMPLATES2[templateName];
|
|
2331
2598
|
await create(projectName, template.repo, templateName);
|
|
2332
2599
|
});
|
|
2333
2600
|
app.command("update-game-sdk").description("Download and update the GameSDK library, types, and documentation").action(async () => {
|
|
2334
2601
|
await updateGameSdk();
|
|
2335
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
|
+
});
|
|
2336
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
|
},
|