@oodarun/cli 0.1.2 → 0.1.4

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/cli.js +81 -17
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -763,6 +763,54 @@ function getAccessToken() {
763
763
  if (process.env.OODA_ACCESS_TOKEN) return process.env.OODA_ACCESS_TOKEN;
764
764
  return readAuthData().accessToken || null;
765
765
  }
766
+ function decodeJwtExp(token) {
767
+ try {
768
+ const payload = JSON.parse(
769
+ Buffer.from(token.split(".")[1], "base64url").toString()
770
+ );
771
+ return typeof payload.exp === "number" ? payload.exp : null;
772
+ } catch {
773
+ return null;
774
+ }
775
+ }
776
+ var _refreshInFlight = null;
777
+ async function ensureFreshAccessToken() {
778
+ if (process.env.OODA_ACCESS_TOKEN) return process.env.OODA_ACCESS_TOKEN;
779
+ const data = readAuthData();
780
+ if (!data.accessToken || !data.refreshToken) return data.accessToken || null;
781
+ const exp = decodeJwtExp(data.accessToken);
782
+ const now = Math.floor(Date.now() / 1e3);
783
+ if (exp && exp - now > 300) return data.accessToken;
784
+ if (_refreshInFlight) return _refreshInFlight;
785
+ _refreshInFlight = refreshAccessToken(data.refreshToken, data.orgId || "").finally(
786
+ () => {
787
+ _refreshInFlight = null;
788
+ }
789
+ );
790
+ return _refreshInFlight;
791
+ }
792
+ async function refreshAccessToken(refreshToken, orgId) {
793
+ try {
794
+ const doFetch = globalThis.__originalFetch ?? globalThis.fetch;
795
+ const res = await doFetch(
796
+ `${ORG_API_BASE}/auth/refresh`,
797
+ {
798
+ method: "POST",
799
+ headers: { "Content-Type": "application/json" },
800
+ body: JSON.stringify({ refreshToken })
801
+ }
802
+ );
803
+ if (!res.ok) return null;
804
+ const body = await res.json();
805
+ const data = readAuthData();
806
+ data.accessToken = body.accessToken;
807
+ data.refreshToken = body.refreshToken;
808
+ writeAuthData(data);
809
+ return body.accessToken;
810
+ } catch {
811
+ return null;
812
+ }
813
+ }
766
814
  function saveJwtTokens(accessToken, refreshToken, userId, orgId) {
767
815
  const data = readAuthData();
768
816
  data.accessToken = accessToken;
@@ -1081,13 +1129,14 @@ function patchFetchForOrg(orgId) {
1081
1129
  if (_orgPatchApplied) return;
1082
1130
  _orgPatchApplied = true;
1083
1131
  const originalFetch = globalThis.fetch;
1132
+ globalThis.__originalFetch = originalFetch;
1084
1133
  globalThis.fetch = (async (input, init) => {
1085
1134
  const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
1086
1135
  const method = init?.method ?? (input instanceof Request ? input.method : void 0);
1087
1136
  const rewritten = rewriteOrgUrl(url, orgId, method);
1088
1137
  if (rewritten) {
1089
1138
  const headers = new Headers(init?.headers || {});
1090
- const jwt = getAccessToken();
1139
+ const jwt = await ensureFreshAccessToken() ?? getAccessToken();
1091
1140
  if (jwt) {
1092
1141
  headers.set("Authorization", `Bearer ${jwt}`);
1093
1142
  }
@@ -1742,27 +1791,29 @@ async function deployToolsViaRest(projectName, token, projectRoot, onProgress) {
1742
1791
  log("Deploying browser overlay tools...");
1743
1792
  const toolsDistDir = getToolsDistDir();
1744
1793
  const toolFiles = ["element-selector.js", "change-applicator.js", "bridge-client.js", "toolbar.js"];
1794
+ const uploads = [];
1745
1795
  for (const file of toolFiles) {
1746
1796
  const localPath = path4.join(toolsDistDir, file);
1747
1797
  try {
1748
1798
  const content = fs4.readFileSync(localPath, "utf-8");
1749
- await writeFile(`/home/user/.ooda/tools/${file}`, content);
1799
+ uploads.push(writeFile(`/home/user/.ooda/tools/${file}`, content));
1750
1800
  } catch {
1751
1801
  log(`Warning: ${file} not found in dist/tools \u2014 skipping`);
1752
1802
  }
1753
1803
  }
1754
- await writeFile(`${projectRoot}/ooda-vite-plugin.mjs`, OODA_VITE_PLUGIN);
1755
- try {
1756
- await exec(`cd "${projectRoot}" && node -e "require('ws')" 2>/dev/null || npm install --save-dev ws 2>/dev/null`);
1757
- } catch {
1758
- }
1759
- await writeFile("/tmp/ooda-patch-config.mjs", OODA_CONFIG_PATCH_SCRIPT);
1760
- try {
1761
- const result = await exec(`node /tmp/ooda-patch-config.mjs "${projectRoot}" 2>&1`);
1762
- log(`Config patch: ${result.trim()}`);
1763
- } catch (err) {
1764
- log(`Config patch failed: ${err instanceof Error ? err.message : String(err)}`);
1765
- }
1804
+ uploads.push(writeFile(`${projectRoot}/ooda-vite-plugin.mjs`, OODA_VITE_PLUGIN));
1805
+ uploads.push(writeFile("/tmp/ooda-patch-config.mjs", OODA_CONFIG_PATCH_SCRIPT));
1806
+ await Promise.all(uploads);
1807
+ const [, patchResult] = await Promise.all([
1808
+ exec(`cd "${projectRoot}" && node -e "require('ws')" 2>/dev/null || npm install --save-dev ws 2>/dev/null`).catch(() => {
1809
+ }),
1810
+ exec(`node /tmp/ooda-patch-config.mjs "${projectRoot}" 2>&1`).catch((err) => {
1811
+ const msg = err instanceof Error ? err.message : String(err);
1812
+ log(`Config patch failed: ${msg}`);
1813
+ return "";
1814
+ })
1815
+ ]);
1816
+ if (patchResult) log(`Config patch: ${String(patchResult).trim()}`);
1766
1817
  }
1767
1818
 
1768
1819
  // src/tools/installer.ts
@@ -2225,8 +2276,21 @@ async function createOrReuseProject(projectName, token, onProgress) {
2225
2276
  });
2226
2277
  if (res.ok) {
2227
2278
  const data = await res.json();
2228
- onProgress({ step: "Waiting for sandbox to start...", detail: "~10s" });
2229
- await new Promise((r) => setTimeout(r, 1e4));
2279
+ onProgress({ step: "Waiting for sandbox to start..." });
2280
+ for (let i = 0; i < 15; i++) {
2281
+ try {
2282
+ const params = new URLSearchParams();
2283
+ params.append("cmd", "echo");
2284
+ params.append("cmd", "ready");
2285
+ const check = await fetch(`${API_BASE}/projects/${projectName}/exec?${params}`, {
2286
+ method: "POST",
2287
+ headers
2288
+ });
2289
+ if (check.ok) break;
2290
+ } catch {
2291
+ }
2292
+ await new Promise((r) => setTimeout(r, 2e3));
2293
+ }
2230
2294
  return data.url;
2231
2295
  }
2232
2296
  if (res.status === 409) {
@@ -5258,7 +5322,7 @@ async function deployFromGitHubFlow(target, apiToken, claudeToken) {
5258
5322
  }
5259
5323
 
5260
5324
  // src/cli/index.ts
5261
- var CLI_VERSION = "0.1.2";
5325
+ var CLI_VERSION = "0.1.4";
5262
5326
  function formatMutationError(result) {
5263
5327
  const parts = [];
5264
5328
  if (result.status !== void 0) parts.push(String(result.status));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oodarun/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Launch Claude Code on cloud dev environments",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",