@clawapps/cli 0.6.0 → 0.6.2

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 (97) hide show
  1. package/README.md +86 -123
  2. package/dist/commands/balance.d.ts +3 -0
  3. package/dist/commands/balance.js +31 -0
  4. package/dist/commands/balance.js.map +1 -0
  5. package/dist/commands/connect.d.ts +7 -0
  6. package/dist/commands/connect.js +143 -0
  7. package/dist/commands/connect.js.map +1 -0
  8. package/dist/commands/helpers/resolve-credentials.d.ts +12 -0
  9. package/dist/commands/helpers/resolve-credentials.js +29 -0
  10. package/dist/commands/helpers/resolve-credentials.js.map +1 -0
  11. package/dist/commands/login-code.d.ts +6 -0
  12. package/dist/commands/login-code.js +27 -0
  13. package/dist/commands/login-code.js.map +1 -0
  14. package/dist/commands/login-poll.d.ts +5 -0
  15. package/dist/commands/login-poll.js +30 -0
  16. package/dist/commands/login-poll.js.map +1 -0
  17. package/dist/commands/login.d.ts +3 -5
  18. package/dist/commands/login.js +66 -128
  19. package/dist/commands/login.js.map +1 -1
  20. package/dist/commands/logout.js +3 -18
  21. package/dist/commands/logout.js.map +1 -1
  22. package/dist/commands/send.d.ts +8 -0
  23. package/dist/commands/send.js +112 -0
  24. package/dist/commands/send.js.map +1 -0
  25. package/dist/commands/sessions.d.ts +6 -0
  26. package/dist/commands/sessions.js +36 -0
  27. package/dist/commands/sessions.js.map +1 -0
  28. package/dist/index.js +49 -34
  29. package/dist/index.js.map +1 -1
  30. package/dist/lib/config.d.ts +4 -15
  31. package/dist/lib/config.js +6 -21
  32. package/dist/lib/config.js.map +1 -1
  33. package/dist/lib/login-service.d.ts +23 -0
  34. package/dist/lib/login-service.js +68 -0
  35. package/dist/lib/login-service.js.map +1 -0
  36. package/dist/lib/relay-client.d.ts +25 -0
  37. package/dist/lib/relay-client.js +113 -0
  38. package/dist/lib/relay-client.js.map +1 -0
  39. package/dist/lib/sse-parser.d.ts +12 -0
  40. package/dist/lib/sse-parser.js +61 -0
  41. package/dist/lib/sse-parser.js.map +1 -0
  42. package/dist/lib/types.d.ts +17 -27
  43. package/package.json +3 -2
  44. package/dist/auth/apple.d.ts +0 -5
  45. package/dist/auth/apple.js +0 -15
  46. package/dist/auth/apple.js.map +0 -1
  47. package/dist/auth/exchange.d.ts +0 -6
  48. package/dist/auth/exchange.js +0 -25
  49. package/dist/auth/exchange.js.map +0 -1
  50. package/dist/auth/google.d.ts +0 -5
  51. package/dist/auth/google.js +0 -16
  52. package/dist/auth/google.js.map +0 -1
  53. package/dist/auth/login-server.d.ts +0 -10
  54. package/dist/auth/login-server.js +0 -62
  55. package/dist/auth/login-server.js.map +0 -1
  56. package/dist/auth/payment-server.d.ts +0 -10
  57. package/dist/auth/payment-server.js +0 -66
  58. package/dist/auth/payment-server.js.map +0 -1
  59. package/dist/auth/qr-poll.d.ts +0 -32
  60. package/dist/auth/qr-poll.js +0 -72
  61. package/dist/auth/qr-poll.js.map +0 -1
  62. package/dist/auth/server.d.ts +0 -17
  63. package/dist/auth/server.js +0 -102
  64. package/dist/auth/server.js.map +0 -1
  65. package/dist/commands/credit.d.ts +0 -1
  66. package/dist/commands/credit.js +0 -28
  67. package/dist/commands/credit.js.map +0 -1
  68. package/dist/commands/helpers/ensure-token.d.ts +0 -6
  69. package/dist/commands/helpers/ensure-token.js +0 -29
  70. package/dist/commands/helpers/ensure-token.js.map +0 -1
  71. package/dist/commands/membership.d.ts +0 -1
  72. package/dist/commands/membership.js +0 -28
  73. package/dist/commands/membership.js.map +0 -1
  74. package/dist/commands/payment-grant.d.ts +0 -5
  75. package/dist/commands/payment-grant.js +0 -132
  76. package/dist/commands/payment-grant.js.map +0 -1
  77. package/dist/commands/recharge-credits.d.ts +0 -1
  78. package/dist/commands/recharge-credits.js +0 -10
  79. package/dist/commands/recharge-credits.js.map +0 -1
  80. package/dist/commands/subscribe.d.ts +0 -1
  81. package/dist/commands/subscribe.js +0 -10
  82. package/dist/commands/subscribe.js.map +0 -1
  83. package/dist/commands/token.d.ts +0 -1
  84. package/dist/commands/token.js +0 -17
  85. package/dist/commands/token.js.map +0 -1
  86. package/dist/commands/whoami.d.ts +0 -1
  87. package/dist/commands/whoami.js +0 -59
  88. package/dist/commands/whoami.js.map +0 -1
  89. package/dist/html/callback.d.ts +0 -12
  90. package/dist/html/callback.js +0 -246
  91. package/dist/html/callback.js.map +0 -1
  92. package/dist/html/logo-data.d.ts +0 -1
  93. package/dist/html/logo-data.js +0 -2
  94. package/dist/html/logo-data.js.map +0 -1
  95. package/dist/lib/api.d.ts +0 -13
  96. package/dist/lib/api.js +0 -26
  97. package/dist/lib/api.js.map +0 -1
