@instafy/cli 0.1.10 → 0.1.11

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/runtime.js +139 -39
  2. package/package.json +1 -1
package/dist/runtime.js CHANGED
@@ -270,6 +270,7 @@ export async function mintRuntimeAccessToken(params) {
270
270
  },
271
271
  body: JSON.stringify({
272
272
  runtimeId: params.runtimeId,
273
+ leaseId: params.leaseId,
273
274
  scopes: params.scopes,
274
275
  }),
275
276
  },
@@ -295,6 +296,55 @@ export async function mintRuntimeAccessToken(params) {
295
296
  }
296
297
  return token;
297
298
  }
299
+ async function requestRuntimeLease(params) {
300
+ const url = params.controllerUrl.replace(/\/$/, "");
301
+ const target = `${url}/projects/${encodeURIComponent(params.projectId)}/runtime/request`;
302
+ const { response, accessToken } = await fetchWithControllerAuth({
303
+ url: target,
304
+ init: {
305
+ method: "POST",
306
+ headers: {
307
+ "content-type": "application/json",
308
+ },
309
+ body: JSON.stringify({
310
+ provider: params.provider,
311
+ displayName: params.displayName,
312
+ idleTtlSeconds: params.idleTtlSeconds,
313
+ requestTunnel: params.requestTunnel,
314
+ runtimeId: params.runtimeId,
315
+ }),
316
+ },
317
+ accessToken: params.accessToken,
318
+ tokenSource: params.tokenSource,
319
+ profile: params.profile,
320
+ cwd: params.cwd,
321
+ });
322
+ if (!response.ok) {
323
+ const text = await response.text().catch(() => "");
324
+ if (response.status === 401 || response.status === 403) {
325
+ throw formatAuthRejectedError({
326
+ status: response.status,
327
+ responseBody: text,
328
+ });
329
+ }
330
+ throw new Error(`Instafy server rejected runtime request (${response.status} ${response.statusText}): ${text}`);
331
+ }
332
+ const payload = (await response.json());
333
+ const runtime = (payload["runtime"] ?? payload);
334
+ const runtimeId = (typeof runtime?.["runtimeId"] === "string" ? runtime["runtimeId"] : null) ??
335
+ (typeof runtime?.["runtime_id"] === "string" ? runtime["runtime_id"] : null) ??
336
+ null;
337
+ const leaseId = (typeof runtime?.["leaseId"] === "string" ? runtime["leaseId"] : null) ??
338
+ (typeof runtime?.["lease_id"] === "string" ? runtime["lease_id"] : null) ??
339
+ null;
340
+ if (!runtimeId || !runtimeId.trim()) {
341
+ throw new Error("Instafy server response missing runtimeId while requesting runtime lease.");
342
+ }
343
+ if (!leaseId || !leaseId.trim()) {
344
+ throw new Error("Instafy server response missing leaseId while requesting runtime lease.");
345
+ }
346
+ return { runtimeId: runtimeId.trim(), leaseId: leaseId.trim(), accessToken };
347
+ }
298
348
  function isProcessAlive(pid) {
299
349
  try {
300
350
  process.kill(pid, 0);
@@ -350,19 +400,6 @@ export async function runtimeStart(options) {
350
400
  env["CONTROLLER_BASE_URL"] ??
351
401
  manifestInfo.manifest?.controllerUrl ??
352
402
  "http://127.0.0.1:8788";
353
- if (!runtimeAccessToken && controllerAccessToken) {
354
- runtimeAccessToken = await mintRuntimeAccessToken({
355
- controllerUrl: env["CONTROLLER_BASE_URL"],
356
- controllerAccessToken,
357
- projectId,
358
- tokenSource: controllerAccessTokenSource,
359
- profile,
360
- cwd,
361
- });
362
- }
363
- if (runtimeAccessToken) {
364
- env["RUNTIME_ACCESS_TOKEN"] = runtimeAccessToken;
365
- }
366
403
  if (options.codexBin)
367
404
  env["CODEX_BIN"] = options.codexBin;
368
405
  if (options.proxyBaseUrl)
@@ -381,25 +418,6 @@ export async function runtimeStart(options) {
381
418
  if (options.originEndpoint && options.originEndpoint.trim()) {
382
419
  env["ORIGIN_ENDPOINT"] = options.originEndpoint.trim();
383
420
  }
384
- let originToken = normalizeToken(options.originToken) ?? normalizeToken(env["ORIGIN_INTERNAL_TOKEN"]);
385
- if (!originToken && runtimeAccessToken) {
386
- originToken = runtimeAccessToken;
387
- }
388
- if (!originToken && controllerAccessToken) {
389
- originToken = await mintRuntimeAccessToken({
390
- controllerUrl: env["CONTROLLER_BASE_URL"],
391
- controllerAccessToken,
392
- projectId,
393
- runtimeId: env["RUNTIME_ID"],
394
- tokenSource: controllerAccessTokenSource,
395
- profile,
396
- cwd,
397
- });
398
- }
399
- if (!originToken) {
400
- throw new Error("Runtime/origin token is required (--origin-token or ORIGIN_INTERNAL_TOKEN), or provide --runtime-token/--controller-access-token to mint/use one");
401
- }
402
- env["ORIGIN_INTERNAL_TOKEN"] = originToken;
403
421
  const skipAuthRaw = env["ORIGIN_SKIP_AUTH"]?.trim().toLowerCase();
404
422
  const skipAuth = skipAuthRaw === "1" || skipAuthRaw === "true" || skipAuthRaw === "yes";
405
423
  const usesTunnel = !env["ORIGIN_ENDPOINT"];
@@ -410,12 +428,10 @@ export async function runtimeStart(options) {
410
428
  }
411
429
  env["RUNTIME_DISPLAY_NAME"] =
412
430
  options.displayName ?? env["RUNTIME_DISPLAY_NAME"] ?? "Instafy CLI Runtime";
413
- const manifestProvider = manifestInfo.manifest?.orgName?.trim() ||
414
- manifestInfo.manifest?.orgId?.toString().trim();
415
431
  env["RUNTIME_PROVIDER"] =
416
- options.provider ?? env["RUNTIME_PROVIDER"] ?? manifestProvider ?? "self-hosted";
432
+ options.provider ?? env["RUNTIME_PROVIDER"] ?? "self-hosted";
417
433
  env["RUNTIME_VERSION"] = env["RUNTIME_VERSION"] ?? "0.1.0";
418
- env["RUNTIME_REQUIRE_CODEX_BIN"] = env["RUNTIME_REQUIRE_CODEX_BIN"] || "1";
434
+ env["RUNTIME_REQUIRE_CODEX_BIN"] = env["RUNTIME_REQUIRE_CODEX_BIN"] || "0";
419
435
  env["RUNTIME_CAPABILITIES"] =
420
436
  env["RUNTIME_CAPABILITIES"] ||
421
437
  JSON.stringify({ fs: true, github: true, supabase: true, runs: true, agent: true, origin: true });
@@ -429,6 +445,90 @@ export async function runtimeStart(options) {
429
445
  const runtimeBin = runtimeMode === "docker" ? null : tryResolveRuntimeBinary();
430
446
  const useDocker = runtimeMode === "docker" ||
431
447
  (runtimeMode === "auto" && !runtimeBin);
448
+ if (useDocker && !isDockerAvailable()) {
449
+ throw new Error("runtime-agent is not available (no local binary and docker is not installed). Install Docker Desktop, or build runtime-agent from source.");
450
+ }
451
+ const originEnabledRaw = env["ORIGIN_ENABLED"]?.trim().toLowerCase();
452
+ const originEnabled = !originEnabledRaw ||
453
+ originEnabledRaw === "1" ||
454
+ originEnabledRaw === "true" ||
455
+ originEnabledRaw === "yes" ||
456
+ originEnabledRaw === "on";
457
+ if (originEnabled && usesTunnel && !useDocker) {
458
+ const ratholeResolved = await resolveRatholeBinaryForCli({
459
+ env,
460
+ version: process.env["RATHOLE_VERSION"] ?? null,
461
+ cacheDir: process.env["RATHOLE_CACHE_DIR"] ?? null,
462
+ logger: (message) => console.log(kleur.cyan(`[rathole] ${message}`)),
463
+ warn: (message) => console.warn(kleur.yellow(message)),
464
+ });
465
+ if (!ratholeResolved) {
466
+ throw new Error("Tunnel is required but rathole is unavailable. Set RATHOLE_BIN (recommended) or pass --origin-endpoint to use a reachable URL.");
467
+ }
468
+ }
469
+ if (originEnabled && usesTunnel && !env["RUNTIME_LEASE_ID"]) {
470
+ const bearer = controllerAccessToken ?? runtimeAccessToken;
471
+ const tokenSource = controllerAccessToken ? controllerAccessTokenSource : "env";
472
+ if (!bearer) {
473
+ throw new Error("Login required to request a tunnel-enabled runtime lease. Run `instafy login` or pass --controller-access-token/--runtime-token.");
474
+ }
475
+ const ttl = typeof env["RUNTIME_LEASE_SECONDS"] === "string" ? Number(env["RUNTIME_LEASE_SECONDS"]) : NaN;
476
+ const idleTtlSeconds = Number.isFinite(ttl) && ttl > 0 ? ttl : undefined;
477
+ const lease = await requestRuntimeLease({
478
+ controllerUrl: env["CONTROLLER_BASE_URL"],
479
+ accessToken: bearer,
480
+ tokenSource,
481
+ profile,
482
+ cwd,
483
+ projectId,
484
+ provider: env["RUNTIME_PROVIDER"],
485
+ displayName: env["RUNTIME_DISPLAY_NAME"],
486
+ idleTtlSeconds,
487
+ requestTunnel: false,
488
+ runtimeId: env["RUNTIME_ID"],
489
+ });
490
+ env["RUNTIME_ID"] = lease.runtimeId;
491
+ env["RUNTIME_LEASE_ID"] = lease.leaseId;
492
+ if (controllerAccessToken && bearer === controllerAccessToken) {
493
+ controllerAccessToken = lease.accessToken;
494
+ env["CONTROLLER_ACCESS_TOKEN"] = controllerAccessToken;
495
+ }
496
+ }
497
+ if (!runtimeAccessToken && controllerAccessToken) {
498
+ runtimeAccessToken = await mintRuntimeAccessToken({
499
+ controllerUrl: env["CONTROLLER_BASE_URL"],
500
+ controllerAccessToken,
501
+ projectId,
502
+ runtimeId: env["RUNTIME_ID"],
503
+ leaseId: env["RUNTIME_LEASE_ID"],
504
+ tokenSource: controllerAccessTokenSource,
505
+ profile,
506
+ cwd,
507
+ });
508
+ }
509
+ if (runtimeAccessToken) {
510
+ env["RUNTIME_ACCESS_TOKEN"] = runtimeAccessToken;
511
+ }
512
+ let originToken = normalizeToken(options.originToken) ?? normalizeToken(env["ORIGIN_INTERNAL_TOKEN"]);
513
+ if (!originToken && runtimeAccessToken) {
514
+ originToken = runtimeAccessToken;
515
+ }
516
+ if (!originToken && controllerAccessToken) {
517
+ originToken = await mintRuntimeAccessToken({
518
+ controllerUrl: env["CONTROLLER_BASE_URL"],
519
+ controllerAccessToken,
520
+ projectId,
521
+ runtimeId: env["RUNTIME_ID"],
522
+ leaseId: env["RUNTIME_LEASE_ID"],
523
+ tokenSource: controllerAccessTokenSource,
524
+ profile,
525
+ cwd,
526
+ });
527
+ }
528
+ if (!originToken) {
529
+ throw new Error("Runtime/origin token is required (--origin-token or ORIGIN_INTERNAL_TOKEN), or provide --runtime-token/--controller-access-token to mint/use one");
530
+ }
531
+ env["ORIGIN_INTERNAL_TOKEN"] = originToken;
432
532
  if (!useDocker) {
433
533
  if (!env["ORIGIN_ENDPOINT"]) {
434
534
  const ratholeResolved = await resolveRatholeBinaryForCli({
@@ -493,9 +593,6 @@ export async function runtimeStart(options) {
493
593
  });
494
594
  return;
495
595
  }
496
- if (!isDockerAvailable()) {
497
- throw new Error("runtime-agent is not available (no local binary and docker is not installed). Install Docker Desktop, or build runtime-agent from source.");
498
- }
499
596
  const image = resolveRuntimeAgentImage();
500
597
  const containerName = `instafy-runtime-${originId}`;
501
598
  const hostPort = String(options.bindPort ?? env["ORIGIN_BIND_PORT"] ?? 54332);
@@ -503,6 +600,9 @@ export async function runtimeStart(options) {
503
600
  const dockerEnv = { ...env };
504
601
  dockerEnv["WORKSPACE_DIR"] = "/workspace";
505
602
  dockerEnv["CODEX_HOME"] = "/workspace/.codex";
603
+ dockerEnv["TMPDIR"] = "/tmp";
604
+ dockerEnv["TMP"] = "/tmp";
605
+ dockerEnv["TEMP"] = "/tmp";
506
606
  dockerEnv["ORIGIN_BIND_HOST"] = "0.0.0.0";
507
607
  dockerEnv["CONTROLLER_BASE_URL"] = normalizeControllerUrlForDocker(env["CONTROLLER_BASE_URL"] ?? "");
508
608
  const envArgs = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instafy/cli",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Run Instafy projects locally, link folders to Studio, and share previews/webhooks via tunnels.",
5
5
  "private": false,
6
6
  "publishConfig": {