🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@opencode-ai/plugin

Package Overview
Dependencies
Maintainers
2
Versions
10037
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@opencode-ai/plugin - npm Package Compare versions

Comparing version
0.0.0-next-16088
to
0.0.0-next-16093
+177
dist/v2/effect/internal/tool.d.ts
import { Agent } from "@opencode-ai/schema/agent";
import { Session } from "@opencode-ai/schema/session";
import { SessionMessage } from "@opencode-ai/schema/session-message";
import type { StandardJSONSchemaV1, StandardSchemaV1 } from "@standard-schema/spec";
import { Effect, JsonSchema, Schema } from "effect";
import type { Hooks, Transform } from "../registration.js";
/** A JSON-compatible value. Tool metadata and encoded outputs must be JSON. */
export type JsonValue = typeof Schema.Json.Type;
/** Compact JSON metadata for tool-specific UI and client behavior. */
export type Metadata = Readonly<Record<string, JsonValue>>;
export interface Context {
readonly sessionID: Session.ID;
readonly agent: Agent.ID;
readonly messageID: SessionMessage.ID;
readonly callID: string;
readonly progress: (update: Progress) => Effect.Effect<void>;
}
/** Live replacement metadata for a running tool. */
export type Progress = Metadata;
export type StandardSchemaType<Input = unknown, Output = Input> = StandardSchemaV1<Input, Output> & StandardJSONSchemaV1<Input, Output>;
export type SchemaType<A = unknown> = Schema.Codec<A, any> | StandardSchemaType<any, A> | JsonSchema.JsonSchema;
type IsAny<A> = 0 extends 1 & A ? true : false;
export type InputValue<S> = IsAny<S> extends true ? any : S extends Schema.Codec<infer A, any> ? A : S extends StandardSchemaV1<any, infer A> ? A : unknown;
export type OutputValue<S> = IsAny<S> extends true ? any : S extends Schema.Codec<infer A, any> ? A : S extends StandardSchemaV1<infer A, any> ? A : unknown;
export type EncodedValue<S> = IsAny<S> extends true ? any : S extends Schema.Codec<any, infer A> ? A : S extends StandardSchemaV1<any, infer A> ? A : unknown;
type ToolDefinition = {
readonly name: string;
readonly description: string;
readonly inputSchema: JsonSchema.JsonSchema;
readonly outputSchema?: JsonSchema.JsonSchema;
};
declare const Failure_base: Schema.Class<Failure, Schema.TaggedStruct<"LLM.ToolFailure", {
readonly message: Schema.String;
readonly error: Schema.optional<Schema.Defect>;
}>, import("effect/Cause").YieldableError>;
export declare class Failure extends Failure_base {
}
declare const RegistrationError_base: Schema.Class<RegistrationError, Schema.TaggedStruct<"Tool.RegistrationError", {
readonly name: Schema.String;
readonly message: Schema.String;
}>, import("effect/Cause").YieldableError>;
export declare class RegistrationError extends RegistrationError_base {
}
export type Content = {
readonly type: "text";
readonly text: string;
} | {
readonly type: "file";
readonly data: string;
readonly mime: string;
readonly name?: string;
};
/** Model-facing tool content: plain text or non-empty rich content. */
export type ModelOutput = string | readonly [Content, ...Content[]];
type BaseTool<Input extends SchemaType<any>> = {
readonly description: string;
readonly input: Input;
};
export type Response<Output extends SchemaType<any>> = {
readonly output: OutputValue<Output>;
readonly content?: ModelOutput;
readonly metadata?: Metadata;
};
export type ContentResponse = {
readonly content: ModelOutput;
readonly metadata?: Metadata;
};
export type Tool<Input extends SchemaType<any>, Output extends SchemaType<any> | undefined = undefined> = BaseTool<Input> & (Output extends SchemaType<any> ? {
readonly output: Output;
readonly execute: (input: InputValue<Input>, context: Context) => Effect.Effect<Response<Output>, Failure>;
} : {
readonly output?: undefined;
readonly execute: (input: InputValue<Input>, context: Context) => Effect.Effect<ContentResponse, Failure>;
});
export type Any = BaseTool<any> & {
readonly output?: SchemaType<any>;
readonly execute: (input: any, context: Context) => Effect.Effect<Response<any> | ContentResponse, Failure>;
};
export declare function make<Input extends SchemaType<any>, Output extends SchemaType<any>>(config: Tool<Input, Output>): Tool<Input, Output>;
export declare function make<Input extends SchemaType<any>>(config: Tool<Input>): Tool<Input>;
export declare function make(config: Any): Any;
export interface RegisterOptions {
readonly namespace?: string;
/** Defaults to true. False exposes the tool directly to the provider. */
readonly codemode?: boolean;
/** Permission action used for whole-tool visibility filtering. */
readonly permission?: string;
}
export interface Registration {
readonly tool: Any;
readonly name: string;
readonly namespace?: string;
readonly permission: string;
}
export declare const validateName: (name: string) => Effect.Effect<void, never, never> | Effect.Effect<never, RegistrationError, never>;
export declare const registrationEntries: (tools: Readonly<Record<string, Any>>, options?: RegisterOptions) => Array<Registration & {
readonly key: string;
}>;
export declare const validateNamespace: (namespace: string) => Effect.Effect<void, never, never> | Effect.Effect<never, RegistrationError, never>;
export declare const toLLMDefinition: (name: string, tool: Any) => ToolDefinition;
export declare function decodeInput(schema: SchemaType<any>, value: unknown): Effect.Effect<any, Failure>;
export declare function encodeOutput(schema: SchemaType<any>, value: unknown): Effect.Effect<any, Failure>;
export interface ToolExecuteBeforeEvent {
readonly tool: string;
readonly sessionID: Session.ID;
readonly agent: Agent.ID;
readonly messageID: SessionMessage.ID;
readonly callID: string;
input: unknown;
}
type ToolHookBase = {
readonly tool: string;
readonly sessionID: Session.ID;
readonly agent: Agent.ID;
readonly messageID: SessionMessage.ID;
readonly callID: string;
readonly input: unknown;
};
export declare const ExecuteAfterOutcome: Schema.toTaggedUnion<"status", readonly [Schema.Struct<{
readonly status: Schema.Literal<"completed">;
readonly content: Schema.NonEmptyArray<Schema.Union<readonly [Schema.Struct<{
readonly type: Schema.Literal<"text">;
readonly text: Schema.String;
}>, Schema.Struct<{
readonly type: Schema.Literal<"file">;
readonly uri: Schema.String;
readonly mime: Schema.String;
readonly name: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
}>]>>;
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>>;
readonly outputPaths: Schema.optional<Schema.$Array<Schema.String>>;
}>, Schema.Struct<{
readonly status: Schema.Literal<"error">;
readonly error: Schema.Struct<{
readonly type: Schema.String;
readonly message: Schema.String;
}>;
readonly content: Schema.optional<Schema.NonEmptyArray<Schema.Union<readonly [Schema.Struct<{
readonly type: Schema.Literal<"text">;
readonly text: Schema.String;
}>, Schema.Struct<{
readonly type: Schema.Literal<"file">;
readonly uri: Schema.String;
readonly mime: Schema.String;
readonly name: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
}>]>>>;
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>>;
readonly outputPaths: Schema.optional<Schema.$Array<Schema.String>>;
}>]>;
type Mutable<A> = {
-readonly [K in keyof A]: A[K];
};
type HookOutcome<A extends {
readonly status: string;
}> = Omit<Mutable<A>, "status"> & Pick<A, "status">;
/** The bounded terminal outcome exposed to tool hooks. */
export type Outcome = typeof ExecuteAfterOutcome.Type extends infer A ? A extends {
readonly status: string;
} ? HookOutcome<A> : never : never;
/**
* The canonical execution outcome as seen by `execute.after` hooks. Hooks
* observe bounded model content, optional metadata, and managed output paths;
* they never observe the raw domain output.
*/
export type ToolExecuteAfterEvent = ToolHookBase & Outcome;
export interface ToolDraft {
add(name: string, tool: Any, options?: RegisterOptions): void;
}
export interface ToolHooks {
readonly "execute.before": ToolExecuteBeforeEvent;
readonly "execute.after": ToolExecuteAfterEvent;
}
export interface ToolDomain {
readonly transform: Transform<ToolDraft>;
readonly hook: Hooks<ToolHooks>;
}
export {};
import { Agent } from "@opencode-ai/schema/agent";
import { LLM } from "@opencode-ai/schema/llm";
import { Session } from "@opencode-ai/schema/session";
import { SessionError } from "@opencode-ai/schema/session-error";
import { SessionMessage } from "@opencode-ai/schema/session-message";
import { Effect, JsonSchema, Schema } from "effect";
export class Failure extends Schema.TaggedErrorClass()("LLM.ToolFailure", {
message: Schema.String,
error: Schema.optional(Schema.Defect()),
}) {
}
export class RegistrationError extends Schema.TaggedErrorClass()("Tool.RegistrationError", {
name: Schema.String,
message: Schema.String,
}) {
}
export function make(config) {
return config;
}
export const validateName = (name) => /^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(name)
? Effect.void
: Effect.fail(new RegistrationError({ name, message: `Invalid tool name: ${name}` }));
export const registrationEntries = (tools, options) => Object.entries(tools).map(([name, tool]) => {
const normalized = name.replace(/[^a-zA-Z0-9_-]/g, "_");
const key = options?.namespace === undefined ? normalized : `${options.namespace.replaceAll(".", "_")}_${normalized}`;
return {
key,
name: normalized,
namespace: options?.namespace,
tool,
permission: options?.permission ?? key,
};
});
export const validateNamespace = (namespace) => namespace.split(".").every((segment) => /^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(segment))
? Effect.void
: Effect.fail(new RegistrationError({ name: namespace, message: `Invalid tool namespace: ${JSON.stringify(namespace)}` }));
export const toLLMDefinition = (name, tool) => ({
name,
description: tool.description,
inputSchema: inputJsonSchema(tool.input),
...(tool.output === undefined ? {} : { outputSchema: outputJsonSchema(tool.output) }),
});
// Schema interpretation
export function decodeInput(schema, value) {
if (Schema.isSchema(schema))
return Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError((error) => new Failure({ message: `Invalid tool input: ${error.message}` })));
if (isStandardSchema(schema))
return validateStandard(schema, value, "Invalid tool input");
return Effect.succeed(value);
}
export function encodeOutput(schema, value) {
if (Schema.isSchema(schema))
return Schema.encodeEffect(schema)(value).pipe(Effect.mapError((error) => new Failure({ message: `Tool returned an invalid value for its output schema: ${error.message}` })));
if (isStandardSchema(schema))
return validateStandard(schema, value, "Tool returned an invalid value for its output schema");
return Schema.decodeUnknownEffect(Schema.Json)(value).pipe(Effect.mapError((error) => new Failure({ message: `Tool returned a non-JSON value for its output schema: ${error.message}` })));
}
function isStandardSchema(schema) {
return "~standard" in schema;
}
function validateStandard(schema, value, prefix) {
return Effect.gen(function* () {
const pending = yield* Effect.try({
try: () => schema["~standard"].validate(value),
catch: (error) => standardFailure(prefix, error),
});
const result = pending instanceof Promise
? yield* Effect.tryPromise({ try: () => pending, catch: (error) => standardFailure(prefix, error) })
: pending;
if (result.issues)
return yield* Effect.fail(new Failure({ message: `${prefix}: ${result.issues.map((issue) => issue.message).join(", ")}` }));
return result.value;
});
}
function standardFailure(prefix, error) {
return new Failure({ message: `${prefix}: ${error instanceof Error ? error.message : String(error)}` });
}
function inputJsonSchema(schema) {
if (isStandardSchema(schema))
return schema["~standard"].jsonSchema.input({ target: "draft-2020-12" });
return Schema.isSchema(schema) ? toJsonSchema(schema) : schema;
}
function outputJsonSchema(schema) {
if (isStandardSchema(schema))
return schema["~standard"].jsonSchema.output({ target: "draft-2020-12" });
return Schema.isSchema(schema) ? toJsonSchema(schema) : schema;
}
function toJsonSchema(schema) {
const document = Schema.toJsonSchemaDocument(schema);
if (Object.keys(document.definitions).length === 0)
return document.schema;
return { ...document.schema, $defs: document.definitions };
}
export const ExecuteAfterOutcome = Schema.Union([
Schema.Struct({
status: Schema.Literal("completed"),
content: Schema.NonEmptyArray(LLM.ToolContent),
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Json)),
outputPaths: Schema.optional(Schema.Array(Schema.String)),
}),
Schema.Struct({
status: Schema.Literal("error"),
error: SessionError.Error,
content: Schema.optional(Schema.NonEmptyArray(LLM.ToolContent)),
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Json)),
outputPaths: Schema.optional(Schema.Array(Schema.String)),
}),
]).pipe(Schema.toTaggedUnion("status"));
import type { Hooks, Transform } from "../registration.js";
export type Context = Omit<import("../../effect/internal/tool.js").Context, "progress"> & {
readonly progress: (update: import("../../effect/internal/tool.js").Progress) => Promise<void>;
};
export type SchemaType<A> = import("../../effect/internal/tool.js").SchemaType<A>;
export type Content = import("../../effect/internal/tool.js").Content;
export type Metadata = import("../../effect/internal/tool.js").Metadata;
export type ModelOutput = import("../../effect/internal/tool.js").ModelOutput;
export type Tool<Input extends SchemaType<any>, Output extends SchemaType<any> | undefined = undefined> = Omit<import("../../effect/internal/tool.js").Tool<Input, Output>, "execute"> & {
readonly execute: (input: import("../../effect/internal/tool.js").InputValue<Input>, context: Context) => Promise<Output extends SchemaType<any> ? import("../../effect/internal/tool.js").Response<Output> : import("../../effect/internal/tool.js").ContentResponse>;
};
export type Any = Omit<import("../../effect/internal/tool.js").Any, "execute"> & {
readonly execute: (input: any, context: Context) => Promise<import("../../effect/internal/tool.js").Response<any> | import("../../effect/internal/tool.js").ContentResponse>;
};
export declare function make<Input extends SchemaType<any>, Output extends SchemaType<any>>(tool: Tool<Input, Output>): Tool<Input, Output>;
export declare function make<Input extends SchemaType<any>>(tool: Tool<Input>): Tool<Input>;
export declare function make(tool: Any): Any;
export type ToolExecuteBeforeEvent = import("../../effect/internal/tool.js").ToolExecuteBeforeEvent;
export type ToolExecuteAfterEvent = import("../../effect/internal/tool.js").ToolExecuteAfterEvent;
export type RegisterOptions = import("../../effect/internal/tool.js").RegisterOptions;
export interface ToolDraft {
add<Input extends SchemaType<any>, Output extends SchemaType<any>>(name: string, tool: Tool<Input, Output>, options?: RegisterOptions): void;
add<Input extends SchemaType<any>>(name: string, tool: Tool<Input>, options?: RegisterOptions): void;
}
export interface ToolHooks {
readonly "execute.before": ToolExecuteBeforeEvent;
readonly "execute.after": ToolExecuteAfterEvent;
}
export interface ToolDomain {
readonly transform: Transform<ToolDraft>;
readonly hook: Hooks<ToolHooks>;
}
export function make(tool) {
return tool;
}
+2
-159