@@ -1,26 +1,11 @@
1
1
  export const CONFIG = {
2
- GOOGLE_CLIENT_ID: '89883978473-52rsbijnbti2lr3imsg9odjc04ulq1ds.apps.googleusercontent.com',
3
- OD_API_BASE: 'https://api.opendigits.ai/api/v1',
4
- CLAW_API_BASE: 'https://api.clawapps.ai/api/v1',
5
- // OD endpoints
6
- OD_GOOGLE_AUTH: 'https://api.opendigits.ai/api/v1/auth/oauth/google',
7
- OD_APPLE_AUTHORIZE: 'https://api.opendigits.ai/api/v1/auth/oauth/apple/authorize',
8
- // ClawApps endpoints
9
- CLAW_EXCHANGE: 'https://api.clawapps.ai/api/v1/auth/exchange',
10
- CLAW_ME: 'https://api.clawapps.ai/api/v1/auth/me',
11
- CLAW_REFRESH: 'https://api.clawapps.ai/api/v1/auth/refresh',
12
- CLAW_LOGOUT: 'https://api.clawapps.ai/api/v1/auth/logout',
13
- // Web
14
- CLAW_WEB_BASE: 'https://clawapps.ai',
15
- // Agent code endpoints
16
- AGENT_CREATE_LOGIN_CODE: 'https://api.clawapps.ai/api/v1/agent/create-login-code',
17
- AGENT_CREATE_PAYMENT_CODE: 'https://api.clawapps.ai/api/v1/agent/create-payment-code',
18
- AGENT_AUTH_CODE: 'https://api.clawapps.ai/api/v1/agent/auth-code',
19
- AUTH_POLL_INTERVAL_MS: 3 * 1000, // 3 seconds
20
- // Timeouts
21
- AUTH_TIMEOUT_MS: 3 * 60 * 1000, // 3 minutes
22
- // Credentials
2
+ // CLI Relay
3
+ CLI_RELAY_BASE: 'https://api.clawapps.ai/cli/v1',
4
+ CLI_CONNECT_TIMEOUT_MS: 30 * 1000,
5
+ CLI_MESSAGE_TIMEOUT_MS: 5 * 60 * 1000,
6
+ // Local storage
23
7
  CREDENTIALS_DIR: '.clawapps',
24
8
  CREDENTIALS_FILE: 'credentials.json',
9
+ SESSIONS_FILE: 'sessions.json',
25
10
  };
26
11
  //# sourceMappingURL=config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,gBAAgB,EAAE,yEAAyE;IAE3F,WAAW,EAAE,kCAAkC;IAC/C,aAAa,EAAE,gCAAgC;IAE/C,eAAe;IACf,cAAc,EAAE,oDAAoD;IACpE,kBAAkB,EAAE,6DAA6D;IAEjF,qBAAqB;IACrB,aAAa,EAAE,8CAA8C;IAC7D,OAAO,EAAE,wCAAwC;IACjD,YAAY,EAAE,6CAA6C;IAC3D,WAAW,EAAE,4CAA4C;IAEzD,MAAM;IACN,aAAa,EAAE,qBAAqB;IAEpC,uBAAuB;IACvB,uBAAuB,EAAE,wDAAwD;IACjF,yBAAyB,EAAE,0DAA0D;IACrF,eAAe,EAAE,gDAAgD;IACjE,qBAAqB,EAAE,CAAC,GAAG,IAAI,EAAE,YAAY;IAE7C,WAAW;IACX,eAAe,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,YAAY;IAE5C,cAAc;IACd,eAAe,EAAE,WAAW;IAC5B,gBAAgB,EAAE,kBAAkB;CAC5B,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,YAAY;IACZ,cAAc,EAAE,gCAAgC;IAChD,sBAAsB,EAAE,EAAE,GAAG,IAAI;IACjC,sBAAsB,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;IAErC,gBAAgB;IAChB,eAAe,EAAE,WAAW;IAC5B,gBAAgB,EAAE,kBAAkB;IACpC,aAAa,EAAE,eAAe;CACtB,CAAC"}
