@meetopenbot/openbot 0.1.6 → 0.1.8
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/index.d.ts +1 -5
- package/dist/index.js +3 -5
- package/dist/model-registry.d.ts +35 -0
- package/dist/model-registry.js +91 -0
- package/dist/runtime.js +94 -39
- package/dist/tools/delegation.d.ts +1 -1
- package/dist/tools/delegation.js +30 -23
- package/dist/types.d.ts +12 -27
- package/dist/types.js +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -12,11 +12,7 @@ export declare const openbotPlugin: {
|
|
|
12
12
|
configSchema: {
|
|
13
13
|
type: "object";
|
|
14
14
|
properties: {
|
|
15
|
-
model:
|
|
16
|
-
type: "string";
|
|
17
|
-
override: true;
|
|
18
|
-
description: string;
|
|
19
|
-
};
|
|
15
|
+
model: import("./model-registry.js").ModelConfigField;
|
|
20
16
|
authMode?: {
|
|
21
17
|
type: "string";
|
|
22
18
|
description: string;
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { defineOpenbotPlugin } from './types.js';
|
|
2
2
|
import { isCloudMode } from './cloud-mode.js';
|
|
3
|
+
import { resolveModelConfigField } from './model-registry.js';
|
|
3
4
|
import { openbotRuntime } from './runtime.js';
|
|
4
5
|
import { bashPlugin } from './tools/bash.js';
|
|
5
6
|
import { memoryPlugin } from './tools/memory.js';
|
|
@@ -10,6 +11,7 @@ import { uiPlugin } from './tools/ui.js';
|
|
|
10
11
|
import { previewPlugin } from './tools/preview.js';
|
|
11
12
|
import { storageToolPlugin } from './tools/storage.js';
|
|
12
13
|
export const OPENBOT_PLUGIN_ID = '@meetopenbot/openbot';
|
|
14
|
+
const modelField = await resolveModelConfigField();
|
|
13
15
|
/**
|
|
14
16
|
* `@meetopenbot/openbot` — the standard, opinionated OpenBot agent runtime.
|
|
15
17
|
*
|
|
@@ -33,11 +35,7 @@ export const openbotPlugin = defineOpenbotPlugin({
|
|
|
33
35
|
},
|
|
34
36
|
}
|
|
35
37
|
: {}),
|
|
36
|
-
model:
|
|
37
|
-
type: 'string',
|
|
38
|
-
override: true,
|
|
39
|
-
description: 'Model from the hosted marketplace registry.',
|
|
40
|
-
},
|
|
38
|
+
model: modelField,
|
|
41
39
|
},
|
|
42
40
|
},
|
|
43
41
|
toolDefinitions: {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type ModelRegistryProvider = {
|
|
2
|
+
label: string;
|
|
3
|
+
models: Array<{
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
description: string;
|
|
7
|
+
}>;
|
|
8
|
+
};
|
|
9
|
+
export type ModelRegistry = {
|
|
10
|
+
providers?: Record<string, ModelRegistryProvider>;
|
|
11
|
+
};
|
|
12
|
+
export type ModelConfigField = {
|
|
13
|
+
type: 'string';
|
|
14
|
+
description: string;
|
|
15
|
+
default?: string;
|
|
16
|
+
override?: boolean;
|
|
17
|
+
enum?: string[];
|
|
18
|
+
options?: Array<{
|
|
19
|
+
label: string;
|
|
20
|
+
value: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
}>;
|
|
23
|
+
};
|
|
24
|
+
export declare const PROVIDER_API_KEY_LINKS: Record<string, string>;
|
|
25
|
+
export declare function fetchModelRegistry(): Promise<ModelRegistry | null>;
|
|
26
|
+
export declare function listApiKeyProviders(registry: ModelRegistry | null): Array<{
|
|
27
|
+
id: string;
|
|
28
|
+
label: string;
|
|
29
|
+
}>;
|
|
30
|
+
export declare function getProviderModelOptions(registry: ModelRegistry | null, provider: string): Array<{
|
|
31
|
+
label: string;
|
|
32
|
+
value: string;
|
|
33
|
+
}> | undefined;
|
|
34
|
+
/** Registry-backed model field for plugin configSchema (`enum` + labeled `options`). */
|
|
35
|
+
export declare function resolveModelConfigField(): Promise<ModelConfigField>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const DEFAULT_REGISTRY_URL = 'https://raw.githubusercontent.com/meetopenbot/openbot-registry/main/registry.json';
|
|
2
|
+
const API_KEY_PROVIDER_IDS = ['openai', 'anthropic', 'google'];
|
|
3
|
+
export const PROVIDER_API_KEY_LINKS = {
|
|
4
|
+
openai: 'https://platform.openai.com/api-keys',
|
|
5
|
+
anthropic: 'https://console.anthropic.com/settings/keys',
|
|
6
|
+
google: 'https://aistudio.google.com/app/apikey',
|
|
7
|
+
};
|
|
8
|
+
const FALLBACK_PROVIDERS = [
|
|
9
|
+
{ id: 'openai', label: 'OpenAI' },
|
|
10
|
+
{ id: 'anthropic', label: 'Anthropic' },
|
|
11
|
+
{ id: 'google', label: 'Google' },
|
|
12
|
+
];
|
|
13
|
+
let cachedRegistry;
|
|
14
|
+
export async function fetchModelRegistry() {
|
|
15
|
+
if (cachedRegistry !== undefined)
|
|
16
|
+
return cachedRegistry;
|
|
17
|
+
const url = process.env.OPENBOT_MODEL_REGISTRY_URL?.trim() || DEFAULT_REGISTRY_URL;
|
|
18
|
+
try {
|
|
19
|
+
const response = await fetch(url, {
|
|
20
|
+
headers: { Accept: 'application/json' },
|
|
21
|
+
signal: AbortSignal.timeout(15000),
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
cachedRegistry = null;
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
cachedRegistry = (await response.json());
|
|
28
|
+
return cachedRegistry;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
cachedRegistry = null;
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function listApiKeyProviders(registry) {
|
|
36
|
+
if (!registry?.providers)
|
|
37
|
+
return FALLBACK_PROVIDERS;
|
|
38
|
+
const providers = API_KEY_PROVIDER_IDS.flatMap((id) => {
|
|
39
|
+
const provider = registry.providers?.[id];
|
|
40
|
+
return provider ? [{ id, label: provider.label }] : [];
|
|
41
|
+
});
|
|
42
|
+
return providers.length > 0 ? providers : FALLBACK_PROVIDERS;
|
|
43
|
+
}
|
|
44
|
+
export function getProviderModelOptions(registry, provider) {
|
|
45
|
+
const models = registry?.providers?.[provider]?.models;
|
|
46
|
+
if (!models?.length)
|
|
47
|
+
return undefined;
|
|
48
|
+
return models.map((m) => ({ label: m.label, value: m.id }));
|
|
49
|
+
}
|
|
50
|
+
function listAllModelOptions(registry) {
|
|
51
|
+
if (!registry?.providers)
|
|
52
|
+
return [];
|
|
53
|
+
const options = [];
|
|
54
|
+
for (const providerId of API_KEY_PROVIDER_IDS) {
|
|
55
|
+
const provider = registry.providers[providerId];
|
|
56
|
+
if (!provider)
|
|
57
|
+
continue;
|
|
58
|
+
for (const model of provider.models ?? []) {
|
|
59
|
+
options.push({
|
|
60
|
+
value: `${providerId}/${model.id}`,
|
|
61
|
+
label: `${provider.label} — ${model.label}`,
|
|
62
|
+
description: model.description,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return options;
|
|
67
|
+
}
|
|
68
|
+
const freeInputModelField = () => ({
|
|
69
|
+
type: 'string',
|
|
70
|
+
override: true,
|
|
71
|
+
description: 'Provider model in provider/model-id format (e.g. openai/gpt-4o-mini).',
|
|
72
|
+
default: 'openai/gpt-4o-mini',
|
|
73
|
+
});
|
|
74
|
+
/** Registry-backed model field for plugin configSchema (`enum` + labeled `options`). */
|
|
75
|
+
export async function resolveModelConfigField() {
|
|
76
|
+
const registry = await fetchModelRegistry();
|
|
77
|
+
const options = listAllModelOptions(registry);
|
|
78
|
+
if (options.length === 0)
|
|
79
|
+
return freeInputModelField();
|
|
80
|
+
const defaultModel = options.find((option) => option.value === 'openai/gpt-4o-mini')?.value ??
|
|
81
|
+
options.find((option) => option.value.startsWith('openai/'))?.value ??
|
|
82
|
+
options[0].value;
|
|
83
|
+
return {
|
|
84
|
+
type: 'string',
|
|
85
|
+
override: true,
|
|
86
|
+
description: 'Model from the OpenBot registry.',
|
|
87
|
+
default: defaultModel,
|
|
88
|
+
enum: options.map((option) => option.value),
|
|
89
|
+
options,
|
|
90
|
+
};
|
|
91
|
+
}
|
package/dist/runtime.js
CHANGED
|
@@ -4,6 +4,7 @@ import { buildContext } from './context.js';
|
|
|
4
4
|
import { OPENBOT_SYSTEM_PROMPT } from './system-prompt.js';
|
|
5
5
|
import { isAuthErrorMessage, isCreditsErrorMessage } from './credits-auth.js';
|
|
6
6
|
import { resolveModel } from './model.js';
|
|
7
|
+
import { fetchModelRegistry, getProviderModelOptions, listApiKeyProviders, PROVIDER_API_KEY_LINKS, } from './model-registry.js';
|
|
7
8
|
async function buildSystemPrompt(state, storage) {
|
|
8
9
|
const context = await buildContext(state, storage);
|
|
9
10
|
const sections = [OPENBOT_SYSTEM_PROMPT, '', context];
|
|
@@ -187,8 +188,8 @@ export const openbotRuntime = (options) => (builder) => {
|
|
|
187
188
|
}
|
|
188
189
|
}
|
|
189
190
|
if (isAuthErrorMessage(errorMessage) && !isCreditsCloudAgent(context.state.agentId)) {
|
|
190
|
-
const registry = await
|
|
191
|
-
const providerActions =
|
|
191
|
+
const registry = await fetchModelRegistry();
|
|
192
|
+
const providerActions = listApiKeyProviders(registry).map((provider) => ({
|
|
192
193
|
id: provider.id,
|
|
193
194
|
label: provider.label,
|
|
194
195
|
variant: 'primary',
|
|
@@ -200,13 +201,7 @@ export const openbotRuntime = (options) => (builder) => {
|
|
|
200
201
|
widgetId: `api_provider_selection_${Date.now()}`,
|
|
201
202
|
title: `Setup AI Provider`,
|
|
202
203
|
description: `Select a provider to continue.`,
|
|
203
|
-
actions: providerActions
|
|
204
|
-
? providerActions
|
|
205
|
-
: [
|
|
206
|
-
{ id: 'openai', label: 'OpenAI', variant: 'primary' },
|
|
207
|
-
{ id: 'anthropic', label: 'Anthropic', variant: 'primary' },
|
|
208
|
-
{ id: 'google', label: 'Google', variant: 'primary' },
|
|
209
|
-
],
|
|
204
|
+
actions: providerActions,
|
|
210
205
|
metadata: {
|
|
211
206
|
type: 'api_provider_selection',
|
|
212
207
|
},
|
|
@@ -259,31 +254,11 @@ export const openbotRuntime = (options) => (builder) => {
|
|
|
259
254
|
const provider = actionId;
|
|
260
255
|
const [_, ...rest] = currentModelString.split('/');
|
|
261
256
|
const currentModelId = rest.join('/');
|
|
262
|
-
const registry = await
|
|
263
|
-
const providerData = registry
|
|
264
|
-
const providerLinks = {
|
|
265
|
-
openai: 'https://platform.openai.com/api-keys',
|
|
266
|
-
anthropic: 'https://console.anthropic.com/settings/keys',
|
|
267
|
-
google: 'https://aistudio.google.com/app/apikey',
|
|
268
|
-
};
|
|
257
|
+
const registry = await fetchModelRegistry();
|
|
258
|
+
const providerData = registry?.providers?.[provider];
|
|
269
259
|
const label = providerData?.label || provider;
|
|
270
|
-
const link =
|
|
271
|
-
const modelOptions =
|
|
272
|
-
label: m.label,
|
|
273
|
-
value: m.id,
|
|
274
|
-
}));
|
|
275
|
-
if (!modelOptions || modelOptions.length === 0) {
|
|
276
|
-
yield {
|
|
277
|
-
type: 'agent:output',
|
|
278
|
-
data: {
|
|
279
|
-
content: `No models are listed for **${label}** in the marketplace registry.`,
|
|
280
|
-
},
|
|
281
|
-
meta: { agentId: context.state.agentId },
|
|
282
|
-
};
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
const defaultModel = modelOptions[0].value;
|
|
286
|
-
const defaultValue = modelOptions.find((m) => m.value === currentModelId)?.value || defaultModel;
|
|
260
|
+
const link = PROVIDER_API_KEY_LINKS[provider] || '';
|
|
261
|
+
const modelOptions = getProviderModelOptions(registry, provider);
|
|
287
262
|
yield {
|
|
288
263
|
type: 'client:ui:widget',
|
|
289
264
|
data: {
|
|
@@ -298,21 +273,49 @@ export const openbotRuntime = (options) => (builder) => {
|
|
|
298
273
|
},
|
|
299
274
|
meta: { agentId: context.state.agentId, threadId },
|
|
300
275
|
};
|
|
276
|
+
if (modelOptions && modelOptions.length > 0) {
|
|
277
|
+
const defaultModelId = modelOptions.find((m) => m.value === currentModelId)?.value || modelOptions[0].value;
|
|
278
|
+
yield {
|
|
279
|
+
type: 'client:ui:widget',
|
|
280
|
+
data: {
|
|
281
|
+
kind: 'choice',
|
|
282
|
+
widgetId: `api_model_selection_${Date.now()}`,
|
|
283
|
+
title: 'Select Model',
|
|
284
|
+
description: `Choose a ${label} model.`,
|
|
285
|
+
actions: modelOptions.map((option) => ({
|
|
286
|
+
id: option.value,
|
|
287
|
+
label: option.label,
|
|
288
|
+
variant: option.value === defaultModelId ? 'primary' : 'secondary',
|
|
289
|
+
})),
|
|
290
|
+
metadata: {
|
|
291
|
+
type: 'api_model_selection',
|
|
292
|
+
provider,
|
|
293
|
+
},
|
|
294
|
+
},
|
|
295
|
+
meta: { agentId: context.state.agentId, threadId },
|
|
296
|
+
};
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
301
299
|
yield {
|
|
302
300
|
type: 'client:ui:widget',
|
|
303
301
|
data: {
|
|
304
302
|
kind: 'form',
|
|
305
303
|
widgetId: `api_key_request_${Date.now()}`,
|
|
306
304
|
title: `${label} Setup`,
|
|
307
|
-
description: `Enter your API key and
|
|
305
|
+
description: `Enter your API key and model ID.`,
|
|
308
306
|
fields: [
|
|
309
307
|
{
|
|
310
308
|
id: 'model',
|
|
311
309
|
label: 'Model',
|
|
312
|
-
type: '
|
|
313
|
-
|
|
310
|
+
type: 'text',
|
|
311
|
+
description: 'Enter the model ID for this provider.',
|
|
312
|
+
placeholder: provider === 'openai'
|
|
313
|
+
? 'gpt-4o-mini'
|
|
314
|
+
: provider === 'anthropic'
|
|
315
|
+
? 'claude-3-5-sonnet-20241022'
|
|
316
|
+
: 'gemini-2.0-flash',
|
|
314
317
|
required: true,
|
|
315
|
-
defaultValue,
|
|
318
|
+
defaultValue: currentModelId || '',
|
|
316
319
|
},
|
|
317
320
|
{
|
|
318
321
|
id: 'apiKey',
|
|
@@ -333,12 +336,64 @@ export const openbotRuntime = (options) => (builder) => {
|
|
|
333
336
|
};
|
|
334
337
|
return;
|
|
335
338
|
}
|
|
339
|
+
if (metadata?.type === 'api_model_selection') {
|
|
340
|
+
const provider = String(metadata.provider);
|
|
341
|
+
const modelId = String(actionId).trim();
|
|
342
|
+
const registry = await fetchModelRegistry();
|
|
343
|
+
const providerData = registry?.providers?.[provider];
|
|
344
|
+
const label = providerData?.label || provider;
|
|
345
|
+
const modelLabel = providerData?.models.find((model) => model.id === modelId)?.label || modelId;
|
|
346
|
+
const link = PROVIDER_API_KEY_LINKS[provider] || '';
|
|
347
|
+
yield {
|
|
348
|
+
type: 'client:ui:widget',
|
|
349
|
+
data: {
|
|
350
|
+
widgetId: event.data.widgetId,
|
|
351
|
+
kind: 'message',
|
|
352
|
+
title: 'Model Selected',
|
|
353
|
+
body: `${modelLabel} was selected.`,
|
|
354
|
+
state: 'submitted',
|
|
355
|
+
display: 'collapsed',
|
|
356
|
+
disabled: true,
|
|
357
|
+
actions: [],
|
|
358
|
+
},
|
|
359
|
+
meta: { agentId: context.state.agentId, threadId },
|
|
360
|
+
};
|
|
361
|
+
yield {
|
|
362
|
+
type: 'client:ui:widget',
|
|
363
|
+
data: {
|
|
364
|
+
kind: 'form',
|
|
365
|
+
widgetId: `api_key_request_${Date.now()}`,
|
|
366
|
+
title: `${label} Setup`,
|
|
367
|
+
description: `Enter your API key to continue.`,
|
|
368
|
+
fields: [
|
|
369
|
+
{
|
|
370
|
+
id: 'apiKey',
|
|
371
|
+
label: 'API Key',
|
|
372
|
+
type: 'password',
|
|
373
|
+
description: `Get your key here: [${link}](${link})`,
|
|
374
|
+
placeholder: `sk-...`,
|
|
375
|
+
required: true,
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
submitLabel: 'Save & Continue',
|
|
379
|
+
metadata: {
|
|
380
|
+
type: 'api_key_request',
|
|
381
|
+
provider,
|
|
382
|
+
model: modelId,
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
meta: { agentId: context.state.agentId, threadId },
|
|
386
|
+
};
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
336
389
|
if (metadata?.type !== 'api_key_request')
|
|
337
390
|
return;
|
|
338
|
-
if (!values?.apiKey
|
|
391
|
+
if (!values?.apiKey)
|
|
339
392
|
return;
|
|
340
393
|
const provider = String(values.provider || metadata.provider);
|
|
341
|
-
const modelId = String(values.model).trim();
|
|
394
|
+
const modelId = String(values.model || metadata.model || '').trim();
|
|
395
|
+
if (!modelId)
|
|
396
|
+
return;
|
|
342
397
|
const apiKey = String(values.apiKey);
|
|
343
398
|
if (provider !== 'openai' && provider !== 'anthropic' && provider !== 'google') {
|
|
344
399
|
yield {
|
package/dist/tools/delegation.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { randomUUID } from
|
|
2
|
-
import { z } from
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { z } from "zod";
|
|
3
3
|
/**
|
|
4
4
|
* `delegation` — allows agents to delegate tasks to other agents.
|
|
5
5
|
*
|
|
@@ -9,29 +9,33 @@ import { z } from 'zod';
|
|
|
9
9
|
*/
|
|
10
10
|
const delegationToolDefinitions = {
|
|
11
11
|
delegate_task: {
|
|
12
|
-
description:
|
|
12
|
+
description: "Delegate a specific task or question to another specialized agent.",
|
|
13
13
|
inputSchema: z.object({
|
|
14
|
-
agentId: z
|
|
15
|
-
|
|
14
|
+
agentId: z
|
|
15
|
+
.string()
|
|
16
|
+
.describe('The ID of the agent to delegate to (e.g., "researcher", "coder").'),
|
|
17
|
+
prompt: z
|
|
18
|
+
.string()
|
|
19
|
+
.describe("The instructions or question for the delegated agent."),
|
|
16
20
|
}),
|
|
17
21
|
},
|
|
18
22
|
};
|
|
19
23
|
export const delegationPlugin = {
|
|
20
|
-
id:
|
|
21
|
-
name:
|
|
22
|
-
description:
|
|
24
|
+
id: "delegation",
|
|
25
|
+
name: "Delegation",
|
|
26
|
+
description: "Allows agents to call upon other agents to solve sub-tasks.",
|
|
23
27
|
toolDefinitions: delegationToolDefinitions,
|
|
24
28
|
factory: (pluginContext) => (builder) => {
|
|
25
29
|
// Handle the tool execution
|
|
26
|
-
builder.on(
|
|
30
|
+
builder.on("action:delegate_task", async function* (event, context) {
|
|
27
31
|
const delegateEvent = event;
|
|
28
32
|
// POLICY: Only the 'system' agent can delegate
|
|
29
33
|
if (context.state.agentId !== pluginContext.host.orchestratorAgentId) {
|
|
30
34
|
yield {
|
|
31
|
-
type:
|
|
35
|
+
type: "action:delegate_task:result",
|
|
32
36
|
data: {
|
|
33
37
|
success: false,
|
|
34
|
-
error:
|
|
38
|
+
error: "Only the system agent can delegate.",
|
|
35
39
|
},
|
|
36
40
|
meta: delegateEvent.meta,
|
|
37
41
|
};
|
|
@@ -43,7 +47,7 @@ export const delegationPlugin = {
|
|
|
43
47
|
return;
|
|
44
48
|
const runAgent = pluginContext.host.runAgent;
|
|
45
49
|
const runId = `dg_${randomUUID()}`;
|
|
46
|
-
let lastAgentOutput =
|
|
50
|
+
let lastAgentOutput = "";
|
|
47
51
|
// Queue to bridge the async onEvent callback to this generator
|
|
48
52
|
const eventQueue = [];
|
|
49
53
|
let resolveNext = null;
|
|
@@ -54,20 +58,19 @@ export const delegationPlugin = {
|
|
|
54
58
|
runId,
|
|
55
59
|
agentId,
|
|
56
60
|
event: {
|
|
57
|
-
type:
|
|
61
|
+
type: "agent:invoke",
|
|
58
62
|
data: {
|
|
59
|
-
role:
|
|
63
|
+
role: "user",
|
|
60
64
|
content: prompt,
|
|
61
65
|
agentId: agentId,
|
|
62
66
|
},
|
|
63
67
|
meta: {
|
|
68
|
+
channelId: context.state.channelId,
|
|
64
69
|
threadId: context.state.threadId,
|
|
65
70
|
parentAgentId: context.state.agentId,
|
|
66
71
|
parentToolCallId: toolCallId,
|
|
67
72
|
},
|
|
68
73
|
},
|
|
69
|
-
channelId: context.state.channelId,
|
|
70
|
-
threadId: context.state.threadId,
|
|
71
74
|
publicBaseUrl: pluginContext.publicBaseUrl,
|
|
72
75
|
// Child events are re-yielded to the parent harness, which persists them once.
|
|
73
76
|
persistEvents: false,
|
|
@@ -79,10 +82,10 @@ export const delegationPlugin = {
|
|
|
79
82
|
...outEvent.meta,
|
|
80
83
|
parentAgentId: context.state.agentId,
|
|
81
84
|
parentToolCallId: toolCallId,
|
|
82
|
-
}
|
|
85
|
+
},
|
|
83
86
|
};
|
|
84
87
|
eventQueue.push(enrichedEvent);
|
|
85
|
-
if (outEvent.type ===
|
|
88
|
+
if (outEvent.type === "agent:output") {
|
|
86
89
|
lastAgentOutput = outEvent.data.content;
|
|
87
90
|
}
|
|
88
91
|
// Wake up the generator loop if it's waiting
|
|
@@ -90,10 +93,12 @@ export const delegationPlugin = {
|
|
|
90
93
|
resolveNext();
|
|
91
94
|
resolveNext = null;
|
|
92
95
|
}
|
|
93
|
-
}
|
|
94
|
-
})
|
|
96
|
+
},
|
|
97
|
+
})
|
|
98
|
+
.catch((error) => {
|
|
95
99
|
console.error(`[delegation] Error in delegated run ${runId}:`, error);
|
|
96
|
-
})
|
|
100
|
+
})
|
|
101
|
+
.finally(() => {
|
|
97
102
|
isFinished = true;
|
|
98
103
|
if (resolveNext) {
|
|
99
104
|
resolveNext();
|
|
@@ -103,7 +108,9 @@ export const delegationPlugin = {
|
|
|
103
108
|
// Yield events from the delegated agent as they arrive
|
|
104
109
|
while (!isFinished || eventQueue.length > 0) {
|
|
105
110
|
if (eventQueue.length === 0) {
|
|
106
|
-
await new Promise(r => {
|
|
111
|
+
await new Promise((r) => {
|
|
112
|
+
resolveNext = r;
|
|
113
|
+
});
|
|
107
114
|
}
|
|
108
115
|
while (eventQueue.length > 0) {
|
|
109
116
|
yield eventQueue.shift();
|
|
@@ -113,7 +120,7 @@ export const delegationPlugin = {
|
|
|
113
120
|
await runPromise;
|
|
114
121
|
// Yield the result back to our own LLM runtime.
|
|
115
122
|
yield {
|
|
116
|
-
type:
|
|
123
|
+
type: "action:delegate_task:result",
|
|
117
124
|
data: {
|
|
118
125
|
success: true,
|
|
119
126
|
output: lastAgentOutput,
|
package/dist/types.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import type { Plugin as SdkPlugin, PluginContext as SdkPluginContext, OpenBotState as SdkOpenBotState, ToolActionEvent, PluginFactory as SdkPluginFactory, PluginBuilder, PluginHandlerContext, OpenBotEvent } from
|
|
2
|
-
export { definePlugin } from
|
|
3
|
-
export type { AgentInvokeEvent, AgentOutputEvent, ConfigSchema, OpenBotEvent, PluginBuilder, PluginFactory, PluginHandlerContext, Storage, ToolDefinition, ToolActionEvent, UIWidgetListItem, UIWidgetResponseEvent, } from
|
|
4
|
-
export type MemoryScopeAlias =
|
|
1
|
+
import type { Plugin as SdkPlugin, PluginContext as SdkPluginContext, OpenBotState as SdkOpenBotState, ToolActionEvent, PluginFactory as SdkPluginFactory, PluginBuilder, PluginHandlerContext, OpenBotEvent } from "@meetopenbot/plugin-sdk";
|
|
2
|
+
export { definePlugin } from "@meetopenbot/plugin-sdk";
|
|
3
|
+
export type { AgentInvokeEvent, AgentOutputEvent, ConfigSchema, OpenBotEvent, PluginBuilder, PluginFactory, PluginHandlerContext, Storage, ToolDefinition, ToolActionEvent, UIWidgetListItem, UIWidgetResponseEvent, } from "@meetopenbot/plugin-sdk";
|
|
4
|
+
export type MemoryScopeAlias = "global" | "agent" | "channel";
|
|
5
5
|
export type DelegateTaskEvent = ToolActionEvent<{
|
|
6
6
|
agentId: string;
|
|
7
7
|
prompt: string;
|
|
8
8
|
}> & {
|
|
9
|
-
type:
|
|
9
|
+
type: "action:delegate_task";
|
|
10
10
|
};
|
|
11
11
|
export type RenderWidgetEvent = ToolActionEvent<Record<string, unknown>> & {
|
|
12
|
-
type:
|
|
12
|
+
type: "action:render_widget";
|
|
13
13
|
};
|
|
14
14
|
/** Runtime state extends the SDK with fields used by the OpenBot agent plugin. */
|
|
15
15
|
export type OpenBotState = SdkOpenBotState & {
|
|
@@ -18,7 +18,7 @@ export type OpenBotState = SdkOpenBotState & {
|
|
|
18
18
|
userName?: string;
|
|
19
19
|
};
|
|
20
20
|
pendingToolCallIds?: string[];
|
|
21
|
-
threadDetails?: SdkOpenBotState[
|
|
21
|
+
threadDetails?: SdkOpenBotState["threadDetails"] & {
|
|
22
22
|
name?: string;
|
|
23
23
|
};
|
|
24
24
|
};
|
|
@@ -32,39 +32,24 @@ export type ActionBuilder = {
|
|
|
32
32
|
};
|
|
33
33
|
export declare function asActionBuilder(builder: PluginBuilder): ActionBuilder;
|
|
34
34
|
export interface PluginHost {
|
|
35
|
+
/** Run context (channelId, threadId) is passed on `event.meta`, not as top-level options. */
|
|
35
36
|
runAgent: (options: {
|
|
36
37
|
runId: string;
|
|
37
38
|
agentId: string;
|
|
38
39
|
event: OpenBotEvent;
|
|
39
|
-
channelId: string;
|
|
40
|
-
threadId?: string;
|
|
41
40
|
persistEvents?: boolean;
|
|
42
41
|
publicBaseUrl?: string;
|
|
43
42
|
onEvent: (event: OpenBotEvent, state?: OpenBotState) => Promise<void>;
|
|
44
43
|
}) => Promise<void>;
|
|
45
44
|
isCloudSystemAgent: (agentId: string) => boolean;
|
|
46
45
|
isCloudMode: () => boolean;
|
|
47
|
-
parseOpenbotAuthMode: (value: unknown) =>
|
|
48
|
-
resolveModelRegistry: () => Promise<{
|
|
49
|
-
providers?: Record<string, {
|
|
50
|
-
label: string;
|
|
51
|
-
models: Array<{
|
|
52
|
-
id: string;
|
|
53
|
-
label: string;
|
|
54
|
-
description: string;
|
|
55
|
-
}>;
|
|
56
|
-
}>;
|
|
57
|
-
}>;
|
|
58
|
-
listApiKeyProvidersFromRegistry: (registry: Awaited<ReturnType<PluginHost['resolveModelRegistry']>>) => Array<{
|
|
59
|
-
id: string;
|
|
60
|
-
label: string;
|
|
61
|
-
}>;
|
|
46
|
+
parseOpenbotAuthMode: (value: unknown) => "credits" | "byok";
|
|
62
47
|
saveConfig: (patch: Record<string, unknown>) => void;
|
|
63
48
|
getBaseDir: () => string;
|
|
64
49
|
resolvePath: (p: string) => string;
|
|
65
50
|
orchestratorAgentId: string;
|
|
66
51
|
openbotPluginId: string;
|
|
67
|
-
defaultCloudAuthMode:
|
|
52
|
+
defaultCloudAuthMode: "credits" | "byok";
|
|
68
53
|
}
|
|
69
54
|
/** Host context extends the SDK with OpenBot runtime wiring. */
|
|
70
55
|
export interface PluginContext extends SdkPluginContext {
|
|
@@ -72,8 +57,8 @@ export interface PluginContext extends SdkPluginContext {
|
|
|
72
57
|
abortSignal?: AbortSignal;
|
|
73
58
|
host: PluginHost;
|
|
74
59
|
}
|
|
75
|
-
export interface Plugin extends Omit<SdkPlugin,
|
|
76
|
-
configSchema?: SdkPlugin[
|
|
60
|
+
export interface Plugin extends Omit<SdkPlugin, "factory" | "configSchema"> {
|
|
61
|
+
configSchema?: SdkPlugin["configSchema"] | Record<string, unknown>;
|
|
77
62
|
factory: (context: PluginContext) => SdkPluginFactory;
|
|
78
63
|
}
|
|
79
64
|
/** Type-safe plugin definition for the extended OpenBot host context. */
|
package/dist/types.js
CHANGED