@meetopenbot/openbot 0.1.11 → 0.1.13

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/history.js CHANGED
@@ -44,6 +44,22 @@ function fillMissingToolResults(messages) {
44
44
  flushPending();
45
45
  return filled;
46
46
  }
47
+ function toolResultText(data) {
48
+ if (data && typeof data === 'object') {
49
+ const output = data.output;
50
+ if (typeof output === 'string' && output.trim())
51
+ return output;
52
+ try {
53
+ return JSON.stringify(data);
54
+ }
55
+ catch {
56
+ return 'No output';
57
+ }
58
+ }
59
+ if (typeof data === 'string' && data.trim())
60
+ return data;
61
+ return 'No output';
62
+ }
47
63
  /**
48
64
  * Converts a raw event log into a valid chain of ModelMessages for the AI SDK.
49
65
  *
@@ -75,7 +91,7 @@ export function eventsToModelMessages(events) {
75
91
  if (invokeEvent.data?.content && invokeEvent.data?.role) {
76
92
  messages.push({
77
93
  role: invokeEvent.data.role,
78
- content: invokeEvent.data.content
94
+ content: invokeEvent.data.content,
79
95
  });
80
96
  }
81
97
  break;
@@ -96,10 +112,7 @@ export function eventsToModelMessages(events) {
96
112
  const last = messages[messages.length - 1];
97
113
  if (last && last.role === 'assistant') {
98
114
  if (typeof last.content === 'string') {
99
- last.content = [
100
- { type: 'text', text: last.content },
101
- toolCall,
102
- ];
115
+ last.content = [{ type: 'text', text: last.content }, toolCall];
103
116
  }
104
117
  else if (Array.isArray(last.content)) {
105
118
  last.content.push(toolCall);
@@ -124,7 +137,7 @@ export function eventsToModelMessages(events) {
124
137
  toolName,
125
138
  output: {
126
139
  type: 'text',
127
- value: event?.data?.output || "No output", // ?.output is from delegation result
140
+ value: toolResultText(event.data),
128
141
  },
129
142
  };
130
143
  const last = messages[messages.length - 1];
package/dist/index.d.ts CHANGED
@@ -1,77 +1,4 @@
1
- export declare const OPENBOT_PLUGIN_ID = "@meetopenbot/openbot";
2
- /**
3
- * `@meetopenbot/openbot` — the standard, opinionated OpenBot agent runtime.
4
- *
5
- * Batteries-included: shell, memory, todo, storage tools, delegation, approval,
6
- * preview, and the LLM loop.
7
- */
8
- export declare const openbotPlugin: {
9
- id: string;
10
- name: string;
11
- description: string;
12
- configSchema: {
13
- type: "object";
14
- properties: {
15
- model: import("./model-registry.js").ModelConfigField;
16
- authMode?: {
17
- type: "string";
18
- description: string;
19
- enum: string[];
20
- default: string;
21
- } | undefined;
22
- };
23
- };
24
- toolDefinitions: {
25
- create_channel: {
26
- description: string;
27
- inputSchema: import("zod").ZodObject<{
28
- channelId: import("zod").ZodString;
29
- spec: import("zod").ZodOptional<import("zod").ZodString>;
30
- initialState: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
31
- cwd: import("zod").ZodOptional<import("zod").ZodString>;
32
- }, import("zod/v4/core").$strip>;
33
- };
34
- patch_channel_details: {
35
- description: string;
36
- inputSchema: import("zod").ZodObject<{
37
- state: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
38
- spec: import("zod").ZodOptional<import("zod").ZodString>;
39
- cwd: import("zod").ZodOptional<import("zod").ZodString>;
40
- }, import("zod/v4/core").$strip>;
41
- };
42
- patch_thread_details: {
43
- description: string;
44
- inputSchema: import("zod").ZodObject<{
45
- state: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
46
- }, import("zod/v4/core").$strip>;
47
- };
48
- create_variable: {
49
- description: string;
50
- inputSchema: import("zod").ZodObject<{
51
- key: import("zod").ZodString;
52
- value: import("zod").ZodString;
53
- secret: import("zod").ZodOptional<import("zod").ZodBoolean>;
54
- }, import("zod/v4/core").$strip>;
55
- };
56
- delete_variable: {
57
- description: string;
58
- inputSchema: import("zod").ZodObject<{
59
- key: import("zod").ZodString;
60
- }, import("zod/v4/core").$strip>;
61
- };
62
- delete_channel: {
63
- description: string;
64
- inputSchema: import("zod").ZodObject<{
65
- channelId: import("zod").ZodString;
66
- }, import("zod/v4/core").$strip>;
67
- };
68
- get_workspace_file_url: {
69
- description: string;
70
- inputSchema: import("zod").ZodObject<{
71
- path: import("zod").ZodString;
72
- }, import("zod/v4/core").$strip>;
73
- };
74
- };
75
- factory: (context: import("./types.js").PluginContext) => (builder: import("melony").MelonyBuilder<import("@meetopenbot/plugin-sdk").OpenBotState, import("./types.js").OpenBotEvent>) => void;
76
- };
77
- export default openbotPlugin;
1
+ import type { Plugin } from '@meetopenbot/plugin-sdk';
2
+ declare const plugin: Plugin;
3
+ export { plugin };
4
+ export default plugin;
@@ -27,7 +27,7 @@ export const OPENBOT_SYSTEM_PROMPT = [
27
27
  '- Do not stop with open `pending` or `in_progress` items unless you are blocked and have told the user why.',
28
28
  '',
29
29
  '# OPERATIONAL GUIDELINES',
30
- '- **Channel and Threads**: The main way to communicate and act is through channels and threads. There might be a channel called "uncategorized" for general purpose communication.',
30
+ '- **Channel and Threads**: The main way to communicate and act is through channels and threads. There is a channel called "general" for getting started and conversations without a dedicated channel.',
31
31
  '- **Delegation**: You can delegate tasks to any specialized agent in the `INSTALLED AGENTS` list using the `delegate` tool.',
32
32
  '- **Durable Memory**: Use the `remember` tool to store important facts, preferences, or project details that should persist across sessions.',
33
33
  '- **Hub-and-Spoke**: Specialized agents cannot communicate directly; as coordinator, you must pass relevant data from one agent to another.',
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { spawn } from 'node:child_process';
3
3
  import { randomUUID } from 'node:crypto';
4
+ import path from 'node:path';
4
5
  import { asActionBuilder } from '../types.js';
5
6
  const DEFAULT_TIMEOUT_MS = 120000;
6
7
  const FOREGROUND_DEV_TIMEOUT_MS = 5000;
@@ -82,9 +83,15 @@ const shellToolDefinitions = {
82
83
  };
83
84
  const shellQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
84
85
  let resolvePathFn = (p) => p;
86
+ const isUsableExecDir = (value) => path.isAbsolute(value) || value.startsWith('~/');
85
87
  const resolveCwd = (context, execDir) => {
86
- const raw = (typeof execDir === 'string' && execDir.trim()) ||
87
- context.state.channelDetails?.cwd ||
88
+ const channelCwd = typeof context.state.channelDetails?.cwd === 'string'
89
+ ? context.state.channelDetails.cwd.trim()
90
+ : '';
91
+ const requested = typeof execDir === 'string' ? execDir.trim() : '';
92
+ const raw = (requested && isUsableExecDir(requested) ? requested : '') ||
93
+ channelCwd ||
94
+ requested ||
88
95
  process.cwd();
89
96
  return resolvePathFn(raw);
90
97
  };
@@ -1,6 +1,35 @@
1
1
  import z from 'zod';
2
2
  import { asActionBuilder } from '../types.js';
3
3
  import { buildWorkspaceFileUrl } from '../utils/workspace-url.js';
4
+ function normalizeChannelId(raw) {
5
+ return raw
6
+ .trim()
7
+ .toLowerCase()
8
+ .replace(/[^a-z0-9]+/g, '-')
9
+ .replace(/(^-|-$)/g, '');
10
+ }
11
+ function displayNameFromChannelId(channelId) {
12
+ return channelId
13
+ .split('-')
14
+ .filter(Boolean)
15
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
16
+ .join(' ');
17
+ }
18
+ function createChannelWidget(args) {
19
+ return {
20
+ type: 'client:ui:widget',
21
+ data: {
22
+ widgetId: args.widgetId,
23
+ kind: 'message',
24
+ title: 'create_channel',
25
+ description: args.channelId || undefined,
26
+ body: args.body,
27
+ display: 'collapsed',
28
+ state: args.state,
29
+ },
30
+ meta: args.meta,
31
+ };
32
+ }
4
33
  const storageToolDefinitions = {
5
34
  create_channel: {
6
35
  description: 'Create a new channel. Use when the user intent is clearly different from the current channel and should be split. Always confirm before creating. Skip for simple Q&A.',
@@ -8,6 +37,10 @@ const storageToolDefinitions = {
8
37
  channelId: z
9
38
  .string()
10
39
  .describe('Unique channel ID (e.g. product-launch, backend-platform, channel_roadmap).'),
40
+ name: z
41
+ .string()
42
+ .optional()
43
+ .describe('Optional display name. Defaults to a title-cased channel ID.'),
11
44
  spec: z
12
45
  .string()
13
46
  .optional()
@@ -15,11 +48,7 @@ const storageToolDefinitions = {
15
48
  initialState: z
16
49
  .record(z.string(), z.unknown())
17
50
  .optional()
18
- .describe('Optional initial state object for the channel.'),
19
- cwd: z
20
- .string()
21
- .optional()
22
- .describe('Optional initial current working directory for the channel. Defaults to an absolute path under ~/openbot/{channelId}.'),
51
+ .describe('Optional initial state object for the channel. Do not set cwd; the runtime assigns the workspace path.'),
23
52
  }),
24
53
  },
25
54
  patch_channel_details: {
@@ -36,9 +65,7 @@ const storageToolDefinitions = {
36
65
  .describe('Markdown content for the channel specification (SPEC.md). Use for goals and rules.'),
37
66
  cwd: z.string().optional().describe('Current working directory for the channel.'),
38
67
  })
39
- .refine((value) => value.state !== undefined ||
40
- value.spec !== undefined ||
41
- value.cwd !== undefined, { message: 'Provide at least one of state, spec, or cwd.' }),
68
+ .refine((value) => value.state !== undefined || value.spec !== undefined || value.cwd !== undefined, { message: 'Provide at least one of state, spec, or cwd.' }),
42
69
  },
43
70
  patch_thread_details: {
44
71
  description: 'Patch current thread details (state). Use for thread metadata such as `name` or `isSmartNamed`. For multi-step task tracking, use `todo_write` instead.',
@@ -84,53 +111,114 @@ export function registerStorageTools(context) {
84
111
  return (builder) => {
85
112
  const actions = asActionBuilder(builder);
86
113
  actions.on('create_channel', async function* (event, context) {
87
- const { channelId, spec, initialState, cwd } = event.data;
88
- const rawChannelId = (channelId || '').trim();
89
- const channelSpec = typeof spec === 'string' ? spec : '';
90
- const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
114
+ const { channelId, name, spec, initialState } = event.data;
115
+ const rawChannelId = normalizeChannelId(channelId || '');
116
+ const resultMeta = {
117
+ ...(event.meta || {}),
118
+ agentId: context.state.agentId,
119
+ threadId: event.meta?.threadId || context.state.threadId,
120
+ };
121
+ const widgetId = typeof event.meta?.toolCallId === 'string'
122
+ ? event.meta.toolCallId
123
+ : `create_channel:${rawChannelId || Date.now()}`;
91
124
  if (!rawChannelId) {
125
+ const error = 'channelId is required';
126
+ yield createChannelWidget({
127
+ widgetId,
128
+ channelId: '',
129
+ body: error,
130
+ state: 'error',
131
+ meta: resultMeta,
132
+ });
92
133
  yield {
93
134
  type: 'action:create_channel:result',
94
- data: { success: false, channelId: '', channelUrl: '' },
135
+ data: {
136
+ success: false,
137
+ channelId: '',
138
+ channelUrl: '',
139
+ error,
140
+ output: error,
141
+ },
95
142
  meta: resultMeta,
96
143
  };
97
144
  return;
98
145
  }
99
146
  const channelUrl = `/channels/${rawChannelId}`;
100
- const mergedInitial = { ...(initialState || {}) };
147
+ const displayName = typeof name === 'string' && name.trim()
148
+ ? name.trim()
149
+ : typeof initialState?.name === 'string' && initialState.name.trim()
150
+ ? initialState.name.trim()
151
+ : displayNameFromChannelId(rawChannelId);
152
+ const mergedInitial = {
153
+ ...(initialState || {}),
154
+ name: displayName,
155
+ };
156
+ delete mergedInitial.cwd;
157
+ const channelSpec = typeof spec === 'string' && spec.trim() ? spec : `# ${displayName}\n\n`;
158
+ yield createChannelWidget({
159
+ widgetId,
160
+ channelId: rawChannelId,
161
+ body: 'Creating…',
162
+ state: 'open',
163
+ meta: resultMeta,
164
+ });
101
165
  try {
102
166
  await storage.createChannel({
103
167
  channelId: rawChannelId,
104
168
  spec: channelSpec,
105
169
  initialState: mergedInitial,
106
- cwd,
107
170
  });
108
- yield {
109
- type: 'action:create_channel:result',
110
- data: { success: true, channelId: rawChannelId, channelUrl },
171
+ const output = `Created channel \`${rawChannelId}\`.`;
172
+ yield createChannelWidget({
173
+ widgetId,
174
+ channelId: rawChannelId,
175
+ body: output,
176
+ state: 'submitted',
111
177
  meta: resultMeta,
112
- };
178
+ });
113
179
  yield {
114
- type: 'agent:output',
115
- data: { content: `Created channel \`${rawChannelId}\`.` },
180
+ type: 'action:create_channel:result',
181
+ data: { success: true, channelId: rawChannelId, channelUrl, output },
116
182
  meta: resultMeta,
117
183
  };
118
184
  }
119
- catch {
185
+ catch (error) {
186
+ const message = error instanceof Error ? error.message : 'Unknown error';
187
+ const output = `Failed to create channel: ${message}`;
188
+ yield createChannelWidget({
189
+ widgetId,
190
+ channelId: rawChannelId,
191
+ body: output,
192
+ state: 'error',
193
+ meta: resultMeta,
194
+ });
120
195
  yield {
121
196
  type: 'action:create_channel:result',
122
- data: { success: false, channelId: rawChannelId, channelUrl },
197
+ data: {
198
+ success: false,
199
+ channelId: rawChannelId,
200
+ channelUrl,
201
+ error: message,
202
+ output,
203
+ },
123
204
  meta: resultMeta,
124
205
  };
125
206
  }
126
207
  });
127
208
  actions.on('delete_channel', async function* (event, context) {
128
209
  const rawChannelId = (event.data?.channelId || '').trim();
129
- const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
210
+ const resultMeta = {
211
+ ...(event.meta || {}),
212
+ agentId: context.state.agentId,
213
+ };
130
214
  if (!rawChannelId) {
131
215
  yield {
132
216
  type: 'action:delete_channel:result',
133
- data: { success: false, channelId: '', error: 'channelId is required' },
217
+ data: {
218
+ success: false,
219
+ channelId: '',
220
+ error: 'channelId is required',
221
+ },
134
222
  meta: resultMeta,
135
223
  };
136
224
  return;
@@ -163,11 +251,18 @@ export function registerStorageTools(context) {
163
251
  actions.on('update_channel', async function* (event, context) {
164
252
  const data = event.data;
165
253
  const targetChannelId = (data.channelId || context.state.channelId || '').trim();
166
- const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
254
+ const resultMeta = {
255
+ ...(event.meta || {}),
256
+ agentId: context.state.agentId,
257
+ };
167
258
  if (!targetChannelId) {
168
259
  yield {
169
260
  type: 'action:update_channel:result',
170
- data: { success: false, channelId: '', updatedFields: [] },
261
+ data: {
262
+ success: false,
263
+ channelId: '',
264
+ updatedFields: [],
265
+ },
171
266
  meta: resultMeta,
172
267
  };
173
268
  return;
@@ -184,7 +279,10 @@ export function registerStorageTools(context) {
184
279
  }
185
280
  try {
186
281
  if (updatedFields.length > 0) {
187
- await storage.patchChannelState({ channelId: targetChannelId, state: patch });
282
+ await storage.patchChannelState({
283
+ channelId: targetChannelId,
284
+ state: patch,
285
+ });
188
286
  }
189
287
  if (targetChannelId === context.state.channelId) {
190
288
  context.state.channelDetails = await storage.getChannelDetails({
@@ -207,7 +305,10 @@ export function registerStorageTools(context) {
207
305
  });
208
306
  actions.on('patch_channel_details', async function* (event, context) {
209
307
  const updatedFields = [];
210
- const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
308
+ const resultMeta = {
309
+ ...(event.meta || {}),
310
+ agentId: context.state.agentId,
311
+ };
211
312
  const data = event.data;
212
313
  try {
213
314
  if (data.state !== undefined) {
@@ -235,13 +336,13 @@ export function registerStorageTools(context) {
235
336
  channelId: context.state.channelId,
236
337
  });
237
338
  yield {
238
- type: "client:ui:widget",
339
+ type: 'client:ui:widget',
239
340
  data: {
240
- widgetId: "patch-channel-details-result" + Date.now(),
241
- kind: "message",
242
- title: "Channel details updated.",
341
+ widgetId: 'patch-channel-details-result' + Date.now(),
342
+ kind: 'message',
343
+ title: 'Channel details updated.',
243
344
  body: `The channel details have been updated. ${updatedFields.join(', ')}`,
244
- display: "collapsed",
345
+ display: 'collapsed',
245
346
  },
246
347
  meta: resultMeta,
247
348
  };
@@ -261,7 +362,10 @@ export function registerStorageTools(context) {
261
362
  });
262
363
  actions.on('patch_thread_details', async function* (event, context) {
263
364
  const updatedFields = [];
264
- const resultMeta = { ...(event.meta || {}), agentId: context.state.agentId };
365
+ const resultMeta = {
366
+ ...(event.meta || {}),
367
+ agentId: context.state.agentId,
368
+ };
265
369
  try {
266
370
  if (!context.state.threadId) {
267
371
  throw new Error('Missing threadId in state for patch_thread_details');
@@ -299,22 +403,42 @@ export function registerStorageTools(context) {
299
403
  if (!filePath) {
300
404
  yield {
301
405
  type: 'action:get_workspace_file_url:result',
302
- data: { success: false, path: '', error: 'Path is required', output: 'Path is required' },
406
+ data: {
407
+ success: false,
408
+ path: '',
409
+ error: 'Path is required',
410
+ output: 'Path is required',
411
+ },
303
412
  meta: { ...(event.meta || {}), toolCallId },
304
413
  };
305
414
  return;
306
415
  }
307
416
  try {
308
- const { size, mimeType } = await storage.getChannelFileStat({ channelId, path: filePath });
417
+ const { size, mimeType } = await storage.getChannelFileStat({
418
+ channelId,
419
+ path: filePath,
420
+ });
309
421
  const url = buildWorkspaceFileUrl({
310
422
  baseUrl: resolvePublicBaseUrl(),
311
423
  channelId,
312
424
  filePath,
313
425
  });
314
- const output = JSON.stringify({ path: filePath, url, mimeType, size });
426
+ const output = JSON.stringify({
427
+ path: filePath,
428
+ url,
429
+ mimeType,
430
+ size,
431
+ });
315
432
  yield {
316
433
  type: 'action:get_workspace_file_url:result',
317
- data: { success: true, path: filePath, url, mimeType, size, output },
434
+ data: {
435
+ success: true,
436
+ path: filePath,
437
+ url,
438
+ mimeType,
439
+ size,
440
+ output,
441
+ },
318
442
  meta: { ...(event.meta || {}), toolCallId },
319
443
  };
320
444
  }
@@ -322,7 +446,12 @@ export function registerStorageTools(context) {
322
446
  const message = error instanceof Error ? error.message : 'Unknown error';
323
447
  yield {
324
448
  type: 'action:get_workspace_file_url:result',
325
- data: { success: false, path: filePath, error: message, output: message },
449
+ data: {
450
+ success: false,
451
+ path: filePath,
452
+ error: message,
453
+ output: message,
454
+ },
326
455
  meta: { ...(event.meta || {}), toolCallId },
327
456
  };
328
457
  }
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@meetopenbot/openbot",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Monolithic OpenBot agent runtime with batteries-included tools.",
5
5
  "type": "module",
6
- "main": "dist/index.js",
7
- "types": "dist/index.d.ts",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
8
  "exports": {
9
- ".": "./dist/index.js"
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
10
14
  },
11
15
  "publishConfig": {
12
16
  "access": "public"
@@ -15,12 +19,15 @@
15
19
  "dist"
16
20
  ],
17
21
  "scripts": {
18
- "build": "tsc"
22
+ "build": "tsc && node ../../scripts/write-plugin-declaration.mjs",
23
+ "dev": "tsc --watch --preserveWatchOutput",
24
+ "typecheck": "tsc --noEmit",
25
+ "prepack": "pnpm build"
19
26
  },
20
27
  "dependencies": {
21
28
  "@ai-sdk/anthropic": "^3.0.33",
22
29
  "@ai-sdk/openai": "^3.0.13",
23
- "@meetopenbot/plugin-sdk": "^0.1.6",
30
+ "@meetopenbot/plugin-sdk": "workspace:^",
24
31
  "ai": "^6.0.42",
25
32
  "zod": "^4.3.5"
26
33
  },
@@ -1,5 +0,0 @@
1
- export type OpenbotAuthMode = 'credits' | 'byok';
2
- /** True when this runtime is a platform-managed cloud deployment. */
3
- export declare const isCloudMode: () => boolean;
4
- /** Default auth mode: Credits on cloud, BYOK locally. */
5
- export declare const defaultAuthMode: () => OpenbotAuthMode;
package/dist/context.d.ts DELETED
@@ -1,11 +0,0 @@
1
- import { OpenBotState } from './types.js';
2
- export declare const DEFAULT_CONTEXT_BUDGET = 8000;
3
- export declare const MAX_CONTEXT_FILES = 50;
4
- /**
5
- * Returns the known context window budget (in tokens) for a given model string.
6
- */
7
- export declare const getContextBudgetForModel: (modelString: string) => number;
8
- /**
9
- * Simplified context builder for MVP.
10
- */
11
- export declare function buildContext(state: OpenBotState, storage?: Record<string, any>): Promise<string>;
@@ -1,16 +0,0 @@
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' | 'google' | 'deepseek';
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;
package/dist/history.d.ts DELETED
@@ -1,9 +0,0 @@
1
- import { OpenBotEvent } from './types.js';
2
- import { type ModelMessage } from 'ai';
3
- /**
4
- * Converts a raw event log into a valid chain of ModelMessages for the AI SDK.
5
- *
6
- * This is a basic implementation that maps events to messages and filters out
7
- * events from sub-processes (delegation) to avoid duplication in history.
8
- */
9
- export declare function eventsToModelMessages(events: OpenBotEvent[]): ModelMessage[];
@@ -1,35 +0,0 @@
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>;
package/dist/model.d.ts DELETED
@@ -1,6 +0,0 @@
1
- import type { LanguageModel } from 'ai';
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/runtime.d.ts DELETED
@@ -1,25 +0,0 @@
1
- import { PluginHost, PluginFactory } from './types.js';
2
- export interface OpenBotRuntimeOptions {
3
- /** Provider model string (e.g. `openai/gpt-4o-mini`, `anthropic/claude-3-5-sonnet-20240620`). */
4
- model?: string;
5
- /** Cloud system agent auth mode; self-hosted agents always use BYOK. */
6
- authMode?: 'credits' | 'byok';
7
- agentId?: string;
8
- storage?: Record<string, any>;
9
- /** Tool definitions merged from all tool plugins attached to this agent. */
10
- toolDefinitions?: Record<string, {
11
- description: string;
12
- inputSchema: unknown;
13
- }>;
14
- /** Fires when the run is stopped; cancels the in-flight LLM call. */
15
- abortSignal?: AbortSignal;
16
- host: PluginHost;
17
- }
18
- /**
19
- * OpenBot agent runtime.
20
- *
21
- * - One `generateText` call per `runLLM` (tools have no `execute`; SDK stops at 1 step).
22
- * - Tool calls become `action:*` events; plugins emit `:result` when done.
23
- * - When a full batch of results is in, `runLLM` runs again with updated history.
24
- */
25
- export declare const openbotRuntime: (options: OpenBotRuntimeOptions) => PluginFactory;
@@ -1 +0,0 @@
1
- export declare const OPENBOT_SYSTEM_PROMPT: string;
@@ -1,3 +0,0 @@
1
- import type { Plugin } from '../types.js';
2
- export declare const approvalPlugin: Plugin;
3
- export default approvalPlugin;
@@ -1,3 +0,0 @@
1
- import type { Plugin } from '../types.js';
2
- export declare const bashPlugin: Plugin;
3
- export default bashPlugin;
@@ -1,3 +0,0 @@
1
- import type { Plugin } from "../types.js";
2
- export declare const delegationPlugin: Plugin;
3
- export default delegationPlugin;
@@ -1,3 +0,0 @@
1
- import type { Plugin } from '../types.js';
2
- export declare const memoryPlugin: Plugin;
3
- export default memoryPlugin;
@@ -1,4 +0,0 @@
1
- import type { Plugin } from '../types.js';
2
- export declare const stopPreviewForChannel: (channelId: string) => void;
3
- export declare const previewPlugin: Plugin;
4
- export default previewPlugin;
@@ -1,57 +0,0 @@
1
- import z from 'zod';
2
- import type { PluginBuilder, PluginContext } from '../types.js';
3
- export declare function registerStorageTools(context: PluginContext): (builder: PluginBuilder) => void;
4
- export declare const storageToolPlugin: {
5
- toolDefinitions: {
6
- create_channel: {
7
- description: string;
8
- inputSchema: z.ZodObject<{
9
- channelId: z.ZodString;
10
- spec: z.ZodOptional<z.ZodString>;
11
- initialState: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
12
- cwd: z.ZodOptional<z.ZodString>;
13
- }, z.z.core.$strip>;
14
- };
15
- patch_channel_details: {
16
- description: string;
17
- inputSchema: z.ZodObject<{
18
- state: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
19
- spec: z.ZodOptional<z.ZodString>;
20
- cwd: z.ZodOptional<z.ZodString>;
21
- }, z.z.core.$strip>;
22
- };
23
- patch_thread_details: {
24
- description: string;
25
- inputSchema: z.ZodObject<{
26
- state: z.ZodRecord<z.ZodString, z.ZodUnknown>;
27
- }, z.z.core.$strip>;
28
- };
29
- create_variable: {
30
- description: string;
31
- inputSchema: z.ZodObject<{
32
- key: z.ZodString;
33
- value: z.ZodString;
34
- secret: z.ZodOptional<z.ZodBoolean>;
35
- }, z.z.core.$strip>;
36
- };
37
- delete_variable: {
38
- description: string;
39
- inputSchema: z.ZodObject<{
40
- key: z.ZodString;
41
- }, z.z.core.$strip>;
42
- };
43
- delete_channel: {
44
- description: string;
45
- inputSchema: z.ZodObject<{
46
- channelId: z.ZodString;
47
- }, z.z.core.$strip>;
48
- };
49
- get_workspace_file_url: {
50
- description: string;
51
- inputSchema: z.ZodObject<{
52
- path: z.ZodString;
53
- }, z.z.core.$strip>;
54
- };
55
- };
56
- register: typeof registerStorageTools;
57
- };
@@ -1,28 +0,0 @@
1
- export type TodoStatus = 'pending' | 'in_progress' | 'completed' | 'cancelled';
2
- export type TodoItem = {
3
- id: string;
4
- content: string;
5
- status: TodoStatus;
6
- };
7
- export type TodoList = {
8
- items: TodoItem[];
9
- updatedAt: string;
10
- };
11
- export declare const MAX_TODO_ITEMS = 20;
12
- /**
13
- * Validate and normalize a todo list write. Throws on invalid input.
14
- * Enforces: non-empty content, known statuses, unique ids, max size,
15
- * and at most one `in_progress` item.
16
- */
17
- export declare function validateTodoItems(items: TodoItem[]): TodoItem[];
18
- export declare const todoService: {
19
- getTodos: (args: {
20
- channelId: string;
21
- threadId: string;
22
- }) => Promise<TodoList>;
23
- writeTodos: (args: {
24
- channelId: string;
25
- threadId: string;
26
- items: TodoItem[];
27
- }) => Promise<TodoList>;
28
- };
@@ -1,3 +0,0 @@
1
- import type { Plugin } from '../types.js';
2
- export declare const todoPlugin: Plugin;
3
- export default todoPlugin;
@@ -1,9 +0,0 @@
1
- import type { Plugin } from '../types.js';
2
- /**
3
- * `ui` — provides a tool for the agent to render interactive UI widgets.
4
- *
5
- * The model can choose which widget to render (form, choice, list, message)
6
- * depending on the situation.
7
- */
8
- export declare const uiPlugin: Plugin;
9
- export default uiPlugin;
package/dist/types.d.ts DELETED
@@ -1,65 +0,0 @@
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
- export type DelegateTaskEvent = ToolActionEvent<{
6
- agentId: string;
7
- prompt: string;
8
- }> & {
9
- type: "action:delegate_task";
10
- };
11
- export type RenderWidgetEvent = ToolActionEvent<Record<string, unknown>> & {
12
- type: "action:render_widget";
13
- };
14
- /** Runtime state extends the SDK with fields used by the OpenBot agent plugin. */
15
- export type OpenBotState = SdkOpenBotState & {
16
- model?: string;
17
- currentUser?: {
18
- userName?: string;
19
- };
20
- pendingToolCallIds?: string[];
21
- threadDetails?: SdkOpenBotState["threadDetails"] & {
22
- name?: string;
23
- };
24
- };
25
- /**
26
- * Builder surface for registering `action:*` handlers.
27
- * SDK `OpenBotEvent` includes a `type: string` fallback that prevents Melony from
28
- * narrowing specific action events; this helper keeps handlers type-safe.
29
- */
30
- export type ActionBuilder = {
31
- on<TData = Record<string, unknown>>(action: string, handler: (event: ToolActionEvent<TData>, context: PluginHandlerContext) => AsyncGenerator<OpenBotEvent> | void): void;
32
- };
33
- export declare function asActionBuilder(builder: PluginBuilder): ActionBuilder;
34
- export interface PluginHost {
35
- /** Run context (channelId, threadId) is passed on `event.meta`, not as top-level options. */
36
- runAgent: (options: {
37
- runId: string;
38
- agentId: string;
39
- event: OpenBotEvent;
40
- persistEvents?: boolean;
41
- publicBaseUrl?: string;
42
- onEvent: (event: OpenBotEvent, state?: OpenBotState) => Promise<void>;
43
- }) => Promise<void>;
44
- isCloudSystemAgent: (agentId: string) => boolean;
45
- isCloudMode: () => boolean;
46
- parseOpenbotAuthMode: (value: unknown) => "credits" | "byok";
47
- saveConfig: (patch: Record<string, unknown>) => void;
48
- getBaseDir: () => string;
49
- resolvePath: (p: string) => string;
50
- orchestratorAgentId: string;
51
- openbotPluginId: string;
52
- defaultCloudAuthMode: "credits" | "byok";
53
- }
54
- /** Host context extends the SDK with OpenBot runtime wiring. */
55
- export interface PluginContext extends SdkPluginContext {
56
- publicBaseUrl: string;
57
- abortSignal?: AbortSignal;
58
- host: PluginHost;
59
- }
60
- export interface Plugin extends Omit<SdkPlugin, "factory" | "configSchema"> {
61
- configSchema?: SdkPlugin["configSchema"] | Record<string, unknown>;
62
- factory: (context: PluginContext) => SdkPluginFactory;
63
- }
64
- /** Type-safe plugin definition for the extended OpenBot host context. */
65
- export declare function defineOpenbotPlugin<T extends Plugin>(definition: T): T;
@@ -1,3 +0,0 @@
1
- export declare const DEFAULT_CHANNELS_DIR = "channels";
2
- export declare function resolvePath(p: string): string;
3
- export declare function getBaseDir(): string;
@@ -1,5 +0,0 @@
1
- export declare function buildWorkspaceFileUrl(args: {
2
- baseUrl: string;
3
- channelId: string;
4
- filePath: string;
5
- }): string;