@bonginkan/maria 4.3.10 → 4.3.13
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 +14 -5
- package/dist/READY.manifest.json +1 -1
- package/dist/bin/maria.cjs +6136 -2202
- package/dist/bin/maria.cjs.map +1 -1
- package/dist/cli.cjs +6130 -2196
- package/dist/cli.cjs.map +1 -1
- package/dist/index.js +33 -9
- package/dist/index.js.map +1 -1
- package/dist/server/express-server.cjs +75 -19
- package/dist/server/express-server.js +75 -19
- package/dist/server-express.cjs +75 -19
- package/dist/server-express.cjs.map +1 -1
- package/package.json +7 -4
- package/src/slash-commands/READY.manifest.json +1 -1
|
@@ -6913,7 +6913,7 @@ function startRateLimitCleanup() {
|
|
|
6913
6913
|
});
|
|
6914
6914
|
}, 10 * 60 * 1e3);
|
|
6915
6915
|
}
|
|
6916
|
-
async function getFirestorePlan(
|
|
6916
|
+
async function getFirestorePlan(uid2) {
|
|
6917
6917
|
try {
|
|
6918
6918
|
const admin = await import('firebase-admin');
|
|
6919
6919
|
if (!admin.apps?.length) {
|
|
@@ -6924,7 +6924,7 @@ async function getFirestorePlan(uid) {
|
|
|
6924
6924
|
}
|
|
6925
6925
|
const { getFirestore } = await import('firebase-admin/firestore');
|
|
6926
6926
|
const db = getFirestore();
|
|
6927
|
-
const doc = await db.doc(`projects/default/users/${
|
|
6927
|
+
const doc = await db.doc(`projects/default/users/${uid2}`).get();
|
|
6928
6928
|
const plan = doc.exists && doc.data()?.plan || "FREE";
|
|
6929
6929
|
return String(plan).toUpperCase();
|
|
6930
6930
|
} catch {
|
|
@@ -8529,6 +8529,7 @@ var IMSFacade = class {
|
|
|
8529
8529
|
var IMSFacade_default = IMSFacade;
|
|
8530
8530
|
|
|
8531
8531
|
// src/server/express-server.ts
|
|
8532
|
+
var jobIndex = /* @__PURE__ */ new Map();
|
|
8532
8533
|
var app = express__default.default();
|
|
8533
8534
|
var port = process.env.PORT || 8080;
|
|
8534
8535
|
app.use(helmet__default.default());
|
|
@@ -8546,7 +8547,7 @@ app.get("/health", (req, res) => {
|
|
|
8546
8547
|
app.get("/api/status", (req, res) => {
|
|
8547
8548
|
res.json({
|
|
8548
8549
|
status: "healthy",
|
|
8549
|
-
version: "4.3.
|
|
8550
|
+
version: "4.3.9",
|
|
8550
8551
|
uptime: process.uptime(),
|
|
8551
8552
|
memory: process.memoryUsage(),
|
|
8552
8553
|
platform: process.platform,
|
|
@@ -8557,7 +8558,7 @@ app.get("/api/status", (req, res) => {
|
|
|
8557
8558
|
app.get("/", (req, res) => {
|
|
8558
8559
|
res.json({
|
|
8559
8560
|
name: "MARIA CODE API",
|
|
8560
|
-
version: "4.3.
|
|
8561
|
+
version: "4.3.9",
|
|
8561
8562
|
status: "running",
|
|
8562
8563
|
environment: process.env.NODE_ENV || "development",
|
|
8563
8564
|
endpoints: {
|
|
@@ -8607,7 +8608,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8607
8608
|
if (!decoded) {
|
|
8608
8609
|
return res.status(401).json({ error: "invalid_token" });
|
|
8609
8610
|
}
|
|
8610
|
-
const
|
|
8611
|
+
const uid2 = decoded.uid || decoded.sub || "unknown";
|
|
8611
8612
|
const email = decoded.email || "";
|
|
8612
8613
|
const displayName = decoded.name || decoded.displayName || (email ? String(email).split("@")[0] : "User");
|
|
8613
8614
|
let provider = decoded.firebase?.sign_in_provider;
|
|
@@ -8618,7 +8619,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8618
8619
|
}
|
|
8619
8620
|
const plan = "FREE";
|
|
8620
8621
|
const response2 = {
|
|
8621
|
-
id:
|
|
8622
|
+
id: uid2,
|
|
8622
8623
|
email,
|
|
8623
8624
|
name: displayName,
|
|
8624
8625
|
provider: provider || "unknown",
|
|
@@ -8702,6 +8703,9 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8702
8703
|
await loadProviderKeys();
|
|
8703
8704
|
const auth = req.headers.authorization;
|
|
8704
8705
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8706
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8707
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8708
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8705
8709
|
const { prompt, model, size = "1024x1024", format = "png", count = 1, seed } = req.body || {};
|
|
8706
8710
|
if (!prompt) return res.status(400).json({ error: "bad_request", message: "prompt required" });
|
|
8707
8711
|
const m2 = /^(\d{2,4})x(\d{2,4})$/.exec(String(size));
|
|
@@ -8723,9 +8727,18 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8723
8727
|
trace: Math.random().toString(36).slice(2, 8).toUpperCase()
|
|
8724
8728
|
};
|
|
8725
8729
|
const saved = await saveArtifacts({ root: process.cwd(), kind: "image" }, buffers.map((b) => ({ bytes: b, ext: `.${format}` })), manifest);
|
|
8730
|
+
jobIndex.set(String(manifest.trace), {
|
|
8731
|
+
id: String(manifest.trace),
|
|
8732
|
+
status: "completed",
|
|
8733
|
+
kind: "image",
|
|
8734
|
+
manifestPath: saved.manifestPath,
|
|
8735
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8736
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8737
|
+
uid: uid2
|
|
8738
|
+
});
|
|
8726
8739
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8727
|
-
await recordConsumption(
|
|
8728
|
-
return res.json({ success: true, data: { url: saved.manifestPath } });
|
|
8740
|
+
await recordConsumption(uid2, { requests: 1, image: Math.max(1, buffers.length) }, idemKey);
|
|
8741
|
+
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8729
8742
|
} catch (error) {
|
|
8730
8743
|
console.error("[Image API] Error:", error);
|
|
8731
8744
|
return res.status(500).json({
|
|
@@ -8770,8 +8783,17 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8770
8783
|
saved = await saveArtifacts({ root: process.cwd(), kind: "video" }, items, manifest);
|
|
8771
8784
|
}
|
|
8772
8785
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8773
|
-
await recordConsumption(
|
|
8774
|
-
|
|
8786
|
+
await recordConsumption(uid, { requests: 1, video: 1 }, idemKey);
|
|
8787
|
+
jobIndex.set(String(manifest.trace), {
|
|
8788
|
+
id: String(manifest.trace),
|
|
8789
|
+
status: "completed",
|
|
8790
|
+
kind: "video",
|
|
8791
|
+
manifestPath: saved.manifestPath,
|
|
8792
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8793
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8794
|
+
uid
|
|
8795
|
+
});
|
|
8796
|
+
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8775
8797
|
} catch (error) {
|
|
8776
8798
|
console.error("[Video API] Error:", error);
|
|
8777
8799
|
return res.status(500).json({
|
|
@@ -8780,6 +8802,40 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8780
8802
|
});
|
|
8781
8803
|
}
|
|
8782
8804
|
});
|
|
8805
|
+
app.get("/api/v1/jobs/:id", async (req, res) => {
|
|
8806
|
+
try {
|
|
8807
|
+
const auth = req.headers.authorization;
|
|
8808
|
+
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8809
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8810
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8811
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8812
|
+
const id = String(req.params.id || "").trim();
|
|
8813
|
+
if (!id) return res.status(400).json({ error: "bad_request", message: "id required" });
|
|
8814
|
+
const info = jobIndex.get(id);
|
|
8815
|
+
if (!info || info.uid && info.uid !== uid2) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8816
|
+
let manifest;
|
|
8817
|
+
if (info.manifestPath) {
|
|
8818
|
+
try {
|
|
8819
|
+
const full = path__namespace.default.resolve(process.cwd(), info.manifestPath);
|
|
8820
|
+
const txt = await fsp__namespace.default.readFile(full, "utf8");
|
|
8821
|
+
manifest = JSON.parse(txt);
|
|
8822
|
+
} catch {
|
|
8823
|
+
}
|
|
8824
|
+
}
|
|
8825
|
+
return res.json({
|
|
8826
|
+
id: info.id,
|
|
8827
|
+
status: info.status,
|
|
8828
|
+
kind: info.kind,
|
|
8829
|
+
manifestPath: info.manifestPath,
|
|
8830
|
+
manifest,
|
|
8831
|
+
createdAt: info.createdAt,
|
|
8832
|
+
updatedAt: info.updatedAt
|
|
8833
|
+
});
|
|
8834
|
+
} catch (error) {
|
|
8835
|
+
console.error("[Jobs API] Error:", error);
|
|
8836
|
+
return res.status(500).json({ error: "internal_error", message: "failed to fetch job" });
|
|
8837
|
+
}
|
|
8838
|
+
});
|
|
8783
8839
|
app.post("/api/v1/code", rateLimitMiddleware, async (req, res) => {
|
|
8784
8840
|
try {
|
|
8785
8841
|
const { prompt, language = "typescript", model = "gpt-4" } = req.body;
|
|
@@ -8935,14 +8991,14 @@ function calcNextReset() {
|
|
|
8935
8991
|
d.setUTCHours(0, 0, 0, 0);
|
|
8936
8992
|
return d.toISOString();
|
|
8937
8993
|
}
|
|
8938
|
-
async function recordConsumption(
|
|
8994
|
+
async function recordConsumption(uid2, consumption, idempotencyKey) {
|
|
8939
8995
|
const db = await getFirestoreSafe();
|
|
8940
8996
|
if (!db) return;
|
|
8941
|
-
const docPath = `projects/default/usage/${
|
|
8997
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8942
8998
|
const usageRef = db.doc(docPath);
|
|
8943
8999
|
const nowISO = (/* @__PURE__ */ new Date()).toISOString();
|
|
8944
9000
|
if (idempotencyKey) {
|
|
8945
|
-
const idemRef = db.doc(`projects/default/usage/${
|
|
9001
|
+
const idemRef = db.doc(`projects/default/usage/${uid2}/consumptions/${idempotencyKey}`);
|
|
8946
9002
|
const idemSnap = await idemRef.get();
|
|
8947
9003
|
if (idemSnap.exists) return;
|
|
8948
9004
|
await idemRef.set({ createdAt: nowISO, consumption });
|
|
@@ -8976,8 +9032,8 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
8976
9032
|
const auth = req.headers.authorization;
|
|
8977
9033
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8978
9034
|
const db = await getFirestoreSafe();
|
|
8979
|
-
const
|
|
8980
|
-
const docPath = `projects/default/usage/${
|
|
9035
|
+
const uid2 = "current";
|
|
9036
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8981
9037
|
let data = null;
|
|
8982
9038
|
if (db) {
|
|
8983
9039
|
const snap = await db.doc(docPath).get();
|
|
@@ -8996,7 +9052,7 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
8996
9052
|
};
|
|
8997
9053
|
await db.doc(docPath).set(data);
|
|
8998
9054
|
}
|
|
8999
|
-
const historySnap = await db.collection(`projects/default/usage/${
|
|
9055
|
+
const historySnap = await db.collection(`projects/default/usage/${uid2}/consumptions`).orderBy("createdAt", "desc").limit(20).get();
|
|
9000
9056
|
const history = historySnap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
9001
9057
|
data.history = history;
|
|
9002
9058
|
} else {
|
|
@@ -9024,11 +9080,11 @@ app.post("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9024
9080
|
const { consumption } = req.body || {};
|
|
9025
9081
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
9026
9082
|
const db = await getFirestoreSafe();
|
|
9027
|
-
const
|
|
9028
|
-
const docPath = `projects/default/usage/${
|
|
9083
|
+
const uid2 = "current";
|
|
9084
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9029
9085
|
let data = null;
|
|
9030
9086
|
if (db) {
|
|
9031
|
-
await recordConsumption(
|
|
9087
|
+
await recordConsumption(uid2, consumption || {}, idemKey);
|
|
9032
9088
|
const snap = await db.doc(docPath).get();
|
|
9033
9089
|
data = snap.exists ? snap.data() : { ok: true };
|
|
9034
9090
|
} else {
|
|
@@ -6913,7 +6913,7 @@ function startRateLimitCleanup() {
|
|
|
6913
6913
|
});
|
|
6914
6914
|
}, 10 * 60 * 1e3);
|
|
6915
6915
|
}
|
|
6916
|
-
async function getFirestorePlan(
|
|
6916
|
+
async function getFirestorePlan(uid2) {
|
|
6917
6917
|
try {
|
|
6918
6918
|
const admin = await import('firebase-admin');
|
|
6919
6919
|
if (!admin.apps?.length) {
|
|
@@ -6924,7 +6924,7 @@ async function getFirestorePlan(uid) {
|
|
|
6924
6924
|
}
|
|
6925
6925
|
const { getFirestore } = await import('firebase-admin/firestore');
|
|
6926
6926
|
const db = getFirestore();
|
|
6927
|
-
const doc = await db.doc(`projects/default/users/${
|
|
6927
|
+
const doc = await db.doc(`projects/default/users/${uid2}`).get();
|
|
6928
6928
|
const plan = doc.exists && doc.data()?.plan || "FREE";
|
|
6929
6929
|
return String(plan).toUpperCase();
|
|
6930
6930
|
} catch {
|
|
@@ -8529,6 +8529,7 @@ var IMSFacade = class {
|
|
|
8529
8529
|
var IMSFacade_default = IMSFacade;
|
|
8530
8530
|
|
|
8531
8531
|
// src/server/express-server.ts
|
|
8532
|
+
var jobIndex = /* @__PURE__ */ new Map();
|
|
8532
8533
|
var app = express__default.default();
|
|
8533
8534
|
var port = process.env.PORT || 8080;
|
|
8534
8535
|
app.use(helmet__default.default());
|
|
@@ -8546,7 +8547,7 @@ app.get("/health", (req, res) => {
|
|
|
8546
8547
|
app.get("/api/status", (req, res) => {
|
|
8547
8548
|
res.json({
|
|
8548
8549
|
status: "healthy",
|
|
8549
|
-
version: "4.3.
|
|
8550
|
+
version: "4.3.9",
|
|
8550
8551
|
uptime: process.uptime(),
|
|
8551
8552
|
memory: process.memoryUsage(),
|
|
8552
8553
|
platform: process.platform,
|
|
@@ -8557,7 +8558,7 @@ app.get("/api/status", (req, res) => {
|
|
|
8557
8558
|
app.get("/", (req, res) => {
|
|
8558
8559
|
res.json({
|
|
8559
8560
|
name: "MARIA CODE API",
|
|
8560
|
-
version: "4.3.
|
|
8561
|
+
version: "4.3.9",
|
|
8561
8562
|
status: "running",
|
|
8562
8563
|
environment: process.env.NODE_ENV || "development",
|
|
8563
8564
|
endpoints: {
|
|
@@ -8607,7 +8608,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8607
8608
|
if (!decoded) {
|
|
8608
8609
|
return res.status(401).json({ error: "invalid_token" });
|
|
8609
8610
|
}
|
|
8610
|
-
const
|
|
8611
|
+
const uid2 = decoded.uid || decoded.sub || "unknown";
|
|
8611
8612
|
const email = decoded.email || "";
|
|
8612
8613
|
const displayName = decoded.name || decoded.displayName || (email ? String(email).split("@")[0] : "User");
|
|
8613
8614
|
let provider = decoded.firebase?.sign_in_provider;
|
|
@@ -8618,7 +8619,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8618
8619
|
}
|
|
8619
8620
|
const plan = "FREE";
|
|
8620
8621
|
const response2 = {
|
|
8621
|
-
id:
|
|
8622
|
+
id: uid2,
|
|
8622
8623
|
email,
|
|
8623
8624
|
name: displayName,
|
|
8624
8625
|
provider: provider || "unknown",
|
|
@@ -8702,6 +8703,9 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8702
8703
|
await loadProviderKeys();
|
|
8703
8704
|
const auth = req.headers.authorization;
|
|
8704
8705
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8706
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8707
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8708
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8705
8709
|
const { prompt, model, size = "1024x1024", format = "png", count = 1, seed } = req.body || {};
|
|
8706
8710
|
if (!prompt) return res.status(400).json({ error: "bad_request", message: "prompt required" });
|
|
8707
8711
|
const m2 = /^(\d{2,4})x(\d{2,4})$/.exec(String(size));
|
|
@@ -8723,9 +8727,18 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8723
8727
|
trace: Math.random().toString(36).slice(2, 8).toUpperCase()
|
|
8724
8728
|
};
|
|
8725
8729
|
const saved = await saveArtifacts({ root: process.cwd(), kind: "image" }, buffers.map((b) => ({ bytes: b, ext: `.${format}` })), manifest);
|
|
8730
|
+
jobIndex.set(String(manifest.trace), {
|
|
8731
|
+
id: String(manifest.trace),
|
|
8732
|
+
status: "completed",
|
|
8733
|
+
kind: "image",
|
|
8734
|
+
manifestPath: saved.manifestPath,
|
|
8735
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8736
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8737
|
+
uid: uid2
|
|
8738
|
+
});
|
|
8726
8739
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8727
|
-
await recordConsumption(
|
|
8728
|
-
return res.json({ success: true, data: { url: saved.manifestPath } });
|
|
8740
|
+
await recordConsumption(uid2, { requests: 1, image: Math.max(1, buffers.length) }, idemKey);
|
|
8741
|
+
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8729
8742
|
} catch (error) {
|
|
8730
8743
|
console.error("[Image API] Error:", error);
|
|
8731
8744
|
return res.status(500).json({
|
|
@@ -8770,8 +8783,17 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8770
8783
|
saved = await saveArtifacts({ root: process.cwd(), kind: "video" }, items, manifest);
|
|
8771
8784
|
}
|
|
8772
8785
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8773
|
-
await recordConsumption(
|
|
8774
|
-
|
|
8786
|
+
await recordConsumption(uid, { requests: 1, video: 1 }, idemKey);
|
|
8787
|
+
jobIndex.set(String(manifest.trace), {
|
|
8788
|
+
id: String(manifest.trace),
|
|
8789
|
+
status: "completed",
|
|
8790
|
+
kind: "video",
|
|
8791
|
+
manifestPath: saved.manifestPath,
|
|
8792
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8793
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8794
|
+
uid
|
|
8795
|
+
});
|
|
8796
|
+
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8775
8797
|
} catch (error) {
|
|
8776
8798
|
console.error("[Video API] Error:", error);
|
|
8777
8799
|
return res.status(500).json({
|
|
@@ -8780,6 +8802,40 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8780
8802
|
});
|
|
8781
8803
|
}
|
|
8782
8804
|
});
|
|
8805
|
+
app.get("/api/v1/jobs/:id", async (req, res) => {
|
|
8806
|
+
try {
|
|
8807
|
+
const auth = req.headers.authorization;
|
|
8808
|
+
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8809
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8810
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8811
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8812
|
+
const id = String(req.params.id || "").trim();
|
|
8813
|
+
if (!id) return res.status(400).json({ error: "bad_request", message: "id required" });
|
|
8814
|
+
const info = jobIndex.get(id);
|
|
8815
|
+
if (!info || info.uid && info.uid !== uid2) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8816
|
+
let manifest;
|
|
8817
|
+
if (info.manifestPath) {
|
|
8818
|
+
try {
|
|
8819
|
+
const full = path__namespace.default.resolve(process.cwd(), info.manifestPath);
|
|
8820
|
+
const txt = await fsp__namespace.default.readFile(full, "utf8");
|
|
8821
|
+
manifest = JSON.parse(txt);
|
|
8822
|
+
} catch {
|
|
8823
|
+
}
|
|
8824
|
+
}
|
|
8825
|
+
return res.json({
|
|
8826
|
+
id: info.id,
|
|
8827
|
+
status: info.status,
|
|
8828
|
+
kind: info.kind,
|
|
8829
|
+
manifestPath: info.manifestPath,
|
|
8830
|
+
manifest,
|
|
8831
|
+
createdAt: info.createdAt,
|
|
8832
|
+
updatedAt: info.updatedAt
|
|
8833
|
+
});
|
|
8834
|
+
} catch (error) {
|
|
8835
|
+
console.error("[Jobs API] Error:", error);
|
|
8836
|
+
return res.status(500).json({ error: "internal_error", message: "failed to fetch job" });
|
|
8837
|
+
}
|
|
8838
|
+
});
|
|
8783
8839
|
app.post("/api/v1/code", rateLimitMiddleware, async (req, res) => {
|
|
8784
8840
|
try {
|
|
8785
8841
|
const { prompt, language = "typescript", model = "gpt-4" } = req.body;
|
|
@@ -8935,14 +8991,14 @@ function calcNextReset() {
|
|
|
8935
8991
|
d.setUTCHours(0, 0, 0, 0);
|
|
8936
8992
|
return d.toISOString();
|
|
8937
8993
|
}
|
|
8938
|
-
async function recordConsumption(
|
|
8994
|
+
async function recordConsumption(uid2, consumption, idempotencyKey) {
|
|
8939
8995
|
const db = await getFirestoreSafe();
|
|
8940
8996
|
if (!db) return;
|
|
8941
|
-
const docPath = `projects/default/usage/${
|
|
8997
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8942
8998
|
const usageRef = db.doc(docPath);
|
|
8943
8999
|
const nowISO = (/* @__PURE__ */ new Date()).toISOString();
|
|
8944
9000
|
if (idempotencyKey) {
|
|
8945
|
-
const idemRef = db.doc(`projects/default/usage/${
|
|
9001
|
+
const idemRef = db.doc(`projects/default/usage/${uid2}/consumptions/${idempotencyKey}`);
|
|
8946
9002
|
const idemSnap = await idemRef.get();
|
|
8947
9003
|
if (idemSnap.exists) return;
|
|
8948
9004
|
await idemRef.set({ createdAt: nowISO, consumption });
|
|
@@ -8976,8 +9032,8 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
8976
9032
|
const auth = req.headers.authorization;
|
|
8977
9033
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8978
9034
|
const db = await getFirestoreSafe();
|
|
8979
|
-
const
|
|
8980
|
-
const docPath = `projects/default/usage/${
|
|
9035
|
+
const uid2 = "current";
|
|
9036
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8981
9037
|
let data = null;
|
|
8982
9038
|
if (db) {
|
|
8983
9039
|
const snap = await db.doc(docPath).get();
|
|
@@ -8996,7 +9052,7 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
8996
9052
|
};
|
|
8997
9053
|
await db.doc(docPath).set(data);
|
|
8998
9054
|
}
|
|
8999
|
-
const historySnap = await db.collection(`projects/default/usage/${
|
|
9055
|
+
const historySnap = await db.collection(`projects/default/usage/${uid2}/consumptions`).orderBy("createdAt", "desc").limit(20).get();
|
|
9000
9056
|
const history = historySnap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
9001
9057
|
data.history = history;
|
|
9002
9058
|
} else {
|
|
@@ -9024,11 +9080,11 @@ app.post("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9024
9080
|
const { consumption } = req.body || {};
|
|
9025
9081
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
9026
9082
|
const db = await getFirestoreSafe();
|
|
9027
|
-
const
|
|
9028
|
-
const docPath = `projects/default/usage/${
|
|
9083
|
+
const uid2 = "current";
|
|
9084
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9029
9085
|
let data = null;
|
|
9030
9086
|
if (db) {
|
|
9031
|
-
await recordConsumption(
|
|
9087
|
+
await recordConsumption(uid2, consumption || {}, idemKey);
|
|
9032
9088
|
const snap = await db.doc(docPath).get();
|
|
9033
9089
|
data = snap.exists ? snap.data() : { ok: true };
|
|
9034
9090
|
} else {
|
package/dist/server-express.cjs
CHANGED
|
@@ -6913,7 +6913,7 @@ function startRateLimitCleanup() {
|
|
|
6913
6913
|
});
|
|
6914
6914
|
}, 10 * 60 * 1e3);
|
|
6915
6915
|
}
|
|
6916
|
-
async function getFirestorePlan(
|
|
6916
|
+
async function getFirestorePlan(uid2) {
|
|
6917
6917
|
try {
|
|
6918
6918
|
const admin = await import('firebase-admin');
|
|
6919
6919
|
if (!admin.apps?.length) {
|
|
@@ -6924,7 +6924,7 @@ async function getFirestorePlan(uid) {
|
|
|
6924
6924
|
}
|
|
6925
6925
|
const { getFirestore } = await import('firebase-admin/firestore');
|
|
6926
6926
|
const db = getFirestore();
|
|
6927
|
-
const doc = await db.doc(`projects/default/users/${
|
|
6927
|
+
const doc = await db.doc(`projects/default/users/${uid2}`).get();
|
|
6928
6928
|
const plan = doc.exists && doc.data()?.plan || "FREE";
|
|
6929
6929
|
return String(plan).toUpperCase();
|
|
6930
6930
|
} catch {
|
|
@@ -8529,6 +8529,7 @@ var IMSFacade = class {
|
|
|
8529
8529
|
var IMSFacade_default = IMSFacade;
|
|
8530
8530
|
|
|
8531
8531
|
// src/server/express-server.ts
|
|
8532
|
+
var jobIndex = /* @__PURE__ */ new Map();
|
|
8532
8533
|
var app = express__default.default();
|
|
8533
8534
|
var port = process.env.PORT || 8080;
|
|
8534
8535
|
app.use(helmet__default.default());
|
|
@@ -8546,7 +8547,7 @@ app.get("/health", (req, res) => {
|
|
|
8546
8547
|
app.get("/api/status", (req, res) => {
|
|
8547
8548
|
res.json({
|
|
8548
8549
|
status: "healthy",
|
|
8549
|
-
version: "4.3.
|
|
8550
|
+
version: "4.3.9",
|
|
8550
8551
|
uptime: process.uptime(),
|
|
8551
8552
|
memory: process.memoryUsage(),
|
|
8552
8553
|
platform: process.platform,
|
|
@@ -8557,7 +8558,7 @@ app.get("/api/status", (req, res) => {
|
|
|
8557
8558
|
app.get("/", (req, res) => {
|
|
8558
8559
|
res.json({
|
|
8559
8560
|
name: "MARIA CODE API",
|
|
8560
|
-
version: "4.3.
|
|
8561
|
+
version: "4.3.9",
|
|
8561
8562
|
status: "running",
|
|
8562
8563
|
environment: process.env.NODE_ENV || "development",
|
|
8563
8564
|
endpoints: {
|
|
@@ -8607,7 +8608,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8607
8608
|
if (!decoded) {
|
|
8608
8609
|
return res.status(401).json({ error: "invalid_token" });
|
|
8609
8610
|
}
|
|
8610
|
-
const
|
|
8611
|
+
const uid2 = decoded.uid || decoded.sub || "unknown";
|
|
8611
8612
|
const email = decoded.email || "";
|
|
8612
8613
|
const displayName = decoded.name || decoded.displayName || (email ? String(email).split("@")[0] : "User");
|
|
8613
8614
|
let provider = decoded.firebase?.sign_in_provider;
|
|
@@ -8618,7 +8619,7 @@ app.get("/api/user/profile", async (req, res) => {
|
|
|
8618
8619
|
}
|
|
8619
8620
|
const plan = "FREE";
|
|
8620
8621
|
const response2 = {
|
|
8621
|
-
id:
|
|
8622
|
+
id: uid2,
|
|
8622
8623
|
email,
|
|
8623
8624
|
name: displayName,
|
|
8624
8625
|
provider: provider || "unknown",
|
|
@@ -8702,6 +8703,9 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8702
8703
|
await loadProviderKeys();
|
|
8703
8704
|
const auth = req.headers.authorization;
|
|
8704
8705
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8706
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8707
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8708
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8705
8709
|
const { prompt, model, size = "1024x1024", format = "png", count = 1, seed } = req.body || {};
|
|
8706
8710
|
if (!prompt) return res.status(400).json({ error: "bad_request", message: "prompt required" });
|
|
8707
8711
|
const m2 = /^(\d{2,4})x(\d{2,4})$/.exec(String(size));
|
|
@@ -8723,9 +8727,18 @@ app.post("/api/v1/image", rateLimitMiddleware, async (req, res) => {
|
|
|
8723
8727
|
trace: Math.random().toString(36).slice(2, 8).toUpperCase()
|
|
8724
8728
|
};
|
|
8725
8729
|
const saved = await saveArtifacts({ root: process.cwd(), kind: "image" }, buffers.map((b) => ({ bytes: b, ext: `.${format}` })), manifest);
|
|
8730
|
+
jobIndex.set(String(manifest.trace), {
|
|
8731
|
+
id: String(manifest.trace),
|
|
8732
|
+
status: "completed",
|
|
8733
|
+
kind: "image",
|
|
8734
|
+
manifestPath: saved.manifestPath,
|
|
8735
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8736
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8737
|
+
uid: uid2
|
|
8738
|
+
});
|
|
8726
8739
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8727
|
-
await recordConsumption(
|
|
8728
|
-
return res.json({ success: true, data: { url: saved.manifestPath } });
|
|
8740
|
+
await recordConsumption(uid2, { requests: 1, image: Math.max(1, buffers.length) }, idemKey);
|
|
8741
|
+
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8729
8742
|
} catch (error) {
|
|
8730
8743
|
console.error("[Image API] Error:", error);
|
|
8731
8744
|
return res.status(500).json({
|
|
@@ -8770,8 +8783,17 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8770
8783
|
saved = await saveArtifacts({ root: process.cwd(), kind: "video" }, items, manifest);
|
|
8771
8784
|
}
|
|
8772
8785
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
8773
|
-
await recordConsumption(
|
|
8774
|
-
|
|
8786
|
+
await recordConsumption(uid, { requests: 1, video: 1 }, idemKey);
|
|
8787
|
+
jobIndex.set(String(manifest.trace), {
|
|
8788
|
+
id: String(manifest.trace),
|
|
8789
|
+
status: "completed",
|
|
8790
|
+
kind: "video",
|
|
8791
|
+
manifestPath: saved.manifestPath,
|
|
8792
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8793
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8794
|
+
uid
|
|
8795
|
+
});
|
|
8796
|
+
return res.json({ success: true, data: { url: saved.manifestPath, jobId: manifest.trace } });
|
|
8775
8797
|
} catch (error) {
|
|
8776
8798
|
console.error("[Video API] Error:", error);
|
|
8777
8799
|
return res.status(500).json({
|
|
@@ -8780,6 +8802,40 @@ app.post("/api/v1/video", rateLimitMiddleware, async (req, res) => {
|
|
|
8780
8802
|
});
|
|
8781
8803
|
}
|
|
8782
8804
|
});
|
|
8805
|
+
app.get("/api/v1/jobs/:id", async (req, res) => {
|
|
8806
|
+
try {
|
|
8807
|
+
const auth = req.headers.authorization;
|
|
8808
|
+
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8809
|
+
const idToken = auth.substring("Bearer ".length).trim();
|
|
8810
|
+
const decoded = await decodeFirebaseToken(idToken).catch(() => null);
|
|
8811
|
+
const uid2 = decoded?.uid || decoded?.sub || "current";
|
|
8812
|
+
const id = String(req.params.id || "").trim();
|
|
8813
|
+
if (!id) return res.status(400).json({ error: "bad_request", message: "id required" });
|
|
8814
|
+
const info = jobIndex.get(id);
|
|
8815
|
+
if (!info || info.uid && info.uid !== uid2) return res.status(404).json({ error: "not_found", message: "job not found" });
|
|
8816
|
+
let manifest;
|
|
8817
|
+
if (info.manifestPath) {
|
|
8818
|
+
try {
|
|
8819
|
+
const full = path__namespace.default.resolve(process.cwd(), info.manifestPath);
|
|
8820
|
+
const txt = await fsp__namespace.default.readFile(full, "utf8");
|
|
8821
|
+
manifest = JSON.parse(txt);
|
|
8822
|
+
} catch {
|
|
8823
|
+
}
|
|
8824
|
+
}
|
|
8825
|
+
return res.json({
|
|
8826
|
+
id: info.id,
|
|
8827
|
+
status: info.status,
|
|
8828
|
+
kind: info.kind,
|
|
8829
|
+
manifestPath: info.manifestPath,
|
|
8830
|
+
manifest,
|
|
8831
|
+
createdAt: info.createdAt,
|
|
8832
|
+
updatedAt: info.updatedAt
|
|
8833
|
+
});
|
|
8834
|
+
} catch (error) {
|
|
8835
|
+
console.error("[Jobs API] Error:", error);
|
|
8836
|
+
return res.status(500).json({ error: "internal_error", message: "failed to fetch job" });
|
|
8837
|
+
}
|
|
8838
|
+
});
|
|
8783
8839
|
app.post("/api/v1/code", rateLimitMiddleware, async (req, res) => {
|
|
8784
8840
|
try {
|
|
8785
8841
|
const { prompt, language = "typescript", model = "gpt-4" } = req.body;
|
|
@@ -8935,14 +8991,14 @@ function calcNextReset() {
|
|
|
8935
8991
|
d.setUTCHours(0, 0, 0, 0);
|
|
8936
8992
|
return d.toISOString();
|
|
8937
8993
|
}
|
|
8938
|
-
async function recordConsumption(
|
|
8994
|
+
async function recordConsumption(uid2, consumption, idempotencyKey) {
|
|
8939
8995
|
const db = await getFirestoreSafe();
|
|
8940
8996
|
if (!db) return;
|
|
8941
|
-
const docPath = `projects/default/usage/${
|
|
8997
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8942
8998
|
const usageRef = db.doc(docPath);
|
|
8943
8999
|
const nowISO = (/* @__PURE__ */ new Date()).toISOString();
|
|
8944
9000
|
if (idempotencyKey) {
|
|
8945
|
-
const idemRef = db.doc(`projects/default/usage/${
|
|
9001
|
+
const idemRef = db.doc(`projects/default/usage/${uid2}/consumptions/${idempotencyKey}`);
|
|
8946
9002
|
const idemSnap = await idemRef.get();
|
|
8947
9003
|
if (idemSnap.exists) return;
|
|
8948
9004
|
await idemRef.set({ createdAt: nowISO, consumption });
|
|
@@ -8976,8 +9032,8 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
8976
9032
|
const auth = req.headers.authorization;
|
|
8977
9033
|
if (!auth || !auth.startsWith("Bearer ")) return res.status(401).json({ error: "unauthorized" });
|
|
8978
9034
|
const db = await getFirestoreSafe();
|
|
8979
|
-
const
|
|
8980
|
-
const docPath = `projects/default/usage/${
|
|
9035
|
+
const uid2 = "current";
|
|
9036
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
8981
9037
|
let data = null;
|
|
8982
9038
|
if (db) {
|
|
8983
9039
|
const snap = await db.doc(docPath).get();
|
|
@@ -8996,7 +9052,7 @@ app.get("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
8996
9052
|
};
|
|
8997
9053
|
await db.doc(docPath).set(data);
|
|
8998
9054
|
}
|
|
8999
|
-
const historySnap = await db.collection(`projects/default/usage/${
|
|
9055
|
+
const historySnap = await db.collection(`projects/default/usage/${uid2}/consumptions`).orderBy("createdAt", "desc").limit(20).get();
|
|
9000
9056
|
const history = historySnap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
9001
9057
|
data.history = history;
|
|
9002
9058
|
} else {
|
|
@@ -9024,11 +9080,11 @@ app.post("/api/v1/usage", rateLimitMiddleware, async (req, res) => {
|
|
|
9024
9080
|
const { consumption } = req.body || {};
|
|
9025
9081
|
const idemKey = req.headers["idempotency-key"] || void 0;
|
|
9026
9082
|
const db = await getFirestoreSafe();
|
|
9027
|
-
const
|
|
9028
|
-
const docPath = `projects/default/usage/${
|
|
9083
|
+
const uid2 = "current";
|
|
9084
|
+
const docPath = `projects/default/usage/${uid2}`;
|
|
9029
9085
|
let data = null;
|
|
9030
9086
|
if (db) {
|
|
9031
|
-
await recordConsumption(
|
|
9087
|
+
await recordConsumption(uid2, consumption || {}, idemKey);
|
|
9032
9088
|
const snap = await db.doc(docPath).get();
|
|
9033
9089
|
data = snap.exists ? snap.data() : { ok: true };
|
|
9034
9090
|
} else {
|