openbot 0.2.14 → 0.3.1
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/agents/openbot/index.js +76 -0
- package/dist/agents/openbot/middleware/approval.js +132 -0
- package/dist/agents/openbot/runtime.js +289 -0
- package/dist/agents/openbot/system-prompt.js +32 -0
- package/dist/agents/openbot/tools/delegation.js +78 -0
- package/dist/agents/openbot/tools/mcp.js +99 -0
- package/dist/agents/openbot/tools/shell.js +91 -0
- package/dist/agents/openbot/tools/storage.js +75 -0
- package/dist/agents/openbot/tools/ui.js +176 -0
- package/dist/agents/system.js +20 -93
- package/dist/app/cli.js +1 -1
- package/dist/app/config.js +4 -1
- package/dist/app/server.js +15 -8
- package/dist/bus/agent-package.js +1 -0
- package/dist/bus/plugin.js +1 -0
- package/dist/bus/services.js +711 -0
- package/dist/bus/types.js +1 -0
- package/dist/harness/context.js +250 -0
- package/dist/harness/event-normalizer.js +59 -0
- package/dist/harness/orchestrator.js +27 -227
- package/dist/harness/process.js +25 -3
- package/dist/harness/queue-processor.js +227 -0
- package/dist/harness/runtime-factory.js +103 -0
- package/dist/plugins/ai-sdk/index.js +37 -0
- package/dist/plugins/ai-sdk/runtime.js +402 -0
- package/dist/plugins/ai-sdk/system-prompt.js +3 -0
- package/dist/plugins/ai-sdk.js +277 -87
- package/dist/plugins/approval/index.js +159 -0
- package/dist/plugins/approval.js +163 -0
- package/dist/plugins/delegation/index.js +79 -0
- package/dist/plugins/delegation.js +67 -11
- package/dist/plugins/mcp/index.js +108 -0
- package/dist/plugins/memory/index.js +71 -0
- package/dist/plugins/shell/index.js +99 -0
- package/dist/plugins/shell.js +123 -0
- package/dist/plugins/storage-tools/index.js +85 -0
- package/dist/plugins/storage.js +240 -5
- package/dist/plugins/ui/index.js +184 -0
- package/dist/plugins/ui.js +185 -21
- package/dist/registry/agents.js +138 -0
- package/dist/registry/plugins.js +93 -50
- package/dist/services/agent-packages.js +103 -0
- package/dist/services/memory.js +152 -0
- package/dist/services/plugins.js +98 -0
- package/dist/services/storage.js +366 -94
- package/docs/agents.md +52 -65
- package/docs/architecture.md +1 -1
- package/docs/plugins.md +70 -58
- package/docs/templates/AGENT.example.md +57 -0
- package/package.json +8 -7
- package/src/app/cli.ts +1 -1
- package/src/app/config.ts +14 -4
- package/src/app/server.ts +23 -10
- package/src/app/types.ts +445 -16
- package/src/assets/icon.svg +4 -1
- package/src/bus/plugin.ts +67 -0
- package/src/bus/services.ts +786 -0
- package/src/bus/types.ts +160 -0
- package/src/harness/context.ts +293 -0
- package/src/harness/event-normalizer.ts +82 -0
- package/src/harness/orchestrator.ts +35 -273
- package/src/harness/process.ts +28 -4
- package/src/harness/queue-processor.ts +309 -0
- package/src/harness/runtime-factory.ts +125 -0
- package/src/plugins/ai-sdk/index.ts +44 -0
- package/src/plugins/ai-sdk/runtime.ts +484 -0
- package/src/plugins/ai-sdk/system-prompt.ts +4 -0
- package/src/plugins/approval/index.ts +228 -0
- package/src/plugins/delegation/index.ts +94 -0
- package/src/plugins/mcp/index.ts +128 -0
- package/src/plugins/memory/index.ts +85 -0
- package/src/plugins/shell/index.ts +123 -0
- package/src/plugins/storage-tools/index.ts +101 -0
- package/src/plugins/ui/index.ts +227 -0
- package/src/registry/plugins.ts +108 -55
- package/src/services/memory.ts +213 -0
- package/src/services/plugins.ts +133 -0
- package/src/services/storage.ts +472 -137
- package/src/agents/system.ts +0 -112
- package/src/plugins/ai-sdk.ts +0 -197
- package/src/plugins/delegation.ts +0 -60
- package/src/plugins/mcp.ts +0 -154
- package/src/plugins/storage.ts +0 -725
- package/src/plugins/ui.ts +0 -57
package/docs/agents.md
CHANGED
|
@@ -1,83 +1,70 @@
|
|
|
1
1
|
# Agents
|
|
2
2
|
|
|
3
|
-
Agents are
|
|
3
|
+
Agents are participants on the OpenBot bus. An agent is just a markdown file
|
|
4
|
+
(`AGENT.md`) that lists which **plugins** compose it. Plugins provide both the
|
|
5
|
+
LLM runtime and the tools the agent can call.
|
|
4
6
|
|
|
5
|
-
##
|
|
7
|
+
## Authoring an agent
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
The
|
|
9
|
+
You define an agent with a YAML-fronted markdown file at
|
|
10
|
+
`~/.openbot/agents/<agentId>/AGENT.md`. The folder name is the agent id.
|
|
9
11
|
|
|
10
|
-
### OS Agent (`os`)
|
|
11
|
-
Specialized in low-level system interactions. It uses the `shell` and `file-system` plugins to execute commands and manage files. (Implementation: `src/agents/system.ts`)
|
|
12
|
-
|
|
13
|
-
### Topic Agent (`topic`)
|
|
14
|
-
A utility agent that observes completions and automatically generates concise titles for conversations to keep the workspace organized.
|
|
15
|
-
|
|
16
|
-
### Codex Agent (`codex`)
|
|
17
|
-
A world-class software engineer agent. It assists with architectural decisions, refactoring, and debugging, with full access to the development environment.
|
|
18
|
-
|
|
19
|
-
## YAML Agents
|
|
20
|
-
|
|
21
|
-
You can define custom agents using YAML files in `~/.openbot/agents/`.
|
|
22
|
-
|
|
23
|
-
### Installing Agents
|
|
24
|
-
|
|
25
|
-
You can easily install official agents using the CLI:
|
|
26
|
-
|
|
27
|
-
```bash
|
|
28
|
-
openbot add codex
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
This will automatically download the agent and install it into your local agents directory.
|
|
32
|
-
|
|
33
|
-
Example `codex.yaml`:
|
|
34
12
|
```yaml
|
|
35
|
-
|
|
36
|
-
|
|
13
|
+
---
|
|
14
|
+
name: Researcher
|
|
15
|
+
description: Web research and synthesis specialist.
|
|
37
16
|
plugins:
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
17
|
+
- id: ai-sdk
|
|
18
|
+
config:
|
|
19
|
+
model: anthropic/claude-3-5-sonnet-20240620
|
|
20
|
+
- id: mcp
|
|
21
|
+
- id: shell
|
|
22
|
+
- id: delegation
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
You are a web research specialist. Use the available tools to gather and
|
|
26
|
+
synthesize information. Be concise and cite sources where relevant.
|
|
43
27
|
```
|
|
44
28
|
|
|
45
|
-
|
|
29
|
+
The body below the frontmatter is the system prompt passed to the runtime
|
|
30
|
+
plugin as `agentDetails.instructions`.
|
|
46
31
|
|
|
47
|
-
|
|
32
|
+
### Required: at least one runtime plugin
|
|
48
33
|
|
|
49
|
-
|
|
34
|
+
A runtime plugin is one that handles `agent:invoke` (the LLM loop). Without
|
|
35
|
+
one, the agent will not respond to user input. Built-in runtime plugins:
|
|
50
36
|
|
|
51
|
-
|
|
37
|
+
- `ai-sdk` — generic LLM runtime (Vercel AI SDK). Consumes tools from other
|
|
38
|
+
plugins listed alongside it.
|
|
39
|
+
- `claude-code` — runs Claude inside the Claude Agent SDK with its own tools.
|
|
40
|
+
- `gemini-cli` — spawns Google's `gemini` CLI in headless mode.
|
|
52
41
|
|
|
53
|
-
|
|
42
|
+
`claude-code` and `gemini-cli` own their own tool loops, so attaching tool
|
|
43
|
+
plugins like `shell` or `mcp` to them has no effect. Pair tool plugins with
|
|
44
|
+
`ai-sdk`.
|
|
54
45
|
|
|
55
|
-
-
|
|
56
|
-
- `index.ts`: The entry point that exports a `TSAgentDefinition`.
|
|
46
|
+
## Built-in agent
|
|
57
47
|
|
|
58
|
-
|
|
48
|
+
OpenBot ships a built-in `system` agent (the orchestrator) with the
|
|
49
|
+
`ai-sdk` runtime plus the standard tool plugins (storage, shell, mcp,
|
|
50
|
+
delegation, ui, approval, memory). It cannot be deleted.
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
import { TSAgentDefinition } from "openbot";
|
|
52
|
+
## Memory
|
|
62
53
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
capabilities: {
|
|
78
|
-
"do_something": "Performs a custom TS-driven action"
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
```
|
|
54
|
+
The `memory` plugin gives every agent three tools — `remember`, `recall`,
|
|
55
|
+
`forget` — backed by an append-only JSONL log at `~/.openbot/memory/log.jsonl`.
|
|
56
|
+
Memories are scoped:
|
|
57
|
+
|
|
58
|
+
- `global` (default) — visible to every agent everywhere.
|
|
59
|
+
- `agent` — visible only to the agent that wrote it.
|
|
60
|
+
- `channel` — visible only inside the active channel.
|
|
61
|
+
|
|
62
|
+
On every LLM turn the runtime injects matching memories into the system prompt
|
|
63
|
+
via the `MemoryProvider` in the context engine, so the model treats remembered
|
|
64
|
+
facts as ground truth without needing to call `recall` first.
|
|
65
|
+
|
|
66
|
+
## Installing community agents
|
|
82
67
|
|
|
83
|
-
|
|
68
|
+
Marketplace entries reference plugin ids (built-in or npm package names).
|
|
69
|
+
Installing an agent ensures every referenced plugin is available locally,
|
|
70
|
+
fetching unknown ids from npm into `~/.openbot/plugins/<id>/` on first use.
|
package/docs/architecture.md
CHANGED
|
@@ -16,7 +16,7 @@ The orchestrator is the central dispatcher within the harness. It receives user
|
|
|
16
16
|
|
|
17
17
|
### 2. Agent Registry
|
|
18
18
|
A dynamic registry that manages all available agents. Agents can be:
|
|
19
|
-
- **Built-in**: Core
|
|
19
|
+
- **Built-in**: Core agent packages shipped with the repo (e.g. `src/agents/openbot/`).
|
|
20
20
|
- **YAML-based**: Rapidly defined agents in `~/.openbot/agents/*/AGENT.md`.
|
|
21
21
|
- **TS Packages**: Advanced agents with custom logic in `~/.openbot/agents/*/index.ts`.
|
|
22
22
|
|
package/docs/plugins.md
CHANGED
|
@@ -1,77 +1,89 @@
|
|
|
1
1
|
# Plugins
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A **Plugin** is the single extension unit on the OpenBot bus. Every agent is
|
|
4
|
+
just a list of plugins. The bus does not distinguish between "runtime" and
|
|
5
|
+
"tool" plugins — those are roles defined entirely by which events a plugin
|
|
6
|
+
subscribes to and emits.
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
- **Runtime plugins** handle `agent:invoke` and run an LLM loop. They may
|
|
9
|
+
consume tools contributed by other plugins via `PluginContext.tools`.
|
|
10
|
+
- **Tool plugins** expose `toolDefinitions` and handle the corresponding
|
|
11
|
+
`action:<tool>` events.
|
|
12
|
+
- **Middleware plugins** observe events and re-emit them with extra logic
|
|
13
|
+
(e.g. the `approval` plugin gates protected actions).
|
|
6
14
|
|
|
7
|
-
|
|
8
|
-
- **storage**: Local file-based persistence for events and state.
|
|
9
|
-
- **mcp**: Model Context Protocol integration.
|
|
10
|
-
- **delegation**: Allows agents to delegate tasks to other agents.
|
|
11
|
-
- **ui**: Server-driven UI components.
|
|
15
|
+
## Plugin contract
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
```ts
|
|
18
|
+
export interface Plugin {
|
|
19
|
+
id: string;
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
image?: string;
|
|
23
|
+
defaultInstructions?: string;
|
|
24
|
+
configSchema?: ConfigSchema;
|
|
25
|
+
toolDefinitions?: Record<string, ToolDefinition>;
|
|
26
|
+
factory: (context: PluginContext) => MelonyPlugin;
|
|
27
|
+
}
|
|
20
28
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
detailKeys: ["command", "cwd"]
|
|
29
|
-
hiddenKeys: ["env"]
|
|
30
|
-
- action: "action:writeFile"
|
|
31
|
-
message: "The agent wants to modify a file."
|
|
32
|
-
detailKeys: ["path"]
|
|
29
|
+
export interface PluginContext {
|
|
30
|
+
agentId: string;
|
|
31
|
+
agentDetails: AgentDetails;
|
|
32
|
+
config: Record<string, unknown>; // from AGENT.md plugins[].config
|
|
33
|
+
storage: Storage;
|
|
34
|
+
tools: Record<string, ToolDefinition>; // merged from all tool plugins
|
|
35
|
+
}
|
|
33
36
|
```
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
The agent loader collects `toolDefinitions` from every plugin attached to the
|
|
39
|
+
same agent into a single map and passes it to every plugin via `context.tools`.
|
|
40
|
+
Runtime plugins read it; tool plugins ignore it. First plugin wins on tool
|
|
41
|
+
name collisions.
|
|
39
42
|
|
|
40
|
-
|
|
43
|
+
## Built-in plugins
|
|
41
44
|
|
|
42
|
-
|
|
45
|
+
| Id | Role | Notes |
|
|
46
|
+
| --------------- | ---------- | --------------------------------------------------------- |
|
|
47
|
+
| `ai-sdk` | Runtime | Generic LLM loop on Vercel AI SDK; consumes external tools |
|
|
48
|
+
| `claude-code` | Runtime | Claude Agent SDK; owns its own tool loop |
|
|
49
|
+
| `gemini-cli` | Runtime | Google `gemini` CLI in headless mode |
|
|
50
|
+
| `shell` | Tool | `shell_exec` |
|
|
51
|
+
| `mcp` | Tool | `mcp_list_tools`, `mcp_call` |
|
|
52
|
+
| `delegation` | Tool | `handoff`, `delegate` |
|
|
53
|
+
| `storage-tools` | Tool | `create_channel`, `patch_*`, `create_variable`, ... |
|
|
54
|
+
| `ui` | Tool | `render_ui_widget` |
|
|
55
|
+
| `approval` | Middleware | Gates protected actions behind a UI confirmation widget |
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
## Community plugins
|
|
45
58
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
summary: string;
|
|
49
|
-
details?: Array<{ label: string; value: string }>;
|
|
50
|
-
rawPayload?: string;
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
What users now see before approving:
|
|
55
|
-
- Action label and event type.
|
|
56
|
-
- A compact details list based on `detailKeys` (or auto-derived keys if omitted).
|
|
57
|
-
- A sanitized full action payload (sensitive keys are redacted and very large values are truncated).
|
|
59
|
+
A community plugin is just an npm package whose default export matches the
|
|
60
|
+
`Plugin` interface. Reference it by its npm package name in AGENT.md:
|
|
58
61
|
|
|
59
|
-
|
|
62
|
+
```yaml
|
|
63
|
+
plugins:
|
|
64
|
+
- id: openbot-plugin-search
|
|
65
|
+
config:
|
|
66
|
+
provider: tavily
|
|
67
|
+
```
|
|
60
68
|
|
|
61
|
-
|
|
69
|
+
On first use OpenBot installs the package into
|
|
70
|
+
`~/.openbot/plugins/<npm-name>/` (scoped packages live under
|
|
71
|
+
`~/.openbot/plugins/@scope/<name>/`).
|
|
62
72
|
|
|
63
|
-
|
|
73
|
+
## Approval plugin
|
|
64
74
|
|
|
65
|
-
|
|
75
|
+
The `approval` plugin reads its rules from per-agent config:
|
|
66
76
|
|
|
67
|
-
```
|
|
68
|
-
|
|
77
|
+
```yaml
|
|
78
|
+
plugins:
|
|
79
|
+
- id: approval
|
|
80
|
+
config:
|
|
81
|
+
rules:
|
|
82
|
+
- action: action:shell_exec
|
|
83
|
+
message: The agent wants to run a terminal command.
|
|
84
|
+
detailKeys: [command, cwd, shell, timeoutMs]
|
|
85
|
+
hiddenKeys: [env]
|
|
69
86
|
```
|
|
70
87
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
A plugin is typically a Node.js package that exports:
|
|
74
|
-
- `name`: Unique identifier.
|
|
75
|
-
- `description`: What the plugin does.
|
|
76
|
-
- `toolDefinitions`: Zod-based definitions for the tools it provides.
|
|
77
|
-
- `factory`: A function that initializes the plugin logic.
|
|
88
|
+
If `rules` is omitted, sensible defaults are applied (currently: gate
|
|
89
|
+
`action:shell_exec`).
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
---
|
|
2
|
+
# OpenBot agent profile (YAML frontmatter)
|
|
3
|
+
#
|
|
4
|
+
# File location: ~/.openbot/agents/<agentId>/AGENT.md
|
|
5
|
+
# The agent id is the folder name (<agentId>), not a field in this file.
|
|
6
|
+
#
|
|
7
|
+
name: Example Agent
|
|
8
|
+
description: One-line description shown in agent pickers and lists.
|
|
9
|
+
|
|
10
|
+
# Plugins compose the agent. Order matters for tool collisions (first wins).
|
|
11
|
+
# At least one plugin must handle `agent:invoke` (a "runtime" plugin like
|
|
12
|
+
# `ai-sdk`, `claude-code`, or `gemini-cli`). Tool plugins like `shell`, `mcp`,
|
|
13
|
+
# `delegation`, `storage-tools`, and `ui` contribute tools to whichever runtime
|
|
14
|
+
# plugin can consume them.
|
|
15
|
+
#
|
|
16
|
+
# Built-in plugin ids: ai-sdk, claude-code, gemini-cli, shell, mcp, delegation,
|
|
17
|
+
# storage-tools, ui, approval.
|
|
18
|
+
#
|
|
19
|
+
# Community plugins are referenced by their npm package name (e.g.
|
|
20
|
+
# `openbot-plugin-search` or `@scope/openbot-plugin-foo`) and are auto-installed
|
|
21
|
+
# on first use into ~/.openbot/plugins/<id>/.
|
|
22
|
+
plugins:
|
|
23
|
+
- id: ai-sdk
|
|
24
|
+
config:
|
|
25
|
+
model: openai/gpt-4o-mini
|
|
26
|
+
- id: shell
|
|
27
|
+
- id: mcp
|
|
28
|
+
- id: delegation
|
|
29
|
+
- id: storage-tools
|
|
30
|
+
- id: ui
|
|
31
|
+
- id: approval
|
|
32
|
+
config:
|
|
33
|
+
rules:
|
|
34
|
+
- action: action:shell_exec
|
|
35
|
+
message: The agent wants to run a terminal command.
|
|
36
|
+
detailKeys: [command, cwd, shell, timeoutMs]
|
|
37
|
+
hiddenKeys: [env]
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
<!--
|
|
41
|
+
Everything below the closing --- is the agent instructions (system prompt body).
|
|
42
|
+
It is stored as markdown and passed to runtime plugins as agentDetails.instructions.
|
|
43
|
+
-->
|
|
44
|
+
|
|
45
|
+
# Role
|
|
46
|
+
|
|
47
|
+
You are **Example Agent**, a specialist for [describe domain here].
|
|
48
|
+
|
|
49
|
+
## Behaviour
|
|
50
|
+
|
|
51
|
+
- Be concise unless the user asks for depth.
|
|
52
|
+
- When unsure, ask a clarifying question instead of guessing.
|
|
53
|
+
|
|
54
|
+
## Scope
|
|
55
|
+
|
|
56
|
+
- **In scope:** [list what you handle]
|
|
57
|
+
- **Out of scope:** [defer to another agent for…]
|
package/package.json
CHANGED
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openbot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=20.12.0"
|
|
8
8
|
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"dev": "tsx watch src/app/cli.ts start",
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/app/cli.js start"
|
|
13
|
+
},
|
|
9
14
|
"bin": {
|
|
10
15
|
"openbot": "./dist/app/cli.js"
|
|
11
16
|
},
|
|
12
17
|
"dependencies": {
|
|
13
18
|
"@ai-sdk/anthropic": "^3.0.33",
|
|
14
19
|
"@ai-sdk/openai": "^3.0.13",
|
|
20
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.138",
|
|
15
21
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
16
22
|
"@types/cors": "^2.8.19",
|
|
17
23
|
"ai": "^6.0.42",
|
|
@@ -30,10 +36,5 @@
|
|
|
30
36
|
"@types/node": "^20.10.1",
|
|
31
37
|
"tsx": "^4.21.0",
|
|
32
38
|
"typescript": "^5.9.3"
|
|
33
|
-
},
|
|
34
|
-
"scripts": {
|
|
35
|
-
"dev": "tsx watch src/app/cli.ts start",
|
|
36
|
-
"build": "tsc",
|
|
37
|
-
"start": "node dist/app/cli.js start"
|
|
38
39
|
}
|
|
39
|
-
}
|
|
40
|
+
}
|
package/src/app/cli.ts
CHANGED
package/src/app/config.ts
CHANGED
|
@@ -10,11 +10,13 @@ export interface OpenBotconfig {
|
|
|
10
10
|
baseDir?: string;
|
|
11
11
|
port?: number;
|
|
12
12
|
mcpServers?: MCPServerConfig[];
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Overrides the default public marketplace registry URL. If omitted or blank,
|
|
15
|
+
* {@link DEFAULT_MARKETPLACE_REGISTRY_URL} is used.
|
|
16
|
+
*/
|
|
17
|
+
marketplaceRegistryUrl?: string;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
|
-
export type PluginSpec = string | { name: string; config?: Record<string, unknown> };
|
|
17
|
-
|
|
18
20
|
export interface MCPServerConfig {
|
|
19
21
|
id: string;
|
|
20
22
|
command: string;
|
|
@@ -36,6 +38,10 @@ export const DEFAULT_CHANNELS_DIR = 'channels';
|
|
|
36
38
|
export const CONFIG_FILE = 'config.json';
|
|
37
39
|
export const VARIABLES_FILE = 'variables.json';
|
|
38
40
|
|
|
41
|
+
/** Public agent registry used when `marketplaceRegistryUrl` is not set. */
|
|
42
|
+
export const DEFAULT_MARKETPLACE_REGISTRY_URL =
|
|
43
|
+
'https://raw.githubusercontent.com/meetopenbot/openbot-registry/main/registry.json';
|
|
44
|
+
|
|
39
45
|
export function resolvePath(p: string) {
|
|
40
46
|
return p.startsWith('~/') ? path.join(os.homedir(), p.slice(2)) : path.resolve(p);
|
|
41
47
|
}
|
|
@@ -72,7 +78,11 @@ export function isConfigured(): boolean {
|
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
export function loadVariables(): { version: number; variables: StoredVariable[] } {
|
|
75
|
-
const
|
|
81
|
+
const config = loadConfig();
|
|
82
|
+
const variablesPath = path.join(
|
|
83
|
+
resolvePath(config.baseDir || DEFAULT_BASE_DIR),
|
|
84
|
+
VARIABLES_FILE,
|
|
85
|
+
);
|
|
76
86
|
if (fs.existsSync(variablesPath)) {
|
|
77
87
|
return JSON.parse(fs.readFileSync(variablesPath, 'utf-8')) as {
|
|
78
88
|
version: number;
|
package/src/app/server.ts
CHANGED
|
@@ -4,8 +4,11 @@ import cors from 'cors';
|
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
import path from 'path';
|
|
6
6
|
import fs from 'fs/promises';
|
|
7
|
+
import { createRequire } from 'module';
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
const pkg = require('../../package.json');
|
|
7
10
|
import { generateId } from 'melony';
|
|
8
|
-
import { DEFAULT_BASE_DIR, loadConfig,
|
|
11
|
+
import { DEFAULT_BASE_DIR, loadConfig, resolvePath } from '../app/config.js';
|
|
9
12
|
import { ActiveRunsSnapshotEvent, OpenBotEvent, OpenBotState } from './types.js';
|
|
10
13
|
import { processService } from '../harness/process.js';
|
|
11
14
|
import { storageService } from '../services/storage.js';
|
|
@@ -28,9 +31,7 @@ export async function startServer(options: ServerOptions = {}) {
|
|
|
28
31
|
.passthrough();
|
|
29
32
|
|
|
30
33
|
const config = loadConfig();
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
processService.applyVariablesToProcessEnv(variables.variables);
|
|
34
|
+
processService.syncWorkspaceVariablesToProcessEnv();
|
|
34
35
|
|
|
35
36
|
const baseDir = config.baseDir || DEFAULT_BASE_DIR;
|
|
36
37
|
const openBotDir = resolvePath(baseDir);
|
|
@@ -79,6 +80,8 @@ export async function startServer(options: ServerOptions = {}) {
|
|
|
79
80
|
|
|
80
81
|
const getClientKey = (channelId: string, threadId?: string) =>
|
|
81
82
|
threadId ? `${channelId}:${threadId}` : channelId;
|
|
83
|
+
const getRunKey = (runId: string, agentId: string, channelId: string, threadId?: string) =>
|
|
84
|
+
`${runId}:${agentId}:${channelId}:${threadId || ''}`;
|
|
82
85
|
|
|
83
86
|
const sendToClientKey = (clientKey: string, chunk: OpenBotEvent) => {
|
|
84
87
|
const threadClients = clients.get(clientKey);
|
|
@@ -116,6 +119,10 @@ export async function startServer(options: ServerOptions = {}) {
|
|
|
116
119
|
app.use(cors());
|
|
117
120
|
app.use(express.json({ limit: '20mb' }));
|
|
118
121
|
|
|
122
|
+
app.get('/api/health', (req, res) => {
|
|
123
|
+
res.json({ status: 'ok', version: pkg.version });
|
|
124
|
+
});
|
|
125
|
+
|
|
119
126
|
app.get('/api/events', (req, res) => {
|
|
120
127
|
const { channelId, threadId } = getContext(req);
|
|
121
128
|
const clientKey = getClientKey(channelId, threadId);
|
|
@@ -196,14 +203,19 @@ export async function startServer(options: ServerOptions = {}) {
|
|
|
196
203
|
const targetClientKey = getClientKey(targetChannelId, targetThreadId);
|
|
197
204
|
|
|
198
205
|
if (chunk.type === 'agent:run:start') {
|
|
199
|
-
activeRuns.set(
|
|
206
|
+
activeRuns.set(
|
|
207
|
+
getRunKey(chunk.data.runId, chunk.data.agentId, chunk.data.channelId, chunk.data.threadId),
|
|
208
|
+
{
|
|
200
209
|
runId: chunk.data.runId,
|
|
201
210
|
channelId: chunk.data.channelId,
|
|
202
211
|
threadId: chunk.data.threadId,
|
|
203
212
|
agentId: chunk.data.agentId,
|
|
204
|
-
|
|
213
|
+
},
|
|
214
|
+
);
|
|
205
215
|
} else if (chunk.type === 'agent:run:end') {
|
|
206
|
-
activeRuns.delete(
|
|
216
|
+
activeRuns.delete(
|
|
217
|
+
getRunKey(chunk.data.runId, chunk.data.agentId, chunk.data.channelId, chunk.data.threadId),
|
|
218
|
+
);
|
|
207
219
|
}
|
|
208
220
|
|
|
209
221
|
await storageService.storeEvent({
|
|
@@ -277,8 +289,9 @@ export async function startServer(options: ServerOptions = {}) {
|
|
|
277
289
|
|
|
278
290
|
app.listen(PORT, () => {
|
|
279
291
|
console.log(`\x1b[32mOpenBot server listening at http://localhost:${PORT}\x1b[0m`);
|
|
280
|
-
console.log(` -
|
|
281
|
-
console.log(` -
|
|
282
|
-
console.log(` -
|
|
292
|
+
console.log(` - Health endpoint: GET /health`);
|
|
293
|
+
console.log(` - Events endpoint: GET /api/events (SSE)`);
|
|
294
|
+
console.log(` - Publish endpoint: POST /api/publish`);
|
|
295
|
+
console.log(` - State endpoint: GET /api/state`);
|
|
283
296
|
});
|
|
284
297
|
}
|