@@ -1,159 +0,2 @@

export * as Tool from "./tool.js";
import { Agent } from "@opencode-ai/schema/agent";
import type { LLM } from "@opencode-ai/schema/llm";
import { Session } from "@opencode-ai/schema/session";
import { SessionMessage } from "@opencode-ai/schema/session-message";
import type { StandardJSONSchemaV1, StandardSchemaV1 } from "@standard-schema/spec";
import { Effect, JsonSchema, Schema } from "effect";
import type { Hooks, Transform } from "./registration.js";
export interface Context {
readonly sessionID: Session.ID;
readonly agent: Agent.ID;
readonly messageID: SessionMessage.ID;
readonly callID: string;
readonly progress: (update: Progress) => Effect.Effect<void>;
}
export interface Progress {
readonly structured: Readonly<Record<string, unknown>>;
readonly content?: ReadonlyArray<Content>;
}
export type StandardSchemaType<Input = unknown, Output = Input> = StandardSchemaV1<Input, Output> & StandardJSONSchemaV1<Input, Output>;
export type SchemaType<A> = Schema.Codec<A, any> | StandardSchemaType<any, A>;
type IsAny<A> = 0 extends 1 & A ? true : false;
export type InputValue<S> = IsAny<S> extends true ? any : S extends Schema.Codec<infer A, any> ? A : S extends StandardSchemaV1<any, infer A> ? A : never;
export type OutputValue<S> = IsAny<S> extends true ? any : S extends Schema.Codec<infer A, any> ? A : S extends StandardSchemaV1<infer A, any> ? A : never;
export type EncodedValue<S> = IsAny<S> extends true ? any : S extends Schema.Codec<any, infer A> ? A : S extends StandardSchemaV1<any, infer A> ? A : never;
type ToolDefinition = {
readonly name: string;
readonly description: string;
readonly inputSchema: JsonSchema.JsonSchema;
readonly outputSchema?: JsonSchema.JsonSchema;
};
type ToolCall = {
readonly input: unknown;
readonly [key: string]: unknown;
};
type ToolResultValue = {
readonly type: "json";
readonly value: unknown;
} | {
readonly type: "text";
readonly value: unknown;
} | {
readonly type: "error";
readonly value: unknown;
} | {
readonly type: "content";
readonly value: ReadonlyArray<LLM.ToolContent>;
};
type ToolOutput = {
readonly structured: unknown;
readonly content: ReadonlyArray<LLM.ToolContent>;
};
declare const Failure_base: Schema.Class<Failure, Schema.TaggedStruct<"LLM.ToolFailure", {
readonly message: Schema.String;
readonly error: Schema.optional<Schema.Defect>;
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
}>, import("effect/Cause").YieldableError>;
export declare class Failure extends Failure_base {
}
declare const RegistrationError_base: Schema.Class<RegistrationError, Schema.TaggedStruct<"Tool.RegistrationError", {
readonly name: Schema.String;
readonly message: Schema.String;
}>, import("effect/Cause").YieldableError>;
export declare class RegistrationError extends RegistrationError_base {
}
export type Content = {
readonly type: "text";
readonly text: string;
} | {
readonly type: "file";
readonly data: string;
readonly mime: string;
readonly name?: string;
};
export type Definition<Input extends SchemaType<any>, Structured extends SchemaType<any>, Output extends SchemaType<any> = any> = {
readonly description: string;
readonly input: Input;
readonly output: Output;
readonly structured?: Structured;
readonly permission?: string;
readonly toStructuredOutput?: (input: {
readonly input: InputValue<Input>;
readonly output: EncodedValue<Output>;
}) => OutputValue<Structured>;
readonly execute: (input: InputValue<Input>, context: Context) => Effect.Effect<OutputValue<Output>, Failure>;
readonly toModelOutput?: (input: {
readonly input: InputValue<Input>;
readonly output: EncodedValue<Output>;
}) => ReadonlyArray<Content>;
};
export type DynamicOutput = {
readonly structured: unknown;
readonly content: ReadonlyArray<Content>;
};
/**
* Config for a tool whose input shape is a raw JSON Schema not known at compile
* time (MCP servers, plugin manifests). Input is passed through as `unknown`;
* `execute` returns the already-projected structured value and model content.
*/
export type DynamicDefinition = {
readonly description: string;
readonly jsonSchema: JsonSchema.JsonSchema;
readonly outputSchema?: JsonSchema.JsonSchema;
readonly permission?: string;
readonly execute: (input: unknown, context: Context) => Effect.Effect<DynamicOutput, Failure>;
};
export type AnyTool = Definition<any, any> | DynamicDefinition;
export declare function make<Input extends SchemaType<any>, Output extends SchemaType<any>, Structured extends SchemaType<any> = Output>(config: Definition<Input, Structured, Output>): Definition<Input, Structured, Output>;
export declare function make(config: DynamicDefinition): DynamicDefinition;
export declare function make(config: AnyTool): AnyTool;
export declare const validateName: (name: string) => Effect.Effect<void, never, never> | Effect.Effect<never, RegistrationError, never>;
export declare const registrationEntries: (tools: Readonly<Record<string, AnyTool>>, namespace?: string) => {
key: string;
name: string;
namespace: string | undefined;
tool: AnyTool;
}[];
export declare const validateNamespace: (namespace: string) => Effect.Effect<void, never, never> | Effect.Effect<never, RegistrationError, never>;
export declare const withPermission: <T extends AnyTool>(tool: T, permission: string) => Omit<T, "permission"> & {
readonly permission: string;
};
export declare const permission: (tool: AnyTool, name: string) => string;
export declare const definition: (name: string, tool: AnyTool) => ToolDefinition;
export declare const settle: (tool: AnyTool, call: ToolCall, context: Context) => Effect.Effect<ToolOutput, Failure>;
export interface ToolExecuteBeforeEvent {
readonly tool: string;
readonly sessionID: Session.ID;
readonly agent: Agent.ID;
readonly messageID: SessionMessage.ID;
readonly callID: string;
input: unknown;
}
export interface ToolExecuteAfterEvent {
readonly tool: string;
readonly sessionID: Session.ID;
readonly agent: Agent.ID;
readonly messageID: SessionMessage.ID;
readonly callID: string;
readonly input: unknown;
result: ToolResultValue;
output?: ToolOutput;
outputPaths?: ReadonlyArray<string>;
}
export interface RegisterOptions {
readonly namespace?: string;
/** Defaults to true. False exposes the tool directly to the provider. */
readonly codemode?: boolean;
}
export interface ToolDraft {
add(name: string, tool: AnyTool, options?: RegisterOptions): void;
}
export interface ToolHooks {
readonly "execute.before": ToolExecuteBeforeEvent;
readonly "execute.after": ToolExecuteAfterEvent;
}
export interface ToolDomain {
readonly transform: Transform<ToolDraft>;
readonly hook: Hooks<ToolHooks>;
}
export * as Tool from "./internal/tool.js";
export * from "./internal/tool.js";