@@ -0,0 +1,23 @@
1
+ export interface LoginCodeResult {
2
+ code: string;
3
+ qr_url: string;
4
+ qr_image: string;
5
+ qr_text: string;
6
+ expires_at: string;
7
+ }
8
+ export interface LoginPollResult {
9
+ success: boolean;
10
+ display_name?: string;
11
+ error?: string;
12
+ }
13
+ /**
14
+ * Create a login code and generate QR image.
15
+ * Returns immediately (non-blocking).
16
+ */
17
+ export declare function createLoginCode(): Promise<LoginCodeResult>;
18
+ /**
19
+ * Poll for login verification.
20
+ * Calls onStatus every poll interval.
21
+ * Returns when verified, expired, or timed out.
22
+ */
23
+ export declare function pollLoginCode(code: string, onStatus?: (remaining: number) => void, timeoutMs?: number): Promise<LoginPollResult>;
@@ -0,0 +1,68 @@
1
+ import QRCode from 'qrcode';
2
+ import { writeFileSync } from 'node:fs';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import { CONFIG } from './config.js';
6
+ import { saveCredentials } from './credentials.js';
7
+ function relayUrl(path) {
8
+ const base = process.env.CLAWAPPS_RELAY_URL || CONFIG.CLI_RELAY_BASE;
9
+ return `${base}${path}`;
10
+ }
11
+ /**
12
+ * Create a login code and generate QR image.
13
+ * Returns immediately (non-blocking).
14
+ */
15
+ export async function createLoginCode() {
16
+ const res = await fetch(relayUrl('/auth/login-code'), {
17
+ method: 'POST',
18
+ headers: { 'Content-Type': 'application/json' },
19
+ body: '{}',
20
+ });
21
+ if (!res.ok)
22
+ throw new Error(`Failed to create login code (${res.status})`);
23
+ const body = await res.json();
24
+ if (!body.data?.qr_url)
25
+ throw new Error('Invalid response from server');
26
+ const { code, qr_url, expires_at } = body.data;
27
+ // Generate QR image (PNG) + QR text file
28
+ const ts = Date.now();
29
+ const qrImagePath = join(tmpdir(), `clawapps-login-qr-${ts}.png`);
30
+ const qrTextPath = join(tmpdir(), `clawapps-login-qr-${ts}.txt`);
31
+ await QRCode.toFile(qrImagePath, qr_url, { width: 300, margin: 2 });
32
+ const qrText = await QRCode.toString(qr_url, { type: 'utf8', small: true });
33
+ writeFileSync(qrTextPath, `Login URL: ${qr_url}\n\n${qrText}`);
34
+ return { code, qr_url, qr_image: qrImagePath, qr_text: qrTextPath, expires_at };
35
+ }
36
+ /**
37
+ * Poll for login verification.
38
+ * Calls onStatus every poll interval.
39
+ * Returns when verified, expired, or timed out.
40
+ */
41
+ export async function pollLoginCode(code, onStatus, timeoutMs = 180000) {
42
+ const pollInterval = 3000;
43
+ const startTime = Date.now();
44
+ while (Date.now() - startTime < timeoutMs) {
45
+ const remaining = Math.ceil((timeoutMs - (Date.now() - startTime)) / 1000);
46
+ onStatus?.(remaining);
47
+ await new Promise(r => setTimeout(r, pollInterval));
48
+ const res = await fetch(relayUrl(`/auth/poll?code=${encodeURIComponent(code)}`));
49
+ const raw = await res.json();
50
+ const inner = raw.data || raw;
51
+ const innerCode = inner.code ?? raw.code;
52
+ const result = inner.data || inner;
53
+ if (innerCode === 0 && result.access_token) {
54
+ await saveCredentials({
55
+ provider: 'wechat',
56
+ access_token: result.access_token,
57
+ refresh_token: result.refresh_token,
58
+ logged_in_at: new Date().toISOString(),
59
+ });
60
+ return { success: true, display_name: result.display_name || undefined };
61
+ }
62
+ if (innerCode === 4008) {
63
+ return { success: false, error: 'Code expired' };
64
+ }
65
+ }
66
+ return { success: false, error: 'Timed out' };
67
+ }
68
+ //# sourceMappingURL=login-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-service.js","sourceRoot":"","sources":["../../src/lib/login-service.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAC,cAAc,CAAC;IACrE,OAAO,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;AAC1B,CAAC;AAgBD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QACpD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAE5E,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAmF,CAAC;IAC/G,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAExE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC;IAE/C,yCAAyC;IACzC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACjE,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACpE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5E,aAAa,CAAC,UAAU,EAAE,cAAc,MAAM,OAAO,MAAM,EAAE,CAAC,CAAC;IAE/D,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;AAClF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAY,EACZ,QAAsC,EACtC,YAAoB,MAAM;IAE1B,MAAM,YAAY,GAAG,IAAI,CAAC;IAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAAC;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3E,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAC;QAEtB,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;QAEpD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,mBAAmB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACjF,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAA6B,CAAC;QAExD,MAAM,KAAK,GAAI,GAAG,CAAC,IAAgC,IAAI,GAAG,CAAC;QAC3D,MAAM,SAAS,GAAI,KAAK,CAAC,IAAe,IAAK,GAAG,CAAC,IAAe,CAAC;QACjE,MAAM,MAAM,GAAI,KAAK,CAAC,IAAgC,IAAI,KAAK,CAAC;QAEhE,IAAI,SAAS,KAAK,CAAC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YAC3C,MAAM,eAAe,CAAC;gBACpB,QAAQ,EAAE,QAAQ;gBAClB,YAAY,EAAE,MAAM,CAAC,YAAsB;gBAC3C,aAAa,EAAE,MAAM,CAAC,aAAuB;gBAC7C,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACvC,CAAC,CAAC;YACH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAG,MAAM,CAAC,YAAuB,IAAI,SAAS,EAAE,CAAC;QACvF,CAAC;QAED,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { RelaySessionResponse, RelayBalanceResponse, SSEEvent, SessionStore, SessionInfo } from './types.js';
2
+ /**
3
+ * Create a new session on the Relay.
4
+ */
5
+ export declare function createSession(token: string): Promise<RelaySessionResponse>;
6
+ /**
7
+ * Send a message and yield SSE events as they arrive.
8
+ */
9
+ export declare function sendMessage(token: string, sessionId: string, content: string): AsyncGenerator<SSEEvent>;
10
+ /**
11
+ * Stop processing for a session.
12
+ */
13
+ export declare function stopProcessing(token: string, sessionId: string): Promise<void>;
14
+ /**
15
+ * Close a session.
16
+ */
17
+ export declare function closeSession(token: string, sessionId: string): Promise<void>;
18
+ /**
19
+ * Get credit balance.
20
+ */
21
+ export declare function getBalance(token: string): Promise<RelayBalanceResponse>;
22
+ export declare function loadSessions(): Promise<SessionStore>;
23
+ export declare function saveSession(info: SessionInfo): Promise<void>;
24
+ export declare function clearSessions(): Promise<void>;
25
+ export declare function getLastSessionId(): Promise<string | null>;
@@ -0,0 +1,113 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { CONFIG } from './config.js';
5
+ import { parseSSE } from './sse-parser.js';
6
+ function relayUrl(path) {
7
+ const base = process.env.CLAWAPPS_RELAY_URL || CONFIG.CLI_RELAY_BASE;
8
+ return `${base}${path}`;
9
+ }
10
+ function authHeaders(token) {
11
+ return {
12
+ 'Authorization': `Bearer ${token}`,
13
+ 'Content-Type': 'application/json',
14
+ };
15
+ }
16
+ /**
17
+ * Create a new session on the Relay.
18
+ */
19
+ export async function createSession(token) {
20
+ const res = await fetch(relayUrl('/session'), {
21
+ method: 'POST',
22
+ headers: authHeaders(token),
23
+ body: '{}',
24
+ });
25
+ if (!res.ok) {
26
+ const err = await res.json().catch(() => ({ message: res.statusText }));
27
+ throw new Error(err.message || `Session creation failed (${res.status})`);
28
+ }
29
+ return await res.json();
30
+ }
31
+ /**
32
+ * Send a message and yield SSE events as they arrive.
33
+ */
34
+ export async function* sendMessage(token, sessionId, content) {
35
+ const res = await fetch(relayUrl(`/session/${sessionId}/message`), {
36
+ method: 'POST',
37
+ headers: authHeaders(token),
38
+ body: JSON.stringify({ content }),
39
+ signal: AbortSignal.timeout(CONFIG.CLI_MESSAGE_TIMEOUT_MS),
40
+ });
41
+ if (!res.ok) {
42
+ const err = await res.json().catch(() => ({ message: res.statusText }));
43
+ throw new Error(err.message || `Send failed (${res.status})`);
44
+ }
45
+ if (!res.body) {
46
+ throw new Error('No response body (SSE stream expected)');
47
+ }
48
+ yield* parseSSE(res.body);
49
+ }
50
+ /**
51
+ * Stop processing for a session.
52
+ */
53
+ export async function stopProcessing(token, sessionId) {
54
+ await fetch(relayUrl(`/session/${sessionId}/stop`), {
55
+ method: 'POST',
56
+ headers: authHeaders(token),
57
+ body: '{}',
58
+ });
59
+ }
60
+ /**
61
+ * Close a session.
62
+ */
63
+ export async function closeSession(token, sessionId) {
64
+ await fetch(relayUrl(`/session/${sessionId}`), {
65
+ method: 'DELETE',
66
+ headers: { 'Authorization': `Bearer ${token}` },
67
+ });
68
+ }
69
+ /**
70
+ * Get credit balance.
71
+ */
72
+ export async function getBalance(token) {
73
+ const res = await fetch(relayUrl('/balance'), {
74
+ method: 'GET',
75
+ headers: { 'Authorization': `Bearer ${token}` },
76
+ });
77
+ if (!res.ok) {
78
+ const err = await res.json().catch(() => ({ message: res.statusText }));
79
+ throw new Error(err.message || `Balance check failed (${res.status})`);
80
+ }
81
+ return await res.json();
82
+ }
83
+ // --- Local session persistence ---
84
+ function sessionsPath() {
85
+ return join(homedir(), CONFIG.CREDENTIALS_DIR, CONFIG.SESSIONS_FILE);
86
+ }
87
+ export async function loadSessions() {
88
+ try {
89
+ const data = await readFile(sessionsPath(), 'utf-8');
90
+ return JSON.parse(data);
91
+ }
92
+ catch {
93
+ return { sessions: {} };
94
+ }
95
+ }
96
+ export async function saveSession(info) {
97
+ const store = await loadSessions();
98
+ store.sessions[info.session_id] = info;
99
+ store.last_session_id = info.session_id;
100
+ const dir = join(homedir(), CONFIG.CREDENTIALS_DIR);
101
+ await mkdir(dir, { recursive: true });
102
+ await writeFile(sessionsPath(), JSON.stringify(store, null, 2), 'utf-8');
103
+ }
104
+ export async function clearSessions() {
105
+ const dir = join(homedir(), CONFIG.CREDENTIALS_DIR);
106
+ await mkdir(dir, { recursive: true });
107
+ await writeFile(sessionsPath(), JSON.stringify({ sessions: {} }, null, 2), 'utf-8');
108
+ }
109
+ export async function getLastSessionId() {
110
+ const store = await loadSessions();
111
+ return store.last_session_id || null;
112
+ }
113
+ //# sourceMappingURL=relay-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-client.js","sourceRoot":"","sources":["../../src/lib/relay-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,MAAM,CAAC,cAAc,CAAC;IACrE,OAAO,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,OAAO;QACL,eAAe,EAAE,UAAU,KAAK,EAAE;QAClC,cAAc,EAAE,kBAAkB;KACnC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAa;IAC/C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;QAC5C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC;QAC3B,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAA2B,CAAC;QAClG,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,4BAA4B,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5E,CAAC;IAED,OAAO,MAAM,GAAG,CAAC,IAAI,EAA0B,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,WAAW,CAChC,KAAa,EACb,SAAiB,EACjB,OAAe;IAEf,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,YAAY,SAAS,UAAU,CAAC,EAAE;QACjE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC;QAC3B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;QACjC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC;KAC3D,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAA2B,CAAC;QAClG,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,gBAAgB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa,EAAE,SAAiB;IACnE,MAAM,KAAK,CAAC,QAAQ,CAAC,YAAY,SAAS,OAAO,CAAC,EAAE;QAClD,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,WAAW,CAAC,KAAK,CAAC;QAC3B,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,KAAa,EAAE,SAAiB;IACjE,MAAM,KAAK,CAAC,QAAQ,CAAC,YAAY,SAAS,EAAE,CAAC,EAAE;QAC7C,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,KAAK,EAAE,EAAE;KAChD,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAa;IAC5C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;QAC5C,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,KAAK,EAAE,EAAE;KAChD,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,CAAC,CAA2B,CAAC;QAClG,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,OAAO,IAAI,yBAAyB,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACzE,CAAC;IAED,OAAO,MAAM,GAAG,CAAC,IAAI,EAA0B,CAAC;AAClD,CAAC;AAED,oCAAoC;AAEpC,SAAS,YAAY;IACnB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAiB;IACjD,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;IACnC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACvC,KAAK,CAAC,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC;IAExC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IACpD,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,YAAY,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IACpD,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,SAAS,CAAC,YAAY,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAC;IACnC,OAAO,KAAK,CAAC,eAAe,IAAI,IAAI,CAAC;AACvC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { SSEEvent } from './types.js';
2
+ /**
3
+ * Parse a Server-Sent Events stream into structured events.
4
+ *
5
+ * SSE format:
6
+ * event: text
7
+ * data: {"content":"hello"}
8
+ *
9
+ * event: complete
10
+ * data: {"success":true}
11
+ */
12
+ export declare function parseSSE(body: ReadableStream<Uint8Array>): AsyncGenerator<SSEEvent>;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Parse a Server-Sent Events stream into structured events.
3
+ *
4
+ * SSE format:
5
+ * event: text
6
+ * data: {"content":"hello"}
7
+ *
8
+ * event: complete
9
+ * data: {"success":true}
10
+ */
11
+ export async function* parseSSE(body) {
12
+ const reader = body.pipeThrough(new TextDecoderStream()).getReader();
13
+ let buffer = '';
14
+ let currentEvent = '';
15
+ let currentData = '';
16
+ try {
17
+ while (true) {
18
+ const { done, value } = await reader.read();
19
+ if (done)
20
+ break;
21
+ buffer += value;
22
+ const lines = buffer.split('\n');
23
+ // Keep the last incomplete line in buffer
24
+ buffer = lines.pop() || '';
25
+ for (const line of lines) {
26
+ if (line.startsWith('event: ')) {
27
+ currentEvent = line.slice(7).trim();
28
+ }
29
+ else if (line.startsWith('data: ')) {
30
+ currentData = line.slice(6);
31
+ }
32
+ else if (line === '' && currentEvent && currentData) {
33
+ // Empty line = end of event
34
+ try {
35
+ const data = JSON.parse(currentData);
36
+ yield { event: currentEvent, data };
37
+ }
38
+ catch {
39
+ yield { event: currentEvent, data: { raw: currentData } };
40
+ }
41
+ currentEvent = '';
42
+ currentData = '';
43
+ }
44
+ }
45
+ }
46
+ // Flush any remaining event
47
+ if (currentEvent && currentData) {
48
+ try {
49
+ const data = JSON.parse(currentData);
50
+ yield { event: currentEvent, data };
51
+ }
52
+ catch {
53
+ yield { event: currentEvent, data: { raw: currentData } };
54
+ }
55
+ }
56
+ }
57
+ finally {
58
+ reader.releaseLock();
59
+ }
60
+ }
61
+ //# sourceMappingURL=sse-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-parser.js","sourceRoot":"","sources":["../../src/lib/sse-parser.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,QAAQ,CAC7B,IAAgC;IAEhC,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,iBAAiB,EAAS,CAAC,CAAC,SAAS,EAAE,CAAC;IAE5E,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,IAAI,WAAW,GAAG,EAAE,CAAC;IAErB,IAAI,CAAC;QACH,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAEhB,MAAM,IAAI,KAAK,CAAC;YAChB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACjC,0CAA0C;YAC1C,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC/B,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;gBACtC,CAAC;qBAAM,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACrC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC9B,CAAC;qBAAM,IAAI,IAAI,KAAK,EAAE,IAAI,YAAY,IAAI,WAAW,EAAE,CAAC;oBACtD,4BAA4B;oBAC5B,IAAI,CAAC;wBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;wBACrC,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;oBACtC,CAAC;oBAAC,MAAM,CAAC;wBACP,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC;oBAC5D,CAAC;oBACD,YAAY,GAAG,EAAE,CAAC;oBAClB,WAAW,GAAG,EAAE,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;QAED,4BAA4B;QAC5B,IAAI,YAAY,IAAI,WAAW,EAAE,CAAC;YAChC,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gBACrC,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;YACtC,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -1,36 +1,26 @@
1
- export type AuthProvider = 'google' | 'apple';
2
- export interface ODTokens {
3
- access_token: string;
4
- refresh_token: string;
5
- }
6
- export interface ClawTokens {
7
- access_token: string;
8
- refresh_token: string;
9
- }
10
1
  export interface Credentials {
11
- provider: AuthProvider;
2
+ provider: string;
12
3
  access_token: string;
13
4
  refresh_token: string;
14
- od_token?: string;
15
- od_refresh_token?: string;
16
5
  logged_in_at: string;
17
6
  }
