@meetopenbot/openbot 0.1.1 → 0.1.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.
@@ -0,0 +1,17 @@
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
+ isCloudSystemAgent?: boolean;
15
+ }): boolean;
16
+ export declare function isCreditsErrorMessage(message: string): boolean;
17
+ export declare function isAuthErrorMessage(message: string): boolean;
@@ -0,0 +1,33 @@
1
+ export const INTEGRATIONS_TOKEN_HEADER = 'x-openbot-integrations-token';
2
+ export const CREDITS_API_KEY_PLACEHOLDER = 'openbot-credits';
3
+ const CREDITS_PROVIDER_PATHS = {
4
+ openai: 'openai/v1',
5
+ anthropic: 'anthropic/v1',
6
+ };
7
+ /** Cloud host injects these when routing LLM calls through OpenBot Credits. */
8
+ export function resolveCreditsAuthConfig() {
9
+ const baseUrl = process.env.OPENBOT_INTEGRATIONS_BASE_URL?.trim();
10
+ const token = process.env.OPENBOT_INTEGRATIONS_TOKEN?.trim();
11
+ if (!baseUrl || !token)
12
+ return undefined;
13
+ return { baseUrl: baseUrl.replace(/\/$/, ''), token };
14
+ }
15
+ export function creditsProviderBaseUrl(config, provider) {
16
+ return `${config.baseUrl}/${CREDITS_PROVIDER_PATHS[provider]}`;
17
+ }
18
+ export function shouldUseCreditsAuth(options) {
19
+ return options?.authMode === 'credits' && options?.isCloudSystemAgent === true;
20
+ }
21
+ export function isCreditsErrorMessage(message) {
22
+ const lower = message.toLowerCase();
23
+ return (lower.includes('insufficient_credits') ||
24
+ lower.includes('insufficient credits') ||
25
+ lower.includes('402'));
26
+ }
27
+ export function isAuthErrorMessage(message) {
28
+ const lower = message.toLowerCase();
29
+ return (lower.includes('api key') ||
30
+ lower.includes('401') ||
31
+ lower.includes('unauthorized') ||
32
+ lower.includes('authentication'));
33
+ }
package/dist/model.d.ts CHANGED
@@ -1,2 +1,7 @@
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
+ isCloudSystemAgent?: boolean;
6
+ }
7
+ export declare function resolveModel(modelString: string, options?: ResolveModelOptions): LanguageModel;
package/dist/model.js CHANGED
@@ -1,18 +1,38 @@
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
+ const apiKey = CREDITS_API_KEY_PLACEHOLDER;
13
+ switch (provider) {
14
+ case 'openai':
15
+ return createOpenAI({ baseURL, apiKey, headers })(modelId);
16
+ case 'anthropic':
17
+ return createAnthropic({ baseURL, apiKey, headers })(modelId);
18
+ }
19
+ }
20
+ export function resolveModel(modelString, options) {
5
21
  const [provider, ...rest] = modelString.split('/');
6
22
  const modelId = rest.join('/');
7
23
  if (!modelId) {
8
24
  throw new Error(`Invalid model string: "${modelString}". Expected "provider/model-id".`);
9
25
  }
26
+ const useCredits = shouldUseCreditsAuth(options);
10
27
  switch (provider) {
11
28
  case 'openai':
12
- return defaultOpenai(modelId);
29
+ return useCredits ? resolveCreditsProvider('openai', modelId) : defaultOpenai(modelId);
13
30
  case 'anthropic':
14
- return anthropic(modelId);
31
+ return useCredits ? resolveCreditsProvider('anthropic', modelId) : anthropic(modelId);
15
32
  case 'google':
33
+ if (useCredits) {
34
+ throw new Error('Google models are not available via OpenBot Credits. Switch to an OpenAI or Anthropic model, or use BYOK mode.');
35
+ }
16
36
  return google(modelId);
17
37
  default:
18
38
  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,11 @@ 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, {
73
+ authMode,
74
+ isCloudSystemAgent: host.isCloudSystemAgent(agentId ?? ''),
75
+ });
76
+ let model = resolveCurrentModel();
72
77
  const isCreditsCloudAgent = (id) => host.isCloudSystemAgent(id ?? '') && authMode === 'credits';
73
78
  const runLLM = async function* (context, threadId, trigger) {
74
79
  if (!storage)
@@ -162,11 +167,29 @@ export const openbotRuntime = (options) => (builder) => {
162
167
  if (abortSignal?.aborted)
163
168
  return;
164
169
  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)) {
170
+ if (isCreditsCloudAgent(context.state.agentId)) {
171
+ if (isCreditsErrorMessage(errorMessage)) {
172
+ yield {
173
+ type: 'agent:output',
174
+ data: {
175
+ content: 'Insufficient workspace credits. Add credits in workspace settings or switch this agent to BYOK mode.',
176
+ },
177
+ meta: { agentId: context.state.agentId, threadId },
178
+ };
179
+ return;
180
+ }
181
+ if (isAuthErrorMessage(errorMessage)) {
182
+ yield {
183
+ type: 'agent:output',
184
+ data: {
185
+ content: 'Could not authenticate via OpenBot Credits. Check your workspace credit balance in settings, or switch this agent to BYOK mode.',
186
+ },
187
+ meta: { agentId: context.state.agentId, threadId },
188
+ };
189
+ return;
190
+ }
191
+ }
192
+ if (isAuthErrorMessage(errorMessage) && !isCreditsCloudAgent(context.state.agentId)) {
170
193
  const registry = await host.resolveModelRegistry();
171
194
  const providerActions = host.listApiKeyProvidersFromRegistry(registry).map((provider) => ({
172
195
  id: provider.id,
@@ -340,7 +363,7 @@ export const openbotRuntime = (options) => (builder) => {
340
363
  await storage.createVariable({ key: envVar, value: apiKey, secret: true });
341
364
  process.env[envVar] = apiKey;
342
365
  currentModelString = newModelString;
343
- model = resolveModel(currentModelString, agentId);
366
+ model = resolveCurrentModel();
344
367
  try {
345
368
  host.saveConfig({ model: currentModelString });
346
369
  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.2",
4
4
  "description": "Monolithic OpenBot agent runtime with batteries-included tools.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",