@@ -1,114 +0,2 @@

export * as Tool from "./tool.js";
import { Agent } from "@opencode-ai/schema/agent";
import { Session } from "@opencode-ai/schema/session";
import { SessionMessage } from "@opencode-ai/schema/session-message";
import { Effect, JsonSchema, Schema } from "effect";
export class Failure extends Schema.TaggedErrorClass()("LLM.ToolFailure", {
message: Schema.String,
error: Schema.optional(Schema.Defect()),
metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
}) {
}
export class RegistrationError extends Schema.TaggedErrorClass()("Tool.RegistrationError", {
name: Schema.String,
message: Schema.String,
}) {
}
export function make(config) {
return config;
}
function toModelContent(part) {
if (part.type === "text")
return { type: "text", text: part.text };
return { type: "file", uri: `data:${part.mime};base64,${part.data}`, mime: part.mime, name: part.name };
}
export const validateName = (name) => /^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(name)
? Effect.void
: Effect.fail(new RegistrationError({ name, message: `Invalid tool name: ${name}` }));
export const registrationEntries = (tools, namespace) => Object.entries(tools).map(([name, tool]) => {
const normalized = name.replace(/[^a-zA-Z0-9_-]/g, "_");
return {
key: namespace === undefined ? normalized : `${namespace.replaceAll(".", "_")}_${normalized}`,
name: normalized,
namespace,
tool,
};
});
export const validateNamespace = (namespace) => namespace.split(".").every((segment) => /^[A-Za-z][A-Za-z0-9_-]{0,63}$/.test(segment))
? Effect.void
: Effect.fail(new RegistrationError({ name: namespace, message: `Invalid tool namespace: ${JSON.stringify(namespace)}` }));
export const withPermission = (tool, permission) => ({ ...tool, permission });
export const permission = (tool, name) => tool.permission ?? name;
export const definition = (name, tool) => "jsonSchema" in tool
? {
name,
description: tool.description,
inputSchema: tool.jsonSchema,
outputSchema: tool.outputSchema,
}
: {
name,
description: tool.description,
inputSchema: inputJsonSchema(tool.input),
outputSchema: outputJsonSchema(tool.structured ?? tool.output),
};
export const settle = (tool, call, context) => Effect.gen(function* () {
if ("jsonSchema" in tool) {
const output = yield* tool.execute(call.input, context);
return { structured: output.structured, content: output.content.map(toModelContent) };
}
const input = yield* decodeInput(tool.input, call.input);
const value = yield* tool.execute(input, context);
const output = yield* encodeOutput(tool.output, value);
const structured = tool.structured && tool.toStructuredOutput
? yield* encodeOutput(tool.structured, tool.toStructuredOutput({ input, output }))
: output;
return {
structured,
content: tool.toModelOutput?.({ input, output }).map(toModelContent) ??
(typeof output === "string" ? [{ type: "text", text: output }] : []),
};
});
function decodeInput(schema, value) {
if (Schema.isSchema(schema))
return Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError((error) => new Failure({ message: `Invalid tool input: ${error.message}` })));
return validateStandard(schema, value, "Invalid tool input");
}
function encodeOutput(schema, value) {
if (Schema.isSchema(schema))
return Schema.encodeEffect(schema)(value).pipe(Effect.mapError((error) => new Failure({ message: `Tool returned an invalid value for its output schema: ${error.message}` })));
return validateStandard(schema, value, "Tool returned an invalid value for its output schema");
}
function validateStandard(schema, value, prefix) {
return Effect.gen(function* () {
const pending = yield* Effect.try({
try: () => schema["~standard"].validate(value),
catch: (error) => standardFailure(prefix, error),
});
const result = pending instanceof Promise
? yield* Effect.tryPromise({ try: () => pending, catch: (error) => standardFailure(prefix, error) })
: pending;
if (result.issues)
return yield* Effect.fail(new Failure({ message: `${prefix}: ${result.issues.map((issue) => issue.message).join(", ")}` }));
return result.value;
});
}
function standardFailure(prefix, error) {
return new Failure({ message: `${prefix}: ${error instanceof Error ? error.message : String(error)}` });
}
function inputJsonSchema(schema) {
if (!Schema.isSchema(schema))
return schema["~standard"].jsonSchema.input({ target: "draft-2020-12" });
return toJsonSchema(schema);
}
function outputJsonSchema(schema) {
if (!Schema.isSchema(schema))
return schema["~standard"].jsonSchema.output({ target: "draft-2020-12" });
return toJsonSchema(schema);
}
function toJsonSchema(schema) {
const document = Schema.toJsonSchemaDocument(schema);
if (Object.keys(document.definitions).length === 0)
return document.schema;
return { ...document.schema, $defs: document.definitions };
}
export * as Tool from "./internal/tool.js";
export * from "./internal/tool.js";

