@meetopenbot/openbot 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,16 @@
1
+ import type { OpenbotAuthMode } from './cloud-mode.js';
2
+ export declare const INTEGRATIONS_TOKEN_HEADER = "x-openbot-integrations-token";
3
+ export declare const CREDITS_API_KEY_PLACEHOLDER = "openbot-credits";
4
+ export interface CreditsAuthConfig {
5
+ baseUrl: string;
6
+ token: string;
7
+ }
8
+ export type CreditsProviderId = 'openai' | 'anthropic';
9
+ /** Cloud host injects these when routing LLM calls through OpenBot Credits. */
10
+ export declare function resolveCreditsAuthConfig(): CreditsAuthConfig | undefined;
11
+ export declare function creditsProviderBaseUrl(config: CreditsAuthConfig, provider: CreditsProviderId): string;
12
+ export declare function shouldUseCreditsAuth(options?: {
13
+ authMode?: OpenbotAuthMode;
14
+ }): boolean;
15
+ export declare function isCreditsErrorMessage(message: string): boolean;
16
+ export declare function isAuthErrorMessage(message: string): boolean;
@@ -0,0 +1,39 @@
1
+ import { isCloudMode } from './cloud-mode.js';
2
+ export const INTEGRATIONS_TOKEN_HEADER = 'x-openbot-integrations-token';
3
+ export const CREDITS_API_KEY_PLACEHOLDER = 'openbot-credits';
4
+ const CREDITS_PROVIDER_PATHS = {
5
+ openai: 'openai/v1',
6
+ anthropic: 'anthropic/v1',
7
+ };
8
+ /** Cloud host injects these when routing LLM calls through OpenBot Credits. */
9
+ export function resolveCreditsAuthConfig() {
10
+ const baseUrl = process.env.OPENBOT_INTEGRATIONS_BASE_URL?.trim();
11
+ const token = process.env.OPENBOT_INTEGRATIONS_TOKEN?.trim();
12
+ if (!baseUrl || !token)
13
+ return undefined;
14
+ return { baseUrl: baseUrl.replace(/\/$/, ''), token };
15
+ }
16
+ export function creditsProviderBaseUrl(config, provider) {
17
+ return `${config.baseUrl}/${CREDITS_PROVIDER_PATHS[provider]}`;
18
+ }
19
+ export function shouldUseCreditsAuth(options) {
20
+ if (options?.authMode === 'byok')
21
+ return false;
22
+ if (options?.authMode === 'credits')
23
+ return true;
24
+ // Cloud host injected integrations credentials — route through proxy even if authMode unset.
25
+ return isCloudMode() && resolveCreditsAuthConfig() !== undefined;
26
+ }
27
+ export function isCreditsErrorMessage(message) {
28
+ const lower = message.toLowerCase();
29
+ return (lower.includes('insufficient_credits') ||
30
+ lower.includes('insufficient credits') ||
31
+ lower.includes('402'));
32
+ }
33
+ export function isAuthErrorMessage(message) {
34
+ const lower = message.toLowerCase();
35
+ return (lower.includes('api key') ||
36
+ lower.includes('401') ||
37
+ lower.includes('unauthorized') ||
38
+ lower.includes('authentication'));
39
+ }
package/dist/model.d.ts CHANGED
@@ -1,2 +1,6 @@
1
1
  import type { LanguageModel } from 'ai';
2
- export declare function resolveModel(modelString: string, _agentId?: string): LanguageModel;
2
+ import type { OpenbotAuthMode } from './cloud-mode.js';
3
+ export interface ResolveModelOptions {
4
+ authMode?: OpenbotAuthMode;
5
+ }
6
+ export declare function resolveModel(modelString: string, options?: ResolveModelOptions): LanguageModel;
package/dist/model.js CHANGED
@@ -1,18 +1,39 @@
1
- import { openai as defaultOpenai } from '@ai-sdk/openai';
2
- import { anthropic } from '@ai-sdk/anthropic';
1
+ import { createOpenAI, openai as defaultOpenai } from '@ai-sdk/openai';
2
+ import { createAnthropic, anthropic } from '@ai-sdk/anthropic';
3
3
  import { google } from '@ai-sdk/google';
