@nomad-e/bluma-cli 0.16.0 → 0.18.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.
Files changed (2) hide show
  1. package/dist/main.js +57 -39
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -15549,20 +15549,6 @@ function normalizeContext(raw) {
15549
15549
  appUrl: typeof raw.appUrl === "string" ? raw.appUrl : null
15550
15550
  };
15551
15551
  }
15552
- function readJsonFile(filePath) {
15553
- try {
15554
- if (!fs5.existsSync(filePath)) {
15555
- return null;
15556
- }
15557
- const parsed = JSON.parse(fs5.readFileSync(filePath, "utf8"));
15558
- if (parsed && typeof parsed === "object") {
15559
- return parsed.appContext && typeof parsed.appContext === "object" ? parsed.appContext : parsed;
15560
- }
15561
- } catch {
15562
- return null;
15563
- }
15564
- return null;
15565
- }
15566
15552
  function readFactorAiWorkspaceManifest(projectDir = process.cwd()) {
15567
15553
  const manifestPath = path6.join(projectDir, "factorai.sh.json");
15568
15554
  try {
@@ -15575,17 +15561,20 @@ function readFactorAiWorkspaceManifest(projectDir = process.cwd()) {
15575
15561
  return null;
15576
15562
  }
15577
15563
  }
15578
- function readContextFromWorkspace() {
15579
- const candidate = path6.join(process.cwd(), "factorai.sh.json");
15580
- const parsed = readJsonFile(candidate);
15581
- if (!parsed) {
15564
+ var FACTORAI_APP_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
15565
+ function isFactorAiAppUuid(value) {
15566
+ return FACTORAI_APP_UUID_RE.test(String(value || "").trim());
15567
+ }
15568
+ function readContextFromWorkspace(projectDir = process.cwd()) {
15569
+ const manifest = readFactorAiWorkspaceManifest(projectDir);
15570
+ if (!manifest) {
15582
15571
  return null;
15583
15572
  }
15584
- const context = normalizeContext(parsed);
15585
- return context;
15573
+ const raw = manifest.appContext && typeof manifest.appContext === "object" ? manifest.appContext : manifest;
15574
+ return normalizeContext(raw);
15586
15575
  }
15587
- function loadFactorAiAppContext() {
15588
- return readContextFromWorkspace();
15576
+ function loadFactorAiAppContext(projectDir = process.cwd()) {
15577
+ return readContextFromWorkspace(projectDir);
15589
15578
  }
15590
15579
  var FACTOR_SH_URL_APP_FIELD = "factor-sh-url-app";
15591
15580
  function resolveFactorShAppLiveUrl(projectDir = process.cwd()) {
@@ -20427,7 +20416,7 @@ async function deployApp(args) {
20427
20416
  // src/app/agent/runtime/native_tool_catalog.ts
20428
20417
  init_sandbox_policy();
20429
20418
  function getFactorAiBaseUrl() {
20430
- const value = process.env.FACTORAI_BASE_URL || process.env.FACTORAI_URL || "";
20419
+ const value = process.env.FACTORAI_BASE_URL || process.env.FACTORAI_URL || process.env.SEVERINO_URL || "";
20431
20420
  const trimmed = value.trim();
20432
20421
  return trimmed || void 0;
20433
20422
  }
@@ -20465,23 +20454,52 @@ async function requestFactorAi(pathname, init = {}) {
20465
20454
  }
20466
20455
  }
20467
20456
  if (!response.ok) {
20468
- const message2 = payload?.error?.message || payload?.message || payload?.error || `FactorAI request failed with status ${response.status}`;
20469
- throw new Error(message2);
20457
+ const message2 = payload?.error?.message || payload?.message || (typeof payload?.error === "string" ? payload.error : void 0) || `FactorAI request failed with status ${response.status}`;
20458
+ const base = getFactorAiBaseUrl();
20459
+ const hint = response.status === 404 && base ? ` (GET ${base}${pathname} \u2014 confirma que deploy_app usou o mesmo host; appIds antigos somem se o severino reiniciou)` : "";
20460
+ throw new Error(`${message2}${hint}`);
20470
20461
  }
20471
20462
  return payload;
20472
20463
  }
20473
- async function factorAiGetAppStatus(args) {
20474
- const appId = String(args?.appId || "").trim();
20475
- if (!appId) {
20476
- return { error: "appId is required." };
20464
+ async function resolveFactorAiAppId(explicitAppId) {
20465
+ const trimmed = String(explicitAppId || "").trim();
20466
+ if (trimmed && isFactorAiAppUuid(trimmed)) {
20467
+ return trimmed;
20468
+ }
20469
+ const fromManifest = loadFactorAiAppContext();
20470
+ if (fromManifest?.appId) {
20471
+ if (!trimmed || trimmed === fromManifest.appId) {
20472
+ return fromManifest.appId;
20473
+ }
20477
20474
  }
20475
+ if (trimmed && !isFactorAiAppUuid(trimmed)) {
20476
+ const listPayload = await requestFactorAi("/api/v1/apps");
20477
+ const apps = listPayload?.data?.apps ?? listPayload?.apps ?? [];
20478
+ if (Array.isArray(apps)) {
20479
+ const match = apps.find(
20480
+ (app) => app?.slug === trimmed || app?.id === trimmed
20481
+ );
20482
+ if (match?.id && isFactorAiAppUuid(match.id)) {
20483
+ return match.id;
20484
+ }
20485
+ }
20486
+ throw new Error(
20487
+ `Invalid appId "${trimmed}": get_app_status exige UUID (ex: 23edf15f-70e3-4eeb-b607-9a6da250343c), n\xE3o o slug da URL. L\xEA factorai.sh.json \u2192 appContext.appId ou lista GET /api/v1/apps.`
20488
+ );
20489
+ }
20490
+ if (fromManifest?.appId) {
20491
+ return fromManifest.appId;
20492
+ }
20493
+ throw new Error(
20494
+ "appId em falta: passa o UUID de factorai.sh.json (appContext.appId) ou faz deploy_app primeiro nesta sess\xE3o."
20495
+ );
20496
+ }
20497
+ async function factorAiGetAppStatus(args) {
20498
+ const appId = await resolveFactorAiAppId(args?.appId);
20478
20499
  return requestFactorAi(`/api/v1/apps/${encodeURIComponent(appId)}`);
20479
20500
  }
20480
20501
  async function factorAiApplyAppChanges(args) {
20481
- const appId = String(args?.appId || "").trim();
20482
- if (!appId) {
20483
- return { error: "appId is required." };
20484
- }
20502
+ const appId = await resolveFactorAiAppId(args?.appId);
20485
20503
  const files = Array.isArray(args?.files) ? args.files : Array.isArray(args?.changes) ? args.changes : [];
20486
20504
  if (files.length === 0) {
20487
20505
  return { error: "files or changes must be a non-empty array." };
@@ -20497,10 +20515,7 @@ async function factorAiApplyAppChanges(args) {
20497
20515
  return response;
20498
20516
  }
20499
20517
  async function factorAiRedeployApp(args) {
20500
- const appId = String(args?.appId || "").trim();
20501
- if (!appId) {
20502
- return { error: "appId is required." };
20503
- }
20518
+ const appId = await resolveFactorAiAppId(args?.appId);
20504
20519
  const response = await requestFactorAi(`/api/v1/apps/${encodeURIComponent(appId)}/redeploy`, {
20505
20520
  method: "POST"
20506
20521
  });
@@ -20596,9 +20611,12 @@ function getFactorAiSandboxToolDefinitions() {
20596
20611
  parameters: {
20597
20612
  type: "object",
20598
20613
  properties: {
20599
- appId: { type: "string", description: "FactorAI app identifier." }
20614
+ appId: {
20615
+ type: "string",
20616
+ description: "UUID from factorai.sh.json (appContext.appId). Optional if manifest exists in cwd. Do not use URL slug."
20617
+ }
20600
20618
  },
20601
- required: ["appId"],
20619
+ required: [],
20602
20620
  additionalProperties: false
20603
20621
  }
20604
20622
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nomad-e/bluma-cli",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "BluMa independent agent for automation and advanced software engineering.",
5
5
  "author": "Alex Fonseca",
6
6
  "license": "Apache-2.0",