@@ -1,34 +0,2 @@

import type { Tool } from "../effect/tool.js";
import type { Hooks, Transform } from "./registration.js";
export type Context = Omit<Tool.Context, "progress"> & {
readonly progress: (update: Tool.Progress) => Promise<void>;
};
export type SchemaType<A> = Tool.SchemaType<A>;
export type Content = Tool.Content;
export type DynamicOutput = Tool.DynamicOutput;
export type Definition<Input extends SchemaType<any>, Output extends SchemaType<any>, Structured extends SchemaType<any> = Output> = Omit<Tool.Definition<Input, Structured, Output>, "execute" | "permission"> & {
readonly name: string;
readonly options?: RegisterOptions;
readonly execute: (input: Tool.InputValue<Input>, context: Context) => Promise<Tool.OutputValue<Output>>;
};
export type DynamicDefinition = Omit<Tool.DynamicDefinition, "execute" | "permission"> & {
readonly name: string;
readonly options?: RegisterOptions;
readonly execute: (input: unknown, context: Context) => Promise<DynamicOutput>;
};
export type AnyTool = Definition<any, any, any> | DynamicDefinition;
export type ToolExecuteBeforeEvent = Tool.ToolExecuteBeforeEvent;
export type ToolExecuteAfterEvent = Tool.ToolExecuteAfterEvent;
export type RegisterOptions = Tool.RegisterOptions;
export interface ToolDraft {
add<Input extends SchemaType<any>, Output extends SchemaType<any>, Structured extends SchemaType<any> = Output>(tool: Definition<Input, Output, Structured>): void;
add(tool: DynamicDefinition): void;
}
export interface ToolHooks {
readonly "execute.before": ToolExecuteBeforeEvent;
readonly "execute.after": ToolExecuteAfterEvent;
}
export interface ToolDomain {
readonly transform: Transform<ToolDraft>;
readonly hook: Hooks<ToolHooks>;
}
export * as Tool from "./internal/tool.js";
export * from "./internal/tool.js";
{
"$schema": "https://json.schemastore.org/package.json",
"name": "@opencode-ai/plugin",
"version": "0.0.0-next-16088",
"version": "0.0.0-next-16093",
"type": "module",

@@ -55,6 +55,6 @@ "license": "MIT",

"@ai-sdk/provider": "3.0.8",
"@opencode-ai/ai": "0.0.0-next-16088",
"@opencode-ai/client": "0.0.0-next-16088",
"@opencode-ai/schema": "0.0.0-next-16088",
"@opencode-ai/sdk": "0.0.0-next-16088",
"@opencode-ai/ai": "0.0.0-next-16093",
"@opencode-ai/client": "0.0.0-next-16093",
"@opencode-ai/schema": "0.0.0-next-16093",
"@opencode-ai/sdk": "0.0.0-next-16093",
"@standard-schema/spec": "^1.1.0",

@@ -61,0 +61,0 @@ "effect": "4.0.0-beta.98",