omnara 0.1.4 → 0.1.6

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 (86) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +6357 -50
  3. package/dist/cli.js.map +7 -1
  4. package/dist/orchestrator/agent-orchestrator.d.ts +4 -1
  5. package/dist/orchestrator/orchestrator-prompt.d.ts +8 -2
  6. package/dist/orchestrator/{types.d.ts → orchestrator-types.d.ts} +14 -0
  7. package/dist/orchestrator/session.d.ts +1 -1
  8. package/dist/orchestrator/tools/worker-tools.d.ts +1 -0
  9. package/dist/orchestrator/utils/session-logger.d.ts +1 -1
  10. package/dist/relay/relay-bridge.d.ts +1 -0
  11. package/dist/utils/browser.d.ts +1 -0
  12. package/dist/utils/claude-code-check.d.ts +21 -0
  13. package/dist/utils/logger.d.ts +127 -0
  14. package/dist/utils/version-check.d.ts +9 -0
  15. package/package.json +12 -5
  16. package/scripts/preinstall.js +141 -0
  17. package/scripts/test-preinstall.js +125 -0
  18. package/dist/auth/auth-provider.js +0 -56
  19. package/dist/auth/auth-provider.js.map +0 -1
  20. package/dist/auth/cli-auth-service.js +0 -44
  21. package/dist/auth/cli-auth-service.js.map +0 -1
  22. package/dist/auth/credential-manager.js +0 -71
  23. package/dist/auth/credential-manager.js.map +0 -1
  24. package/dist/auth/credentials-store.js +0 -69
  25. package/dist/auth/credentials-store.js.map +0 -1
  26. package/dist/auth/login-flow.js +0 -196
  27. package/dist/auth/login-flow.js.map +0 -1
  28. package/dist/auth/loopback-listener.js +0 -155
  29. package/dist/auth/loopback-listener.js.map +0 -1
  30. package/dist/auth/pkce.js +0 -15
  31. package/dist/auth/pkce.js.map +0 -1
  32. package/dist/auth/supabase-client.js +0 -10
  33. package/dist/auth/supabase-client.js.map +0 -1
  34. package/dist/auth/supabase-config.js +0 -21
  35. package/dist/auth/supabase-config.js.map +0 -1
  36. package/dist/commands/agent.js +0 -172
  37. package/dist/commands/agent.js.map +0 -1
  38. package/dist/commands/auth.js +0 -84
  39. package/dist/commands/auth.js.map +0 -1
  40. package/dist/commands/index.js +0 -3
  41. package/dist/commands/index.js.map +0 -1
  42. package/dist/http/api-client.js +0 -118
  43. package/dist/http/api-client.js.map +0 -1
  44. package/dist/http/user-sessions.js +0 -9
  45. package/dist/http/user-sessions.js.map +0 -1
  46. package/dist/orchestrator/agent-orchestrator.js +0 -592
  47. package/dist/orchestrator/agent-orchestrator.js.map +0 -1
  48. package/dist/orchestrator/ai-client.js +0 -77
  49. package/dist/orchestrator/ai-client.js.map +0 -1
  50. package/dist/orchestrator/orchestrator-prompt.js +0 -13
  51. package/dist/orchestrator/orchestrator-prompt.js.map +0 -1
  52. package/dist/orchestrator/session.js +0 -295
  53. package/dist/orchestrator/session.js.map +0 -1
  54. package/dist/orchestrator/tools/worker-status-tool.js +0 -41
  55. package/dist/orchestrator/tools/worker-status-tool.js.map +0 -1
  56. package/dist/orchestrator/tools/worker-tools.js +0 -149
  57. package/dist/orchestrator/tools/worker-tools.js.map +0 -1
  58. package/dist/orchestrator/types.js +0 -30
  59. package/dist/orchestrator/types.js.map +0 -1
  60. package/dist/orchestrator/utils/async-queue.js +0 -70
  61. package/dist/orchestrator/utils/async-queue.js.map +0 -1
  62. package/dist/orchestrator/utils/session-logger.js +0 -47
  63. package/dist/orchestrator/utils/session-logger.js.map +0 -1
  64. package/dist/orchestrator/worker-manager.js +0 -418
  65. package/dist/orchestrator/worker-manager.js.map +0 -1
  66. package/dist/relay/relay-bridge.js +0 -601
  67. package/dist/relay/relay-bridge.js.map +0 -1
  68. package/dist/relay/relay-service.js +0 -23
  69. package/dist/relay/relay-service.js.map +0 -1
  70. package/dist/repl/terminal-repl.js +0 -262
  71. package/dist/repl/terminal-repl.js.map +0 -1
  72. package/dist/schemas/generated.d.ts +0 -244
  73. package/dist/schemas/generated.js +0 -5
  74. package/dist/schemas/generated.js.map +0 -1
  75. package/dist/schemas/index.js +0 -2
  76. package/dist/schemas/index.js.map +0 -1
  77. package/dist/scripts/generate-schema-types.d.ts +0 -1
  78. package/dist/scripts/generate-schema-types.js +0 -53
  79. package/dist/scripts/generate-schema-types.js.map +0 -1
  80. package/dist/scripts/sync-schemas.d.ts +0 -1
  81. package/dist/scripts/sync-schemas.js +0 -28
  82. package/dist/scripts/sync-schemas.js.map +0 -1
  83. package/dist/utils/prompt.js +0 -13
  84. package/dist/utils/prompt.js.map +0 -1
  85. package/dist/voice/voice-service.js +0 -25
  86. package/dist/voice/voice-service.js.map +0 -1