4
- export function resolveModel(modelString, _agentId) {
4
+ import { CREDITS_API_KEY_PLACEHOLDER, INTEGRATIONS_TOKEN_HEADER, creditsProviderBaseUrl, resolveCreditsAuthConfig, shouldUseCreditsAuth, } from './credits-auth.js';
5
+ function resolveCreditsProvider(provider, modelId) {
6
+ const config = resolveCreditsAuthConfig();
7
+ if (!config) {
8
+ throw new Error('OpenBot Credits is not configured. The cloud host must set OPENBOT_INTEGRATIONS_BASE_URL and OPENBOT_INTEGRATIONS_TOKEN.');
9
+ }
10
+ const baseURL = creditsProviderBaseUrl(config, provider);
11
+ const headers = { [INTEGRATIONS_TOKEN_HEADER]: config.token };
12
+ // Any non-empty key satisfies the SDK; the integrations gateway authenticates via header.
13
+ const apiKey = config.token || CREDITS_API_KEY_PLACEHOLDER;
14
+ switch (provider) {
15
+ case 'openai':
16
+ return createOpenAI({ baseURL, apiKey, headers })(modelId);
17
+ case 'anthropic':
18
+ return createAnthropic({ baseURL, apiKey, headers })(modelId);
19
+ }
20
+ }
21
+ export function resolveModel(modelString, options) {
5
22
  const [provider, ...rest] = modelString.split('/');
6
23
  const modelId = rest.join('/');
7
24
  if (!modelId) {
8
25
  throw new Error(`Invalid model string: "${modelString}". Expected "provider/model-id".`);
9
26
  }
27
+ const useCredits = shouldUseCreditsAuth(options);
10
28
  switch (provider) {
11
29
  case 'openai':
12
- return defaultOpenai(modelId);
30
+ return useCredits ? resolveCreditsProvider('openai', modelId) : defaultOpenai(modelId);
13
31
  case 'anthropic':
14
- return anthropic(modelId);
32
+ return useCredits ? resolveCreditsProvider('anthropic', modelId) : anthropic(modelId);
15
33
  case 'google':
34
+ if (useCredits) {
35
+ throw new Error('Google models are not available via OpenBot Credits. Switch to an OpenAI or Anthropic model, or use BYOK mode.');
36
+ }
16
37
  return google(modelId);
17
38
  default:
18
39
  throw new Error(`Unsupported AI provider: "${provider}"`);
package/dist/runtime.js CHANGED
@@ -2,6 +2,7 @@ import { generateText } from 'ai';
2
2
  import { eventsToModelMessages } from './history.js';
3
3
  import { buildContext } from './context.js';
4
4
  import { OPENBOT_SYSTEM_PROMPT } from './system-prompt.js';
5
+ import { isAuthErrorMessage, isCreditsErrorMessage } from './credits-auth.js';
5
6
  import { resolveModel } from './model.js';
6
7
  async function buildSystemPrompt(state, storage) {
7
8
  const context = await buildContext(state, storage);
@@ -68,7 +69,8 @@ function createToolBatchTracker(state, storage, channelId, threadId) {
68
69
  export const openbotRuntime = (options) => (builder) => {
69
70
  const { model: modelString = 'openai/gpt-4o-mini', authMode = 'byok', agentId, storage, toolDefinitions = {}, abortSignal, host, } = options;
70
71
  let currentModelString = modelString;
71
- let model = resolveModel(currentModelString, agentId);
72
+ const resolveCurrentModel = () => resolveModel(currentModelString, { authMode });
73
+ let model = resolveCurrentModel();
72
74
  const isCreditsCloudAgent = (id) => host.isCloudSystemAgent(id ?? '') && authMode === 'credits';
73
75
  const runLLM = async function* (context, threadId, trigger) {
74
76
  if (!storage)
@@ -162,11 +164,29 @@ export const openbotRuntime = (options) => (builder) => {
162
164
  if (abortSignal?.aborted)
163
165
  return;
164
166
  const errorMessage = error instanceof Error ? error.message : String(error);
165
- const isApiKeyError = errorMessage.includes('API key') ||
166
- errorMessage.includes('401') ||
167
- errorMessage.includes('Unauthorized') ||
168
- errorMessage.includes('authentication');
169
- if (isApiKeyError && !isCreditsCloudAgent(context.state.agentId)) {
167
+ if (isCreditsCloudAgent(context.state.agentId)) {
168
+ if (isCreditsErrorMessage(errorMessage)) {
169
+ yield {
170
+ type: 'agent:output',
171
+ data: {
172
+ content: 'Insufficient workspace credits. Add credits in workspace settings or switch this agent to BYOK mode.',
173
+ },
174
+ meta: { agentId: context.state.agentId, threadId },
175
+ };
176
+ return;
177
+ }
178
+ if (isAuthErrorMessage(errorMessage)) {
179
+ yield {
180
+ type: 'agent:output',
181
+ data: {
182
+ content: 'Could not authenticate via OpenBot Credits. Check your workspace credit balance in settings, or switch this agent to BYOK mode.',
183
+ },
184
+ meta: { agentId: context.state.agentId, threadId },
185
+ };
186
+ return;
187
+ }
188
+ }
189
+ if (isAuthErrorMessage(errorMessage) && !isCreditsCloudAgent(context.state.agentId)) {
170
190
  const registry = await host.resolveModelRegistry();
171
191
  const providerActions = host.listApiKeyProvidersFromRegistry(registry).map((provider) => ({
172
192
  id: provider.id,
@@ -340,7 +360,7 @@ export const openbotRuntime = (options) => (builder) => {
340
360
  await storage.createVariable({ key: envVar, value: apiKey, secret: true });
341
361
  process.env[envVar] = apiKey;
342
362
  currentModelString = newModelString;
343
- model = resolveModel(currentModelString, agentId);
363
+ model = resolveCurrentModel();
344
364
  try {
345
365
  host.saveConfig({ model: currentModelString });
346
366
  const details = await storage.getAgentDetails({ agentId: context.state.agentId });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meetopenbot/openbot",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Monolithic OpenBot agent runtime with batteries-included tools.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",