orchestrating 0.1.15 → 0.1.16

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/bin/orch +62 -7
  2. package/package.json +1 -1
package/bin/orch CHANGED
@@ -53,6 +53,39 @@ function clearAuth() {
53
53
  } catch {}
54
54
  }
55
55
 
56
+ // --- Supabase config (public anon key, same as browser dashboard) ---
57
+ const SUPABASE_URL = process.env.SUPABASE_URL || "https://vhyqfzdskgrmnxrdaqql.supabase.co";
58
+ const SUPABASE_ANON_KEY = process.env.SUPABASE_ANON_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InZoeXFmemRza2dybW54cmRhcXFsIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzE1NjU5NTYsImV4cCI6MjA4NzE0MTk1Nn0.hWAceFshHoeTlnwThM08enNWG-ZeXICl3uyi-AmIJEk";
59
+
60
+ async function refreshAuthToken() {
61
+ const auth = loadStoredAuth();
62
+ if (!auth || !auth.refresh_token) return null;
63
+
64
+ try {
65
+ const res = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=refresh_token`, {
66
+ method: "POST",
67
+ headers: {
68
+ "Content-Type": "application/json",
69
+ "apikey": SUPABASE_ANON_KEY,
70
+ },
71
+ body: JSON.stringify({ refresh_token: auth.refresh_token }),
72
+ });
73
+
74
+ if (!res.ok) return null;
75
+
76
+ const data = await res.json();
77
+ if (data.access_token) {
78
+ saveAuth({
79
+ access_token: data.access_token,
80
+ refresh_token: data.refresh_token || auth.refresh_token,
81
+ expires_at: data.expires_at || 0,
82
+ });
83
+ return data.access_token;
84
+ }
85
+ } catch {}
86
+ return null;
87
+ }
88
+
56
89
  function getAuthToken() {
57
90
  // 1. Env var override
58
91
  if (process.env.ORC_TOKEN || process.env.CAST_TOKEN || process.env.AUTH_TOKEN) {
@@ -61,16 +94,18 @@ function getAuthToken() {
61
94
  // 2. Stored credentials
62
95
  const auth = loadStoredAuth();
63
96
  if (auth && auth.access_token) {
64
- // Check expiry — if expired and we have a refresh token, caller should refresh
65
- if (auth.expires_at && Date.now() / 1000 > auth.expires_at) {
66
- // Token expired — still return it, server will reject and CLI can prompt re-login
67
- return auth.access_token;
68
- }
69
97
  return auth.access_token;
70
98
  }
71
99
  return "";
72
100
  }
73
101
 
102
+ function isTokenExpired() {
103
+ const auth = loadStoredAuth();
104
+ if (!auth || !auth.expires_at) return false;
105
+ // Expired or expires within 5 minutes
106
+ return Date.now() / 1000 > auth.expires_at - 300;
107
+ }
108
+
74
109
  // --- Login command ---
75
110
  async function handleLogin() {
76
111
  const loginUrl = process.env.ORC_LOGIN_URL || "https://orchestrat.ing/cli-auth";
@@ -216,10 +251,21 @@ const spawnArgs = commandArgs.slice(1);
216
251
  let sessionId;
217
252
  const hostname = os.hostname();
218
253
  const serverUrl = process.env.ORC_URL || process.env.CAST_URL || "wss://api.orchestrat.ing/ws";
219
- const authToken = getAuthToken();
254
+ let authToken = getAuthToken();
220
255
  const cwdFolder = path.basename(process.cwd());
221
256
  const effectiveLabel = label || cwdFolder || commandArgs.join(" ");
222
257
 
258
+ // Refresh token on startup if expired or about to expire
259
+ if (authToken && isTokenExpired()) {
260
+ const refreshed = await refreshAuthToken();
261
+ if (refreshed) {
262
+ authToken = refreshed;
263
+ process.stderr.write(`${DIM}[orch] Token refreshed${RESET}\n`);
264
+ } else {
265
+ process.stderr.write("\x1b[33mToken expired. Run 'orch login' to re-authenticate.\x1b[0m\n");
266
+ }
267
+ }
268
+
223
269
  // Warn if no auth and connecting to remote server
224
270
  if (!authToken && !serverUrl.includes("localhost") && !serverUrl.includes("127.0.0.1")) {
225
271
  console.error("\x1b[33mNo credentials found. Run 'orch login' to authenticate.\x1b[0m");
@@ -829,7 +875,16 @@ function printLocalEvent(event) {
829
875
 
830
876
  // --- WebSocket connection ---
831
877
 
832
- function connectWs() {
878
+ async function connectWs() {
879
+ // Refresh token if expired before (re)connecting
880
+ if (isTokenExpired()) {
881
+ const refreshed = await refreshAuthToken();
882
+ if (refreshed) {
883
+ authToken = refreshed;
884
+ process.stderr.write(`${DIM}[orch] Token refreshed${RESET}\n`);
885
+ }
886
+ }
887
+
833
888
  if (ws) {
834
889
  ws.removeAllListeners();
835
890
  ws.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchestrating",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "Stream terminal sessions to the orchestrat.ing dashboard",
5
5
  "type": "module",
6
6
  "bin": {