18
- export interface PaymentGrantResult {
19
- payment_token?: string;
20
- auto_payment: boolean;
7
+ export interface RelaySessionResponse {
8
+ session_id: string;
21
9
  }
22
- export interface AuthCodeLoginResult {
23
- access_token: string;
24
- refresh_token: string;
10
+ export interface RelayBalanceResponse {
11
+ credits: number;
12
+ membership: string;
13
+ display_name?: string | null;
14
+ }
15
+ export interface SSEEvent {
16
+ event: string;
17
+ data: Record<string, unknown>;
25
18
  }
26
- export interface AuthCodePaymentResult {
27
- one_time_pay_token?: string;
28
- auto_pay_enabled: boolean;
19
+ export interface SessionInfo {
20
+ session_id: string;
21
+ created_at: string;
29
22
  }
30
- export interface UserInfo {
31
- id: string;
32
- email: string;
33
- name?: string;
34
- avatar?: string;
35
- [key: string]: unknown;
23
+ export interface SessionStore {
24
+ last_session_id?: string;
25
+ sessions: Record<string, SessionInfo>;
36
26
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@clawapps/cli",
3
- "version": "0.6.0",
4
- "description": "ClawApps CLI - Login and manage your ClawApps account from the terminal",
3
+ "version": "0.6.2",
4
+ "description": "ClawApps CLI - AI agent platform client",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "clawapps": "./bin/claw.js"
@@ -31,6 +31,7 @@
31
31
  "commander": "^14.0.3",
32
32
  "open": "^11.0.0",
33
33
  "ora": "^8.2.0",
34
+ "qrcode": "^1.5.4",
34
35
  "qrcode-terminal": "^0.12.0"
35
36
  },
36
37
  "devDependencies": {
@@ -1,5 +0,0 @@
1
- /**
2
- * Build the Apple OAuth URL via OpenDigits.
3
- * OD handles the Apple OAuth flow and redirects back to our localhost with tokens.
4
- */
5
- export declare function buildAppleAuthUrl(redirectUri: string): string;
@@ -1,15 +0,0 @@
1
- import { CONFIG } from '../lib/config.js';
2
- import { randomBytes } from 'node:crypto';
3
- /**
4
- * Build the Apple OAuth URL via OpenDigits.
5
- * OD handles the Apple OAuth flow and redirects back to our localhost with tokens.
6
- */
7
- export function buildAppleAuthUrl(redirectUri) {
8
- const state = randomBytes(16).toString('hex');
9
- const params = new URLSearchParams({
10
- redirect_uri: redirectUri,
11
- state,
12
- });
13
- return `${CONFIG.OD_APPLE_AUTHORIZE}?${params.toString()}`;
14
- }
15
- //# sourceMappingURL=apple.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"apple.js","sourceRoot":"","sources":["../../src/auth/apple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,YAAY,EAAE,WAAW;QACzB,KAAK;KACN,CAAC,CAAC;IAEH,OAAO,GAAG,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC7D,CAAC"}
@@ -1,6 +0,0 @@
1
- import type { ODTokens, ClawTokens } from '../lib/types.js';
2
- /**
3
- * Exchange a Google access_token for OpenDigits tokens.
4
- */
5
- export declare function googleToOD(googleAccessToken: string): Promise<ODTokens>;
6
- export declare function odToClawApps(odTokens: ODTokens): Promise<ClawTokens>;
@@ -1,25 +0,0 @@
1
- import { CONFIG } from '../lib/config.js';
2
- import { apiPost } from '../lib/api.js';
3
- /**
4
- * Exchange a Google access_token for OpenDigits tokens.
5
- */
6
- export async function googleToOD(googleAccessToken) {
7
- const res = await apiPost(CONFIG.OD_GOOGLE_AUTH, {
8
- access_token: googleAccessToken,
9
- });
10
- if (!res.ok) {
11
- throw new Error(`Google → OD exchange failed (${res.status}): ${JSON.stringify(res.data)}`);
12
- }
13
- return res.data.data;
14
- }
15
- export async function odToClawApps(odTokens) {
16
- const res = await apiPost(CONFIG.CLAW_EXCHANGE, {
17
- od_token: odTokens.access_token,
18
- od_refresh_token: odTokens.refresh_token,
19
- });
20
- if (!res.ok) {
21
- throw new Error(`OD → ClawApps exchange failed (${res.status}): ${JSON.stringify(res.data)}`);
22
- }
23
- return res.data.data;
24
- }
25
- //# sourceMappingURL=exchange.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"exchange.js","sourceRoot":"","sources":["../../src/auth/exchange.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAUxC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,iBAAyB;IACxD,MAAM,GAAG,GAAG,MAAM,OAAO,CAA0B,MAAM,CAAC,cAAc,EAAE;QACxE,YAAY,EAAE,iBAAiB;KAChC,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AACvB,CAAC;AAYD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAkB;IACnD,MAAM,GAAG,GAAG,MAAM,OAAO,CAA8B,MAAM,CAAC,aAAa,EAAE;QAC3E,QAAQ,EAAE,QAAQ,CAAC,YAAY;QAC/B,gBAAgB,EAAE,QAAQ,CAAC,aAAa;KACzC,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AACvB,CAAC"}
@@ -1,5 +0,0 @@
1
- /**
2
- * Build the Google OAuth implicit flow URL.
3
- * Uses response_type=token to get access_token in the URL hash fragment.
4
- */
5
- export declare function buildGoogleAuthUrl(redirectUri: string): string;
@@ -1,16 +0,0 @@
1
- import { CONFIG } from '../lib/config.js';
2
- /**
3
- * Build the Google OAuth implicit flow URL.
4
- * Uses response_type=token to get access_token in the URL hash fragment.
5
- */
6
- export function buildGoogleAuthUrl(redirectUri) {
7
- const params = new URLSearchParams({
8
- client_id: CONFIG.GOOGLE_CLIENT_ID,
9
- redirect_uri: redirectUri,
10
- response_type: 'token',
11
- scope: 'openid email profile',
12
- prompt: 'select_account',
13
- });
14
- return `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
15
- }
16
- //# sourceMappingURL=google.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"google.js","sourceRoot":"","sources":["../../src/auth/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAmB;IACpD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;QACjC,SAAS,EAAE,MAAM,CAAC,gBAAgB;QAClC,YAAY,EAAE,WAAW;QACzB,aAAa,EAAE,OAAO;QACtB,KAAK,EAAE,sBAAsB;QAC7B,MAAM,EAAE,gBAAgB;KACzB,CAAC,CAAC;IAEH,OAAO,gDAAgD,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;AAC7E,CAAC"}
@@ -1,10 +0,0 @@
1
- import type { ClawTokens } from '../lib/types.js';
2
- /**
3
- * Start a local HTTP server that receives ClawApps tokens from the web login page redirect.
4
- * The web page redirects to: http://localhost:{port}/callback?access_token=xxx&refresh_token=xxx
5
- */
6
- export declare function startLoginCallbackServer(): Promise<{
7
- port: number;
8
- result: Promise<ClawTokens>;
9
- close: () => void;
10
- }>;
@@ -1,62 +0,0 @@
1
- import { createServer } from 'node:http';
2
- import { URL } from 'node:url';
3
- import { CONFIG } from '../lib/config.js';
4
- import { getSuccessHtml, getErrorHtml } from '../html/callback.js';
5
- /**
6
- * Start a local HTTP server that receives ClawApps tokens from the web login page redirect.
7
- * The web page redirects to: http://localhost:{port}/callback?access_token=xxx&refresh_token=xxx
8
- */
9
- export function startLoginCallbackServer() {
10
- return new Promise((resolveServer, rejectServer) => {
11
- let resultResolve;
12
- let resultReject;
13
- const resultPromise = new Promise((resolve, reject) => {
14
- resultResolve = resolve;
15
- resultReject = reject;
16
- });
17
- const server = createServer((req, res) => {
18
- const port = server.address().port;
19
- const url = new URL(req.url || '/', `http://localhost:${port}`);
20
- if (url.pathname === '/callback') {
21
- const accessToken = url.searchParams.get('access_token');
22
- const refreshToken = url.searchParams.get('refresh_token');
23
- if (accessToken && refreshToken) {
24
- res.writeHead(200, { 'Content-Type': 'text/html' });
25
- res.end(getSuccessHtml());
26
- resultResolve({ access_token: accessToken, refresh_token: refreshToken });
27
- }
28
- else {
29
- res.writeHead(200, { 'Content-Type': 'text/html' });
30
- res.end(getErrorHtml('Missing tokens. Please try again.'));
31
- resultReject(new Error('Callback missing tokens'));
32
- }
33
- return;
34
- }
35
- res.writeHead(404, { 'Content-Type': 'text/plain' });
36
- res.end('Not found');
37
- });
38
- server.listen(0, '127.0.0.1', () => {
39
- const addr = server.address();
40
- const timeout = setTimeout(() => {
41
- resultReject(new Error('Authentication timed out. Please try again.'));
42
- server.close();
43
- }, CONFIG.AUTH_TIMEOUT_MS);
44
- resultPromise.finally(() => {
45
- clearTimeout(timeout);
46
- setTimeout(() => server.close(), 500);
47
- });
48
- resolveServer({
49
- port: addr.port,
50
- result: resultPromise,
51
- close: () => {
52
- clearTimeout(timeout);
53
- server.close();
54
- },
55
- });
56
- });
57
- server.on('error', (err) => {
58
- rejectServer(err);
59
- });
60
- });
61
- }
62
- //# sourceMappingURL=login-server.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login-server.js","sourceRoot":"","sources":["../../src/auth/login-server.ts"],"names":[],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- import type { PaymentGrantResult } from '../lib/types.js';
2
- /**
3
- * Start a local HTTP server that receives payment grant result from the web page redirect.
4
- * The web page redirects to: http://localhost:{port}/callback?payment_token=xxx&auto_payment=1
5
- */
6
- export declare function startPaymentCallbackServer(): Promise<{
7
- port: number;
8
- result: Promise<PaymentGrantResult>;
9
- close: () => void;
10
- }>;