refineo-cli 0.0.3
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/dist/cjs/api.js +230 -0
- package/dist/cjs/cli.js +498 -0
- package/dist/cjs/config.js +90 -0
- package/dist/cjs/index.js +250 -0
- package/dist/cjs/types.js +18 -0
- package/dist/esm/api.d.ts +18 -0
- package/dist/esm/api.d.ts.map +1 -0
- package/dist/esm/api.js +200 -0
- package/dist/esm/cli.d.ts +3 -0
- package/dist/esm/cli.d.ts.map +1 -0
- package/dist/esm/cli.js +475 -0
- package/dist/esm/config.d.ts +23 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +60 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +214 -0
- package/dist/esm/types.d.ts +59 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +0 -0
- package/package.json +65 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
API_BASE_URL: () => API_BASE_URL,
|
|
24
|
+
clearCredentials: () => clearCredentials,
|
|
25
|
+
getPlatformInfo: () => getPlatformInfo,
|
|
26
|
+
getUsage: () => getUsage,
|
|
27
|
+
humanize: () => humanize,
|
|
28
|
+
isTokenExpired: () => isTokenExpired,
|
|
29
|
+
loadCredentials: () => loadCredentials,
|
|
30
|
+
pollForToken: () => pollForToken,
|
|
31
|
+
saveCredentials: () => saveCredentials,
|
|
32
|
+
startDeviceCodeFlow: () => startDeviceCodeFlow
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(index_exports);
|
|
35
|
+
|
|
36
|
+
// src/config.ts
|
|
37
|
+
var import_os = require("os");
|
|
38
|
+
var import_path = require("path");
|
|
39
|
+
var import_fs = require("fs");
|
|
40
|
+
var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".refineo");
|
|
41
|
+
var CREDENTIALS_FILE = (0, import_path.join)(CONFIG_DIR, "credentials.json");
|
|
42
|
+
var API_BASE_URL = process.env.REFINEO_API_URL || "https://refineo.app";
|
|
43
|
+
function ensureConfigDir() {
|
|
44
|
+
if (!(0, import_fs.existsSync)(CONFIG_DIR)) {
|
|
45
|
+
(0, import_fs.mkdirSync)(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function loadCredentials() {
|
|
49
|
+
try {
|
|
50
|
+
if (!(0, import_fs.existsSync)(CREDENTIALS_FILE)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const data = (0, import_fs.readFileSync)(CREDENTIALS_FILE, "utf-8");
|
|
54
|
+
return JSON.parse(data);
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function saveCredentials(credentials) {
|
|
60
|
+
ensureConfigDir();
|
|
61
|
+
(0, import_fs.writeFileSync)(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), {
|
|
62
|
+
mode: 384
|
|
63
|
+
// Read/write for owner only
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function clearCredentials() {
|
|
67
|
+
try {
|
|
68
|
+
if ((0, import_fs.existsSync)(CREDENTIALS_FILE)) {
|
|
69
|
+
(0, import_fs.unlinkSync)(CREDENTIALS_FILE);
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function isTokenExpired(credentials) {
|
|
75
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
76
|
+
return credentials.expiresAt <= now + 60;
|
|
77
|
+
}
|
|
78
|
+
function getPlatformInfo() {
|
|
79
|
+
const platform = process.platform;
|
|
80
|
+
const arch = process.arch;
|
|
81
|
+
const nodeVersion = process.version;
|
|
82
|
+
let os = "Unknown";
|
|
83
|
+
if (platform === "darwin") os = "macOS";
|
|
84
|
+
else if (platform === "win32") os = "Windows";
|
|
85
|
+
else if (platform === "linux") os = "Linux";
|
|
86
|
+
return `refineo-cli/0.1.0 (${os}; ${arch}) Node/${nodeVersion}`;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/api.ts
|
|
90
|
+
var USER_AGENT = getPlatformInfo();
|
|
91
|
+
async function apiRequest(path, options = {}) {
|
|
92
|
+
const credentials = loadCredentials();
|
|
93
|
+
if (!credentials) {
|
|
94
|
+
throw new Error("Not logged in. Run: refineo login");
|
|
95
|
+
}
|
|
96
|
+
let token = credentials.accessToken;
|
|
97
|
+
if (isTokenExpired(credentials)) {
|
|
98
|
+
const refreshed = await refreshToken(credentials.refreshToken);
|
|
99
|
+
if (refreshed) {
|
|
100
|
+
token = refreshed.accessToken;
|
|
101
|
+
} else {
|
|
102
|
+
throw new Error("Session expired. Run: refineo login");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const response = await fetch(`${API_BASE_URL}${path}`, {
|
|
106
|
+
...options,
|
|
107
|
+
headers: {
|
|
108
|
+
"Content-Type": "application/json",
|
|
109
|
+
"Authorization": `Bearer ${token}`,
|
|
110
|
+
"User-Agent": USER_AGENT,
|
|
111
|
+
...options.headers
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
if (!response.ok) {
|
|
115
|
+
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
116
|
+
throw new Error(error.message || error.error_description || error.error || `HTTP ${response.status}`);
|
|
117
|
+
}
|
|
118
|
+
return response.json();
|
|
119
|
+
}
|
|
120
|
+
async function refreshToken(refreshTokenValue) {
|
|
121
|
+
try {
|
|
122
|
+
const response = await fetch(`${API_BASE_URL}/api/auth/device/refresh`, {
|
|
123
|
+
method: "POST",
|
|
124
|
+
headers: {
|
|
125
|
+
"Content-Type": "application/json",
|
|
126
|
+
"User-Agent": USER_AGENT
|
|
127
|
+
},
|
|
128
|
+
body: JSON.stringify({
|
|
129
|
+
refresh_token: refreshTokenValue,
|
|
130
|
+
grant_type: "refresh_token"
|
|
131
|
+
})
|
|
132
|
+
});
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
const data = await response.json();
|
|
137
|
+
const oldCredentials = loadCredentials();
|
|
138
|
+
const credentials = {
|
|
139
|
+
accessToken: data.access_token,
|
|
140
|
+
refreshToken: data.refresh_token,
|
|
141
|
+
expiresAt: data.expires_at,
|
|
142
|
+
user: oldCredentials?.user || { email: "", tier: "" }
|
|
143
|
+
};
|
|
144
|
+
saveCredentials(credentials);
|
|
145
|
+
return credentials;
|
|
146
|
+
} catch {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async function startDeviceCodeFlow() {
|
|
151
|
+
const response = await fetch(`${API_BASE_URL}/api/auth/device/code`, {
|
|
152
|
+
method: "POST",
|
|
153
|
+
headers: {
|
|
154
|
+
"Content-Type": "application/json",
|
|
155
|
+
"User-Agent": USER_AGENT
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
if (!response.ok) {
|
|
159
|
+
throw new Error("Failed to start login flow");
|
|
160
|
+
}
|
|
161
|
+
return response.json();
|
|
162
|
+
}
|
|
163
|
+
async function pollForToken(deviceCode, interval, expiresIn, onPoll) {
|
|
164
|
+
const startTime = Date.now();
|
|
165
|
+
const timeout = expiresIn * 1e3;
|
|
166
|
+
while (Date.now() - startTime < timeout) {
|
|
167
|
+
onPoll?.();
|
|
168
|
+
const response = await fetch(`${API_BASE_URL}/api/auth/device/token`, {
|
|
169
|
+
method: "POST",
|
|
170
|
+
headers: {
|
|
171
|
+
"Content-Type": "application/json",
|
|
172
|
+
"User-Agent": USER_AGENT
|
|
173
|
+
},
|
|
174
|
+
body: JSON.stringify({
|
|
175
|
+
device_code: deviceCode,
|
|
176
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
177
|
+
})
|
|
178
|
+
});
|
|
179
|
+
const data = await response.json();
|
|
180
|
+
if (response.ok) {
|
|
181
|
+
const tokenData = data;
|
|
182
|
+
const credentials = {
|
|
183
|
+
accessToken: tokenData.access_token,
|
|
184
|
+
refreshToken: tokenData.refresh_token,
|
|
185
|
+
expiresAt: tokenData.expires_at,
|
|
186
|
+
user: tokenData.user || { email: "", tier: "" }
|
|
187
|
+
};
|
|
188
|
+
saveCredentials(credentials);
|
|
189
|
+
return credentials;
|
|
190
|
+
}
|
|
191
|
+
const error = data;
|
|
192
|
+
if (error.error === "authorization_pending") {
|
|
193
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1e3));
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (error.error === "slow_down") {
|
|
197
|
+
await new Promise((resolve) => setTimeout(resolve, (interval + 5) * 1e3));
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
if (error.error === "access_denied") {
|
|
201
|
+
throw new Error(
|
|
202
|
+
error.error_description || "Access denied. CLI requires Pro or Ultra subscription."
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
if (error.error === "expired_token") {
|
|
206
|
+
throw new Error("Login timed out. Please try again.");
|
|
207
|
+
}
|
|
208
|
+
throw new Error(error.error_description || error.error || "Login failed");
|
|
209
|
+
}
|
|
210
|
+
throw new Error("Login timed out. Please try again.");
|
|
211
|
+
}
|
|
212
|
+
async function humanize(text, model = "enhanced") {
|
|
213
|
+
const result = await apiRequest("/api/humanize", {
|
|
214
|
+
method: "POST",
|
|
215
|
+
body: JSON.stringify({
|
|
216
|
+
text,
|
|
217
|
+
model: model === "standard" ? "BALANCE" : "ENHANCED"
|
|
218
|
+
})
|
|
219
|
+
});
|
|
220
|
+
return {
|
|
221
|
+
humanizedText: result.data.humanizedText,
|
|
222
|
+
wordCount: result.data.wordCount,
|
|
223
|
+
model: result.data.model
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
async function getUsage() {
|
|
227
|
+
const result = await apiRequest("/api/usage");
|
|
228
|
+
return {
|
|
229
|
+
tier: result.tier,
|
|
230
|
+
used: result.used,
|
|
231
|
+
limit: result.limit,
|
|
232
|
+
remaining: result.remaining,
|
|
233
|
+
resetDate: result.resetDate,
|
|
234
|
+
wordLimit: result.wordLimit,
|
|
235
|
+
rateLimit: result.rateLimit
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
239
|
+
0 && (module.exports = {
|
|
240
|
+
API_BASE_URL,
|
|
241
|
+
clearCredentials,
|
|
242
|
+
getPlatformInfo,
|
|
243
|
+
getUsage,
|
|
244
|
+
humanize,
|
|
245
|
+
isTokenExpired,
|
|
246
|
+
loadCredentials,
|
|
247
|
+
pollForToken,
|
|
248
|
+
saveCredentials,
|
|
249
|
+
startDeviceCodeFlow
|
|
250
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// src/types.ts
|
|
17
|
+
var types_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(types_exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Credentials, DeviceCodeResponse, HumanizeResult, UsageStats } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Start device code flow
|
|
4
|
+
*/
|
|
5
|
+
export declare function startDeviceCodeFlow(): Promise<DeviceCodeResponse>;
|
|
6
|
+
/**
|
|
7
|
+
* Poll for device code authorization
|
|
8
|
+
*/
|
|
9
|
+
export declare function pollForToken(deviceCode: string, interval: number, expiresIn: number, onPoll?: () => void): Promise<Credentials>;
|
|
10
|
+
/**
|
|
11
|
+
* Humanize text
|
|
12
|
+
*/
|
|
13
|
+
export declare function humanize(text: string, model?: 'standard' | 'enhanced'): Promise<HumanizeResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Get usage stats
|
|
16
|
+
*/
|
|
17
|
+
export declare function getUsage(): Promise<UsageStats>;
|
|
18
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/api.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAGlB,cAAc,EACd,UAAU,EACX,MAAM,YAAY,CAAC;AAoFpB;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAcvE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,IAAI,GAClB,OAAO,CAAC,WAAW,CAAC,CA8DtB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,UAAU,GAAG,UAAuB,GAC1C,OAAO,CAAC,cAAc,CAAC,CAqBzB;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,CAoBpD"}
|
package/dist/esm/api.js
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
// src/config.ts
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
5
|
+
var CONFIG_DIR = join(homedir(), ".refineo");
|
|
6
|
+
var CREDENTIALS_FILE = join(CONFIG_DIR, "credentials.json");
|
|
7
|
+
var API_BASE_URL = process.env.REFINEO_API_URL || "https://refineo.app";
|
|
8
|
+
function ensureConfigDir() {
|
|
9
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
10
|
+
mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function loadCredentials() {
|
|
14
|
+
try {
|
|
15
|
+
if (!existsSync(CREDENTIALS_FILE)) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const data = readFileSync(CREDENTIALS_FILE, "utf-8");
|
|
19
|
+
return JSON.parse(data);
|
|
20
|
+
} catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function saveCredentials(credentials) {
|
|
25
|
+
ensureConfigDir();
|
|
26
|
+
writeFileSync(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), {
|
|
27
|
+
mode: 384
|
|
28
|
+
// Read/write for owner only
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
function isTokenExpired(credentials) {
|
|
32
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
33
|
+
return credentials.expiresAt <= now + 60;
|
|
34
|
+
}
|
|
35
|
+
function getPlatformInfo() {
|
|
36
|
+
const platform = process.platform;
|
|
37
|
+
const arch = process.arch;
|
|
38
|
+
const nodeVersion = process.version;
|
|
39
|
+
let os = "Unknown";
|
|
40
|
+
if (platform === "darwin") os = "macOS";
|
|
41
|
+
else if (platform === "win32") os = "Windows";
|
|
42
|
+
else if (platform === "linux") os = "Linux";
|
|
43
|
+
return `refineo-cli/0.1.0 (${os}; ${arch}) Node/${nodeVersion}`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/api.ts
|
|
47
|
+
var USER_AGENT = getPlatformInfo();
|
|
48
|
+
async function apiRequest(path, options = {}) {
|
|
49
|
+
const credentials = loadCredentials();
|
|
50
|
+
if (!credentials) {
|
|
51
|
+
throw new Error("Not logged in. Run: refineo login");
|
|
52
|
+
}
|
|
53
|
+
let token = credentials.accessToken;
|
|
54
|
+
if (isTokenExpired(credentials)) {
|
|
55
|
+
const refreshed = await refreshToken(credentials.refreshToken);
|
|
56
|
+
if (refreshed) {
|
|
57
|
+
token = refreshed.accessToken;
|
|
58
|
+
} else {
|
|
59
|
+
throw new Error("Session expired. Run: refineo login");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const response = await fetch(`${API_BASE_URL}${path}`, {
|
|
63
|
+
...options,
|
|
64
|
+
headers: {
|
|
65
|
+
"Content-Type": "application/json",
|
|
66
|
+
"Authorization": `Bearer ${token}`,
|
|
67
|
+
"User-Agent": USER_AGENT,
|
|
68
|
+
...options.headers
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
if (!response.ok) {
|
|
72
|
+
const error = await response.json().catch(() => ({ error: "Unknown error" }));
|
|
73
|
+
throw new Error(error.message || error.error_description || error.error || `HTTP ${response.status}`);
|
|
74
|
+
}
|
|
75
|
+
return response.json();
|
|
76
|
+
}
|
|
77
|
+
async function refreshToken(refreshTokenValue) {
|
|
78
|
+
try {
|
|
79
|
+
const response = await fetch(`${API_BASE_URL}/api/auth/device/refresh`, {
|
|
80
|
+
method: "POST",
|
|
81
|
+
headers: {
|
|
82
|
+
"Content-Type": "application/json",
|
|
83
|
+
"User-Agent": USER_AGENT
|
|
84
|
+
},
|
|
85
|
+
body: JSON.stringify({
|
|
86
|
+
refresh_token: refreshTokenValue,
|
|
87
|
+
grant_type: "refresh_token"
|
|
88
|
+
})
|
|
89
|
+
});
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const data = await response.json();
|
|
94
|
+
const oldCredentials = loadCredentials();
|
|
95
|
+
const credentials = {
|
|
96
|
+
accessToken: data.access_token,
|
|
97
|
+
refreshToken: data.refresh_token,
|
|
98
|
+
expiresAt: data.expires_at,
|
|
99
|
+
user: oldCredentials?.user || { email: "", tier: "" }
|
|
100
|
+
};
|
|
101
|
+
saveCredentials(credentials);
|
|
102
|
+
return credentials;
|
|
103
|
+
} catch {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async function startDeviceCodeFlow() {
|
|
108
|
+
const response = await fetch(`${API_BASE_URL}/api/auth/device/code`, {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: {
|
|
111
|
+
"Content-Type": "application/json",
|
|
112
|
+
"User-Agent": USER_AGENT
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw new Error("Failed to start login flow");
|
|
117
|
+
}
|
|
118
|
+
return response.json();
|
|
119
|
+
}
|
|
120
|
+
async function pollForToken(deviceCode, interval, expiresIn, onPoll) {
|
|
121
|
+
const startTime = Date.now();
|
|
122
|
+
const timeout = expiresIn * 1e3;
|
|
123
|
+
while (Date.now() - startTime < timeout) {
|
|
124
|
+
onPoll?.();
|
|
125
|
+
const response = await fetch(`${API_BASE_URL}/api/auth/device/token`, {
|
|
126
|
+
method: "POST",
|
|
127
|
+
headers: {
|
|
128
|
+
"Content-Type": "application/json",
|
|
129
|
+
"User-Agent": USER_AGENT
|
|
130
|
+
},
|
|
131
|
+
body: JSON.stringify({
|
|
132
|
+
device_code: deviceCode,
|
|
133
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code"
|
|
134
|
+
})
|
|
135
|
+
});
|
|
136
|
+
const data = await response.json();
|
|
137
|
+
if (response.ok) {
|
|
138
|
+
const tokenData = data;
|
|
139
|
+
const credentials = {
|
|
140
|
+
accessToken: tokenData.access_token,
|
|
141
|
+
refreshToken: tokenData.refresh_token,
|
|
142
|
+
expiresAt: tokenData.expires_at,
|
|
143
|
+
user: tokenData.user || { email: "", tier: "" }
|
|
144
|
+
};
|
|
145
|
+
saveCredentials(credentials);
|
|
146
|
+
return credentials;
|
|
147
|
+
}
|
|
148
|
+
const error = data;
|
|
149
|
+
if (error.error === "authorization_pending") {
|
|
150
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1e3));
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (error.error === "slow_down") {
|
|
154
|
+
await new Promise((resolve) => setTimeout(resolve, (interval + 5) * 1e3));
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (error.error === "access_denied") {
|
|
158
|
+
throw new Error(
|
|
159
|
+
error.error_description || "Access denied. CLI requires Pro or Ultra subscription."
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if (error.error === "expired_token") {
|
|
163
|
+
throw new Error("Login timed out. Please try again.");
|
|
164
|
+
}
|
|
165
|
+
throw new Error(error.error_description || error.error || "Login failed");
|
|
166
|
+
}
|
|
167
|
+
throw new Error("Login timed out. Please try again.");
|
|
168
|
+
}
|
|
169
|
+
async function humanize(text, model = "enhanced") {
|
|
170
|
+
const result = await apiRequest("/api/humanize", {
|
|
171
|
+
method: "POST",
|
|
172
|
+
body: JSON.stringify({
|
|
173
|
+
text,
|
|
174
|
+
model: model === "standard" ? "BALANCE" : "ENHANCED"
|
|
175
|
+
})
|
|
176
|
+
});
|
|
177
|
+
return {
|
|
178
|
+
humanizedText: result.data.humanizedText,
|
|
179
|
+
wordCount: result.data.wordCount,
|
|
180
|
+
model: result.data.model
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
async function getUsage() {
|
|
184
|
+
const result = await apiRequest("/api/usage");
|
|
185
|
+
return {
|
|
186
|
+
tier: result.tier,
|
|
187
|
+
used: result.used,
|
|
188
|
+
limit: result.limit,
|
|
189
|
+
remaining: result.remaining,
|
|
190
|
+
resetDate: result.resetDate,
|
|
191
|
+
wordLimit: result.wordLimit,
|
|
192
|
+
rateLimit: result.rateLimit
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
export {
|
|
196
|
+
getUsage,
|
|
197
|
+
humanize,
|
|
198
|
+
pollForToken,
|
|
199
|
+
startDeviceCodeFlow
|
|
200
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":""}
|