orchestrating 0.1.15 → 0.1.17
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/bin/orch +74 -9
- 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
|
-
|
|
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();
|
|
@@ -873,8 +928,18 @@ function connectWs() {
|
|
|
873
928
|
if (msg.type === "error") {
|
|
874
929
|
process.stderr.write(`${RED}Server error: ${msg.error}${RESET}\n`);
|
|
875
930
|
if (/unauthorized|auth|token/i.test(msg.error || "")) {
|
|
876
|
-
|
|
877
|
-
|
|
931
|
+
// Try to refresh token before giving up
|
|
932
|
+
refreshAuthToken().then((refreshed) => {
|
|
933
|
+
if (refreshed) {
|
|
934
|
+
authToken = refreshed;
|
|
935
|
+
process.stderr.write(`${DIM}[orch] Token refreshed, reconnecting…${RESET}\n`);
|
|
936
|
+
authFailed = false;
|
|
937
|
+
connectWs();
|
|
938
|
+
} else {
|
|
939
|
+
process.stderr.write(`${RED}Run 'orch login' to authenticate.${RESET}\n`);
|
|
940
|
+
authFailed = true;
|
|
941
|
+
}
|
|
942
|
+
});
|
|
878
943
|
}
|
|
879
944
|
return;
|
|
880
945
|
}
|