🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@feniix/bridgekit

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@feniix/bridgekit - npm Package Compare versions

Comparing version
0.9.5
to
0.10.0
+39
-1
CHANGELOG.md

@@ -7,4 +7,42 @@ # Changelog

## [0.9.5] - Unreleased
## [0.10.0] - Unreleased
### Removed (breaking)
- `PortableToolHost<TExtension extends string>` type alias — replaced by the
fixed `PortableToolBuiltInHost = "pi" | "mcp" | "test"` union.
- `<THost extends string>` generic parameter on `PortableTool`,
`PortableToolContext`, `definePortableTool`, `executePortableTool`, and
`validatePortableToolArgs`. Host is now a fixed literal union; adapters
outside `"pi" | "mcp"` should cast at their adapter boundary instead of
extending the type union.
Migration: drop the second generic argument from any of those types.
`PortableTool<typeof params, "custom">` becomes `PortableTool<typeof params>`.
`PortableToolContext<"custom">` becomes `PortableToolContext` (cast `host`
at the consumer if a custom literal is needed).
Cast pattern (custom literal at the adapter boundary):
```ts
// PortableToolContext.host is fixed to PortableToolBuiltInHost.
// A direct `as "custom-runtime"` fails under strict (TS2352 — no overlap);
// cast through `unknown` instead.
const ctx: PortableToolContext = {
host: "custom-runtime" as unknown as PortableToolBuiltInHost,
};
```
Caveat: the cast lies at the type-system boundary, so
`switch (ctx.host) { ... default: assertNever(ctx.host); }` patterns will
fall through on the custom literal at runtime. For custom dispatch, carry
the host identifier on an adapter-owned field rather than on `ctx.host`,
or do a runtime allowlist check before exhaustive narrowing.
No consumer in tree or in the three known downstream consumers
(pi-sequential-thinking, pi-exa, pi-code-reasoning) used the generic.
Resolves [#5](https://github.com/feniix/bridgekit/issues/5).
## [0.9.5] - 2026-05-27
### Documentation

@@ -11,0 +49,0 @@

+5
-6

@@ -40,5 +40,4 @@ import type { Static, TSchema } from "typebox";

export type PortableToolBuiltInHost = "pi" | "mcp" | "test";
export type PortableToolHost<TExtension extends string = never> = PortableToolBuiltInHost | TExtension;
export interface PortableToolContext<THost extends string = PortableToolBuiltInHost> {
host: THost;
export interface PortableToolContext {
host: PortableToolBuiltInHost;
signal?: AbortSignal;

@@ -143,3 +142,3 @@ progress?: (update: PortableToolResult) => void;

}
export interface PortableTool<TParams extends TSchema = TSchema, THost extends string = PortableToolBuiltInHost> {
export interface PortableTool<TParams extends TSchema = TSchema> {
name: string;

@@ -149,3 +148,3 @@ title: string;

parameters: TParams;
execute: (args: Static<TParams>, ctx: PortableToolContext<THost>) => PortableToolResult | Promise<PortableToolResult>;
execute: (args: Static<TParams>, ctx: PortableToolContext) => PortableToolResult | Promise<PortableToolResult>;
/**

@@ -162,2 +161,2 @@ * Optional per-host metadata. Adapters consume the keys they recognise;

}
export declare function definePortableTool<TParams extends TSchema, THost extends string = PortableToolBuiltInHost>(tool: PortableTool<TParams, THost>): PortableTool<TParams, THost>;
export declare function definePortableTool<TParams extends TSchema>(tool: PortableTool<TParams>): PortableTool<TParams>;
import type { TSchema } from "typebox";
import type { PortableTool, PortableToolBuiltInHost, PortableToolContext, PortableToolResult, PortableValidationError } from "./define-tool.js";
export declare function validatePortableToolArgs<THost extends string = PortableToolBuiltInHost>(tool: PortableTool<TSchema, THost>, args: unknown): {
import type { PortableTool, PortableToolContext, PortableToolResult, PortableValidationError } from "./define-tool.js";
export declare function validatePortableToolArgs(tool: PortableTool<TSchema>, args: unknown): {
ok: true;

@@ -9,2 +9,2 @@ } | {

};
export declare function executePortableTool<THost extends string = PortableToolBuiltInHost>(tool: PortableTool<TSchema, THost>, args: unknown, ctx: PortableToolContext<NoInfer<THost>>): Promise<PortableToolResult>;
export declare function executePortableTool(tool: PortableTool<TSchema>, args: unknown, ctx: PortableToolContext): Promise<PortableToolResult>;

@@ -1,3 +0,3 @@

export { definePortableTool, type McpHostExtras, type PiHostExtras, type PortableTool, type PortableToolBuiltInHost, type PortableToolContext, type PortableToolErrorDetails, type PortableToolHost, type PortableToolHostExtras, type PortableToolResult, type PortableValidationError, } from "./core/define-tool.js";
export { definePortableTool, type McpHostExtras, type PiHostExtras, type PortableTool, type PortableToolBuiltInHost, type PortableToolContext, type PortableToolErrorDetails, type PortableToolHostExtras, type PortableToolResult, type PortableValidationError, } from "./core/define-tool.js";
export { executePortableTool, validatePortableToolArgs } from "./core/execute-tool.js";
export { isDomainFailure, isValidationFailure, type PortableDomainFailure, type PortableValidationFailure, } from "./core/result-guards.js";

@@ -286,50 +286,4 @@ # BridgeKit examples

## 4. Use custom host typing for custom adapters
## 4. Per-host metadata via `hostExtras`
Default portable tools accept only built-in hosts: `"pi" | "mcp" | "test"`.
If you are writing a custom adapter, opt in explicitly so the handler can safely narrow `ctx.host`:
```ts
import { Type } from "typebox";
import {
definePortableTool,
executePortableTool,
type PortableTool,
type PortableToolContext,
type PortableToolHost,
} from "@feniix/bridgekit";
const params = Type.Object({ text: Type.String() });
type CustomHost = "custom-runtime";
type CustomTool = PortableTool<typeof params, CustomHost>;
const customTool = definePortableTool<typeof params, CustomHost>({
name: "custom_echo",
title: "Custom Echo",
description: "Echoes text in a custom runtime.",
parameters: params,
execute(args, ctx) {
const host: CustomHost = ctx.host;
return { text: `${host}: ${args.text}` };
},
});
async function runCustomTool(tool: CustomTool, text: string) {
const ctx: PortableToolContext<CustomHost> = { host: "custom-runtime" };
return executePortableTool(tool, { text }, ctx);
}
const hostValue: PortableToolHost<CustomHost> = "custom-runtime";
void hostValue;
void customTool;
```
Use `PortableToolHost<CustomHost>` for values that can be either a built-in host or your custom extension. Use `PortableToolContext<CustomHost>` or `PortableTool<Schema, CustomHost>` when a tool is custom-host-only.
---
## 5. Per-host metadata via `hostExtras`
When a tool needs host-specific metadata — pi's `pendingMessage` for a "Processing..." signal, MCP's annotations as advisory hints to clients — the canonical place is `PortableTool.hostExtras`. Each host has its own namespace; adapters read the keys they recognise and ignore the rest. Tools that omit `hostExtras` see no behavior change.

@@ -370,3 +324,3 @@

- Set only the fields the adapter recognises; unrecognised keys are silently ignored, but they add noise to the definition.
- For custom-host adapters, extend `PortableToolHostExtras` via `declare module "@feniix/bridgekit"` so consumers of your adapter get type safety on the new namespace.
- If you ship an adapter for a host outside `"pi" | "mcp"`, cast `ctx.host` at the adapter boundary (the host union is fixed since 0.10.0). For type-safe per-host metadata in your adapter's namespace, extend `PortableToolHostExtras` via `declare module "@feniix/bridgekit"` so consumers of your adapter get type safety on the new namespace.

@@ -451,3 +405,3 @@ See `docs/rfc-host-extras.md` for the full design rationale (which fields qualify, why a top-level field beats a sidecar map, the closure rule for future additions).

## 6. Package checklist
## 5. Package checklist

@@ -454,0 +408,0 @@ For publishable tool packages:

@@ -9,3 +9,3 @@ # @feniix/bridgekit

2. `llms.txt` — compact agent-facing usage rules and anti-patterns.
3. `examples/README.md` — copyable end-to-end layouts for shared tools, pi extension wiring, MCP stdio server wiring, and custom hosts.
3. `examples/README.md` — copyable end-to-end layouts for shared tools, pi extension wiring, MCP stdio server wiring, and per-host metadata via `hostExtras`.
4. Published declarations such as `dist/src/index.d.ts`, `dist/src/pi.d.ts`, and `dist/src/mcp.d.ts` — canonical installed-package type contracts. In a source checkout, the matching `src/` files contain implementation context.

@@ -100,19 +100,2 @@

## Custom host typing
Default tools accept only built-in hosts: `"pi" | "mcp" | "test"`.
For a custom adapter, opt in explicitly:
```ts
const customTool = definePortableTool<typeof params, "custom-host">({
// ...
execute(args, ctx) {
const host: "custom-host" = ctx.host;
return { text: host };
},
});
```
Use `PortableToolHost<"custom-host">` when a value may be either a built-in host or that extension.
## Mixed source-loaded hosts and compiled MCP bins

@@ -119,0 +102,0 @@

{
"name": "@feniix/bridgekit",
"version": "0.9.5",
"version": "0.10.0",
"description": "BridgeKit defines TypeBox-backed tools once and adapts them to pi, MCP, and other hosts.",

@@ -5,0 +5,0 @@ "keywords": [

@@ -66,3 +66,3 @@ # BridgeKit

- Define a tool once; ship it to pi and MCP (and custom hosts) without per-host forks.
- Define a tool once; ship it to pi and MCP without per-host forks.
- Host-neutral tool files: no pi or MCP SDK imports in the tool definition itself.

@@ -84,3 +84,2 @@ - TypeBox schemas pass through to MCP `inputSchema` directly — no JSON Schema conversion step.

type PortableToolContext,
type PortableToolHost,
type PortableToolResult,

@@ -237,37 +236,2 @@ type PortableValidationError,

### Custom host typing
Default portable tools accept the built-in host union:
```ts
type BuiltIn = "pi" | "mcp" | "test";
```
Custom adapters opt in explicitly:
```ts
import { Type } from "typebox";
import { definePortableTool, type PortableToolHost } from "@feniix/bridgekit";
const params = Type.Object({ text: Type.String() });
type CustomHost = "custom-runtime";
export const customTool = definePortableTool<typeof params, CustomHost>({
name: "custom_echo",
title: "Custom Echo",
description: "Echoes text in a custom runtime.",
parameters: params,
execute(args, ctx) {
const host: CustomHost = ctx.host;
return { text: `${host}: ${args.text}` };
},
});
const hostValue: PortableToolHost<CustomHost> = "custom-runtime";
void hostValue;
```
Use `PortableToolHost<CustomHost>` for values that may be either a built-in host or your extension. Use the `PortableTool`/`PortableToolContext` generic when a tool or adapter is custom-host-only.
## Best practices

@@ -312,3 +276,3 @@

2. `llms.txt` — compact agent-facing usage rules and anti-patterns.
3. `examples/README.md` — copyable layouts for shared tools, pi extensions, MCP stdio servers, and custom hosts.
3. `examples/README.md` — copyable layouts for shared tools, pi extensions, MCP stdio servers, and per-host metadata via `hostExtras`.
4. Published declarations such as `dist/src/index.d.ts`, `dist/src/pi.d.ts`, and `dist/src/mcp.d.ts` — canonical installed-package type contracts. In a source checkout, the matching `src/` files contain the same implementation context.