@oodarun/cli 0.1.4 → 0.1.5
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 +56 -52
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1804,15 +1804,11 @@ async function deployToolsViaRest(projectName, token, projectRoot, onProgress) {
|
|
|
1804
1804
|
uploads.push(writeFile(`${projectRoot}/ooda-vite-plugin.mjs`, OODA_VITE_PLUGIN));
|
|
1805
1805
|
uploads.push(writeFile("/tmp/ooda-patch-config.mjs", OODA_CONFIG_PATCH_SCRIPT));
|
|
1806
1806
|
await Promise.all(uploads);
|
|
1807
|
-
const
|
|
1808
|
-
|
|
1809
|
-
})
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
log(`Config patch failed: ${msg}`);
|
|
1813
|
-
return "";
|
|
1814
|
-
})
|
|
1815
|
-
]);
|
|
1807
|
+
const patchResult = await exec(`node /tmp/ooda-patch-config.mjs "${projectRoot}" 2>&1`).catch((err) => {
|
|
1808
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1809
|
+
log(`Config patch failed: ${msg}`);
|
|
1810
|
+
return "";
|
|
1811
|
+
});
|
|
1816
1812
|
if (patchResult) log(`Config patch: ${String(patchResult).trim()}`);
|
|
1817
1813
|
}
|
|
1818
1814
|
|
|
@@ -2987,6 +2983,8 @@ async function patchServerConfig(projectName, token, projectRoot, onProgress) {
|
|
|
2987
2983
|
console.log("[project-provisioner] Server config patch result:", result.trim());
|
|
2988
2984
|
}
|
|
2989
2985
|
async function provisionFromFolder(localPath, projectName, token, onProgress, branchName, gitInfo, claudeToken, claudeEnv, githubToken) {
|
|
2986
|
+
const t0 = Date.now();
|
|
2987
|
+
const progress = (p) => onProgress({ ...p, step: `[+${((Date.now() - t0) / 1e3).toFixed(1)}s] ${p.step}` });
|
|
2990
2988
|
const projectRoot = `/home/user/${path5.basename(localPath)}`;
|
|
2991
2989
|
const headers = { Authorization: `Bearer ${token}` };
|
|
2992
2990
|
async function exec(cmd) {
|
|
@@ -3011,20 +3009,20 @@ async function provisionFromFolder(localPath, projectName, token, onProgress, br
|
|
|
3011
3009
|
try {
|
|
3012
3010
|
const project = detectProject(localPath);
|
|
3013
3011
|
console.log(`[project-provisioner] Detected: framework=${project.framework}, pm=${project.packageManager}, config=${project.configFile}`);
|
|
3014
|
-
const projectUrl = await createOrReuseProject(projectName, token,
|
|
3015
|
-
const fileCount = await uploadFolder(localPath, projectRoot, projectName, token,
|
|
3016
|
-
|
|
3012
|
+
const projectUrl = await createOrReuseProject(projectName, token, progress);
|
|
3013
|
+
const fileCount = await uploadFolder(localPath, projectRoot, projectName, token, progress);
|
|
3014
|
+
progress({ step: "Upload complete", detail: `${fileCount} files` });
|
|
3017
3015
|
const effectiveClaudeToken = claudeToken || process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
3018
3016
|
if (effectiveClaudeToken) {
|
|
3019
|
-
await setupClaudeAuth(projectName, token, effectiveClaudeToken,
|
|
3017
|
+
await setupClaudeAuth(projectName, token, effectiveClaudeToken, progress, claudeEnv);
|
|
3020
3018
|
}
|
|
3021
|
-
await deployClaudeConfig(projectName, token, projectRoot, project.framework,
|
|
3019
|
+
await deployClaudeConfig(projectName, token, projectRoot, project.framework, progress, gitInfo || null, branchName || null);
|
|
3022
3020
|
await writeRemoteFile("/home/user/.ooda/publish.mjs", PUBLISH_SCRIPT2);
|
|
3023
|
-
await patchServerConfig(projectName, token, projectRoot,
|
|
3024
|
-
await installSourcePlugin(projectName, token, projectRoot, project.framework,
|
|
3021
|
+
await patchServerConfig(projectName, token, projectRoot, progress);
|
|
3022
|
+
await installSourcePlugin(projectName, token, projectRoot, project.framework, progress);
|
|
3025
3023
|
try {
|
|
3026
3024
|
await deployToolsViaRest(projectName, token, projectRoot, (msg) => {
|
|
3027
|
-
|
|
3025
|
+
progress({ step: msg });
|
|
3028
3026
|
});
|
|
3029
3027
|
} catch (err) {
|
|
3030
3028
|
console.warn("[project-provisioner] Tool deployment failed:", err instanceof Error ? err.message : String(err));
|
|
@@ -3040,21 +3038,21 @@ async function provisionFromFolder(localPath, projectName, token, onProgress, br
|
|
|
3040
3038
|
(t) => t.mcp?.transport === "stdio"
|
|
3041
3039
|
);
|
|
3042
3040
|
if (hasInstallableTools) {
|
|
3043
|
-
|
|
3041
|
+
progress({ step: "Installing MCP tools..." });
|
|
3044
3042
|
await installToolsViaRest(projectName, token, projectRoot, tools, pm, (msg) => {
|
|
3045
|
-
|
|
3043
|
+
progress({ step: msg });
|
|
3046
3044
|
});
|
|
3047
3045
|
}
|
|
3048
3046
|
if (hasMcpTools) {
|
|
3049
3047
|
const mcpJson = serializeMcpJson(tools);
|
|
3050
3048
|
await writeRemoteFile(`${projectRoot}/.mcp.json`, mcpJson);
|
|
3051
|
-
|
|
3049
|
+
progress({ step: "Wrote .mcp.json" });
|
|
3052
3050
|
}
|
|
3053
3051
|
} catch (err) {
|
|
3054
3052
|
console.warn("[project-provisioner] MCP tool setup failed:", err instanceof Error ? err.message : String(err));
|
|
3055
3053
|
}
|
|
3056
3054
|
if (branchName && gitInfo?.isGitRepo) {
|
|
3057
|
-
|
|
3055
|
+
progress({ step: "Initializing git on project..." });
|
|
3058
3056
|
const userName = gitInfo.userName || "Ooda User";
|
|
3059
3057
|
const userEmail = gitInfo.userEmail || "user@ooda.dev";
|
|
3060
3058
|
const gitInitScript = [
|
|
@@ -3076,7 +3074,7 @@ async function provisionFromFolder(localPath, projectName, token, onProgress, br
|
|
|
3076
3074
|
console.log(`[project-provisioner] Added remote: ${gitInfo.originUrl}`);
|
|
3077
3075
|
}
|
|
3078
3076
|
if (githubToken) {
|
|
3079
|
-
|
|
3077
|
+
progress({ step: "Setting up git credentials..." });
|
|
3080
3078
|
const homeDir = "/home/user";
|
|
3081
3079
|
await exec(`git config --global credential.helper store`);
|
|
3082
3080
|
await writeRemoteFile(
|
|
@@ -3090,7 +3088,7 @@ async function provisionFromFolder(localPath, projectName, token, onProgress, br
|
|
|
3090
3088
|
console.error("[project-provisioner] Git init failed:", err);
|
|
3091
3089
|
}
|
|
3092
3090
|
}
|
|
3093
|
-
|
|
3091
|
+
progress({ step: "Ready for setup", detail: projectUrl });
|
|
3094
3092
|
return {
|
|
3095
3093
|
success: true,
|
|
3096
3094
|
projectName,
|
|
@@ -3162,6 +3160,8 @@ async function detectProjectRemote(projectName, token, projectRoot) {
|
|
|
3162
3160
|
return { framework, packageManager, devCommand, configFile };
|
|
3163
3161
|
}
|
|
3164
3162
|
async function provisionFromGitHub(parsed, projectName, token, onProgress, githubToken, claudeToken) {
|
|
3163
|
+
const t0 = Date.now();
|
|
3164
|
+
const progress = (p) => onProgress({ ...p, step: `[+${((Date.now() - t0) / 1e3).toFixed(1)}s] ${p.step}` });
|
|
3165
3165
|
const headers = { Authorization: `Bearer ${token}` };
|
|
3166
3166
|
let homeDir = "/home/user";
|
|
3167
3167
|
async function exec(cmd) {
|
|
@@ -3184,8 +3184,8 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
|
|
|
3184
3184
|
});
|
|
3185
3185
|
}
|
|
3186
3186
|
try {
|
|
3187
|
-
const projectUrl = await createOrReuseProject(projectName, token,
|
|
3188
|
-
|
|
3187
|
+
const projectUrl = await createOrReuseProject(projectName, token, progress);
|
|
3188
|
+
progress({ step: "Waiting for sandbox to be ready..." });
|
|
3189
3189
|
for (let i = 0; i < 15; i++) {
|
|
3190
3190
|
const check = await exec("test -d /home/user && echo OK || echo NOT_READY");
|
|
3191
3191
|
const trimmed = check.trim();
|
|
@@ -3199,7 +3199,7 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
|
|
|
3199
3199
|
console.log(`[project-provisioner] Sandbox home directory: ${homeDir}`);
|
|
3200
3200
|
const projectRoot = `${homeDir}/${parsed.repo}`;
|
|
3201
3201
|
const cloneUrl = buildAuthenticatedCloneUrl(parsed, githubToken);
|
|
3202
|
-
|
|
3202
|
+
progress({ step: "Cloning from GitHub...", detail: `${parsed.owner}/${parsed.repo}` });
|
|
3203
3203
|
const cloneOutput = await exec(
|
|
3204
3204
|
`cd ${homeDir} && git clone ${cloneUrl} ${parsed.repo} 2>&1`
|
|
3205
3205
|
);
|
|
@@ -3219,7 +3219,7 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
|
|
|
3219
3219
|
const workingBranch = `ooda/${baseBranch}`;
|
|
3220
3220
|
await exec(`cd ${projectRoot} && git checkout -b ${workingBranch} 2>&1`);
|
|
3221
3221
|
if (githubToken) {
|
|
3222
|
-
|
|
3222
|
+
progress({ step: "Setting up git credentials..." });
|
|
3223
3223
|
await exec(`cd ${projectRoot} && git remote set-url origin https://github.com/${parsed.owner}/${parsed.repo}.git`);
|
|
3224
3224
|
await exec(`git config --global credential.helper store`);
|
|
3225
3225
|
await writeRemoteFile(
|
|
@@ -3229,12 +3229,12 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
|
|
|
3229
3229
|
);
|
|
3230
3230
|
}
|
|
3231
3231
|
await exec(`cd ${projectRoot} && git config user.name "ooda" && git config user.email "dev@ooda.run"`);
|
|
3232
|
-
|
|
3232
|
+
progress({ step: "Detecting project..." });
|
|
3233
3233
|
const project = await detectProjectRemote(projectName, token, projectRoot);
|
|
3234
3234
|
console.log(`[project-provisioner] Detected: framework=${project.framework}, pm=${project.packageManager}`);
|
|
3235
3235
|
const effectiveClaudeToken = claudeToken || process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
3236
3236
|
if (effectiveClaudeToken) {
|
|
3237
|
-
await setupClaudeAuth(projectName, token, effectiveClaudeToken,
|
|
3237
|
+
await setupClaudeAuth(projectName, token, effectiveClaudeToken, progress);
|
|
3238
3238
|
}
|
|
3239
3239
|
const gitInfo = {
|
|
3240
3240
|
isGitRepo: true,
|
|
@@ -3244,7 +3244,7 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
|
|
|
3244
3244
|
userName: "ooda",
|
|
3245
3245
|
userEmail: "dev@ooda.run"
|
|
3246
3246
|
};
|
|
3247
|
-
await deployClaudeConfig(projectName, token, projectRoot, project.framework,
|
|
3247
|
+
await deployClaudeConfig(projectName, token, projectRoot, project.framework, progress, gitInfo, workingBranch);
|
|
3248
3248
|
const gitWorkflowPatch = `
|
|
3249
3249
|
## Git Workflow
|
|
3250
3250
|
- This project was cloned from GitHub (${parsed.owner}/${parsed.repo}).
|
|
@@ -3266,11 +3266,11 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
|
|
|
3266
3266
|
);
|
|
3267
3267
|
await writeRemoteFile(`${projectRoot}/CLAUDE.md`, updatedClaudeMd);
|
|
3268
3268
|
await writeRemoteFile(`${homeDir}/.ooda/publish.mjs`, PUBLISH_SCRIPT2);
|
|
3269
|
-
await patchServerConfig(projectName, token, projectRoot,
|
|
3270
|
-
await installSourcePlugin(projectName, token, projectRoot, project.framework,
|
|
3269
|
+
await patchServerConfig(projectName, token, projectRoot, progress);
|
|
3270
|
+
await installSourcePlugin(projectName, token, projectRoot, project.framework, progress);
|
|
3271
3271
|
try {
|
|
3272
3272
|
await deployToolsViaRest(projectName, token, projectRoot, (msg) => {
|
|
3273
|
-
|
|
3273
|
+
progress({ step: msg });
|
|
3274
3274
|
});
|
|
3275
3275
|
} catch (err) {
|
|
3276
3276
|
console.warn("[project-provisioner] Tool deployment failed:", err instanceof Error ? err.message : String(err));
|
|
@@ -3292,21 +3292,21 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
|
|
|
3292
3292
|
(t) => t.mcp?.transport === "stdio"
|
|
3293
3293
|
);
|
|
3294
3294
|
if (hasInstallableTools) {
|
|
3295
|
-
|
|
3295
|
+
progress({ step: "Installing MCP tools..." });
|
|
3296
3296
|
await installToolsViaRest(projectName, token, projectRoot, tools, pm, (msg) => {
|
|
3297
|
-
|
|
3297
|
+
progress({ step: msg });
|
|
3298
3298
|
});
|
|
3299
3299
|
}
|
|
3300
3300
|
if (hasMcpTools) {
|
|
3301
3301
|
const mcpJson = serializeMcpJson(tools);
|
|
3302
3302
|
await writeRemoteFile(`${projectRoot}/.mcp.json`, mcpJson);
|
|
3303
|
-
|
|
3303
|
+
progress({ step: "Wrote .mcp.json" });
|
|
3304
3304
|
}
|
|
3305
3305
|
}
|
|
3306
3306
|
} catch (err) {
|
|
3307
3307
|
console.warn("[project-provisioner] MCP tool setup failed:", err instanceof Error ? err.message : String(err));
|
|
3308
3308
|
}
|
|
3309
|
-
|
|
3309
|
+
progress({ step: "Ready for setup", detail: projectUrl });
|
|
3310
3310
|
return {
|
|
3311
3311
|
success: true,
|
|
3312
3312
|
projectName,
|
|
@@ -3321,6 +3321,8 @@ async function provisionFromGitHub(parsed, projectName, token, onProgress, githu
|
|
|
3321
3321
|
}
|
|
3322
3322
|
}
|
|
3323
3323
|
async function provisionFromTemplate(projectName, templateId, token, onProgress, claudeToken, claudeEnv) {
|
|
3324
|
+
const t0 = Date.now();
|
|
3325
|
+
const progress = (p) => onProgress({ ...p, step: `[+${((Date.now() - t0) / 1e3).toFixed(1)}s] ${p.step}` });
|
|
3324
3326
|
const { getProjectTemplateById: getProjectTemplateById2 } = await Promise.resolve().then(() => (init_project_templates(), project_templates_exports));
|
|
3325
3327
|
const template = getProjectTemplateById2(templateId);
|
|
3326
3328
|
if (!template) {
|
|
@@ -3356,20 +3358,20 @@ async function provisionFromTemplate(projectName, templateId, token, onProgress,
|
|
|
3356
3358
|
}
|
|
3357
3359
|
}
|
|
3358
3360
|
try {
|
|
3359
|
-
const projectUrl = await createOrReuseProject(projectName, token,
|
|
3360
|
-
|
|
3361
|
+
const projectUrl = await createOrReuseProject(projectName, token, progress);
|
|
3362
|
+
progress({ step: "Uploading template files...", detail: `${template.files.length} files` });
|
|
3361
3363
|
for (const file of template.files) {
|
|
3362
3364
|
await writeFile(`${projectRoot}/${file.path}`, file.content);
|
|
3363
3365
|
}
|
|
3364
3366
|
const effectiveClaudeToken = claudeToken || process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
3365
3367
|
if (effectiveClaudeToken) {
|
|
3366
|
-
await setupClaudeAuth(projectName, token, effectiveClaudeToken,
|
|
3368
|
+
await setupClaudeAuth(projectName, token, effectiveClaudeToken, progress, claudeEnv);
|
|
3367
3369
|
}
|
|
3368
|
-
await deployClaudeConfig(projectName, token, projectRoot, "vite",
|
|
3370
|
+
await deployClaudeConfig(projectName, token, projectRoot, "vite", progress);
|
|
3369
3371
|
await writeFile("/home/user/.ooda/publish.mjs", PUBLISH_SCRIPT2);
|
|
3370
3372
|
try {
|
|
3371
3373
|
await deployToolsViaRest(projectName, token, projectRoot, (msg) => {
|
|
3372
|
-
|
|
3374
|
+
progress({ step: msg });
|
|
3373
3375
|
});
|
|
3374
3376
|
} catch {
|
|
3375
3377
|
}
|
|
@@ -3383,26 +3385,26 @@ async function provisionFromTemplate(projectName, templateId, token, onProgress,
|
|
|
3383
3385
|
(t) => t.mcp?.transport === "stdio"
|
|
3384
3386
|
);
|
|
3385
3387
|
if (hasInstallableTools) {
|
|
3386
|
-
|
|
3388
|
+
progress({ step: "Installing MCP tools..." });
|
|
3387
3389
|
await installToolsViaRest(projectName, token, projectRoot, tools, "npm", (msg) => {
|
|
3388
|
-
|
|
3390
|
+
progress({ step: msg });
|
|
3389
3391
|
});
|
|
3390
3392
|
}
|
|
3391
3393
|
if (hasMcpTools) {
|
|
3392
3394
|
const mcpJson = serializeMcpJson(tools);
|
|
3393
3395
|
await writeFile(`${projectRoot}/.mcp.json`, mcpJson);
|
|
3394
|
-
|
|
3396
|
+
progress({ step: "Wrote .mcp.json" });
|
|
3395
3397
|
}
|
|
3396
3398
|
} catch (err) {
|
|
3397
3399
|
console.warn("[project-provisioner] MCP tool setup failed:", err instanceof Error ? err.message : String(err));
|
|
3398
3400
|
}
|
|
3399
|
-
|
|
3401
|
+
progress({ step: "Starting dev server..." });
|
|
3400
3402
|
await exec("pkill -f vite || true");
|
|
3401
3403
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
3402
3404
|
exec(`cd ${projectRoot} && ${template.startCmd}`).catch(() => {
|
|
3403
3405
|
});
|
|
3404
3406
|
await new Promise((r) => setTimeout(r, 6e3));
|
|
3405
|
-
|
|
3407
|
+
progress({ step: "Done!", detail: projectUrl });
|
|
3406
3408
|
return {
|
|
3407
3409
|
success: true,
|
|
3408
3410
|
projectName,
|
|
@@ -4616,6 +4618,8 @@ function getActiveProject() {
|
|
|
4616
4618
|
return _activeProject;
|
|
4617
4619
|
}
|
|
4618
4620
|
async function connectAndRunClaude(projectName, apiToken, claudeToken, projectUrl, initialPrompt, previewUrl) {
|
|
4621
|
+
const t0 = Date.now();
|
|
4622
|
+
const elapsed = () => `[+${((Date.now() - t0) / 1e3).toFixed(1)}s]`;
|
|
4619
4623
|
console.log(`
|
|
4620
4624
|
${c.cyan}Connecting to ${c.bold}${projectName}${c.reset}${c.cyan}...${c.reset}`);
|
|
4621
4625
|
const orgClaude = isOrgMode() ? getOrgClaudeConfig() : null;
|
|
@@ -4677,7 +4681,7 @@ async function connectAndRunClaude(projectName, apiToken, claudeToken, projectUr
|
|
|
4677
4681
|
return;
|
|
4678
4682
|
}
|
|
4679
4683
|
const projectRoot = await findProjectRoot(projectName, apiToken);
|
|
4680
|
-
console.log(` ${c.green}${c.bold}\u2713${c.reset} Connected`);
|
|
4684
|
+
console.log(` ${c.green}${c.bold}\u2713${c.reset} Connected ${c.gray}${elapsed()}${c.reset}`);
|
|
4681
4685
|
pushPhase("setup", "Writing config files");
|
|
4682
4686
|
const devServerStatus = await readDevServerStatus(client);
|
|
4683
4687
|
if (devServerStatus) {
|
|
@@ -4808,7 +4812,7 @@ with open(p, 'w') as f: json.dump(d, f)
|
|
|
4808
4812
|
}
|
|
4809
4813
|
}
|
|
4810
4814
|
pushPhase("starting", "Launching Claude Code");
|
|
4811
|
-
console.log(` ${c.gray}Launching claude in ${projectRoot}...${c.reset}
|
|
4815
|
+
console.log(` ${c.gray}${elapsed()} Launching claude in ${projectRoot}...${c.reset}
|
|
4812
4816
|
`);
|
|
4813
4817
|
if (process.stdin.readable) {
|
|
4814
4818
|
process.stdin.resume();
|
|
@@ -5073,8 +5077,8 @@ ${text}`;
|
|
|
5073
5077
|
`);
|
|
5074
5078
|
break;
|
|
5075
5079
|
}
|
|
5076
|
-
const
|
|
5077
|
-
if (cmdAlive ||
|
|
5080
|
+
const elapsed2 = Date.now() - spawnedAt;
|
|
5081
|
+
if (cmdAlive || elapsed2 >= EARLY_DROP_THRESHOLD_MS) {
|
|
5078
5082
|
break;
|
|
5079
5083
|
}
|
|
5080
5084
|
if (attempt < MAX_SPAWN_RETRIES) {
|
|
@@ -5322,7 +5326,7 @@ async function deployFromGitHubFlow(target, apiToken, claudeToken) {
|
|
|
5322
5326
|
}
|
|
5323
5327
|
|
|
5324
5328
|
// src/cli/index.ts
|
|
5325
|
-
var CLI_VERSION = "0.1.
|
|
5329
|
+
var CLI_VERSION = "0.1.5";
|
|
5326
5330
|
function formatMutationError(result) {
|
|
5327
5331
|
const parts = [];
|
|
5328
5332
|
if (result.status !== void 0) parts.push(String(result.status));
|