@objectstack/runtime 6.5.1 → 6.7.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/index.js CHANGED
@@ -2107,7 +2107,16 @@ var Runtime = class {
2107
2107
  init_load_artifact_bundle();
2108
2108
  import { resolve as resolvePath2 } from "path";
2109
2109
  import { mkdirSync } from "fs";
2110
+ import { homedir } from "os";
2110
2111
  import { z } from "zod";
2112
+ function resolveObjectStackHome() {
2113
+ const raw = process.env.OS_HOME?.trim();
2114
+ if (raw && raw.length > 0) {
2115
+ if (raw.startsWith("~")) return resolvePath2(homedir(), raw.slice(1).replace(/^[/\\]/, ""));
2116
+ return resolvePath2(raw);
2117
+ }
2118
+ return resolvePath2(homedir(), ".objectstack");
2119
+ }
2111
2120
  var StandaloneStackConfigSchema = z.object({
2112
2121
  databaseUrl: z.string().optional(),
2113
2122
  databaseAuthToken: z.string().optional(),
@@ -2138,7 +2147,7 @@ async function createStandaloneStack(config) {
2138
2147
  const environmentId = cfg.environmentId ?? process.env.OS_ENVIRONMENT_ID ?? "proj_local";
2139
2148
  const artifactPathInput = cfg.artifactPath ?? process.env.OS_ARTIFACT_PATH ?? resolvePath2(cwd, "dist/objectstack.json");
2140
2149
  const artifactPath = isHttpUrl(artifactPathInput) ? artifactPathInput : artifactPathInput.startsWith("/") ? artifactPathInput : resolvePath2(cwd, artifactPathInput);
2141
- const dbUrl = cfg.databaseUrl ?? process.env.OS_DATABASE_URL?.trim() ?? process.env.TURSO_DATABASE_URL?.trim() ?? `file:${resolvePath2(cwd, ".objectstack/data/standalone.db")}`;
2150
+ const dbUrl = cfg.databaseUrl ?? process.env.OS_DATABASE_URL?.trim() ?? process.env.TURSO_DATABASE_URL?.trim() ?? `file:${resolvePath2(resolveObjectStackHome(), "data/standalone.db")}`;
2142
2151
  const dbAuthToken = cfg.databaseAuthToken ?? process.env.OS_DATABASE_AUTH_TOKEN?.trim() ?? process.env.TURSO_AUTH_TOKEN?.trim();
2143
2152
  const explicitDriver = cfg.databaseDriver ?? process.env.OS_DATABASE_DRIVER?.trim();
2144
2153
  const dbDriver = explicitDriver ?? detectDriverFromUrl(dbUrl);
@@ -2147,7 +2156,14 @@ async function createStandaloneStack(config) {
2147
2156
  const { InMemoryDriver } = await import("@objectstack/driver-memory");
2148
2157
  driverPlugin = new DriverPlugin2(new InMemoryDriver());
2149
2158
  } else if (dbDriver === "turso") {
2150
- const { TursoDriver } = await import("@objectstack/driver-turso");
2159
+ let TursoDriver;
2160
+ try {
2161
+ ({ TursoDriver } = await import("@objectstack/driver-turso"));
2162
+ } catch (err) {
2163
+ throw new Error(
2164
+ `[StandaloneStack] libsql/turso URL detected ("${dbUrl}") but @objectstack/driver-turso is not installed. Install it with: npm install @objectstack/driver-turso (or use a file: URL to default to better-sqlite3). (${err?.message ?? err})`
2165
+ );
2166
+ }
2151
2167
  driverPlugin = new DriverPlugin2(
2152
2168
  new TursoDriver({ url: dbUrl, authToken: dbAuthToken })
2153
2169
  );
@@ -2248,7 +2264,7 @@ async function createStandaloneStack(config) {
2248
2264
 
2249
2265
  // src/default-host.ts
2250
2266
  import { resolve as resolvePath3 } from "path";
2251
- import { existsSync } from "fs";
2267
+ import { existsSync, mkdirSync as mkdirSync2, writeFileSync } from "fs";
2252
2268
  init_load_artifact_bundle();
2253
2269
  function resolveDefaultArtifactPath(explicitPath, cwd = process.cwd()) {
2254
2270
  const candidate = explicitPath ?? process.env.OS_ARTIFACT_PATH ?? resolvePath3(cwd, "dist/objectstack.json");
@@ -2258,12 +2274,42 @@ function resolveDefaultArtifactPath(explicitPath, cwd = process.cwd()) {
2258
2274
  }
2259
2275
  async function createDefaultHostConfig(options = {}) {
2260
2276
  const { requireArtifact = true, ...standaloneOpts } = options;
2261
- const resolvedArtifact = resolveDefaultArtifactPath(standaloneOpts.artifactPath);
2277
+ let resolvedArtifact = resolveDefaultArtifactPath(standaloneOpts.artifactPath);
2262
2278
  if (!resolvedArtifact && requireArtifact) {
2263
2279
  throw new Error(
2264
2280
  "[createDefaultHostConfig] No artifact source available. Set OS_ARTIFACT_PATH (file path or http(s):// URL), place the artifact at <cwd>/dist/objectstack.json, or pass `{ artifactPath: ... }` explicitly. To boot an empty kernel anyway, pass `{ requireArtifact: false }`."
2265
2281
  );
2266
2282
  }
2283
+ if (!resolvedArtifact && !requireArtifact) {
2284
+ const home = resolveObjectStackHome();
2285
+ const stubPath = resolvePath3(home, "dist/objectstack.json");
2286
+ if (!existsSync(stubPath)) {
2287
+ mkdirSync2(resolvePath3(stubPath, ".."), { recursive: true });
2288
+ writeFileSync(
2289
+ stubPath,
2290
+ JSON.stringify(
2291
+ {
2292
+ manifest: {
2293
+ id: "com.objectstack.empty",
2294
+ name: "empty",
2295
+ version: "0.0.0",
2296
+ type: "app",
2297
+ description: "Empty starter kernel \u2014 install apps via the Studio marketplace."
2298
+ },
2299
+ objects: [],
2300
+ views: [],
2301
+ apps: [],
2302
+ flows: [],
2303
+ requires: []
2304
+ },
2305
+ null,
2306
+ 2
2307
+ ),
2308
+ "utf8"
2309
+ );
2310
+ }
2311
+ resolvedArtifact = stubPath;
2312
+ }
2267
2313
  return createStandaloneStack({
2268
2314
  ...standaloneOpts,
2269
2315
  artifactPath: resolvedArtifact
@@ -6821,6 +6867,8 @@ var KernelManager = class {
6821
6867
  this.maxSize = config.maxSize ?? 32;
6822
6868
  this.ttlMs = config.ttlMs ?? 15 * 60 * 1e3;
6823
6869
  this.logger = config.logger ?? console;
6870
+ this.freshnessProbe = config.freshnessProbe;
6871
+ this.staleCheckIntervalMs = config.staleCheckIntervalMs ?? 1e4;
6824
6872
  }
6825
6873
  /** Returns the currently cached environmentIds (ordered by insertion). */
6826
6874
  keys() {
@@ -6843,8 +6891,31 @@ var KernelManager = class {
6843
6891
  if (this.ttlMs > 0 && Date.now() - existing.lastAccess > this.ttlMs) {
6844
6892
  await this.evict(environmentId);
6845
6893
  } else {
6846
- existing.lastAccess = Date.now();
6847
- return existing.kernel;
6894
+ if (this.freshnessProbe) {
6895
+ const now = Date.now();
6896
+ if (now - existing.lastStaleCheckAt >= this.staleCheckIntervalMs) {
6897
+ existing.lastStaleCheckAt = now;
6898
+ let stale = false;
6899
+ try {
6900
+ stale = await this.freshnessProbe(environmentId, existing.createdAt);
6901
+ } catch (err) {
6902
+ this.logger.warn?.("[KernelManager] freshness probe failed", { environmentId, err });
6903
+ }
6904
+ if (stale) {
6905
+ this.logger.info?.("[KernelManager] kernel evicted by freshness probe", { environmentId });
6906
+ await this.evict(environmentId);
6907
+ } else {
6908
+ existing.lastAccess = Date.now();
6909
+ return existing.kernel;
6910
+ }
6911
+ } else {
6912
+ existing.lastAccess = Date.now();
6913
+ return existing.kernel;
6914
+ }
6915
+ } else {
6916
+ existing.lastAccess = Date.now();
6917
+ return existing.kernel;
6918
+ }
6848
6919
  }
6849
6920
  }
6850
6921
  const inflight = this.pending.get(environmentId);
@@ -6852,7 +6923,7 @@ var KernelManager = class {
6852
6923
  const promise = (async () => {
6853
6924
  const kernel = await this.factory.create(environmentId);
6854
6925
  const now = Date.now();
6855
- this.cache.set(environmentId, { kernel, createdAt: now, lastAccess: now });
6926
+ this.cache.set(environmentId, { kernel, createdAt: now, lastAccess: now, lastStaleCheckAt: now });
6856
6927
  await this.enforceMaxSize();
6857
6928
  return kernel;
6858
6929
  })();
@@ -7020,6 +7091,30 @@ var ArtifactApiClient = class {
7020
7091
  if (!found?.headCommitId) return null;
7021
7092
  return { commitId: String(found.headCommitId), publishedAt: found.headPublishedAt ?? null };
7022
7093
  }
7094
+ /**
7095
+ * Cheap freshness probe — returns the env's `last_published_at`
7096
+ * (and best-effort current commit) without rebuilding the artifact.
7097
+ * Used by `KernelManager` on cache hits to detect when a per-env
7098
+ * kernel has been invalidated by an upstream change (marketplace
7099
+ * install/uninstall, artifact publish) so it can be rebuilt
7100
+ * without waiting for the 15-minute LRU TTL to expire.
7101
+ *
7102
+ * Returns `null` on definitive 404 / unknown env. Errors propagate
7103
+ * (caller decides whether to treat unreachable cloud as fresh or
7104
+ * stale — typically fresh, so a brief outage doesn't churn every
7105
+ * cached kernel).
7106
+ */
7107
+ async getFreshness(environmentId) {
7108
+ const url = `${this.base}/api/v1/cloud/environments/${encodeURIComponent(environmentId)}/freshness`;
7109
+ const res = await this.request(url);
7110
+ if (res === null) return null;
7111
+ const body = res.success === false ? null : res.data ?? res;
7112
+ if (!body || typeof body !== "object") return null;
7113
+ const envId = typeof body.environmentId === "string" ? body.environmentId : environmentId;
7114
+ const lastPublishedAt = typeof body.lastPublishedAt === "string" ? body.lastPublishedAt : null;
7115
+ const commitId = typeof body.commitId === "string" ? body.commitId : null;
7116
+ return { environmentId: envId, lastPublishedAt, commitId };
7117
+ }
7023
7118
  /** Drop cached entries for a project (and any matching hostname). */
7024
7119
  invalidate(environmentId) {
7025
7120
  this.artifactCache.delete(environmentId);
@@ -7233,7 +7328,14 @@ async function createDriver(driverType, databaseUrl, authToken) {
7233
7328
  }
7234
7329
  case "libsql":
7235
7330
  case "turso": {
7236
- const { TursoDriver } = await import("@objectstack/driver-turso");
7331
+ let TursoDriver;
7332
+ try {
7333
+ ({ TursoDriver } = await import("@objectstack/driver-turso"));
7334
+ } catch (err) {
7335
+ throw new Error(
7336
+ `[ArtifactEnvironmentRegistry] libsql/turso driver requested but @objectstack/driver-turso is not installed. Install it with: npm install @objectstack/driver-turso. (${err?.message ?? err})`
7337
+ );
7338
+ }
7237
7339
  return new TursoDriver({ url: databaseUrl, authToken });
7238
7340
  }
7239
7341
  case "postgres":
@@ -7771,7 +7873,30 @@ var ArtifactKernelFactory = class {
7771
7873
  };
7772
7874
 
7773
7875
  // src/cloud/auth-proxy-plugin.ts
7876
+ import { createHmac as createHmac3, randomUUID as randomUUID2 } from "crypto";
7774
7877
  var AUTH_PREFIX = "/api/v1/auth";
7878
+ function signSessionCookieValue(rawToken, secret) {
7879
+ const signature = createHmac3("sha256", secret).update(rawToken).digest("base64");
7880
+ return encodeURIComponent(`${rawToken}.${signature}`);
7881
+ }
7882
+ function buildSetCookieHeader(name, encodedValue, attrs, maxAgeSec) {
7883
+ const parts = [`${name}=${encodedValue}`];
7884
+ const a = attrs ?? {};
7885
+ if (a.path) parts.push(`Path=${a.path}`);
7886
+ else parts.push("Path=/");
7887
+ if (Number.isFinite(maxAgeSec) && maxAgeSec > 0) parts.push(`Max-Age=${Math.floor(maxAgeSec)}`);
7888
+ if (a.domain) parts.push(`Domain=${a.domain}`);
7889
+ if (a.sameSite) {
7890
+ const ss = String(a.sameSite);
7891
+ parts.push(`SameSite=${ss.charAt(0).toUpperCase() + ss.slice(1)}`);
7892
+ } else {
7893
+ parts.push("SameSite=Lax");
7894
+ }
7895
+ if (a.secure) parts.push("Secure");
7896
+ if (a.httpOnly !== false) parts.push("HttpOnly");
7897
+ if (a.partitioned) parts.push("Partitioned");
7898
+ return parts.join("; ");
7899
+ }
7775
7900
  function pickHandler(svc) {
7776
7901
  if (!svc) return void 0;
7777
7902
  if (typeof svc.handleRequest === "function") return svc.handleRequest.bind(svc);
@@ -7865,6 +7990,115 @@ var AuthProxyPlugin = class {
7865
7990
  return c.json({ hasOwner: true });
7866
7991
  }
7867
7992
  }
7993
+ if (c.req.method === "POST" && subPath === "sso-handoff-issue") {
7994
+ try {
7995
+ const expected = (process.env.OS_CLOUD_API_KEY ?? "").trim();
7996
+ if (!expected) {
7997
+ return c.json({ error: "sso_handoff_disabled", reason: "OS_CLOUD_API_KEY unset on env runtime" }, 503);
7998
+ }
7999
+ const authz = c.req.header("authorization") ?? "";
8000
+ const provided = authz.toLowerCase().startsWith("bearer ") ? authz.slice(7).trim() : "";
8001
+ if (!provided || provided !== expected) {
8002
+ return c.json({ error: "unauthorized" }, 401);
8003
+ }
8004
+ if (typeof authSvc?.getAuthContext !== "function") {
8005
+ return c.json({ error: "auth_service_unavailable" }, 503);
8006
+ }
8007
+ const handoffAuthCtx = await authSvc.getAuthContext();
8008
+ const internal = handoffAuthCtx?.internalAdapter;
8009
+ if (!internal?.createVerificationValue) {
8010
+ return c.json({ error: "verification_api_unavailable" }, 503);
8011
+ }
8012
+ let body = {};
8013
+ try {
8014
+ body = await c.req.json();
8015
+ } catch {
8016
+ body = {};
8017
+ }
8018
+ const email = String(body?.email ?? "").toLowerCase().trim();
8019
+ if (!email) return c.json({ error: "email_required" }, 400);
8020
+ const name = body?.name == null ? null : String(body.name);
8021
+ const by = body?.by == null ? "service" : String(body.by);
8022
+ const envIdInBody = body?.envId == null ? null : String(body.envId);
8023
+ const handoff = randomUUID2().replace(/-/g, "") + randomUUID2().replace(/-/g, "");
8024
+ const ttlSec = 60;
8025
+ const expiresAt = new Date(Date.now() + ttlSec * 1e3);
8026
+ await internal.createVerificationValue({
8027
+ identifier: `sso-handoff:${handoff}`,
8028
+ value: JSON.stringify({ email, name, by, envId: envIdInBody ?? environmentId }),
8029
+ expiresAt
8030
+ });
8031
+ return c.json({
8032
+ token: handoff,
8033
+ expiresAt: expiresAt.toISOString(),
8034
+ ttlSec
8035
+ });
8036
+ } catch (err) {
8037
+ ctx.logger?.error?.("[AuthProxyPlugin] sso-handoff-issue failed", err instanceof Error ? err : new Error(String(err)));
8038
+ return c.json({ error: "sso_handoff_issue_failed", message: String(err?.message ?? err) }, 500);
8039
+ }
8040
+ }
8041
+ if (c.req.method === "GET" && subPath === "sso-exchange") {
8042
+ try {
8043
+ const token = (url.searchParams.get("token") ?? "").trim();
8044
+ const nextRaw = url.searchParams.get("next") ?? "/";
8045
+ const next = nextRaw.startsWith("/") ? nextRaw : "/";
8046
+ if (!token) return c.text("missing token", 400);
8047
+ if (typeof authSvc?.getAuthContext !== "function") {
8048
+ return c.text("auth service unavailable", 503);
8049
+ }
8050
+ const authCtx = await authSvc.getAuthContext();
8051
+ const internal = authCtx?.internalAdapter;
8052
+ if (!internal?.consumeVerificationValue) {
8053
+ return c.text("verification API unavailable", 503);
8054
+ }
8055
+ const consumed = await internal.consumeVerificationValue(`sso-handoff:${token}`);
8056
+ if (!consumed) return c.text("invalid or expired token", 401);
8057
+ const expiresAt = consumed?.expiresAt ? new Date(consumed.expiresAt).getTime() : 0;
8058
+ if (!expiresAt || expiresAt < Date.now()) return c.text("expired token", 401);
8059
+ let payload = {};
8060
+ try {
8061
+ payload = JSON.parse(String(consumed.value));
8062
+ } catch {
8063
+ payload = { email: String(consumed.value) };
8064
+ }
8065
+ const email = String(payload.email ?? "").toLowerCase().trim();
8066
+ if (!email) return c.text("handoff missing email", 400);
8067
+ const found = await internal.findUserByEmail(email, { includeAccounts: true });
8068
+ let userId = found?.user?.id;
8069
+ let hasCredentialAccount = (found?.accounts ?? []).some((a) => a.providerId === "credential" && a.password);
8070
+ if (!userId) {
8071
+ const created = await internal.createUser({
8072
+ email,
8073
+ name: payload.name ?? email,
8074
+ emailVerified: true
8075
+ });
8076
+ userId = created?.id;
8077
+ hasCredentialAccount = false;
8078
+ }
8079
+ if (!userId) return c.text("failed to provision user", 500);
8080
+ const session = await internal.createSession(userId, false);
8081
+ const rawToken = session?.token;
8082
+ const sessionExpiresAt = session?.expiresAt ? new Date(session.expiresAt) : new Date(Date.now() + 7 * 24 * 3600 * 1e3);
8083
+ if (!rawToken) return c.text("failed to mint session", 500);
8084
+ const secret = authCtx?.secret ?? "";
8085
+ if (!secret) return c.text("auth secret unavailable", 503);
8086
+ const cookieName = authCtx?.authCookies?.sessionToken?.name ?? "better-auth.session_token";
8087
+ const cookieAttrs = authCtx?.authCookies?.sessionToken?.attributes ?? {};
8088
+ const encoded = signSessionCookieValue(rawToken, secret);
8089
+ const maxAgeSec = Math.max(60, Math.floor((sessionExpiresAt.getTime() - Date.now()) / 1e3));
8090
+ const setCookie = buildSetCookieHeader(cookieName, encoded, cookieAttrs, maxAgeSec);
8091
+ const finalNext = hasCredentialAccount ? next : `/_console/system/profile?recovery_needed=true&next=${encodeURIComponent(next)}`;
8092
+ const headers = new Headers();
8093
+ headers.set("Set-Cookie", setCookie);
8094
+ headers.set("Location", finalNext);
8095
+ headers.set("Cache-Control", "no-store");
8096
+ return new Response(null, { status: 302, headers });
8097
+ } catch (err) {
8098
+ ctx.logger?.error?.("[AuthProxyPlugin] sso-exchange failed", err instanceof Error ? err : new Error(String(err)));
8099
+ return c.text(`sso-exchange failed: ${err?.message ?? String(err)}`, 500);
8100
+ }
8101
+ }
7868
8102
  const fn = await resolveAuthHandler(authSvc);
7869
8103
  if (!fn) {
7870
8104
  return c.json({ error: "auth_service_unavailable", environmentId }, 503);
@@ -8047,20 +8281,46 @@ var RuntimeConfigPlugin = class {
8047
8281
  return;
8048
8282
  }
8049
8283
  const rawApp = httpServer.getRawApp();
8050
- const payload = {
8051
- cloudUrl: this.cloudUrl,
8052
- singleEnvironment: this.singleEnvironment,
8053
- features: {
8054
- installLocal: this.installLocal,
8055
- marketplace: true
8284
+ const features = {
8285
+ installLocal: this.installLocal,
8286
+ marketplace: true
8287
+ };
8288
+ let envRegistry = null;
8289
+ try {
8290
+ envRegistry = ctx.getService("env-registry");
8291
+ } catch {
8292
+ }
8293
+ const handler = async (c) => {
8294
+ const rawHost = c.req.header("host") ?? "";
8295
+ const host = rawHost.split(":")[0].toLowerCase().trim();
8296
+ let defaultEnvironmentId;
8297
+ let defaultOrgId;
8298
+ let resolvedSingleEnv = this.singleEnvironment;
8299
+ if (envRegistry && host && typeof envRegistry.resolveHostname === "function") {
8300
+ try {
8301
+ const resolved = await envRegistry.resolveHostname(host);
8302
+ if (resolved?.environmentId) {
8303
+ defaultEnvironmentId = resolved.environmentId;
8304
+ if (resolved.organizationId) defaultOrgId = String(resolved.organizationId);
8305
+ resolvedSingleEnv = true;
8306
+ }
8307
+ } catch {
8308
+ }
8056
8309
  }
8310
+ return c.json({
8311
+ cloudUrl: this.cloudUrl,
8312
+ singleEnvironment: resolvedSingleEnv,
8313
+ defaultOrgId,
8314
+ defaultEnvironmentId,
8315
+ features
8316
+ });
8057
8317
  };
8058
- const handler = (c) => c.json(payload);
8059
8318
  rawApp.get("/api/v1/runtime/config", handler);
8060
8319
  rawApp.get("/api/v1/studio/runtime-config", handler);
8061
8320
  ctx.logger?.info?.("[RuntimeConfigPlugin] mounted /api/v1/runtime/config", {
8062
8321
  cloudUrl: this.cloudUrl || "(empty)",
8063
- installLocal: this.installLocal
8322
+ installLocal: this.installLocal,
8323
+ perHostEnvResolution: !!envRegistry
8064
8324
  });
8065
8325
  });
8066
8326
  };
@@ -8261,7 +8521,21 @@ var ObjectOSEnvironmentPlugin = class {
8261
8521
  factory,
8262
8522
  maxSize: this.config.kernelCacheSize,
8263
8523
  ttlMs: this.config.kernelTtlMs,
8264
- logger: ctx.logger
8524
+ logger: ctx.logger,
8525
+ // Only the HTTP client exposes /freshness; file-mode (CLI dev)
8526
+ // has no upstream to probe.
8527
+ freshnessProbe: this.config.controlPlaneUrl === "file" ? void 0 : async (envId, builtAtMs) => {
8528
+ const fresh = await client.getFreshness(envId);
8529
+ if (!fresh) return false;
8530
+ const t = fresh.lastPublishedAt ? Date.parse(fresh.lastPublishedAt) : NaN;
8531
+ if (!Number.isFinite(t)) return false;
8532
+ if (t <= builtAtMs) return false;
8533
+ try {
8534
+ client.invalidate(envId);
8535
+ } catch {
8536
+ }
8537
+ return true;
8538
+ }
8265
8539
  });
8266
8540
  this.kernelManager = kernelManager;
8267
8541
  ctx.registerService("env-registry", envRegistry);
@@ -8313,7 +8587,7 @@ async function createObjectOSStack(config) {
8313
8587
  }
8314
8588
 
8315
8589
  // src/cloud/marketplace-install-local-plugin.ts
8316
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, readdirSync, unlinkSync, writeFileSync } from "fs";
8590
+ import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
8317
8591
  import { join, resolve } from "path";
8318
8592
  var ROUTE_BASE = "/api/v1/marketplace/install-local";
8319
8593
  var DEFAULT_DIR = ".objectstack/installed-packages";
@@ -8446,8 +8720,8 @@ var MarketplaceInstallLocalPlugin = class {
8446
8720
  installedBy: userId
8447
8721
  };
8448
8722
  try {
8449
- mkdirSync2(this.storageDir, { recursive: true });
8450
- writeFileSync(join(this.storageDir, safeFilename(manifestId)), JSON.stringify(entry, null, 2), "utf8");
8723
+ mkdirSync3(this.storageDir, { recursive: true });
8724
+ writeFileSync2(join(this.storageDir, safeFilename(manifestId)), JSON.stringify(entry, null, 2), "utf8");
8451
8725
  } catch (err) {
8452
8726
  return c.json({
8453
8727
  success: false,
@@ -8866,6 +9140,7 @@ export {
8866
9140
  resolveDefaultArtifactPath,
8867
9141
  resolveErrorReporter,
8868
9142
  resolveMetrics,
9143
+ resolveObjectStackHome,
8869
9144
  resolveRequestId,
8870
9145
  seedPlatformSsoClient
8871
9146
  };