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.
@@ -0,0 +1,214 @@
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 clearCredentials() {
32
+ try {
33
+ if (existsSync(CREDENTIALS_FILE)) {
34
+ unlinkSync(CREDENTIALS_FILE);
35
+ }
36
+ } catch {
37
+ }
38
+ }
39
+ function isTokenExpired(credentials) {
40
+ const now = Math.floor(Date.now() / 1e3);
41
+ return credentials.expiresAt <= now + 60;
42
+ }
43
+ function getPlatformInfo() {
44
+ const platform = process.platform;
45
+ const arch = process.arch;
46
+ const nodeVersion = process.version;
47
+ let os = "Unknown";
48
+ if (platform === "darwin") os = "macOS";
49
+ else if (platform === "win32") os = "Windows";
50
+ else if (platform === "linux") os = "Linux";
51
+ return `refineo-cli/0.1.0 (${os}; ${arch}) Node/${nodeVersion}`;
52
+ }
53
+
54
+ // src/api.ts
55
+ var USER_AGENT = getPlatformInfo();
56
+ async function apiRequest(path, options = {}) {
57
+ const credentials = loadCredentials();
58
+ if (!credentials) {
59
+ throw new Error("Not logged in. Run: refineo login");
60
+ }
61
+ let token = credentials.accessToken;
62
+ if (isTokenExpired(credentials)) {
63
+ const refreshed = await refreshToken(credentials.refreshToken);
64
+ if (refreshed) {
65
+ token = refreshed.accessToken;
66
+ } else {
67
+ throw new Error("Session expired. Run: refineo login");
68
+ }
69
+ }
70
+ const response = await fetch(`${API_BASE_URL}${path}`, {
71
+ ...options,
72
+ headers: {
73
+ "Content-Type": "application/json",
74
+ "Authorization": `Bearer ${token}`,
75
+ "User-Agent": USER_AGENT,
76
+ ...options.headers
77
+ }
78
+ });
79
+ if (!response.ok) {
80
+ const error = await response.json().catch(() => ({ error: "Unknown error" }));
81
+ throw new Error(error.message || error.error_description || error.error || `HTTP ${response.status}`);
82
+ }
83
+ return response.json();
84
+ }
85
+ async function refreshToken(refreshTokenValue) {
86
+ try {
87
+ const response = await fetch(`${API_BASE_URL}/api/auth/device/refresh`, {
88
+ method: "POST",
89
+ headers: {
90
+ "Content-Type": "application/json",
91
+ "User-Agent": USER_AGENT
92
+ },
93
+ body: JSON.stringify({
94
+ refresh_token: refreshTokenValue,
95
+ grant_type: "refresh_token"
96
+ })
97
+ });
98
+ if (!response.ok) {
99
+ return null;
100
+ }
101
+ const data = await response.json();
102
+ const oldCredentials = loadCredentials();
103
+ const credentials = {
104
+ accessToken: data.access_token,
105
+ refreshToken: data.refresh_token,
106
+ expiresAt: data.expires_at,
107
+ user: oldCredentials?.user || { email: "", tier: "" }
108
+ };
109
+ saveCredentials(credentials);
110
+ return credentials;
111
+ } catch {
112
+ return null;
113
+ }
114
+ }
115
+ async function startDeviceCodeFlow() {
116
+ const response = await fetch(`${API_BASE_URL}/api/auth/device/code`, {
117
+ method: "POST",
118
+ headers: {
119
+ "Content-Type": "application/json",
120
+ "User-Agent": USER_AGENT
121
+ }
122
+ });
123
+ if (!response.ok) {
124
+ throw new Error("Failed to start login flow");
125
+ }
126
+ return response.json();
127
+ }
128
+ async function pollForToken(deviceCode, interval, expiresIn, onPoll) {
129
+ const startTime = Date.now();
130
+ const timeout = expiresIn * 1e3;
131
+ while (Date.now() - startTime < timeout) {
132
+ onPoll?.();
133
+ const response = await fetch(`${API_BASE_URL}/api/auth/device/token`, {
134
+ method: "POST",
135
+ headers: {
136
+ "Content-Type": "application/json",
137
+ "User-Agent": USER_AGENT
138
+ },
139
+ body: JSON.stringify({
140
+ device_code: deviceCode,
141
+ grant_type: "urn:ietf:params:oauth:grant-type:device_code"
142
+ })
143
+ });
144
+ const data = await response.json();
145
+ if (response.ok) {
146
+ const tokenData = data;
147
+ const credentials = {
148
+ accessToken: tokenData.access_token,
149
+ refreshToken: tokenData.refresh_token,
150
+ expiresAt: tokenData.expires_at,
151
+ user: tokenData.user || { email: "", tier: "" }
152
+ };
153
+ saveCredentials(credentials);
154
+ return credentials;
155
+ }
156
+ const error = data;
157
+ if (error.error === "authorization_pending") {
158
+ await new Promise((resolve) => setTimeout(resolve, interval * 1e3));
159
+ continue;
160
+ }
161
+ if (error.error === "slow_down") {
162
+ await new Promise((resolve) => setTimeout(resolve, (interval + 5) * 1e3));
163
+ continue;
164
+ }
165
+ if (error.error === "access_denied") {
166
+ throw new Error(
167
+ error.error_description || "Access denied. CLI requires Pro or Ultra subscription."
168
+ );
169
+ }
170
+ if (error.error === "expired_token") {
171
+ throw new Error("Login timed out. Please try again.");
172
+ }
173
+ throw new Error(error.error_description || error.error || "Login failed");
174
+ }
175
+ throw new Error("Login timed out. Please try again.");
176
+ }
177
+ async function humanize(text, model = "enhanced") {
178
+ const result = await apiRequest("/api/humanize", {
179
+ method: "POST",
180
+ body: JSON.stringify({
181
+ text,
182
+ model: model === "standard" ? "BALANCE" : "ENHANCED"
183
+ })
184
+ });
185
+ return {
186
+ humanizedText: result.data.humanizedText,
187
+ wordCount: result.data.wordCount,
188
+ model: result.data.model
189
+ };
190
+ }
191
+ async function getUsage() {
192
+ const result = await apiRequest("/api/usage");
193
+ return {
194
+ tier: result.tier,
195
+ used: result.used,
196
+ limit: result.limit,
197
+ remaining: result.remaining,
198
+ resetDate: result.resetDate,
199
+ wordLimit: result.wordLimit,
200
+ rateLimit: result.rateLimit
201
+ };
202
+ }
203
+ export {
204
+ API_BASE_URL,
205
+ clearCredentials,
206
+ getPlatformInfo,
207
+ getUsage,
208
+ humanize,
209
+ isTokenExpired,
210
+ loadCredentials,
211
+ pollForToken,
212
+ saveCredentials,
213
+ startDeviceCodeFlow
214
+ };
@@ -0,0 +1,59 @@
1
+ export interface Credentials {
2
+ accessToken: string;
3
+ refreshToken: string;
4
+ expiresAt: number;
5
+ user: {
6
+ email: string;
7
+ name?: string;
8
+ tier: string;
9
+ };
10
+ }
11
+ export interface DeviceCodeResponse {
12
+ device_code: string;
13
+ user_code: string;
14
+ verification_uri: string;
15
+ verification_uri_complete: string;
16
+ expires_in: number;
17
+ interval: number;
18
+ }
19
+ export interface TokenResponse {
20
+ access_token: string;
21
+ refresh_token: string;
22
+ token_type: string;
23
+ expires_in: number;
24
+ expires_at: number;
25
+ user?: {
26
+ email: string;
27
+ name?: string;
28
+ tier: string;
29
+ };
30
+ }
31
+ export interface TokenErrorResponse {
32
+ error: string;
33
+ error_description?: string;
34
+ upgrade_url?: string;
35
+ }
36
+ export interface HumanizeOptions {
37
+ text: string;
38
+ model?: 'standard' | 'enhanced';
39
+ }
40
+ export interface HumanizeResult {
41
+ humanizedText: string;
42
+ wordCount: number;
43
+ model: string;
44
+ }
45
+ export interface UsageStats {
46
+ tier: string;
47
+ used: number;
48
+ limit: number;
49
+ remaining: number;
50
+ resetDate?: string;
51
+ wordLimit: number;
52
+ rateLimit?: number;
53
+ }
54
+ export interface APIError {
55
+ error: string;
56
+ message: string;
57
+ details?: unknown;
58
+ }
59
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,yBAAyB,EAAE,MAAM,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB"}
File without changes
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "refineo-cli",
3
+ "version": "0.0.3",
4
+ "description": "Refineo AI Text Humanizer CLI - Transform AI-generated text into natural human writing",
5
+ "type": "module",
6
+ "main": "./dist/esm/index.js",
7
+ "module": "./dist/esm/index.js",
8
+ "types": "./dist/esm/index.d.ts",
9
+ "bin": {
10
+ "refineo": "./dist/esm/cli.js"
11
+ },
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/esm/index.d.ts",
15
+ "import": "./dist/esm/index.js",
16
+ "require": "./dist/cjs/index.js"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "build": "npm run build:esm && npm run build:cjs && npm run build:types",
21
+ "build:esm": "esbuild src/*.ts --bundle --platform=node --format=esm --outdir=dist/esm --packages=external",
22
+ "build:cjs": "esbuild src/*.ts --bundle --platform=node --format=cjs --outdir=dist/cjs --packages=external",
23
+ "build:types": "tsc --emitDeclarationOnly --outDir dist/esm",
24
+ "dev": "tsc --watch",
25
+ "start": "node dist/esm/cli.js",
26
+ "test": "vitest run",
27
+ "test:watch": "vitest",
28
+ "typecheck": "tsc --noEmit",
29
+ "prepublishOnly": "npm run build"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "keywords": [
37
+ "refineo",
38
+ "ai",
39
+ "humanizer",
40
+ "text",
41
+ "writing",
42
+ "cli",
43
+ "mcp"
44
+ ],
45
+ "author": "Refineo",
46
+ "license": "MIT",
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "https://github.com/refineo/refineo-ai-tools.git"
50
+ },
51
+ "bugs": {
52
+ "url": "https://github.com/refineo/refineo-ai-tools/issues"
53
+ },
54
+ "homepage": "https://refineo.ai",
55
+ "engines": {
56
+ "node": ">=18.0.0"
57
+ },
58
+ "dependencies": {},
59
+ "devDependencies": {
60
+ "@types/node": "^22.0.0",
61
+ "esbuild": "^0.24.0",
62
+ "typescript": "^5.7.0",
63
+ "vitest": "^2.1.0"
64
+ }
65
+ }