@@ -1,44 +0,0 @@
1
- import { ApiClient } from '../http/api-client.js';
2
- export async function createCliAuthSession(client, options = {}) {
3
- const body = {};
4
- if (options.frontendUrl) {
5
- body.frontend_url = options.frontendUrl;
6
- }
7
- if (options.loopbackRedirectUri) {
8
- body.loopback_redirect_uri = options.loopbackRedirectUri;
9
- }
10
- if (options.loopbackState) {
11
- body.loopback_state = options.loopbackState;
12
- }
13
- if (options.pkceChallenge) {
14
- body.pkce_challenge = options.pkceChallenge;
15
- body.pkce_challenge_method = options.pkceChallengeMethod ?? 'S256';
16
- }
17
- const wire = await client.postJson('/api/v1/cli-auth/session', body);
18
- return {
19
- sessionId: wire.session_id,
20
- verificationUri: wire.verification_uri,
21
- verificationUriComplete: wire.verification_uri_complete,
22
- expiresIn: wire.expires_in,
23
- pollInterval: wire.poll_interval,
24
- };
25
- }
26
- export async function exchangeCliCode(client, sessionId, code, options = {}) {
27
- const requestBody = {
28
- session_id: sessionId,
29
- code,
30
- };
31
- if (options.codeVerifier) {
32
- requestBody.code_verifier = options.codeVerifier;
33
- }
34
- const wire = await client.postJson('/api/v1/cli-auth/exchange', requestBody);
35
- return {
36
- accessToken: wire.access_token,
37
- accessTokenExpiresIn: wire.access_token_expires_in,
38
- refreshToken: wire.refresh_token,
39
- refreshTokenExpiresIn: wire.refresh_token_expires_in,
40
- relayWsPath: wire.relay_ws_path,
41
- relayHeartbeatIntervalSec: wire.relay_heartbeat_interval_sec,
42
- };
43
- }
44
- //# sourceMappingURL=cli-auth-service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli-auth-service.js","sourceRoot":"","sources":["../../src/auth/cli-auth-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AA0DlD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAiB,EACjB,UAAuC,EAAE;IAEzC,MAAM,IAAI,GAA6B,EAAE,CAAC;IAC1C,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC;IAC1C,CAAC;IACD,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;QAChC,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAC9C,CAAC;IACD,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;QAC5C,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,mBAAmB,IAAI,MAAM,CAAC;IACrE,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAChC,0BAA0B,EAC1B,IAAI,CACL,CAAC;IACF,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,eAAe,EAAE,IAAI,CAAC,gBAAgB;QACtC,uBAAuB,EAAE,IAAI,CAAC,yBAAyB;QACvD,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,YAAY,EAAE,IAAI,CAAC,aAAa;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAiB,EACjB,SAAiB,EACjB,IAAY,EACZ,UAAqC,EAAE;IAEvC,MAAM,WAAW,GAAwB;QACvC,UAAU,EAAE,SAAS;QACrB,IAAI;KACL,CAAC;IACF,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,WAAW,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;IACnD,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAChC,2BAA2B,EAC3B,WAAW,CACZ,CAAC;IACF,OAAO;QACL,WAAW,EAAE,IAAI,CAAC,YAAY;QAC9B,oBAAoB,EAAE,IAAI,CAAC,uBAAuB;QAClD,YAAY,EAAE,IAAI,CAAC,aAAa;QAChC,qBAAqB,EAAE,IAAI,CAAC,wBAAwB;QACpD,WAAW,EAAE,IAAI,CAAC,aAAa;QAC/B,yBAAyB,EAAE,IAAI,CAAC,4BAA4B;KAC7D,CAAC;AACJ,CAAC"}
@@ -1,71 +0,0 @@
1
- import { CredentialsStore } from './credentials-store.js';
2
- import { buildSupabaseClient } from './supabase-client.js';
3
- import { getSupabaseAuthConfig } from './supabase-config.js';
4
- const EXPIRY_BUFFER_MS = 60_000; // refresh tokens one minute before expiry
5
- export async function ensureAuthContext(store, backendUrl) {
6
- const credentials = await store.load();
7
- if (!credentials) {
8
- throw new Error('No credentials found. Run `omnara auth login` first.');
9
- }
10
- if (!credentials.refreshToken) {
11
- throw new Error('Refresh token unavailable. Please run `omnara auth login`.');
12
- }
13
- if (!credentials.accessToken) {
14
- return await refreshWithStoredToken(store, credentials, backendUrl, 'No access token stored.');
15
- }
16
- if (!isExpiring(credentials.accessTokenExpiresAt, EXPIRY_BUFFER_MS)) {
17
- return { credentials, accessToken: credentials.accessToken };
18
- }
19
- return await refreshWithStoredToken(store, credentials, backendUrl, 'Access token expired.');
20
- }
21
- async function refreshWithStoredToken(store, credentials, backendUrl, reason) {
22
- const refreshToken = credentials.refreshToken;
23
- if (!refreshToken) {
24
- throw new Error(`${reason} Refresh token unavailable. Please run \`omnara auth login\`.`);
25
- }
26
- if (credentials.refreshTokenExpiresAt && isExpiring(credentials.refreshTokenExpiresAt, 0)) {
27
- throw new Error('Refresh token expired. Please run `omnara auth login`.');
28
- }
29
- const supabaseConfig = await getSupabaseAuthConfig(backendUrl);
30
- const supabase = buildSupabaseClient(supabaseConfig);
31
- const { data, error } = await supabase.auth.refreshSession({ refresh_token: refreshToken });
32
- if (error || !data?.session) {
33
- throw new Error(`${reason} Failed to refresh Supabase session: ${error?.message ?? 'unknown error'}.`);
34
- }
35
- const updated = applySession(credentials, data.session);
36
- await store.save(updated);
37
- if (!updated.accessToken) {
38
- throw new Error('Supabase refresh completed without an access token.');
39
- }
40
- return { credentials: updated, accessToken: updated.accessToken };
41
- }
42
- function isExpiring(expiresAtIso, bufferMs) {
43
- if (!expiresAtIso) {
44
- return true;
45
- }
46
- const timestamp = Date.parse(expiresAtIso);
47
- if (Number.isNaN(timestamp)) {
48
- return true;
49
- }
50
- return timestamp - bufferMs <= Date.now();
51
- }
52
- function applySession(credentials, session) {
53
- const expiresAt = deriveAccessExpiry(session);
54
- return {
55
- ...credentials,
56
- accessToken: session.access_token,
57
- accessTokenExpiresAt: expiresAt,
58
- refreshToken: session.refresh_token ?? credentials.refreshToken,
59
- refreshTokenExpiresAt: credentials.refreshTokenExpiresAt,
60
- };
61
- }
62
- function deriveAccessExpiry(session) {
63
- if (session.expires_at) {
64
- return new Date(session.expires_at * 1000).toISOString();
65
- }
66
- if (session.expires_in) {
67
- return new Date(Date.now() + session.expires_in * 1000).toISOString();
68
- }
69
- return undefined;
70
- }
71
- //# sourceMappingURL=credential-manager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"credential-manager.js","sourceRoot":"","sources":["../../src/auth/credential-manager.ts"],"names":[],"mappings":"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"}
@@ -1,69 +0,0 @@
1
- import fs from 'fs/promises';
2
- import os from 'os';
3
- import path from 'path';
4
- const DEFAULT_DIR = path.join(os.homedir(), '.omnara');
5
- export const DEFAULT_CREDENTIALS_PATH = path.join(DEFAULT_DIR, 'credentials.json');
6
- const DEFAULT_FILE_MODE = 0o600;
7
- const DEFAULT_DIR_MODE = 0o700;
8
- function isStoredCredentials(value) {
9
- return Boolean(value) && typeof value === 'object';
10
- }
11
- export class CredentialsStore {
12
- filePath;
13
- constructor(filePath = DEFAULT_CREDENTIALS_PATH) {
14
- this.filePath = filePath;
15
- }
16
- async load() {
17
- try {
18
- const raw = await fs.readFile(this.filePath, 'utf8');
19
- const parsed = JSON.parse(raw);
20
- if (!isStoredCredentials(parsed)) {
21
- throw new Error('File does not contain valid credentials data');
22
- }
23
- return parsed;
24
- }
25
- catch (error) {
26
- if (isFileNotFound(error)) {
27
- return null;
28
- }
29
- throw new Error(`Failed to read credentials from ${this.filePath}: ${extractErrorMessage(error)}`);
30
- }
31
- }
32
- async save(credentials) {
33
- const payload = {
34
- accessToken: credentials.accessToken,
35
- accessTokenExpiresAt: credentials.accessTokenExpiresAt,
36
- refreshToken: credentials.refreshToken,
37
- refreshTokenExpiresAt: credentials.refreshTokenExpiresAt,
38
- };
39
- await fs.mkdir(path.dirname(this.filePath), { recursive: true, mode: DEFAULT_DIR_MODE });
40
- const tempPath = `${this.filePath}.tmp`;
41
- const serialized = JSON.stringify(payload, null, 2);
42
- await fs.writeFile(tempPath, serialized, { mode: DEFAULT_FILE_MODE });
43
- await fs.chmod(tempPath, DEFAULT_FILE_MODE);
44
- await fs.rename(tempPath, this.filePath);
45
- }
46
- async clear() {
47
- try {
48
- await fs.unlink(this.filePath);
49
- }
50
- catch (error) {
51
- if (!isFileNotFound(error)) {
52
- throw new Error(`Failed to remove credentials file ${this.filePath}: ${extractErrorMessage(error)}`);
53
- }
54
- }
55
- }
56
- }
57
- function isFileNotFound(error) {
58
- return Boolean(error &&
59
- typeof error === 'object' &&
60
- 'code' in error &&
61
- error.code === 'ENOENT');
62
- }
63
- function extractErrorMessage(error) {
64
- if (error instanceof Error && error.message) {
65
- return error.message;
66
- }
67
- return String(error);
68
- }
69
- //# sourceMappingURL=credentials-store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"credentials-store.js","sourceRoot":"","sources":["../../src/auth/credentials-store.ts"],"names":[],"mappings":"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"}
@@ -1,196 +0,0 @@
1
- import { spawn } from 'child_process';
2
- import { ApiClient, ApiError, normalizeBaseUrl } from '../http/api-client.js';
3
- import { CredentialsStore } from './credentials-store.js';
4
- import { prompt } from '../utils/prompt.js';
5
- import { createCliAuthSession, exchangeCliCode, } from './cli-auth-service.js';
6
- import { generatePkcePair } from './pkce.js';
7
- import { LoopbackListener } from './loopback-listener.js';
8
- export async function performVerificationLogin({ backendUrlOption, frontendUrlOption, store, }) {
9
- const backendUrl = resolveBackendUrl(backendUrlOption);
10
- const frontendUrl = resolveFrontendUrl(frontendUrlOption);
11
- const client = new ApiClient({ baseUrl: backendUrl });
12
- console.log('\nAuthenticating CLI…');
13
- const loopback = await LoopbackListener.create();
14
- const pkce = loopback ? generatePkcePair() : null;
15
- const sessionOptions = {
16
- frontendUrl,
17
- };
18
- if (loopback && pkce) {
19
- sessionOptions.loopbackRedirectUri = loopback.redirectUri;
20
- sessionOptions.loopbackState = loopback.state;
21
- sessionOptions.pkceChallenge = pkce.challenge;
22
- sessionOptions.pkceChallengeMethod = pkce.method;
23
- }
24
- const session = await createCliAuthSession(client, sessionOptions);
25
- printSessionInstructions(session);
26
- tryOpenBrowser(session.verificationUriComplete);
27
- let completed = false;
28
- let successLogged = false;
29
- let latestCredentials = null;
30
- const completeLogin = async (code, codeVerifier) => {
31
- if (completed) {
32
- return;
33
- }
34
- const exchange = await exchangeCliCode(client, session.sessionId, code, codeVerifier ? { codeVerifier } : {});
35
- const updated = mergeCredentialsAfterExchange({
36
- exchange,
37
- });
38
- await store.save(updated);
39
- latestCredentials = updated;
40
- if (!successLogged) {
41
- console.log('\nLogin successful. Credentials saved.');
42
- successLogged = true;
43
- }
44
- completed = true;
45
- };
46
- const loopbackTask = loopback && pkce
47
- ? waitForLoopback(loopback, session.sessionId, async (code) => {
48
- await completeLogin(code, pkce.verifier);
49
- if (typeof process.stdin.emit === 'function') {
50
- process.stdin.emit('data', '\n');
51
- }
52
- })
53
- : null;
54
- if (!loopbackTask && !completed) {
55
- console.log('\nWaiting for approval in the browser…');
56
- }
57
- while (!completed) {
58
- const input = await prompt('\nFallback code if automatic login doesn\'t complete: ');
59
- const cleaned = input.trim();
60
- if (completed) {
61
- break;
62
- }
63
- if (!cleaned) {
64
- continue;
65
- }
66
- if (!/^[0-9]{6}$/.test(cleaned)) {
67
- console.log('Codes must be exactly six digits.');
68
- continue;
69
- }
70
- try {
71
- await completeLogin(cleaned);
72
- }
73
- catch (error) {
74
- if (error instanceof ApiError) {
75
- if (error.status === 401) {
76
- console.log('Code not recognized. Double-check the digits shown in the browser.');
77
- continue;
78
- }
79
- if (error.status === 409) {
80
- console.log('Browser approval already completed. Finishing up…');
81
- completed = true;
82
- break;
83
- }
84
- }
85
- await loopback?.stop();
86
- throw error;
87
- }
88
- }
89
- await loopback?.stop();
90
- if (!latestCredentials) {
91
- const stored = await store.load();
92
- if (stored) {
93
- latestCredentials = stored;
94
- }
95
- else {
96
- throw new Error('Login completed but credentials were not stored.');
97
- }
98
- }
99
- return latestCredentials;
100
- }
101
- const DEFAULT_BACKEND_URL = 'https://omnara-voice.onrender.com/';
102
- const DEFAULT_FRONTEND_URL = 'https://voice.omnara.com/';
103
- export function resolveBackendUrl(option) {
104
- const candidate = option ?? process.env.OMNARA_BACKEND_URL ?? DEFAULT_BACKEND_URL;
105
- return normalizeBaseUrl(candidate);
106
- }
107
- export function resolveFrontendUrl(option) {
108
- const candidate = option ?? process.env.OMNARA_FRONTEND_URL ?? DEFAULT_FRONTEND_URL;
109
- return normalizeBaseUrl(candidate);
110
- }
111
- export function mergeCredentialsAfterExchange(args) {
112
- const now = Date.now();
113
- const accessExpiresAt = new Date(now + args.exchange.accessTokenExpiresIn * 1000).toISOString();
114
- const refreshExpiresAt = new Date(now + args.exchange.refreshTokenExpiresIn * 1000).toISOString();
115
- return {
116
- accessToken: args.exchange.accessToken,
117
- accessTokenExpiresAt: accessExpiresAt,
118
- refreshToken: args.exchange.refreshToken,
119
- refreshTokenExpiresAt: refreshExpiresAt,
120
- };
121
- }
122
- export function formatDuration(ms) {
123
- const totalSeconds = Math.round(ms / 1000);
124
- if (totalSeconds < 60) {
125
- return `${totalSeconds}s`;
126
- }
127
- const totalMinutes = Math.round(totalSeconds / 60);
128
- if (totalMinutes < 60) {
129
- const seconds = totalSeconds % 60;
130
- return seconds > 0 ? `${totalMinutes}m ${seconds}s` : `${totalMinutes}m`;
131
- }
132
- const totalHours = Math.floor(totalMinutes / 60);
133
- const minutes = totalMinutes % 60;
134
- if (totalHours < 48) {
135
- return minutes > 0 ? `${totalHours}h ${minutes}m` : `${totalHours}h`;
136
- }
137
- const totalDays = Math.floor(totalHours / 24);
138
- const hours = totalDays % 24;
139
- return hours > 0 ? `${totalDays}d ${hours}h` : `${totalDays}d`;
140
- }
141
- function reportLoopbackError(error) {
142
- if (error instanceof ApiError) {
143
- console.log(`Automatic login failed (HTTP ${error.status}). Paste the 6-digit code shown in the browser.`);
144
- return;
145
- }
146
- console.log(`Automatic login failed: ${extractErrorMessage(error)}`);
147
- }
148
- function printSessionInstructions(session) {
149
- console.log('\nOpen this link in your browser if it did not open automatically:');
150
- console.log(` ${session.verificationUriComplete}`);
151
- console.log('Approve the request, then return to the CLI.');
152
- }
153
- function tryOpenBrowser(url) {
154
- const command = process.platform === 'darwin'
155
- ? 'open'
156
- : process.platform === 'win32'
157
- ? 'cmd'
158
- : 'xdg-open';
159
- const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
160
- try {
161
- const child = spawn(command, args, { stdio: 'ignore', detached: true });
162
- child.unref();
163
- }
164
- catch {
165
- // Ignore failures; user can open manually.
166
- }
167
- }
168
- function extractErrorMessage(error) {
169
- if (error instanceof Error && error.message) {
170
- return error.message;
171
- }
172
- return String(error);
173
- }
174
- async function waitForLoopback(listener, sessionId, onCode) {
175
- try {
176
- const callback = await listener.waitForCallback();
177
- if (callback.sessionId && callback.sessionId !== sessionId) {
178
- console.log('Received browser callback for a different session.');
179
- return;
180
- }
181
- if (callback.state && callback.state !== listener.state) {
182
- console.log('Received browser callback with unexpected state.');
183
- return;
184
- }
185
- try {
186
- await onCode(callback.code);
187
- }
188
- catch (error) {
189
- reportLoopbackError(error);
190
- }
191
- }
192
- catch (error) {
193
- console.log(`Loopback listener error: ${extractErrorMessage(error)}`);
194
- }
195
- }
196
- //# sourceMappingURL=login-flow.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"login-flow.js","sourceRoot":"","sources":["../../src/auth/login-flow.ts"],"names":[],"mappings":"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"}
@@ -1,155 +0,0 @@
1
- import http from 'http';
2
- import { randomBytes } from 'crypto';
3
- const CALLBACK_PATH = '/callback';
4
- const LISTEN_HOST = '127.0.0.1';
5
- export class LoopbackListener {
6
- static async create() {
7
- const listener = new LoopbackListener(generateState());
8
- try {
9
- await listener.start();
10
- return listener;
11
- }
12
- catch {
13
- await listener.stop().catch(() => undefined);
14
- return null;
15
- }
16
- }
17
- state;
18
- redirectUri;
19
- server;
20
- resolveCallback = null;
21
- rejectCallback = null;
22
- pending = null;
23
- constructor(state) {
24
- this.state = state;
25
- this.redirectUri = '';
26
- this.server = http.createServer((request, response) => {
27
- void this.handleRequest(request, response);
28
- });
29
- }
30
- async waitForCallback() {
31
- if (this.pending) {
32
- return this.pending;
33
- }
34
- this.pending = new Promise((resolve, reject) => {
35
- this.resolveCallback = resolve;
36
- this.rejectCallback = reject;
37
- });
38
- return this.pending;
39
- }
40
- async stop() {
41
- if (!this.server.listening) {
42
- return;
43
- }
44
- await new Promise((resolve) => {
45
- this.server.close(() => resolve());
46
- });
47
- }
48
- async start() {
49
- await new Promise((resolve, reject) => {
50
- this.server.once('error', reject);
51
- this.server.listen(0, LISTEN_HOST, () => {
52
- this.server.removeListener('error', reject);
53
- resolve();
54
- });
55
- });
56
- const address = this.server.address();
57
- if (!address || typeof address === 'string') {
58
- throw new Error('Loopback listener failed to bind');
59
- }
60
- const { port } = address;
61
- this.redirectUri = `http://${LISTEN_HOST}:${port}${CALLBACK_PATH}`;
62
- }
63
- async handleRequest(request, response) {
64
- if (request.method !== 'GET' || !request.url) {
65
- this.respond(response, 405, 'Method Not Allowed');
66
- return;
67
- }
68
- const url = new URL(request.url, `http://${request.headers.host ?? LISTEN_HOST}`);
69
- if (url.pathname !== CALLBACK_PATH) {
70
- this.respond(response, 404, 'Not Found');
71
- return;
72
- }
73
- const code = url.searchParams.get('code');
74
- const sessionId = url.searchParams.get('session');
75
- const state = url.searchParams.get('state');
76
- if (!code) {
77
- this.respond(response, 400, buildMessageHtml('Missing authorization code. Return to your CLI and try again.'));
78
- return;
79
- }
80
- this.respond(response, 200, buildSuccessHtml());
81
- if (this.resolveCallback) {
82
- this.resolveCallback({ code, sessionId, state });
83
- this.resolveCallback = null;
84
- this.rejectCallback = null;
85
- }
86
- void this.stop();
87
- }
88
- respond(response, status, body) {
89
- response.writeHead(status, {
90
- 'content-type': 'text/html; charset=utf-8',
91
- 'cache-control': 'no-store',
92
- });
93
- response.end(body);
94
- }
95
- }
96
- function buildSuccessHtml() {
97
- const redirectTarget = 'https://voice.omnara.com/dashboard';
98
- return `<!doctype html>
99
- <html lang="en">
100
- <head>
101
- <meta charset="utf-8" />
102
- <meta name="viewport" content="width=device-width,initial-scale=1" />
103
- <meta http-equiv="refresh" content="3;url=${redirectTarget}" />
104
- <title>Omnara CLI Login</title>
105
- <style>
106
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #090909; color: #f4f4f5; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; }
107
- .card { max-width: 420px; padding: 2.5rem; background: rgba(32, 32, 36, 0.85); border-radius: 14px; box-shadow: 0 20px 40px rgba(0,0,0,0.35); text-align: center; }
108
- h1 { font-size: 1.5rem; margin-bottom: 0.75rem; }
109
- p { margin: 0 0 0.75rem; line-height: 1.5; }
110
- .note { font-size: 0.85rem; color: rgba(244,244,245,0.7); }
111
- </style>
112
- </head>
113
- <body>
114
- <div class="card">
115
- <h1>Redirecting back to the CLI…</h1>
116
- <p>Your authentication details were sent to the Omnara CLI. Return to your terminal to continue.</p>
117
- <p class="note">If this page doesn't close automatically, you can manually open the Omnara dashboard.</p>
118
- </div>
119
- </body>
120
- </html>`;
121
- }
122
- function generateState() {
123
- return base64UrlEncode(randomBytes(32));
124
- }
125
- function base64UrlEncode(input) {
126
- const buffer = typeof input === 'string' ? Buffer.from(input, 'utf8') : Buffer.from(input);
127
- return buffer
128
- .toString('base64')
129
- .replace(/\+/g, '-')
130
- .replace(/\//g, '_')
131
- .replace(/=+$/g, '');
132
- }
133
- function buildMessageHtml(message) {
134
- return `<!doctype html>
135
- <html lang="en">
136
- <head>
137
- <meta charset="utf-8" />
138
- <meta name="viewport" content="width=device-width,initial-scale=1" />
139
- <title>Omnara CLI Login</title>
140
- <style>
141
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #090909; color: #f4f4f5; display: flex; align-items: center; justify-content: center; min-height: 100vh; margin: 0; }
142
- .card { max-width: 420px; padding: 2.5rem; background: rgba(32, 32, 36, 0.85); border-radius: 14px; box-shadow: 0 20px 40px rgba(0,0,0,0.35); text-align: center; }
143
- h1 { font-size: 1.4rem; margin-bottom: 0.75rem; }
144
- p { margin: 0; line-height: 1.6; }
145
- </style>
146
- </head>
147
- <body>
148
- <div class="card">
149
- <h1>Omnara CLI Login</h1>
150
- <p>${message}</p>
151
- </div>
152
- </body>
153
- </html>`;
154
- }
155
- //# sourceMappingURL=loopback-listener.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"loopback-listener.js","sourceRoot":"","sources":["../../src/auth/loopback-listener.ts"],"names":[],"mappings":"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"}
package/dist/auth/pkce.js DELETED
@@ -1,15 +0,0 @@
1
- import { createHash, randomBytes } from 'crypto';
2
- export function generatePkcePair() {
3
- const verifier = base64UrlEncode(randomBytes(32));
4
- const challenge = base64UrlEncode(createHash('sha256').update(verifier).digest());
5
- return { verifier, challenge, method: 'S256' };
6
- }
7
- function base64UrlEncode(input) {
8
- const buffer = typeof input === 'string' ? Buffer.from(input, 'utf8') : Buffer.from(input);
9
- return buffer
10
- .toString('base64')
11
- .replace(/\+/g, '-')
12
- .replace(/\//g, '_')
13
- .replace(/=+$/g, '');
14
- }
15
- //# sourceMappingURL=pkce.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/auth/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAQjD,MAAM,UAAU,gBAAgB;IAC9B,MAAM,QAAQ,GAAG,eAAe,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAClF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,eAAe,CAAC,KAAmC;IAC1D,MAAM,MAAM,GACV,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAA4B,CAAC,CAAC;IACrG,OAAO,MAAM;SACV,QAAQ,CAAC,QAAQ,CAAC;SAClB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;SACnB,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC"}
@@ -1,10 +0,0 @@
1
- import { createClient } from '@supabase/supabase-js';
2
- export function buildSupabaseClient(config) {
3
- return createClient(config.url, config.anonKey, {
4
- auth: {
5
- persistSession: false,
6
- detectSessionInUrl: false,
7
- },
8
- });
9
- }
10
- //# sourceMappingURL=supabase-client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"supabase-client.js","sourceRoot":"","sources":["../../src/auth/supabase-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,uBAAuB,CAAC;AAI1E,MAAM,UAAU,mBAAmB,CAAC,MAA0B;IAC5D,OAAO,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,OAAO,EAAE;QAC9C,IAAI,EAAE;YACJ,cAAc,EAAE,KAAK;YACrB,kBAAkB,EAAE,KAAK;SAC1B;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -1,21 +0,0 @@
1
- import { ApiClient } from '../http/api-client.js';
2
- const CACHE = new Map();
3
- export async function getSupabaseAuthConfig(baseUrl) {
4
- const normalized = normalizeBaseUrl(baseUrl);
5
- const cached = CACHE.get(normalized);
6
- if (cached) {
7
- return cached;
8
- }
9
- const client = new ApiClient({ baseUrl: normalized });
10
- const response = await client.getJson('/api/v1/auth/config');
11
- const config = {
12
- url: response.supabase_url,
13
- anonKey: response.supabase_anon_key,
14
- };
15
- CACHE.set(normalized, config);
16
- return config;
17
- }
18
- function normalizeBaseUrl(raw) {
19
- return raw.endsWith('/') ? raw : `${raw}/`;
20
- }
21
- //# sourceMappingURL=supabase-config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"supabase-config.js","sourceRoot":"","sources":["../../src/auth/supabase-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAYlD,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAe;IACzD,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACrC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAyB,qBAAqB,CAAC,CAAC;IACrF,MAAM,MAAM,GAAuB;QACjC,GAAG,EAAE,QAAQ,CAAC,YAAY;QAC1B,OAAO,EAAE,QAAQ,CAAC,iBAAiB;KACpC,CAAC;IACF,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACnC,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;AAC7C,CAAC"}