@browxai/plugin-example 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kalebtec
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # @browxai/plugin-example
2
+
3
+ The canonical browxai reference plugin. Exercises every primitive of
4
+ the v1 plugin-runtime contract — a `register(api)` entry module,
5
+ namespaced tool registration, an empty `capabilities` array (runs on a
6
+ server with the default capability set), an empty `dependsOn` graph, a
7
+ unit-test file, and a typed `schema.d.ts` SDK overlay. It is the
8
+ fixture the plugin-runtime keystone test loads end-to-end, and the
9
+ layout plugin authors copy to start their own plugin (see
10
+ `docs/plugin-authoring.md` in the browxai repo).
11
+
12
+ Three tools:
13
+
14
+ - `example.echo({msg})` → `{ok, result}` — round-trip primitive.
15
+ - `example.add({a, b})` → `{ok, sum}` — typed-arg demonstration.
16
+ - `example.now()` → `{ok, iso, epochMs}` — argless tool shape.
17
+
18
+ ## Install
19
+
20
+ ```sh
21
+ $ browxai plugin install @browxai/plugin-example
22
+ ```
23
+
24
+ No extra capabilities required. Restart the browxai server after
25
+ install (plugin lifecycle is resolved-once-at-server-start). The tools
26
+ surface as `example.echo` (etc.) on MCP `tools/list`, and on the SDK as
27
+ `client.plugins.example.echo(...)`.
28
+
29
+ ## Full reference
30
+
31
+ The first-party plugin reference — tool tables, error envelopes, and a
32
+ usage walkthrough for this plugin and the three canvas adapters — lives
33
+ at <https://browxai.com/plugins/first-party/>.
@@ -0,0 +1,48 @@
1
+ interface ToolResponse {
2
+ readonly content: ReadonlyArray<{
3
+ type: "text";
4
+ text: string;
5
+ } | {
6
+ type: "image";
7
+ data: string;
8
+ mimeType: string;
9
+ }>;
10
+ }
11
+ interface PluginApi {
12
+ readonly namespace: string;
13
+ readonly declaredCapabilities: ReadonlyArray<string>;
14
+ registerTool(name: string, def: {
15
+ description: string;
16
+ inputSchema?: Record<string, any> | undefined;
17
+ }, handler: (args: unknown) => Promise<ToolResponse>): void;
18
+ callTool(name: string, args?: Record<string, unknown>): Promise<ToolResponse>;
19
+ log: {
20
+ info(msg: string, meta?: Record<string, unknown>): void;
21
+ warn(msg: string, meta?: Record<string, unknown>): void;
22
+ error(msg: string, meta?: Record<string, unknown>): void;
23
+ };
24
+ }
25
+ /**
26
+ * Build the per-tool handlers as plain functions so the plugin's
27
+ * unit-test suite can exercise them WITHOUT spinning up the full
28
+ * runtime — the test file imports these directly.
29
+ */
30
+ export declare const handlers: {
31
+ /** `example.echo({ msg })` → `{ ok: true, result: msg }`. The
32
+ * classic round-trip primitive — used by the keystone to assert
33
+ * end-to-end MCP dispatch through the plugin runtime. */
34
+ echo: (args: unknown) => Promise<ToolResponse>;
35
+ /** `example.add({ a, b })` → `{ ok: true, sum: a + b }`. Trivial
36
+ * math primitive — demonstrates the handler's typed-arg pattern. */
37
+ add: (args: unknown) => Promise<ToolResponse>;
38
+ /** `example.now()` → `{ ok: true, iso, epochMs }`. Argless tool
39
+ * shape; demonstrates that an empty input schema is fine. */
40
+ now: () => Promise<ToolResponse>;
41
+ };
42
+ /**
43
+ * Plugin entry. The runtime imports this module via
44
+ * `await import(<entryPath>)` and calls `register(api)`. The named
45
+ * export takes precedence over a default export.
46
+ */
47
+ export declare function register(api: PluginApi): void;
48
+ export default register;
package/dist/index.js ADDED
@@ -0,0 +1,81 @@
1
+ // @browxai/plugin-example — the canonical reference plugin.
2
+ //
3
+ // Exercises every primitive of the v1 plugin-runtime contract:
4
+ // - `register(api)` entry point as a named export.
5
+ // - Three tools, all under the declared namespace `example.`.
6
+ // - No declared capabilities (the simplest case — runs on a server
7
+ // with the default capability set).
8
+ // - Empty `dependsOn` (no inter-plugin composition).
9
+ //
10
+ // Plugin authors: copy this layout, change `package.json#browxai`,
11
+ // add your own tools in `register(api)`. See `docs/plugin-authoring.md`.
12
+ //
13
+ // The `PluginApi` shape is documented in the host's plugin-authoring
14
+ // guide. We inline a minimal type here so the plugin doesn't import
15
+ // from a host-internal module — once `@browxai/plugin-types`
16
+ // ships, plugins will import the interface from there.
17
+ const json = (obj) => ({
18
+ content: [{ type: "text", text: JSON.stringify(obj, null, 2) }],
19
+ });
20
+ /**
21
+ * Build the per-tool handlers as plain functions so the plugin's
22
+ * unit-test suite can exercise them WITHOUT spinning up the full
23
+ * runtime — the test file imports these directly.
24
+ */
25
+ // Arrow-property form (not method-syntax) so call sites can pass
26
+ // `handlers.echo` as a value without tripping `unbound-method`. Bodies
27
+ // are sync — they return `Promise.resolve(...)` to honour the
28
+ // `Promise<ToolResponse>` handler contract without an empty `async`.
29
+ export const handlers = {
30
+ /** `example.echo({ msg })` → `{ ok: true, result: msg }`. The
31
+ * classic round-trip primitive — used by the keystone to assert
32
+ * end-to-end MCP dispatch through the plugin runtime. */
33
+ echo: (args) => {
34
+ const a = (args ?? {});
35
+ const msg = typeof a.msg === "string" ? a.msg : "";
36
+ return Promise.resolve(json({ ok: true, result: msg }));
37
+ },
38
+ /** `example.add({ a, b })` → `{ ok: true, sum: a + b }`. Trivial
39
+ * math primitive — demonstrates the handler's typed-arg pattern. */
40
+ add: (args) => {
41
+ const a = (args ?? {});
42
+ const left = typeof a.a === "number" ? a.a : 0;
43
+ const right = typeof a.b === "number" ? a.b : 0;
44
+ return Promise.resolve(json({ ok: true, sum: left + right }));
45
+ },
46
+ /** `example.now()` → `{ ok: true, iso, epochMs }`. Argless tool
47
+ * shape; demonstrates that an empty input schema is fine. */
48
+ now: () => {
49
+ const ms = Date.now();
50
+ return Promise.resolve(json({ ok: true, iso: new Date(ms).toISOString(), epochMs: ms }));
51
+ },
52
+ };
53
+ /**
54
+ * Plugin entry. The runtime imports this module via
55
+ * `await import(<entryPath>)` and calls `register(api)`. The named
56
+ * export takes precedence over a default export.
57
+ */
58
+ export function register(api) {
59
+ api.log.info("example plugin: registering tools", { namespace: api.namespace });
60
+ // Tool names MUST be prefixed with the plugin's namespace. The
61
+ // runtime throws synchronously if a registration violates this.
62
+ // The Zod schema is the same shape host tools use; the plugin
63
+ // doesn't have to import Zod itself if the inputSchema is an
64
+ // empty object — the schema is consulted by MCP's `tools/list` and
65
+ // is purely informational at the plugin layer.
66
+ api.registerTool(`${api.namespace}.echo`, {
67
+ description: "Round-trip primitive — returns whatever `msg` was passed. Useful for proving the plugin runtime is reachable end-to-end (keystone uses this).",
68
+ inputSchema: {},
69
+ }, handlers.echo);
70
+ api.registerTool(`${api.namespace}.add`, {
71
+ description: "Sums two numeric args. Trivial demonstration of the handler's typed-arg pattern.",
72
+ inputSchema: {},
73
+ }, handlers.add);
74
+ api.registerTool(`${api.namespace}.now`, {
75
+ description: "Returns the current ISO timestamp + epoch milliseconds. No args.",
76
+ inputSchema: {},
77
+ }, handlers.now);
78
+ }
79
+ // Also export as default for the "default export is the register fn"
80
+ // alternative loading path (the runtime accepts either).
81
+ export default register;
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@browxai/plugin-example",
3
+ "version": "0.1.0",
4
+ "description": "Reference browxai plugin — exercises every registry feature (tool registration, capability declaration, dependency declaration). Canonical source for plugin authors.",
5
+ "author": "Kalebtec",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "keywords": [
9
+ "browxai",
10
+ "browxai-plugin",
11
+ "mcp",
12
+ "browser-automation",
13
+ "ai-agent"
14
+ ],
15
+ "homepage": "https://browxai.com/plugins/first-party/",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/kalebteccom/browxai.git",
19
+ "directory": "packages/plugins/example"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/kalebteccom/browxai/issues"
23
+ },
24
+ "main": "dist/index.js",
25
+ "types": "dist/index.d.ts",
26
+ "files": [
27
+ "dist",
28
+ "schema.d.ts",
29
+ "LICENSE"
30
+ ],
31
+ "publishConfig": {
32
+ "access": "public",
33
+ "provenance": true
34
+ },
35
+ "scripts": {
36
+ "build": "tsc -p tsconfig.json",
37
+ "typecheck": "tsc -p tsconfig.json --noEmit",
38
+ "test": "vitest run"
39
+ },
40
+ "browxai": {
41
+ "apiVersion": "1.0.0",
42
+ "browxaiVersion": "^0.7.0",
43
+ "namespace": "example",
44
+ "register": "dist/index.js",
45
+ "capabilities": [],
46
+ "trust": "kalebtec",
47
+ "dependsOn": []
48
+ },
49
+ "engines": {
50
+ "node": ">=20"
51
+ },
52
+ "devDependencies": {
53
+ "typescript": "^5.5.0",
54
+ "vitest": "^2.0.0"
55
+ }
56
+ }
package/schema.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ // Typed SDK overlay for `@browxai/plugin-example` consumers.
2
+ //
3
+ // SDK consumers import the schema type + compose it via the host's
4
+ // `BrowxaiClientWithPlugins` helper to get autocomplete on every
5
+ // example tool — `client.plugins.example.echo({msg:"hi"})` — with full
6
+ // argument typing.
7
+ //
8
+ // import type { ExamplePluginSchema } from "@browxai/plugin-example/schema";
9
+ // import type { BrowxaiClientWithPlugins } from "browxai";
10
+ //
11
+ // const client = (await createBrowxai({...})) as BrowxaiClientWithPlugins<ExamplePluginSchema>;
12
+ // await client.plugins.example.echo({msg: "hello"});
13
+
14
+ // We declare the relevant subset of the BrowxaiResult envelope here
15
+ // rather than importing it — keeps the schema declaration free of
16
+ // runtime deps. Adopters who want the structured payload can also
17
+ // import the host's `BrowxaiResult` type and substitute it.
18
+ interface ExampleBrowxaiResult {
19
+ readonly content: ReadonlyArray<
20
+ { type: "text"; text: string } | { type: "image"; data: string; mimeType: string }
21
+ >;
22
+ readonly data?: Record<string, unknown>;
23
+ }
24
+
25
+ export interface ExamplePluginSchema {
26
+ readonly example: {
27
+ /** Round-trip primitive — returns `{ok:true, result:msg}`. */
28
+ echo(args: { msg: string }): Promise<ExampleBrowxaiResult>;
29
+ /** Sums two numeric args — returns `{ok:true, sum: a+b}`. */
30
+ add(args: { a: number; b: number }): Promise<ExampleBrowxaiResult>;
31
+ /** Argless tool — returns `{ok:true, iso, epochMs}`. */
32
+ now(args?: Record<string, never>): Promise<ExampleBrowxaiResult>;
33
+ };
34
+ }