orchestrating 0.1.14 → 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 +64 -8
  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,8 +251,20 @@ 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();
220
- const effectiveLabel = label || commandArgs.join(" ") || "continue";
254
+ let authToken = getAuthToken();
255
+ const cwdFolder = path.basename(process.cwd());
256
+ const effectiveLabel = label || cwdFolder || commandArgs.join(" ");
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
+ }
221
268
 
222
269
  // Warn if no auth and connecting to remote server
223
270
  if (!authToken && !serverUrl.includes("localhost") && !serverUrl.includes("127.0.0.1")) {
@@ -828,7 +875,16 @@ function printLocalEvent(event) {
828
875
 
829
876
  // --- WebSocket connection ---
830
877
 
831
- 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
+
832
888
  if (ws) {
833
889
  ws.removeAllListeners();
834
890
  ws.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchestrating",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "Stream terminal sessions to the orchestrat.ing dashboard",
5
5
  "type": "module",
6
6
  "bin": {