gencow 0.1.55 → 0.1.56

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/bin/gencow.mjs CHANGED
@@ -2790,8 +2790,13 @@ process.exit(0);
2790
2790
  const startMs = Date.now();
2791
2791
  const { create: tarCreate } = await import("tar");
2792
2792
  const chunks = [];
2793
+ // ⚠️ 프로젝트 루트에서 functionsDir("gencow/")를 포함하여 패키징.
2794
+ // deployBundle()이 dataDir에 strip:0으로 추출하므로
2795
+ // tar 내부 구조가 gencow/schema.ts 형태여야 dataDir/gencow/에 위치함.
2796
+ // (기존: cwd=absoluteFunctions → ./schema.ts → dataDir/schema.ts → 404)
2797
+ const projectRoot = resolve(absoluteFunctions, "..");
2793
2798
  await new Promise((res, rej) => {
2794
- tarCreate({ cwd: absoluteFunctions, gzip: true }, ["."])
2799
+ tarCreate({ cwd: projectRoot, gzip: true }, [functionsDir])
2795
2800
  .on("data", c => chunks.push(c))
2796
2801
  .on("end", res)
2797
2802
  .on("error", rej);
@@ -2929,8 +2934,11 @@ ${BOLD}${CYAN}🚀 Gencow Cloud Dev${RESET}
2929
2934
  let debounceTimer = null;
2930
2935
  let pendingFile = null;
2931
2936
 
2937
+ const GENERATED_FILES = new Set(["api.ts", "README.md"]); // dev:local(L1197)과 동일
2932
2938
  watch(absoluteFunctions, { recursive: true }, (eventType, filename) => {
2933
- if (!filename || filename.includes("node_modules") || filename.endsWith("api.ts")) return;
2939
+ if (!filename || filename.includes("node_modules")) return;
2940
+ const basename = (filename.includes("/") ? filename.split("/").pop() : filename) ?? filename;
2941
+ if (GENERATED_FILES.has(basename)) return;
2934
2942
  pendingFile = filename;
2935
2943
  clearTimeout(debounceTimer);
2936
2944
  debounceTimer = setTimeout(async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.55",
3
+ "version": "0.1.56",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {
package/server/index.js CHANGED
@@ -71944,6 +71944,9 @@ async function main() {
71944
71944
  await rawSql(`ALTER TABLE apps ADD COLUMN IF NOT EXISTS static_deployed_at TIMESTAMP`);
71945
71945
  await rawSql(`ALTER TABLE apps ADD COLUMN IF NOT EXISTS static_size BIGINT`);
71946
71946
  await rawSql(`ALTER TABLE deployments ADD COLUMN IF NOT EXISTS env TEXT DEFAULT 'dev'`);
71947
+ await rawSql(`ALTER TABLE usage_snapshots ADD COLUMN IF NOT EXISTS static_bandwidth_bytes BIGINT DEFAULT 0 NOT NULL`);
71948
+ await rawSql(`ALTER TABLE usage_snapshots ADD COLUMN IF NOT EXISTS static_requests INTEGER DEFAULT 0 NOT NULL`);
71949
+ await rawSql(`ALTER TABLE usage_snapshots ADD COLUMN IF NOT EXISTS static_storage_bytes BIGINT DEFAULT 0 NOT NULL`);
71947
71950
  console.log("[db] schema upgrade \u2713");
71948
71951
  } catch (e) {
71949
71952
  console.warn("[db] schema upgrade warning:", e?.message);
@@ -72092,6 +72095,32 @@ async function main() {
72092
72095
  const msg = e instanceof Error ? e.message : String(e);
72093
72096
  console.error("[platform] Auto-recovery failed:", msg);
72094
72097
  }
72098
+ const platformPort = process.env.PORT || "4100";
72099
+ const USAGE_CRON_INTERVAL = 60 * 60 * 1e3;
72100
+ setInterval(async () => {
72101
+ try {
72102
+ const res = await fetch(`http://localhost:${platformPort}/internal/usage/snapshot`, {
72103
+ method: "POST"
72104
+ });
72105
+ if (res.ok) {
72106
+ const result = await res.json();
72107
+ console.log(`[usage-cron] Storage snapshot \u2713`, result);
72108
+ } else {
72109
+ console.warn(`[usage-cron] Snapshot failed: ${res.status}`);
72110
+ }
72111
+ } catch (e) {
72112
+ const msg = e instanceof Error ? e.message : String(e);
72113
+ console.warn(`[usage-cron] Snapshot error:`, msg);
72114
+ }
72115
+ }, USAGE_CRON_INTERVAL);
72116
+ setTimeout(async () => {
72117
+ try {
72118
+ await fetch(`http://localhost:${platformPort}/internal/usage/snapshot`, { method: "POST" });
72119
+ console.log(`[usage-cron] Initial snapshot \u2713`);
72120
+ } catch {
72121
+ }
72122
+ }, 1e4);
72123
+ console.log(`[platform] Usage cron registered (every 1h, first in 10s)`);
72095
72124
  }
72096
72125
  app.on(["POST", "GET"], "/api/auth/**", betterAuthHandler);
72097
72126
  appModule.setDb?.(db);
@@ -72138,15 +72167,31 @@ async function main() {
72138
72167
  chat: async (opts) => {
72139
72168
  const model = opts.model || "gpt-4o-mini";
72140
72169
  if (IS_BAAS) {
72170
+ const appName = process.env.GENCOW_APP_NAME || "";
72141
72171
  const res = await fetch(`${METERING_URL}/platform/ai/chat`, {
72142
72172
  method: "POST",
72143
72173
  headers: {
72144
72174
  "Content-Type": "application/json",
72145
72175
  "X-App-Token": INTERNAL_TOKEN
72146
72176
  },
72147
- body: JSON.stringify({ model, ...opts })
72177
+ body: JSON.stringify({ model, appName, ...opts })
72148
72178
  });
72149
- return res.json();
72179
+ const json4 = await res.json();
72180
+ if (!res.ok || json4.error) {
72181
+ throw new Error(
72182
+ `AI proxy error (${res.status}): ${json4.error ?? "Unknown error"}. \uBAA8\uB378: ${model}`
72183
+ );
72184
+ }
72185
+ return {
72186
+ text: json4.text ?? "",
72187
+ usage: json4.usage ?? {
72188
+ promptTokens: 0,
72189
+ completionTokens: 0,
72190
+ totalTokens: 0
72191
+ },
72192
+ creditsCharged: json4.creditsCharged ?? 0,
72193
+ model: json4.model ?? model
72194
+ };
72150
72195
  }
72151
72196
  if (!localKey) {
72152
72197
  throw new Error(