@meetopenbot/openbot 0.2.2 → 0.2.4
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/dist/auto-model.js +1 -1
- package/dist/index.js +11 -14
- package/dist/model.js +15 -11
- package/dist/runtime.js +2 -2
- package/package.json +2 -2
- package/dist/cloud-mode.js +0 -4
- package/dist/credits-auth.js +0 -41
- package/dist/model-registry.js +0 -94
package/dist/auto-model.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { shouldUseCreditsAuth } from '
|
|
1
|
+
import { shouldUseCreditsAuth } from '@meetopenbot/plugin-sdk';
|
|
2
2
|
/** Product alias shown in the picker. Never sent to a provider or the credits proxy. */
|
|
3
3
|
export const AUTO_MODEL_ID = 'openbot/auto';
|
|
4
4
|
export const AUTO_MODEL_OPTION = {
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { defineOpenbotPlugin } from "./types.js";
|
|
2
|
-
import {
|
|
3
|
-
import { AUTO_MODEL_ID } from "./auto-model.js";
|
|
4
|
-
import { resolveModelConfigField } from "./model-registry.js";
|
|
2
|
+
import { cloudAuthModeProperties, modelConfigField, } from "@meetopenbot/plugin-sdk";
|
|
3
|
+
import { AUTO_MODEL_ID, AUTO_MODEL_OPTION } from "./auto-model.js";
|
|
5
4
|
import { openbotRuntime } from "./runtime.js";
|
|
6
5
|
import { bashPlugin } from "./tools/bash.js";
|
|
7
6
|
import { memoryPlugin } from "./tools/memory.js";
|
|
@@ -14,7 +13,13 @@ import { uiPlugin } from "./tools/ui.js";
|
|
|
14
13
|
import { previewPlugin } from "./tools/preview.js";
|
|
15
14
|
import { storageToolPlugin } from "./tools/storage.js";
|
|
16
15
|
export const OPENBOT_PLUGIN_ID = "@meetopenbot/openbot";
|
|
17
|
-
const modelField = await
|
|
16
|
+
const modelField = await modelConfigField({
|
|
17
|
+
providers: ["openai", "anthropic", "google", "deepseek"],
|
|
18
|
+
extraOptions: [AUTO_MODEL_OPTION],
|
|
19
|
+
defaultValue: AUTO_MODEL_ID,
|
|
20
|
+
description: "Auto, or a model from the OpenBot registry.",
|
|
21
|
+
fallbackDescription: "Auto, or a provider model in provider/model-id format (e.g. openai/gpt-4o-mini).",
|
|
22
|
+
});
|
|
18
23
|
const SPECIALIST_TOOL_NAMES = new Set([
|
|
19
24
|
...Object.keys(bashPlugin.toolDefinitions ?? {}),
|
|
20
25
|
...Object.keys(previewPlugin.toolDefinitions ?? {}),
|
|
@@ -33,16 +38,7 @@ export const openbotPlugin = defineOpenbotPlugin({
|
|
|
33
38
|
configSchema: {
|
|
34
39
|
type: "object",
|
|
35
40
|
properties: {
|
|
36
|
-
...(
|
|
37
|
-
? {
|
|
38
|
-
authMode: {
|
|
39
|
-
type: "string",
|
|
40
|
-
description: "Credits — use your workspace credit balance via OpenBot. BYOK — bring your own API key.",
|
|
41
|
-
enum: ["credits", "byok"],
|
|
42
|
-
default: "credits",
|
|
43
|
-
},
|
|
44
|
-
}
|
|
45
|
-
: {}),
|
|
41
|
+
...cloudAuthModeProperties(),
|
|
46
42
|
model: modelField,
|
|
47
43
|
},
|
|
48
44
|
},
|
|
@@ -92,3 +88,4 @@ export const openbotPlugin = defineOpenbotPlugin({
|
|
|
92
88
|
},
|
|
93
89
|
});
|
|
94
90
|
export default openbotPlugin;
|
|
91
|
+
export { openbotPlugin as plugin };
|
package/dist/model.js
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import { createOpenAI, openai as defaultOpenai } from '@ai-sdk/openai';
|
|
2
2
|
import { createAnthropic, anthropic } from '@ai-sdk/anthropic';
|
|
3
3
|
import { expandModelString } from './auto-model.js';
|
|
4
|
-
import { CREDITS_API_KEY_PLACEHOLDER, INTEGRATIONS_TOKEN_HEADER, creditsProviderBaseUrl, resolveCreditsAuthConfig, shouldUseCreditsAuth, } from '
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
import { CREDITS_API_KEY_PLACEHOLDER, INTEGRATIONS_TOKEN_HEADER, creditsProviderBaseUrl, resolveCreditsAuthConfig, shouldUseCreditsAuth, } from '@meetopenbot/plugin-sdk';
|
|
5
|
+
function deepseekChat(modelId) {
|
|
6
|
+
return createOpenAI({
|
|
7
|
+
baseURL: 'https://api.deepseek.com',
|
|
8
|
+
apiKey: process.env.DEEPSEEK_API_KEY,
|
|
9
|
+
}).chat(modelId);
|
|
10
|
+
}
|
|
11
|
+
function googleChat(modelId) {
|
|
12
|
+
return createOpenAI({
|
|
13
|
+
baseURL: 'https://generativelanguage.googleapis.com/v1beta/openai',
|
|
14
|
+
apiKey: process.env.GOOGLE_GENERATIVE_AI_API_KEY,
|
|
15
|
+
}).chat(modelId);
|
|
16
|
+
}
|
|
13
17
|
/**
|
|
14
18
|
* OpenAI-compatible Chat Completions. Gemini/DeepSeek gateways only speak this.
|
|
15
19
|
* Do not use for OpenAI itself — gpt-5.6-luna rejects function tools on
|
|
@@ -56,9 +60,9 @@ export function resolveModel(modelString, options) {
|
|
|
56
60
|
case 'anthropic':
|
|
57
61
|
return useCredits ? resolveCreditsProvider('anthropic', modelId) : anthropic(modelId);
|
|
58
62
|
case 'google':
|
|
59
|
-
return useCredits ? resolveCreditsProvider('google', modelId) :
|
|
63
|
+
return useCredits ? resolveCreditsProvider('google', modelId) : googleChat(modelId);
|
|
60
64
|
case 'deepseek':
|
|
61
|
-
return useCredits ? resolveCreditsProvider('deepseek', modelId) :
|
|
65
|
+
return useCredits ? resolveCreditsProvider('deepseek', modelId) : deepseekChat(modelId);
|
|
62
66
|
default:
|
|
63
67
|
throw new Error(`Unsupported AI provider: "${provider}"`);
|
|
64
68
|
}
|
package/dist/runtime.js
CHANGED
|
@@ -2,10 +2,10 @@ 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 '
|
|
5
|
+
import { isAuthErrorMessage, isCreditsErrorMessage } from '@meetopenbot/plugin-sdk';
|
|
6
6
|
import { AUTO_MODEL_ID, isAutoModel, isRetryableModelError, listAutoModelCandidates, } from './auto-model.js';
|
|
7
7
|
import { resolveModel } from './model.js';
|
|
8
|
-
import { fetchModelRegistry, getProviderModelOptions, listApiKeyProviders, PROVIDER_API_KEY_LINKS, } from '
|
|
8
|
+
import { fetchModelRegistry, getProviderModelOptions, listApiKeyProviders, PROVIDER_API_KEY_LINKS, } from '@meetopenbot/plugin-sdk';
|
|
9
9
|
async function buildSystemPrompt(state, storage) {
|
|
10
10
|
const context = await buildContext(state, storage);
|
|
11
11
|
const sections = [OPENBOT_SYSTEM_PROMPT, '', context];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@meetopenbot/openbot",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "OpenBot coordinator runtime: ask specialists, route work into Spaces, and track todos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"@ai-sdk/openai": "^3.0.13",
|
|
24
24
|
"ai": "^6.0.42",
|
|
25
25
|
"zod": "^4.3.5",
|
|
26
|
-
"@meetopenbot/plugin-sdk": "^0.
|
|
26
|
+
"@meetopenbot/plugin-sdk": "^0.4.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^20.10.1",
|
package/dist/cloud-mode.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/** True when this runtime is a platform-managed cloud deployment. */
|
|
2
|
-
export const isCloudMode = () => process.env.OPENBOT_CLOUD_MODE === '1';
|
|
3
|
-
/** Default auth mode: Credits on cloud, BYOK locally. */
|
|
4
|
-
export const defaultAuthMode = () => (isCloudMode() ? 'credits' : 'byok');
|
package/dist/credits-auth.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
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
|
-
google: 'google/v1',
|
|
8
|
-
deepseek: 'deepseek/v1',
|
|
9
|
-
};
|
|
10
|
-
/** Cloud host injects these when routing LLM calls through OpenBot Credits. */
|
|
11
|
-
export function resolveCreditsAuthConfig() {
|
|
12
|
-
const baseUrl = process.env.OPENBOT_INTEGRATIONS_BASE_URL?.trim();
|
|
13
|
-
const token = process.env.OPENBOT_INTEGRATIONS_TOKEN?.trim();
|
|
14
|
-
if (!baseUrl || !token)
|
|
15
|
-
return undefined;
|
|
16
|
-
return { baseUrl: baseUrl.replace(/\/$/, ''), token };
|
|
17
|
-
}
|
|
18
|
-
export function creditsProviderBaseUrl(config, provider) {
|
|
19
|
-
return `${config.baseUrl}/${CREDITS_PROVIDER_PATHS[provider]}`;
|
|
20
|
-
}
|
|
21
|
-
export function shouldUseCreditsAuth(options) {
|
|
22
|
-
if (options?.authMode === 'byok')
|
|
23
|
-
return false;
|
|
24
|
-
if (options?.authMode === 'credits')
|
|
25
|
-
return true;
|
|
26
|
-
// Cloud host injected integrations credentials — route through proxy even if authMode unset.
|
|
27
|
-
return isCloudMode() && resolveCreditsAuthConfig() !== undefined;
|
|
28
|
-
}
|
|
29
|
-
export function isCreditsErrorMessage(message) {
|
|
30
|
-
const lower = message.toLowerCase();
|
|
31
|
-
return (lower.includes('insufficient_credits') ||
|
|
32
|
-
lower.includes('insufficient credits') ||
|
|
33
|
-
lower.includes('402'));
|
|
34
|
-
}
|
|
35
|
-
export function isAuthErrorMessage(message) {
|
|
36
|
-
const lower = message.toLowerCase();
|
|
37
|
-
return (lower.includes('api key') ||
|
|
38
|
-
lower.includes('401') ||
|
|
39
|
-
lower.includes('unauthorized') ||
|
|
40
|
-
lower.includes('authentication'));
|
|
41
|
-
}
|
package/dist/model-registry.js
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { AUTO_MODEL_ID, AUTO_MODEL_OPTION } from './auto-model.js';
|
|
2
|
-
const DEFAULT_REGISTRY_URL = 'https://raw.githubusercontent.com/meetopenbot/openbot-registry/main/registry.json';
|
|
3
|
-
const API_KEY_PROVIDER_IDS = ['openai', 'anthropic', 'google', 'deepseek'];
|
|
4
|
-
export const PROVIDER_API_KEY_LINKS = {
|
|
5
|
-
openai: 'https://platform.openai.com/api-keys',
|
|
6
|
-
anthropic: 'https://console.anthropic.com/settings/keys',
|
|
7
|
-
google: 'https://aistudio.google.com/app/apikey',
|
|
8
|
-
deepseek: 'https://platform.deepseek.com/api_keys',
|
|
9
|
-
};
|
|
10
|
-
const FALLBACK_PROVIDERS = [
|
|
11
|
-
{ id: 'openai', label: 'OpenAI' },
|
|
12
|
-
{ id: 'anthropic', label: 'Anthropic' },
|
|
13
|
-
{ id: 'google', label: 'Google' },
|
|
14
|
-
{ id: 'deepseek', label: 'DeepSeek' },
|
|
15
|
-
];
|
|
16
|
-
let cachedRegistry;
|
|
17
|
-
export async function fetchModelRegistry() {
|
|
18
|
-
if (cachedRegistry !== undefined)
|
|
19
|
-
return cachedRegistry;
|
|
20
|
-
const url = process.env.OPENBOT_MODEL_REGISTRY_URL?.trim() || DEFAULT_REGISTRY_URL;
|
|
21
|
-
try {
|
|
22
|
-
const response = await fetch(url, {
|
|
23
|
-
headers: { Accept: 'application/json' },
|
|
24
|
-
signal: AbortSignal.timeout(15000),
|
|
25
|
-
});
|
|
26
|
-
if (!response.ok) {
|
|
27
|
-
cachedRegistry = null;
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
cachedRegistry = (await response.json());
|
|
31
|
-
return cachedRegistry;
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
cachedRegistry = null;
|
|
35
|
-
return null;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
export function listApiKeyProviders(registry) {
|
|
39
|
-
if (!registry?.providers)
|
|
40
|
-
return FALLBACK_PROVIDERS;
|
|
41
|
-
const providers = API_KEY_PROVIDER_IDS.flatMap((id) => {
|
|
42
|
-
const provider = registry.providers?.[id];
|
|
43
|
-
return provider ? [{ id, label: provider.label }] : [];
|
|
44
|
-
});
|
|
45
|
-
return providers.length > 0 ? providers : FALLBACK_PROVIDERS;
|
|
46
|
-
}
|
|
47
|
-
export function getProviderModelOptions(registry, provider) {
|
|
48
|
-
const models = registry?.providers?.[provider]?.models;
|
|
49
|
-
if (!models?.length)
|
|
50
|
-
return undefined;
|
|
51
|
-
return models.map((m) => ({ label: m.label, value: m.id }));
|
|
52
|
-
}
|
|
53
|
-
function listAllModelOptions(registry) {
|
|
54
|
-
if (!registry?.providers)
|
|
55
|
-
return [];
|
|
56
|
-
const options = [];
|
|
57
|
-
for (const providerId of API_KEY_PROVIDER_IDS) {
|
|
58
|
-
const provider = registry.providers[providerId];
|
|
59
|
-
if (!provider)
|
|
60
|
-
continue;
|
|
61
|
-
for (const model of provider.models ?? []) {
|
|
62
|
-
options.push({
|
|
63
|
-
value: `${providerId}/${model.id}`,
|
|
64
|
-
label: `${provider.label} — ${model.label}`,
|
|
65
|
-
description: model.description,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return options;
|
|
70
|
-
}
|
|
71
|
-
function withAutoOption(options) {
|
|
72
|
-
if (options.some((option) => option.value === AUTO_MODEL_ID))
|
|
73
|
-
return options;
|
|
74
|
-
return [AUTO_MODEL_OPTION, ...options];
|
|
75
|
-
}
|
|
76
|
-
const freeInputModelField = () => ({
|
|
77
|
-
type: 'string',
|
|
78
|
-
description: 'Auto, or a provider model in provider/model-id format (e.g. openai/gpt-4o-mini).',
|
|
79
|
-
default: AUTO_MODEL_ID,
|
|
80
|
-
});
|
|
81
|
-
/** Registry-backed model field for plugin configSchema (`enum` + labeled `options`). */
|
|
82
|
-
export async function resolveModelConfigField() {
|
|
83
|
-
const registry = await fetchModelRegistry();
|
|
84
|
-
const options = withAutoOption(listAllModelOptions(registry));
|
|
85
|
-
if (options.length === 1)
|
|
86
|
-
return freeInputModelField();
|
|
87
|
-
return {
|
|
88
|
-
type: 'string',
|
|
89
|
-
description: 'Auto, or a model from the OpenBot registry.',
|
|
90
|
-
default: AUTO_MODEL_ID,
|
|
91
|
-
enum: options.map((option) => option.value),
|
|
92
|
-
options,
|
|
93
|
-
};
|
|
94
|
-
}
|