@chatbridge/core 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 7milch
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @chatbridge/core
2
+
3
+ Core session flows and errors for [chatbridge](https://github.com/7milch/chatbridge-cli).
@@ -0,0 +1,4 @@
1
+ import { AuthStore, type AuthStoreOptions } from "@chatbridge/runtime";
2
+ /** Builds an AuthStore, translating an unusable provider name into the
3
+ * framework error the CLI maps to exit code 5. */
4
+ export declare function createAuthStore(opts: AuthStoreOptions): AuthStore;
@@ -0,0 +1,13 @@
1
+ import { AuthStore, validateProviderName, } from "@chatbridge/runtime";
2
+ import { InvalidProviderError } from "./errors.js";
3
+ /** Builds an AuthStore, translating an unusable provider name into the
4
+ * framework error the CLI maps to exit code 5. */
5
+ export function createAuthStore(opts) {
6
+ try {
7
+ validateProviderName(opts.providerName);
8
+ }
9
+ catch (err) {
10
+ throw new InvalidProviderError(`Provider name ${JSON.stringify(opts.providerName)} cannot be used as a file name: use lowercase letters, digits, ".", "_" or "-" (1-64 chars, starting with a letter or digit).`, { cause: err });
11
+ }
12
+ return new AuthStore(opts);
13
+ }
@@ -0,0 +1,22 @@
1
+ /** Base class for all framework errors. The CLI maps `code` to exit codes.
2
+ * `options.cause` carries the underlying error (never auth content). */
3
+ export declare class ChatBridgeError extends Error {
4
+ readonly code: string;
5
+ constructor(code: string, message: string, options?: ErrorOptions);
6
+ }
7
+ export declare class AuthRequiredError extends ChatBridgeError {
8
+ constructor(message: string, options?: ErrorOptions);
9
+ }
10
+ export declare class AuthExpiredError extends ChatBridgeError {
11
+ constructor(message: string, options?: ErrorOptions);
12
+ }
13
+ export declare class ResponseTimeoutError extends ChatBridgeError {
14
+ constructor(message: string, options?: ErrorOptions);
15
+ }
16
+ export declare class ProviderLoadError extends ChatBridgeError {
17
+ constructor(message: string, options?: ErrorOptions);
18
+ }
19
+ /** The provider's `name` cannot be used as an auth-state file name. */
20
+ export declare class InvalidProviderError extends ChatBridgeError {
21
+ constructor(message: string, options?: ErrorOptions);
22
+ }
package/dist/errors.js ADDED
@@ -0,0 +1,36 @@
1
+ /** Base class for all framework errors. The CLI maps `code` to exit codes.
2
+ * `options.cause` carries the underlying error (never auth content). */
3
+ export class ChatBridgeError extends Error {
4
+ code;
5
+ constructor(code, message, options) {
6
+ super(message, options);
7
+ this.code = code;
8
+ this.name = new.target.name;
9
+ }
10
+ }
11
+ export class AuthRequiredError extends ChatBridgeError {
12
+ constructor(message, options) {
13
+ super("AUTH_REQUIRED", message, options);
14
+ }
15
+ }
16
+ export class AuthExpiredError extends ChatBridgeError {
17
+ constructor(message, options) {
18
+ super("AUTH_EXPIRED", message, options);
19
+ }
20
+ }
21
+ export class ResponseTimeoutError extends ChatBridgeError {
22
+ constructor(message, options) {
23
+ super("RESPONSE_TIMEOUT", message, options);
24
+ }
25
+ }
26
+ export class ProviderLoadError extends ChatBridgeError {
27
+ constructor(message, options) {
28
+ super("PROVIDER_LOAD", message, options);
29
+ }
30
+ }
31
+ /** The provider's `name` cannot be used as an auth-state file name. */
32
+ export class InvalidProviderError extends ChatBridgeError {
33
+ constructor(message, options) {
34
+ super("INVALID_PROVIDER", message, options);
35
+ }
36
+ }
@@ -0,0 +1,6 @@
1
+ export * from "./errors.js";
2
+ export { type LoginOptions, type OneShotOptions, runLogin, runOneShot, } from "./session.js";
3
+ export { createAuthStore } from "./create-auth-store.js";
4
+ export { AuthStore, type AuthStoreOptions, BrowserRuntime, validateProviderName, } from "@chatbridge/runtime";
5
+ export type { Provider } from "@chatbridge/provider";
6
+ export { defineProvider } from "@chatbridge/provider";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./errors.js";
2
+ export { runLogin, runOneShot, } from "./session.js";
3
+ export { createAuthStore } from "./create-auth-store.js";
4
+ export { AuthStore, BrowserRuntime, validateProviderName, } from "@chatbridge/runtime";
5
+ export { defineProvider } from "@chatbridge/provider";
@@ -0,0 +1,23 @@
1
+ import type { Provider } from "@chatbridge/provider";
2
+ import { type AuthStore } from "@chatbridge/runtime";
3
+ export interface OneShotOptions {
4
+ provider: Provider;
5
+ authStore: AuthStore;
6
+ prompt: string;
7
+ headless: boolean;
8
+ timeoutMs: number;
9
+ /** Progress messages (stderr in the CLI). Never receives auth content. */
10
+ onProgress?: (message: string) => void;
11
+ }
12
+ /** Runs one browser step; a Playwright TimeoutError becomes a framework
13
+ * ResponseTimeoutError that names the step and keeps the original as cause. */
14
+ export declare function runStep<T>(name: string, timeoutMs: number, fn: () => Promise<T>): Promise<T>;
15
+ /** One-shot flow: restore auth -> new chat -> send -> wait -> return text. */
16
+ export declare function runOneShot(opts: OneShotOptions): Promise<string>;
17
+ export interface LoginOptions {
18
+ provider: Provider;
19
+ authStore: AuthStore;
20
+ onProgress?: (message: string) => void;
21
+ }
22
+ /** Headful login flow: the user logs in manually; we poll for completion. */
23
+ export declare function runLogin(opts: LoginOptions): Promise<void>;
@@ -0,0 +1,71 @@
1
+ import { BrowserRuntime } from "@chatbridge/runtime";
2
+ import { AuthExpiredError, AuthRequiredError, ResponseTimeoutError, } from "./errors.js";
3
+ /** Runs one browser step; a Playwright TimeoutError becomes a framework
4
+ * ResponseTimeoutError that names the step and keeps the original as cause. */
5
+ export async function runStep(name, timeoutMs, fn) {
6
+ try {
7
+ return await fn();
8
+ }
9
+ catch (err) {
10
+ if (err instanceof Error && err.name === "TimeoutError") {
11
+ throw new ResponseTimeoutError(`Timed out during ${name} after ${timeoutMs} ms.`, { cause: err });
12
+ }
13
+ throw err;
14
+ }
15
+ }
16
+ /** One-shot flow: restore auth -> new chat -> send -> wait -> return text. */
17
+ export async function runOneShot(opts) {
18
+ const { provider, authStore, onProgress, timeoutMs } = opts;
19
+ if (!authStore.has()) {
20
+ throw new AuthRequiredError(`No saved auth state for provider "${provider.name}". Run \`auth login\` first.`);
21
+ }
22
+ onProgress?.("Opening browser...");
23
+ const rt = await BrowserRuntime.launch({
24
+ headless: opts.headless,
25
+ provider,
26
+ authStore,
27
+ });
28
+ try {
29
+ rt.page.setDefaultTimeout(timeoutMs);
30
+ await runStep("goto", timeoutMs, () => rt.page.goto(provider.chatUrl));
31
+ const loggedIn = await runStep("isLoggedIn", timeoutMs, () => provider.isLoggedIn(rt.page));
32
+ if (!loggedIn) {
33
+ throw new AuthExpiredError(`Auth state for "${provider.name}" is no longer valid. Run \`auth login\` again.`);
34
+ }
35
+ await runStep("startNewChat", timeoutMs, () => provider.startNewChat(rt.page));
36
+ onProgress?.("Sending prompt...");
37
+ await runStep("sendMessage", timeoutMs, () => provider.sendMessage(rt.page, opts.prompt));
38
+ onProgress?.("Waiting for response...");
39
+ return await runStep("waitForResponse", timeoutMs, () => provider.waitForResponse(rt.page));
40
+ }
41
+ finally {
42
+ await rt.close();
43
+ }
44
+ }
45
+ const LOGIN_NAVIGATION_TIMEOUT_MS = 30_000;
46
+ /** Headful login flow: the user logs in manually; we poll for completion. */
47
+ export async function runLogin(opts) {
48
+ const { provider, authStore, onProgress } = opts;
49
+ onProgress?.("Opening browser...");
50
+ const rt = await BrowserRuntime.launch({
51
+ headless: false,
52
+ provider,
53
+ authStore,
54
+ });
55
+ try {
56
+ rt.page.setDefaultTimeout(LOGIN_NAVIGATION_TIMEOUT_MS);
57
+ await runStep("navigateToLogin", LOGIN_NAVIGATION_TIMEOUT_MS, () => provider.navigateToLogin(rt.page));
58
+ onProgress?.(`Please log in to ${provider.name}.`);
59
+ // Poll until the provider reports completion. No overall deadline:
60
+ // the user may need time for MFA; Ctrl-C aborts.
61
+ while (!(await provider.isLoggedIn(rt.page))) {
62
+ await rt.page.waitForTimeout(1000);
63
+ }
64
+ onProgress?.("✓ Login detected");
65
+ await rt.saveAuthState();
66
+ onProgress?.("✓ Session saved");
67
+ }
68
+ finally {
69
+ await rt.close();
70
+ }
71
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@chatbridge/core",
3
+ "version": "0.1.0",
4
+ "description": "Core session flows and errors for chatbridge",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/7milch/chatbridge-cli.git",
9
+ "directory": "packages/core"
10
+ },
11
+ "keywords": ["chatbridge", "playwright", "chat"],
12
+ "type": "module",
13
+ "engines": {
14
+ "node": ">=20"
15
+ },
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ }
21
+ },
22
+ "files": ["dist", "README.md", "LICENSE"],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "dependencies": {
27
+ "@chatbridge/provider": "0.1.0",
28
+ "@chatbridge/runtime": "0.1.0"
29
+ },
30
+ "devDependencies": {
31
+ "@chatbridge/example-dummy-chat": "0.0.0"
32
+ }
33
+ }