omnara 0.1.0

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 (111) hide show
  1. package/README.md +20 -0
  2. package/bin/omnara.js +16 -0
  3. package/dist/auth/auth-provider.d.ts +18 -0
  4. package/dist/auth/auth-provider.js +58 -0
  5. package/dist/auth/auth-provider.js.map +1 -0
  6. package/dist/auth/cli-auth-service.d.ts +18 -0
  7. package/dist/auth/cli-auth-service.js +30 -0
  8. package/dist/auth/cli-auth-service.js.map +1 -0
  9. package/dist/auth/credential-manager.d.ts +6 -0
  10. package/dist/auth/credential-manager.js +73 -0
  11. package/dist/auth/credential-manager.js.map +1 -0
  12. package/dist/auth/credentials-store.d.ts +14 -0
  13. package/dist/auth/credentials-store.js +75 -0
  14. package/dist/auth/credentials-store.js.map +1 -0
  15. package/dist/auth/login-flow.d.ts +15 -0
  16. package/dist/auth/login-flow.js +107 -0
  17. package/dist/auth/login-flow.js.map +1 -0
  18. package/dist/auth/supabase-client.d.ts +3 -0
  19. package/dist/auth/supabase-client.js +13 -0
  20. package/dist/auth/supabase-client.js.map +1 -0
  21. package/dist/auth/supabase-config.d.ts +5 -0
  22. package/dist/auth/supabase-config.js +24 -0
  23. package/dist/auth/supabase-config.js.map +1 -0
  24. package/dist/cli.d.ts +3 -0
  25. package/dist/cli.js +53 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/commands/agent.d.ts +7 -0
  28. package/dist/commands/agent.js +174 -0
  29. package/dist/commands/agent.js.map +1 -0
  30. package/dist/commands/auth.d.ts +2 -0
  31. package/dist/commands/auth.js +87 -0
  32. package/dist/commands/auth.js.map +1 -0
  33. package/dist/commands/hello.d.ts +2 -0
  34. package/dist/commands/hello.js +12 -0
  35. package/dist/commands/hello.js.map +1 -0
  36. package/dist/commands/index.d.ts +2 -0
  37. package/dist/commands/index.js +9 -0
  38. package/dist/commands/index.js.map +1 -0
  39. package/dist/generated/relay.d.ts +240 -0
  40. package/dist/generated/relay.js +2376 -0
  41. package/dist/generated/relay.js.map +1 -0
  42. package/dist/http/api-client.d.ts +24 -0
  43. package/dist/http/api-client.js +122 -0
  44. package/dist/http/api-client.js.map +1 -0
  45. package/dist/messaging/proto-codec.d.ts +5 -0
  46. package/dist/messaging/proto-codec.js +387 -0
  47. package/dist/messaging/proto-codec.js.map +1 -0
  48. package/dist/orchestrator/agent-orchestrator.d.ts +57 -0
  49. package/dist/orchestrator/agent-orchestrator.js +401 -0
  50. package/dist/orchestrator/agent-orchestrator.js.map +1 -0
  51. package/dist/orchestrator/ai-client.d.ts +16 -0
  52. package/dist/orchestrator/ai-client.js +74 -0
  53. package/dist/orchestrator/ai-client.js.map +1 -0
  54. package/dist/orchestrator/session.d.ts +37 -0
  55. package/dist/orchestrator/session.js +260 -0
  56. package/dist/orchestrator/session.js.map +1 -0
  57. package/dist/orchestrator/tools/worker-tools.d.ts +7 -0
  58. package/dist/orchestrator/tools/worker-tools.js +58 -0
  59. package/dist/orchestrator/tools/worker-tools.js.map +1 -0
  60. package/dist/orchestrator/types.d.ts +140 -0
  61. package/dist/orchestrator/types.js +33 -0
  62. package/dist/orchestrator/types.js.map +1 -0
  63. package/dist/orchestrator/utils/session-logger.d.ts +7 -0
  64. package/dist/orchestrator/utils/session-logger.js +53 -0
  65. package/dist/orchestrator/utils/session-logger.js.map +1 -0
  66. package/dist/orchestrator/worker-manager.d.ts +65 -0
  67. package/dist/orchestrator/worker-manager.js +241 -0
  68. package/dist/orchestrator/worker-manager.js.map +1 -0
  69. package/dist/relay/relay-bridge.d.ts +35 -0
  70. package/dist/relay/relay-bridge.js +306 -0
  71. package/dist/relay/relay-bridge.js.map +1 -0
  72. package/dist/relay/relay-service.d.ts +20 -0
  73. package/dist/relay/relay-service.js +28 -0
  74. package/dist/relay/relay-service.js.map +1 -0
  75. package/dist/repl/terminal-repl.d.ts +9 -0
  76. package/dist/repl/terminal-repl.js +258 -0
  77. package/dist/repl/terminal-repl.js.map +1 -0
  78. package/dist/server/agent-server.d.ts +46 -0
  79. package/dist/server/agent-server.js +429 -0
  80. package/dist/server/agent-server.js.map +1 -0
  81. package/dist/server/ai-client.d.ts +16 -0
  82. package/dist/server/ai-client.js +74 -0
  83. package/dist/server/ai-client.js.map +1 -0
  84. package/dist/server/session.d.ts +35 -0
  85. package/dist/server/session.js +272 -0
  86. package/dist/server/session.js.map +1 -0
  87. package/dist/server/subagents.d.ts +19 -0
  88. package/dist/server/subagents.js +42 -0
  89. package/dist/server/subagents.js.map +1 -0
  90. package/dist/server/tools/worker-tools.d.ts +2 -0
  91. package/dist/server/tools/worker-tools.js +37 -0
  92. package/dist/server/tools/worker-tools.js.map +1 -0
  93. package/dist/server/types.d.ts +120 -0
  94. package/dist/server/types.js +29 -0
  95. package/dist/server/types.js.map +1 -0
  96. package/dist/server/utils/session-logger.d.ts +7 -0
  97. package/dist/server/utils/session-logger.js +53 -0
  98. package/dist/server/utils/session-logger.js.map +1 -0
  99. package/dist/server/worker-manager.d.ts +67 -0
  100. package/dist/server/worker-manager.js +207 -0
  101. package/dist/server/worker-manager.js.map +1 -0
  102. package/dist/test-agent.d.ts +1 -0
  103. package/dist/test-agent.js +63 -0
  104. package/dist/test-agent.js.map +1 -0
  105. package/dist/utils/prompt.d.ts +1 -0
  106. package/dist/utils/prompt.js +19 -0
  107. package/dist/utils/prompt.js.map +1 -0
  108. package/dist/voice/voice-service.d.ts +19 -0
  109. package/dist/voice/voice-service.js +27 -0
  110. package/dist/voice/voice-service.js.map +1 -0
  111. package/package.json +58 -0
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # Omnara CLI
2
+
3
+ The Omnara CLI launches a coding agent that streams its activity to your Omnara dashboard at [omnara.com](https://omnara.com). Sign in once, start the orchestrator from your terminal, and follow along (or respond) from the web or mobile apps. You can also attach a real-time voice worker to any active session.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npm install -g omnara
9
+
10
+ # Start the synced coding agent experience
11
+ omnara
12
+ ```
13
+
14
+ Running `omnara` bootstraps the agent orchestrator. The first launch prompts you to authenticate in the browser; after that the CLI reconnects automatically.
15
+
16
+ ## Helpful Commands
17
+
18
+ - `omnara auth login|status|logout` — manage the cached Omnara credentials used by the CLI.
19
+ - `omnara agent voice --session-id <id>` — invite the Omnara voice worker into an existing agent session so you can talk to your coder in real time.
20
+ - `omnara agent orchestrator` — launch the orchestrator explicitly when scripting or running in headless environments.
package/bin/omnara.js ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+
6
+ const distEntry = path.join(__dirname, '..', 'dist', 'cli.js');
7
+
8
+ if (!fs.existsSync(distEntry)) {
9
+ console.error(
10
+ 'Could not find the compiled CLI at dist/cli.js. ' +
11
+ 'Run `npm install` followed by `npm run build` inside the omnara package.',
12
+ );
13
+ process.exit(1);
14
+ }
15
+
16
+ require(distEntry);
@@ -0,0 +1,18 @@
1
+ import { CredentialsStore } from './credentials-store';
2
+ import { type AuthContext } from './credential-manager';
3
+ export interface AuthProviderOptions {
4
+ store: CredentialsStore;
5
+ backendUrl: string;
6
+ frontendUrl?: string;
7
+ logger?: Console;
8
+ }
9
+ export declare class AuthProvider {
10
+ private readonly options;
11
+ private cached;
12
+ private readonly backendUrl;
13
+ constructor(options: AuthProviderOptions);
14
+ getAuthContext(): Promise<AuthContext>;
15
+ getAccessToken(): Promise<string>;
16
+ private loadAuthContext;
17
+ }
18
+ export declare function createAuthProvider(options: AuthProviderOptions): Promise<AuthProvider>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuthProvider = void 0;
4
+ exports.createAuthProvider = createAuthProvider;
5
+ const credential_manager_1 = require("./credential-manager");
6
+ const login_flow_1 = require("./login-flow");
7
+ const api_client_1 = require("../http/api-client");
8
+ class AuthProvider {
9
+ constructor(options) {
10
+ this.options = options;
11
+ this.cached = null;
12
+ this.backendUrl = (0, api_client_1.normalizeBaseUrl)(options.backendUrl);
13
+ }
14
+ async getAuthContext() {
15
+ const auth = await this.loadAuthContext();
16
+ this.cached = auth;
17
+ return auth;
18
+ }
19
+ async getAccessToken() {
20
+ const auth = await this.getAuthContext();
21
+ return auth.accessToken;
22
+ }
23
+ async loadAuthContext() {
24
+ try {
25
+ return await (0, credential_manager_1.ensureAuthContext)(this.options.store, this.backendUrl);
26
+ }
27
+ catch (error) {
28
+ if (!shouldAttemptLogin(error)) {
29
+ throw error;
30
+ }
31
+ this.options.logger?.log('CLI login required. Opening browser flow…');
32
+ await (0, login_flow_1.performVerificationLogin)({
33
+ backendUrlOption: this.backendUrl,
34
+ frontendUrlOption: this.options.frontendUrl,
35
+ store: this.options.store,
36
+ });
37
+ return await (0, credential_manager_1.ensureAuthContext)(this.options.store, this.backendUrl);
38
+ }
39
+ }
40
+ }
41
+ exports.AuthProvider = AuthProvider;
42
+ function shouldAttemptLogin(error) {
43
+ if (!(error instanceof Error)) {
44
+ return false;
45
+ }
46
+ const message = error.message.toLowerCase();
47
+ return (message.includes('no credentials found') ||
48
+ message.includes('run `omnara auth login` first') ||
49
+ message.includes('refresh token expired') ||
50
+ message.includes('refresh token unavailable') ||
51
+ message.includes('access token expired'));
52
+ }
53
+ async function createAuthProvider(options) {
54
+ const provider = new AuthProvider(options);
55
+ await provider.getAuthContext();
56
+ return provider;
57
+ }
58
+ //# sourceMappingURL=auth-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-provider.js","sourceRoot":"","sources":["../../src/auth/auth-provider.ts"],"names":[],"mappings":";;;AAiEA,gDAIC;AAlED,6DAA2E;AAC3E,6CAAwD;AACxD,mDAAsD;AAStD,MAAa,YAAY;IAIvB,YAA6B,OAA4B;QAA5B,YAAO,GAAP,OAAO,CAAqB;QAHjD,WAAM,GAAuB,IAAI,CAAC;QAIxC,IAAI,CAAC,UAAU,GAAG,IAAA,6BAAgB,EAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QACzC,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,eAAe;QAC3B,IAAI,CAAC;YACH,OAAO,MAAM,IAAA,sCAAiB,EAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACtE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/B,MAAM,KAAK,CAAC;YACd,CAAC;YACD,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,2CAA2C,CAAC,CAAC;YACtE,MAAM,IAAA,qCAAwB,EAAC;gBAC7B,gBAAgB,EAAE,IAAI,CAAC,UAAU;gBACjC,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;gBAC3C,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK;aAC1B,CAAC,CAAC;YACH,OAAO,MAAM,IAAA,sCAAiB,EAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;CACF;AAnCD,oCAmCC;AAED,SAAS,kBAAkB,CAAC,KAAc;IACxC,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,CACL,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;QACxC,OAAO,CAAC,QAAQ,CAAC,+BAA+B,CAAC;QACjD,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAC;QACzC,OAAO,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QAC7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CACzC,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,kBAAkB,CAAC,OAA4B;IACnE,MAAM,QAAQ,GAAG,IAAI,YAAY,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,QAAQ,CAAC,cAAc,EAAE,CAAC;IAChC,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { ApiClient } from '../http/api-client';
2
+ export interface CliAuthSession {
3
+ sessionId: string;
4
+ verificationUri: string;
5
+ verificationUriComplete: string;
6
+ expiresIn: number;
7
+ pollInterval: number;
8
+ }
9
+ export interface ExchangeCliCodeResult {
10
+ accessToken: string;
11
+ accessTokenExpiresIn: number;
12
+ refreshToken: string;
13
+ refreshTokenExpiresIn: number;
14
+ relayWsPath: string;
15
+ relayHeartbeatIntervalSec: number;
16
+ }
17
+ export declare function createCliAuthSession(client: ApiClient, frontendUrl?: string): Promise<CliAuthSession>;
18
+ export declare function exchangeCliCode(client: ApiClient, sessionId: string, code: string): Promise<ExchangeCliCodeResult>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCliAuthSession = createCliAuthSession;
4
+ exports.exchangeCliCode = exchangeCliCode;
5
+ async function createCliAuthSession(client, frontendUrl) {
6
+ const body = frontendUrl ? { frontend_url: frontendUrl } : {};
7
+ const wire = await client.postJson('/api/v1/cli-auth/session', body);
8
+ return {
9
+ sessionId: wire.session_id,
10
+ verificationUri: wire.verification_uri,
11
+ verificationUriComplete: wire.verification_uri_complete,
12
+ expiresIn: wire.expires_in,
13
+ pollInterval: wire.poll_interval,
14
+ };
15
+ }
16
+ async function exchangeCliCode(client, sessionId, code) {
17
+ const wire = await client.postJson('/api/v1/cli-auth/exchange', {
18
+ session_id: sessionId,
19
+ code,
20
+ });
21
+ return {
22
+ accessToken: wire.access_token,
23
+ accessTokenExpiresIn: wire.access_token_expires_in,
24
+ refreshToken: wire.refresh_token,
25
+ refreshTokenExpiresIn: wire.refresh_token_expires_in,
26
+ relayWsPath: wire.relay_ws_path,
27
+ relayHeartbeatIntervalSec: wire.relay_heartbeat_interval_sec,
28
+ };
29
+ }
30
+ //# sourceMappingURL=cli-auth-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-auth-service.js","sourceRoot":"","sources":["../../src/auth/cli-auth-service.ts"],"names":[],"mappings":";;AA6CA,oDAgBC;AAED,0CAoBC;AAtCM,KAAK,UAAU,oBAAoB,CACxC,MAAiB,EACjB,WAAoB;IAEpB,MAAM,IAAI,GAA6B,WAAW,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxF,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;AAEM,KAAK,UAAU,eAAe,CACnC,MAAiB,EACjB,SAAiB,EACjB,IAAY;IAEZ,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,QAAQ,CAChC,2BAA2B,EAC3B;QACE,UAAU,EAAE,SAAS;QACrB,IAAI;KACL,CACF,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"}
@@ -0,0 +1,6 @@
1
+ import { CredentialsStore, type StoredCredentials } from './credentials-store';
2
+ export interface AuthContext {
3
+ credentials: StoredCredentials;
4
+ accessToken: string;
5
+ }
6
+ export declare function ensureAuthContext(store: CredentialsStore, backendUrl: string): Promise<AuthContext>;
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureAuthContext = ensureAuthContext;
4
+ const supabase_client_1 = require("./supabase-client");
5
+ const supabase_config_1 = require("./supabase-config");
6
+ const EXPIRY_BUFFER_MS = 60000; // refresh tokens one minute before expiry
7
+ async function ensureAuthContext(store, backendUrl) {
8
+ const credentials = await store.load();
9
+ if (!credentials) {
10
+ throw new Error('No credentials found. Run `omnara auth login` first.');
11
+ }
12
+ if (!credentials.refreshToken) {
13
+ throw new Error('Refresh token unavailable. Please run `omnara auth login`.');
14
+ }
15
+ if (!credentials.accessToken) {
16
+ return await refreshWithStoredToken(store, credentials, backendUrl, 'No access token stored.');
17
+ }
18
+ if (!isExpiring(credentials.accessTokenExpiresAt, EXPIRY_BUFFER_MS)) {
19
+ return { credentials, accessToken: credentials.accessToken };
20
+ }
21
+ return await refreshWithStoredToken(store, credentials, backendUrl, 'Access token expired.');
22
+ }
23
+ async function refreshWithStoredToken(store, credentials, backendUrl, reason) {
24
+ const refreshToken = credentials.refreshToken;
25
+ if (!refreshToken) {
26
+ throw new Error(`${reason} Refresh token unavailable. Please run \`omnara auth login\`.`);
27
+ }
28
+ if (credentials.refreshTokenExpiresAt && isExpiring(credentials.refreshTokenExpiresAt, 0)) {
29
+ throw new Error('Refresh token expired. Please run `omnara auth login`.');
30
+ }
31
+ const supabaseConfig = await (0, supabase_config_1.getSupabaseAuthConfig)(backendUrl);
32
+ const supabase = (0, supabase_client_1.buildSupabaseClient)(supabaseConfig);
33
+ const { data, error } = await supabase.auth.refreshSession({ refresh_token: refreshToken });
34
+ if (error || !data?.session) {
35
+ throw new Error(`${reason} Failed to refresh Supabase session: ${error?.message ?? 'unknown error'}.`);
36
+ }
37
+ const updated = applySession(credentials, data.session);
38
+ await store.save(updated);
39
+ if (!updated.accessToken) {
40
+ throw new Error('Supabase refresh completed without an access token.');
41
+ }
42
+ return { credentials: updated, accessToken: updated.accessToken };
43
+ }
44
+ function isExpiring(expiresAtIso, bufferMs) {
45
+ if (!expiresAtIso) {
46
+ return true;
47
+ }
48
+ const timestamp = Date.parse(expiresAtIso);
49
+ if (Number.isNaN(timestamp)) {
50
+ return true;
51
+ }
52
+ return timestamp - bufferMs <= Date.now();
53
+ }
54
+ function applySession(credentials, session) {
55
+ const expiresAt = deriveAccessExpiry(session);
56
+ return {
57
+ ...credentials,
58
+ accessToken: session.access_token,
59
+ accessTokenExpiresAt: expiresAt,
60
+ refreshToken: session.refresh_token ?? credentials.refreshToken,
61
+ refreshTokenExpiresAt: credentials.refreshTokenExpiresAt,
62
+ };
63
+ }
64
+ function deriveAccessExpiry(session) {
65
+ if (session.expires_at) {
66
+ return new Date(session.expires_at * 1000).toISOString();
67
+ }
68
+ if (session.expires_in) {
69
+ return new Date(Date.now() + session.expires_in * 1000).toISOString();
70
+ }
71
+ return undefined;
72
+ }
73
+ //# sourceMappingURL=credential-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-manager.js","sourceRoot":"","sources":["../../src/auth/credential-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface StoredCredentials {
2
+ accessToken?: string;
3
+ accessTokenExpiresAt?: string;
4
+ refreshToken?: string;
5
+ refreshTokenExpiresAt?: string;
6
+ }
7
+ export declare const DEFAULT_CREDENTIALS_PATH: string;
8
+ export declare class CredentialsStore {
9
+ private readonly filePath;
10
+ constructor(filePath?: string);
11
+ load(): Promise<StoredCredentials | null>;
12
+ save(credentials: StoredCredentials): Promise<void>;
13
+ clear(): Promise<void>;
14
+ }
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CredentialsStore = exports.DEFAULT_CREDENTIALS_PATH = void 0;
7
+ const promises_1 = __importDefault(require("fs/promises"));
8
+ const os_1 = __importDefault(require("os"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const DEFAULT_DIR = path_1.default.join(os_1.default.homedir(), '.omnara');
11
+ exports.DEFAULT_CREDENTIALS_PATH = path_1.default.join(DEFAULT_DIR, 'credentials.json');
12
+ const DEFAULT_FILE_MODE = 0o600;
13
+ const DEFAULT_DIR_MODE = 0o700;
14
+ function isStoredCredentials(value) {
15
+ return Boolean(value) && typeof value === 'object';
16
+ }
17
+ class CredentialsStore {
18
+ constructor(filePath = exports.DEFAULT_CREDENTIALS_PATH) {
19
+ this.filePath = filePath;
20
+ }
21
+ async load() {
22
+ try {
23
+ const raw = await promises_1.default.readFile(this.filePath, 'utf8');
24
+ const parsed = JSON.parse(raw);
25
+ if (!isStoredCredentials(parsed)) {
26
+ throw new Error('File does not contain valid credentials data');
27
+ }
28
+ return parsed;
29
+ }
30
+ catch (error) {
31
+ if (isFileNotFound(error)) {
32
+ return null;
33
+ }
34
+ throw new Error(`Failed to read credentials from ${this.filePath}: ${extractErrorMessage(error)}`);
35
+ }
36
+ }
37
+ async save(credentials) {
38
+ const payload = {
39
+ accessToken: credentials.accessToken,
40
+ accessTokenExpiresAt: credentials.accessTokenExpiresAt,
41
+ refreshToken: credentials.refreshToken,
42
+ refreshTokenExpiresAt: credentials.refreshTokenExpiresAt,
43
+ };
44
+ await promises_1.default.mkdir(path_1.default.dirname(this.filePath), { recursive: true, mode: DEFAULT_DIR_MODE });
45
+ const tempPath = `${this.filePath}.tmp`;
46
+ const serialized = JSON.stringify(payload, null, 2);
47
+ await promises_1.default.writeFile(tempPath, serialized, { mode: DEFAULT_FILE_MODE });
48
+ await promises_1.default.chmod(tempPath, DEFAULT_FILE_MODE);
49
+ await promises_1.default.rename(tempPath, this.filePath);
50
+ }
51
+ async clear() {
52
+ try {
53
+ await promises_1.default.unlink(this.filePath);
54
+ }
55
+ catch (error) {
56
+ if (!isFileNotFound(error)) {
57
+ throw new Error(`Failed to remove credentials file ${this.filePath}: ${extractErrorMessage(error)}`);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ exports.CredentialsStore = CredentialsStore;
63
+ function isFileNotFound(error) {
64
+ return Boolean(error &&
65
+ typeof error === 'object' &&
66
+ 'code' in error &&
67
+ error.code === 'ENOENT');
68
+ }
69
+ function extractErrorMessage(error) {
70
+ if (error instanceof Error && error.message) {
71
+ return error.message;
72
+ }
73
+ return String(error);
74
+ }
75
+ //# sourceMappingURL=credentials-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials-store.js","sourceRoot":"","sources":["../../src/auth/credentials-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { CredentialsStore, type StoredCredentials } from './credentials-store';
2
+ import { type ExchangeCliCodeResult } from './cli-auth-service';
3
+ interface LoginOptions {
4
+ backendUrlOption?: string;
5
+ frontendUrlOption?: string;
6
+ store: CredentialsStore;
7
+ }
8
+ export declare function performVerificationLogin({ backendUrlOption, frontendUrlOption, store, }: LoginOptions): Promise<StoredCredentials>;
9
+ export declare function resolveBackendUrl(option?: string): string;
10
+ export declare function resolveFrontendUrl(option?: string): string;
11
+ export declare function mergeCredentialsAfterExchange(args: {
12
+ exchange: ExchangeCliCodeResult;
13
+ }): StoredCredentials;
14
+ export declare function formatDuration(ms: number): string;
15
+ export {};
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.performVerificationLogin = performVerificationLogin;
4
+ exports.resolveBackendUrl = resolveBackendUrl;
5
+ exports.resolveFrontendUrl = resolveFrontendUrl;
6
+ exports.mergeCredentialsAfterExchange = mergeCredentialsAfterExchange;
7
+ exports.formatDuration = formatDuration;
8
+ const child_process_1 = require("child_process");
9
+ const api_client_1 = require("../http/api-client");
10
+ const prompt_1 = require("../utils/prompt");
11
+ const cli_auth_service_1 = require("./cli-auth-service");
12
+ async function performVerificationLogin({ backendUrlOption, frontendUrlOption, store, }) {
13
+ const backendUrl = resolveBackendUrl(backendUrlOption);
14
+ const frontendUrl = resolveFrontendUrl(frontendUrlOption);
15
+ const client = new api_client_1.ApiClient({ baseUrl: backendUrl });
16
+ console.log('\nAuthentication required. Launching browser flow…');
17
+ const session = await (0, cli_auth_service_1.createCliAuthSession)(client, frontendUrl);
18
+ printSessionInstructions(session);
19
+ tryOpenBrowser(session.verificationUriComplete);
20
+ while (true) {
21
+ const input = await (0, prompt_1.prompt)('\nEnter the 6-digit verification code: ');
22
+ const cleaned = input.trim();
23
+ if (!/^[0-9]{6}$/.test(cleaned)) {
24
+ console.log('Codes must be exactly six digits.');
25
+ continue;
26
+ }
27
+ try {
28
+ const exchange = await (0, cli_auth_service_1.exchangeCliCode)(client, session.sessionId, cleaned);
29
+ const updated = mergeCredentialsAfterExchange({
30
+ exchange,
31
+ });
32
+ await store.save(updated);
33
+ console.log('\nLogin successful. Credentials saved.');
34
+ return updated;
35
+ }
36
+ catch (error) {
37
+ if (error instanceof api_client_1.ApiError && error.status === 401) {
38
+ console.log('That code was not recognized. Paste the code shown in the browser.');
39
+ continue;
40
+ }
41
+ throw error;
42
+ }
43
+ }
44
+ }
45
+ const DEFAULT_BACKEND_URL = 'https://omnara-voice.onrender.com/';
46
+ const DEFAULT_FRONTEND_URL = 'https://voice.omnara.com/';
47
+ function resolveBackendUrl(option) {
48
+ const candidate = option ?? process.env.OMNARA_BACKEND_URL ?? DEFAULT_BACKEND_URL;
49
+ return (0, api_client_1.normalizeBaseUrl)(candidate);
50
+ }
51
+ function resolveFrontendUrl(option) {
52
+ const candidate = option ?? process.env.OMNARA_FRONTEND_URL ?? DEFAULT_FRONTEND_URL;
53
+ return (0, api_client_1.normalizeBaseUrl)(candidate);
54
+ }
55
+ function mergeCredentialsAfterExchange(args) {
56
+ const now = Date.now();
57
+ const accessExpiresAt = new Date(now + args.exchange.accessTokenExpiresIn * 1000).toISOString();
58
+ const refreshExpiresAt = new Date(now + args.exchange.refreshTokenExpiresIn * 1000).toISOString();
59
+ return {
60
+ accessToken: args.exchange.accessToken,
61
+ accessTokenExpiresAt: accessExpiresAt,
62
+ refreshToken: args.exchange.refreshToken,
63
+ refreshTokenExpiresAt: refreshExpiresAt,
64
+ };
65
+ }
66
+ function formatDuration(ms) {
67
+ const totalSeconds = Math.round(ms / 1000);
68
+ if (totalSeconds < 60) {
69
+ return `${totalSeconds}s`;
70
+ }
71
+ const totalMinutes = Math.round(totalSeconds / 60);
72
+ if (totalMinutes < 60) {
73
+ const seconds = totalSeconds % 60;
74
+ return seconds > 0 ? `${totalMinutes}m ${seconds}s` : `${totalMinutes}m`;
75
+ }
76
+ const totalHours = Math.floor(totalMinutes / 60);
77
+ const minutes = totalMinutes % 60;
78
+ if (totalHours < 48) {
79
+ return minutes > 0 ? `${totalHours}h ${minutes}m` : `${totalHours}h`;
80
+ }
81
+ const totalDays = Math.floor(totalHours / 24);
82
+ const hours = totalDays % 24;
83
+ return hours > 0 ? `${totalDays}d ${hours}h` : `${totalDays}d`;
84
+ }
85
+ function printSessionInstructions(session) {
86
+ console.log('\n1. Open the following URL in your browser:');
87
+ console.log(` ${session.verificationUriComplete}`);
88
+ console.log('\n2. Sign in (if prompted) and click “Authorize CLI access”.');
89
+ console.log(` This link expires in about ${formatDuration(session.expiresIn * 1000)}.`);
90
+ console.log('\n3. Return here and paste the 6-digit code when prompted.');
91
+ }
92
+ function tryOpenBrowser(url) {
93
+ const command = process.platform === 'darwin'
94
+ ? 'open'
95
+ : process.platform === 'win32'
96
+ ? 'cmd'
97
+ : 'xdg-open';
98
+ const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
99
+ try {
100
+ const child = (0, child_process_1.spawn)(command, args, { stdio: 'ignore', detached: true });
101
+ child.unref();
102
+ }
103
+ catch {
104
+ // Ignore failures; user can open manually.
105
+ }
106
+ }
107
+ //# sourceMappingURL=login-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-flow.js","sourceRoot":"","sources":["../../src/auth/login-flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type SupabaseClient } from '@supabase/supabase-js';
2
+ import type { SupabaseAuthConfig } from './supabase-config';
3
+ export declare function buildSupabaseClient(config: SupabaseAuthConfig): SupabaseClient;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildSupabaseClient = buildSupabaseClient;
4
+ const supabase_js_1 = require("@supabase/supabase-js");
5
+ function buildSupabaseClient(config) {
6
+ return (0, supabase_js_1.createClient)(config.url, config.anonKey, {
7
+ auth: {
8
+ persistSession: false,
9
+ detectSessionInUrl: false,
10
+ },
11
+ });
12
+ }
13
+ //# sourceMappingURL=supabase-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase-client.js","sourceRoot":"","sources":["../../src/auth/supabase-client.ts"],"names":[],"mappings":";;AAIA,kDAOC;AAXD,uDAA0E;AAI1E,SAAgB,mBAAmB,CAAC,MAA0B;IAC5D,OAAO,IAAA,0BAAY,EAAC,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"}
@@ -0,0 +1,5 @@
1
+ export interface SupabaseAuthConfig {
2
+ url: string;
3
+ anonKey: string;
4
+ }
5
+ export declare function getSupabaseAuthConfig(baseUrl: string): Promise<SupabaseAuthConfig>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSupabaseAuthConfig = getSupabaseAuthConfig;
4
+ const api_client_1 = require("../http/api-client");
5
+ const CACHE = new Map();
6
+ async function getSupabaseAuthConfig(baseUrl) {
7
+ const normalized = normalizeBaseUrl(baseUrl);
8
+ const cached = CACHE.get(normalized);
9
+ if (cached) {
10
+ return cached;
11
+ }
12
+ const client = new api_client_1.ApiClient({ baseUrl: normalized });
13
+ const response = await client.getJson('/api/v1/auth/config');
14
+ const config = {
15
+ url: response.supabase_url,
16
+ anonKey: response.supabase_anon_key,
17
+ };
18
+ CACHE.set(normalized, config);
19
+ return config;
20
+ }
21
+ function normalizeBaseUrl(raw) {
22
+ return raw.endsWith('/') ? raw : `${raw}/`;
23
+ }
24
+ //# sourceMappingURL=supabase-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase-config.js","sourceRoot":"","sources":["../../src/auth/supabase-config.ts"],"names":[],"mappings":";;AAcA,sDAeC;AA7BD,mDAA+C;AAY/C,MAAM,KAAK,GAAG,IAAI,GAAG,EAA8B,CAAC;AAE7C,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,sBAAS,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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createProgram(): Command;
3
+ export declare function run(argv: readonly string[]): Promise<void>;
package/dist/cli.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createProgram = createProgram;
7
+ exports.run = run;
8
+ const path_1 = __importDefault(require("path"));
9
+ const commander_1 = require("commander");
10
+ const package_json_1 = __importDefault(require("../package.json"));
11
+ const commands_1 = require("./commands");
12
+ function createProgram() {
13
+ const program = new commander_1.Command();
14
+ program
15
+ .name('omnara')
16
+ .description(package_json_1.default.description ?? 'Command-line interface for Omnara.')
17
+ .version(package_json_1.default.version)
18
+ .option('--backend-url <url>', 'Override backend API base URL used for login')
19
+ .option('--frontend-url <url>', 'Override frontend URL opened during login')
20
+ .action(async () => {
21
+ const options = program.opts();
22
+ await (0, commands_1.runAgentOrchestrator)(options);
23
+ });
24
+ // Register top-level commands here.
25
+ program.addCommand((0, commands_1.buildAgentCommand)());
26
+ program.addCommand((0, commands_1.buildAuthCommand)());
27
+ return program;
28
+ }
29
+ async function run(argv) {
30
+ const program = createProgram();
31
+ try {
32
+ await program.parseAsync(argv);
33
+ }
34
+ catch (error) {
35
+ // Commander will already have logged the error. Set non-zero exit for clarity.
36
+ program.error(error.message, { exitCode: 1 });
37
+ }
38
+ }
39
+ function invokedViaBin() {
40
+ if (!module || !module.parent) {
41
+ return false;
42
+ }
43
+ const parentPath = path_1.default.normalize(module.parent.filename ?? '');
44
+ const expectedSuffix = path_1.default.join('bin', 'omnara.js');
45
+ return parentPath.endsWith(expectedSuffix);
46
+ }
47
+ if (require.main === module || invokedViaBin()) {
48
+ run(process.argv).catch((error) => {
49
+ console.error(error);
50
+ process.exitCode = 1;
51
+ });
52
+ }
53
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;AAUA,sCAmBC;AAED,kBASC;AAxCD,gDAAwB;AACxB,yCAAoC;AACpC,mEAA0C;AAC1C,yCAKoB;AAEpB,SAAgB,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,QAAQ,CAAC;SACd,WAAW,CAAC,sBAAW,CAAC,WAAW,IAAI,oCAAoC,CAAC;SAC5E,OAAO,CAAC,sBAAW,CAAC,OAAO,CAAC;SAC5B,MAAM,CAAC,qBAAqB,EAAE,8CAA8C,CAAC;SAC7E,MAAM,CAAC,sBAAsB,EAAE,2CAA2C,CAAC;SAC3E,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAuB,CAAC;QACpD,MAAM,IAAA,+BAAoB,EAAC,OAAO,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEL,oCAAoC;IACpC,OAAO,CAAC,UAAU,CAAC,IAAA,4BAAiB,GAAE,CAAC,CAAC;IACxC,OAAO,CAAC,UAAU,CAAC,IAAA,2BAAgB,GAAE,CAAC,CAAC;IAEvC,OAAO,OAAO,CAAC;AACjB,CAAC;AAEM,KAAK,UAAU,GAAG,CAAC,IAAuB;IAC/C,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,UAAU,CAAC,IAAgB,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,+EAA+E;QAC/E,OAAO,CAAC,KAAK,CAAE,KAAe,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,SAAS,aAAa;IACpB,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,UAAU,GAAG,cAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAChE,MAAM,cAAc,GAAG,cAAI,CAAC,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACrD,OAAO,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AAC7C,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,aAAa,EAAE,EAAE,CAAC;IAC/C,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QACzC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { Command } from 'commander';
2
+ export declare function buildAgentCommand(): Command;
3
+ export interface OrchestratorOptions {
4
+ backendUrl?: string;
5
+ frontendUrl?: string;
6
+ }
7
+ export declare function runAgentOrchestrator(options?: OrchestratorOptions): Promise<void>;