@opencode-ai/plugin 0.0.0-next-15632 → 0.0.0-next-15634
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/v2/effect/tool.d.ts +25 -21
- package/dist/v2/effect/tool.js +69 -71
- package/dist/v2/promise/tool.d.ts +6 -46
- package/package.json +6 -5
package/dist/v2/effect/tool.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Agent } from "@opencode-ai/schema/agent";
|
|
|
3
3
|
import type { LLM } from "@opencode-ai/schema/llm";
|
|
4
4
|
import { Session } from "@opencode-ai/schema/session";
|
|
5
5
|
import { SessionMessage } from "@opencode-ai/schema/session-message";
|
|
6
|
+
import type { StandardJSONSchemaV1, StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
7
|
import { Effect, JsonSchema, Schema } from "effect";
|
|
7
8
|
import type { Hooks, Transform } from "./registration.js";
|
|
8
9
|
export interface Context {
|
|
@@ -16,7 +17,12 @@ export interface Progress {
|
|
|
16
17
|
readonly structured: Readonly<Record<string, unknown>>;
|
|
17
18
|
readonly content?: ReadonlyArray<Content>;
|
|
18
19
|
}
|
|
19
|
-
export type
|
|
20
|
+
export type StandardSchemaType<Input = unknown, Output = Input> = StandardSchemaV1<Input, Output> & StandardJSONSchemaV1<Input, Output>;
|
|
21
|
+
export type SchemaType<A> = Schema.Codec<A, any> | StandardSchemaType<any, A>;
|
|
22
|
+
type IsAny<A> = 0 extends 1 & A ? true : false;
|
|
23
|
+
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;
|
|
24
|
+
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;
|
|
25
|
+
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;
|
|
20
26
|
type ToolDefinition = {
|
|
21
27
|
readonly name: string;
|
|
22
28
|
readonly description: string;
|
|
@@ -44,14 +50,6 @@ type ToolOutput = {
|
|
|
44
50
|
readonly structured: unknown;
|
|
45
51
|
readonly content: ReadonlyArray<LLM.ToolContent>;
|
|
46
52
|
};
|
|
47
|
-
declare const TypeId: unique symbol;
|
|
48
|
-
export interface Definition<Input extends SchemaType<any>, Output extends SchemaType<any>> {
|
|
49
|
-
readonly [TypeId]: {
|
|
50
|
-
readonly _Input: Input;
|
|
51
|
-
readonly _Output: Output;
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
export type AnyTool = Definition<any, any>;
|
|
55
53
|
declare const Failure_base: Schema.Class<Failure, Schema.TaggedStruct<"LLM.ToolFailure", {
|
|
56
54
|
readonly message: Schema.String;
|
|
57
55
|
readonly error: Schema.optional<Schema.Defect>;
|
|
@@ -74,19 +72,20 @@ export type Content = {
|
|
|
74
72
|
readonly mime: string;
|
|
75
73
|
readonly name?: string;
|
|
76
74
|
};
|
|
77
|
-
type
|
|
75
|
+
export type Definition<Input extends SchemaType<any>, Structured extends SchemaType<any>, Output extends SchemaType<any> = any> = {
|
|
78
76
|
readonly description: string;
|
|
79
77
|
readonly input: Input;
|
|
80
78
|
readonly output: Output;
|
|
81
79
|
readonly structured?: Structured;
|
|
80
|
+
readonly permission?: string;
|
|
82
81
|
readonly toStructuredOutput?: (input: {
|
|
83
|
-
readonly input:
|
|
84
|
-
readonly output: Output
|
|
85
|
-
}) =>
|
|
86
|
-
readonly execute: (input:
|
|
82
|
+
readonly input: InputValue<Input>;
|
|
83
|
+
readonly output: EncodedValue<Output>;
|
|
84
|
+
}) => OutputValue<Structured>;
|
|
85
|
+
readonly execute: (input: InputValue<Input>, context: Context) => Effect.Effect<OutputValue<Output>, Failure>;
|
|
87
86
|
readonly toModelOutput?: (input: {
|
|
88
|
-
readonly input:
|
|
89
|
-
readonly output: Output
|
|
87
|
+
readonly input: InputValue<Input>;
|
|
88
|
+
readonly output: EncodedValue<Output>;
|
|
90
89
|
}) => ReadonlyArray<Content>;
|
|
91
90
|
};
|
|
92
91
|
export type DynamicOutput = {
|
|
@@ -98,14 +97,17 @@ export type DynamicOutput = {
|
|
|
98
97
|
* time (MCP servers, plugin manifests). Input is passed through as `unknown`;
|
|
99
98
|
* `execute` returns the already-projected structured value and model content.
|
|
100
99
|
*/
|
|
101
|
-
type
|
|
100
|
+
export type DynamicDefinition = {
|
|
102
101
|
readonly description: string;
|
|
103
102
|
readonly jsonSchema: JsonSchema.JsonSchema;
|
|
104
103
|
readonly outputSchema?: JsonSchema.JsonSchema;
|
|
104
|
+
readonly permission?: string;
|
|
105
105
|
readonly execute: (input: unknown, context: Context) => Effect.Effect<DynamicOutput, Failure>;
|
|
106
106
|
};
|
|
107
|
-
export
|
|
108
|
-
export declare function make(config:
|
|
107
|
+
export type AnyTool = Definition<any, any> | DynamicDefinition;
|
|
108
|
+
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>;
|
|
109
|
+
export declare function make(config: DynamicDefinition): DynamicDefinition;
|
|
110
|
+
export declare function make(config: AnyTool): AnyTool;
|
|
109
111
|
export declare const validateName: (name: string) => Effect.Effect<void, never, never> | Effect.Effect<never, RegistrationError, never>;
|
|
110
112
|
export declare const registrationEntries: (tools: Readonly<Record<string, AnyTool>>, group?: string) => {
|
|
111
113
|
key: string;
|
|
@@ -113,10 +115,12 @@ export declare const registrationEntries: (tools: Readonly<Record<string, AnyToo
|
|
|
113
115
|
group: string | undefined;
|
|
114
116
|
tool: AnyTool;
|
|
115
117
|
}[];
|
|
116
|
-
export declare const withPermission: <
|
|
118
|
+
export declare const withPermission: <T extends AnyTool>(tool: T, permission: string) => Omit<T, "permission"> & {
|
|
119
|
+
readonly permission: string;
|
|
120
|
+
};
|
|
117
121
|
export declare const permission: (tool: AnyTool, name: string) => string;
|
|
118
122
|
export declare const definition: (name: string, tool: AnyTool) => ToolDefinition;
|
|
119
|
-
export declare const settle: (tool: AnyTool, call: ToolCall, context: Context) => Effect.Effect<ToolOutput, Failure
|
|
123
|
+
export declare const settle: (tool: AnyTool, call: ToolCall, context: Context) => Effect.Effect<ToolOutput, Failure>;
|
|
120
124
|
export interface ToolExecuteBeforeEvent {
|
|
121
125
|
readonly tool: string;
|
|
122
126
|
readonly sessionID: Session.ID;
|
package/dist/v2/effect/tool.js
CHANGED
|
@@ -14,65 +14,8 @@ export class RegistrationError extends Schema.TaggedErrorClass()("Tool.Registrat
|
|
|
14
14
|
message: Schema.String,
|
|
15
15
|
}) {
|
|
16
16
|
}
|
|
17
|
-
const runtimes = new WeakMap();
|
|
18
17
|
export function make(config) {
|
|
19
|
-
|
|
20
|
-
return makeDynamic(config);
|
|
21
|
-
return makeTyped(config);
|
|
22
|
-
}
|
|
23
|
-
function makeTyped(config) {
|
|
24
|
-
const tool = Object.freeze({});
|
|
25
|
-
const definitions = new Map();
|
|
26
|
-
runtimes.set(tool, {
|
|
27
|
-
definition: (name) => {
|
|
28
|
-
const cached = definitions.get(name);
|
|
29
|
-
if (cached)
|
|
30
|
-
return cached;
|
|
31
|
-
const definition = {
|
|
32
|
-
name,
|
|
33
|
-
description: config.description,
|
|
34
|
-
inputSchema: toJsonSchema(config.input),
|
|
35
|
-
outputSchema: toJsonSchema(config.structured ?? config.output),
|
|
36
|
-
};
|
|
37
|
-
definitions.set(name, definition);
|
|
38
|
-
return definition;
|
|
39
|
-
},
|
|
40
|
-
settle: (call, context) => Schema.decodeUnknownEffect(config.input)(call.input).pipe(Effect.mapError((error) => new Failure({ message: `Invalid tool input: ${error.message}` })), Effect.flatMap((input) => config.execute(input, context).pipe(Effect.flatMap((output) => Schema.encodeEffect(config.output)(output).pipe(Effect.flatMap((output) => {
|
|
41
|
-
if (!config.structured || !config.toStructuredOutput)
|
|
42
|
-
return Effect.succeed({ output, structured: output });
|
|
43
|
-
return Schema.encodeEffect(config.structured)(config.toStructuredOutput({ input, output })).pipe(Effect.map((structured) => ({ output, structured })));
|
|
44
|
-
}), Effect.mapError((error) => new Failure({
|
|
45
|
-
message: `Tool returned an invalid value for its output schema: ${error.message}`,
|
|
46
|
-
})))), Effect.map(({ output, structured }) => ({
|
|
47
|
-
structured,
|
|
48
|
-
content: config.toModelOutput?.({ input, output }).map(toModelContent) ??
|
|
49
|
-
(typeof output === "string" ? [{ type: "text", text: output }] : []),
|
|
50
|
-
}))))),
|
|
51
|
-
});
|
|
52
|
-
return tool;
|
|
53
|
-
}
|
|
54
|
-
function makeDynamic(config) {
|
|
55
|
-
const tool = Object.freeze({});
|
|
56
|
-
const definitions = new Map();
|
|
57
|
-
runtimes.set(tool, {
|
|
58
|
-
definition: (name) => {
|
|
59
|
-
const cached = definitions.get(name);
|
|
60
|
-
if (cached)
|
|
61
|
-
return cached;
|
|
62
|
-
const definition = {
|
|
63
|
-
name,
|
|
64
|
-
description: config.description,
|
|
65
|
-
inputSchema: config.jsonSchema,
|
|
66
|
-
outputSchema: config.outputSchema,
|
|
67
|
-
};
|
|
68
|
-
definitions.set(name, definition);
|
|
69
|
-
return definition;
|
|
70
|
-
},
|
|
71
|
-
settle: (call, context) => config
|
|
72
|
-
.execute(call.input, context)
|
|
73
|
-
.pipe(Effect.map((output) => ({ structured: output.structured, content: output.content.map(toModelContent) }))),
|
|
74
|
-
});
|
|
75
|
-
return tool;
|
|
18
|
+
return config;
|
|
76
19
|
}
|
|
77
20
|
function toModelContent(part) {
|
|
78
21
|
if (part.type === "text")
|
|
@@ -92,19 +35,74 @@ export const registrationEntries = (tools, group) => Object.entries(tools).map((
|
|
|
92
35
|
tool,
|
|
93
36
|
};
|
|
94
37
|
});
|
|
95
|
-
export const withPermission = (tool, permission) => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
38
|
+
export const withPermission = (tool, permission) => ({ ...tool, permission });
|
|
39
|
+
export const permission = (tool, name) => tool.permission ?? name;
|
|
40
|
+
export const definition = (name, tool) => "jsonSchema" in tool
|
|
41
|
+
? {
|
|
42
|
+
name,
|
|
43
|
+
description: tool.description,
|
|
44
|
+
inputSchema: tool.jsonSchema,
|
|
45
|
+
outputSchema: tool.outputSchema,
|
|
46
|
+
}
|
|
47
|
+
: {
|
|
48
|
+
name,
|
|
49
|
+
description: tool.description,
|
|
50
|
+
inputSchema: inputJsonSchema(tool.input),
|
|
51
|
+
outputSchema: outputJsonSchema(tool.structured ?? tool.output),
|
|
52
|
+
};
|
|
53
|
+
export const settle = (tool, call, context) => Effect.gen(function* () {
|
|
54
|
+
if ("jsonSchema" in tool) {
|
|
55
|
+
const output = yield* tool.execute(call.input, context);
|
|
56
|
+
return { structured: output.structured, content: output.content.map(toModelContent) };
|
|
57
|
+
}
|
|
58
|
+
const input = yield* decodeInput(tool.input, call.input);
|
|
59
|
+
const value = yield* tool.execute(input, context);
|
|
60
|
+
const output = yield* encodeOutput(tool.output, value);
|
|
61
|
+
const structured = tool.structured && tool.toStructuredOutput
|
|
62
|
+
? yield* encodeOutput(tool.structured, tool.toStructuredOutput({ input, output }))
|
|
63
|
+
: output;
|
|
64
|
+
return {
|
|
65
|
+
structured,
|
|
66
|
+
content: tool.toModelOutput?.({ input, output }).map(toModelContent) ??
|
|
67
|
+
(typeof output === "string" ? [{ type: "text", text: output }] : []),
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
function decodeInput(schema, value) {
|
|
71
|
+
if (Schema.isSchema(schema))
|
|
72
|
+
return Schema.decodeUnknownEffect(schema)(value).pipe(Effect.mapError((error) => new Failure({ message: `Invalid tool input: ${error.message}` })));
|
|
73
|
+
return validateStandard(schema, value, "Invalid tool input");
|
|
74
|
+
}
|
|
75
|
+
function encodeOutput(schema, value) {
|
|
76
|
+
if (Schema.isSchema(schema))
|
|
77
|
+
return Schema.encodeEffect(schema)(value).pipe(Effect.mapError((error) => new Failure({ message: `Tool returned an invalid value for its output schema: ${error.message}` })));
|
|
78
|
+
return validateStandard(schema, value, "Tool returned an invalid value for its output schema");
|
|
79
|
+
}
|
|
80
|
+
function validateStandard(schema, value, prefix) {
|
|
81
|
+
return Effect.gen(function* () {
|
|
82
|
+
const pending = yield* Effect.try({
|
|
83
|
+
try: () => schema["~standard"].validate(value),
|
|
84
|
+
catch: (error) => standardFailure(prefix, error),
|
|
85
|
+
});
|
|
86
|
+
const result = pending instanceof Promise
|
|
87
|
+
? yield* Effect.tryPromise({ try: () => pending, catch: (error) => standardFailure(prefix, error) })
|
|
88
|
+
: pending;
|
|
89
|
+
if (result.issues)
|
|
90
|
+
return yield* Effect.fail(new Failure({ message: `${prefix}: ${result.issues.map((issue) => issue.message).join(", ")}` }));
|
|
91
|
+
return result.value;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function standardFailure(prefix, error) {
|
|
95
|
+
return new Failure({ message: `${prefix}: ${error instanceof Error ? error.message : String(error)}` });
|
|
96
|
+
}
|
|
97
|
+
function inputJsonSchema(schema) {
|
|
98
|
+
if (!Schema.isSchema(schema))
|
|
99
|
+
return schema["~standard"].jsonSchema.input({ target: "draft-2020-12" });
|
|
100
|
+
return toJsonSchema(schema);
|
|
101
|
+
}
|
|
102
|
+
function outputJsonSchema(schema) {
|
|
103
|
+
if (!Schema.isSchema(schema))
|
|
104
|
+
return schema["~standard"].jsonSchema.output({ target: "draft-2020-12" });
|
|
105
|
+
return toJsonSchema(schema);
|
|
108
106
|
}
|
|
109
107
|
function toJsonSchema(schema) {
|
|
110
108
|
const document = Schema.toJsonSchemaDocument(schema);
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import type { Tool } from "../effect/tool.js";
|
|
2
|
-
import type { Agent } from "@opencode-ai/schema/agent";
|
|
3
|
-
import type { Session } from "@opencode-ai/schema/session";
|
|
4
|
-
import type { SessionMessage } from "@opencode-ai/schema/session-message";
|
|
5
|
-
import type { JsonSchema, Schema } from "effect";
|
|
6
2
|
import type { Hooks, Transform } from "./registration.js";
|
|
7
3
|
export type Context = Omit<Tool.Context, "progress"> & {
|
|
8
4
|
readonly progress: (update: Tool.Progress) => Promise<void>;
|
|
@@ -10,56 +6,20 @@ export type Context = Omit<Tool.Context, "progress"> & {
|
|
|
10
6
|
export type SchemaType<A> = Tool.SchemaType<A>;
|
|
11
7
|
export type Content = Tool.Content;
|
|
12
8
|
export type DynamicOutput = Tool.DynamicOutput;
|
|
13
|
-
export type Definition<Input extends SchemaType<any>, Output extends SchemaType<any>, Structured extends SchemaType<any> = Output> = {
|
|
9
|
+
export type Definition<Input extends SchemaType<any>, Output extends SchemaType<any>, Structured extends SchemaType<any> = Output> = Omit<Tool.Definition<Input, Structured, Output>, "execute" | "permission"> & {
|
|
14
10
|
readonly name: string;
|
|
15
11
|
readonly options?: RegisterOptions;
|
|
16
|
-
readonly
|
|
17
|
-
readonly input: Input;
|
|
18
|
-
readonly output: Output;
|
|
19
|
-
readonly structured?: Structured;
|
|
20
|
-
readonly toStructuredOutput?: (input: {
|
|
21
|
-
readonly input: Schema.Schema.Type<Input>;
|
|
22
|
-
readonly output: Output["Encoded"];
|
|
23
|
-
}) => Schema.Schema.Type<Structured>;
|
|
24
|
-
readonly execute: (input: Schema.Schema.Type<Input>, context: Context) => Promise<Schema.Schema.Type<Output>>;
|
|
25
|
-
readonly toModelOutput?: (input: {
|
|
26
|
-
readonly input: Schema.Schema.Type<Input>;
|
|
27
|
-
readonly output: Output["Encoded"];
|
|
28
|
-
}) => ReadonlyArray<Content>;
|
|
12
|
+
readonly execute: (input: Tool.InputValue<Input>, context: Context) => Promise<Tool.OutputValue<Output>>;
|
|
29
13
|
};
|
|
30
|
-
export type DynamicDefinition = {
|
|
14
|
+
export type DynamicDefinition = Omit<Tool.DynamicDefinition, "execute" | "permission"> & {
|
|
31
15
|
readonly name: string;
|
|
32
16
|
readonly options?: RegisterOptions;
|
|
33
|
-
readonly description: string;
|
|
34
|
-
readonly jsonSchema: JsonSchema.JsonSchema;
|
|
35
|
-
readonly outputSchema?: JsonSchema.JsonSchema;
|
|
36
17
|
readonly execute: (input: unknown, context: Context) => Promise<DynamicOutput>;
|
|
37
18
|
};
|
|
38
19
|
export type AnyTool = Definition<any, any, any> | DynamicDefinition;
|
|
39
|
-
export
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
readonly agent: Agent.ID;
|
|
43
|
-
readonly messageID: SessionMessage.ID;
|
|
44
|
-
readonly callID: string;
|
|
45
|
-
input: unknown;
|
|
46
|
-
}
|
|
47
|
-
export interface ToolExecuteAfterEvent {
|
|
48
|
-
readonly tool: string;
|
|
49
|
-
readonly sessionID: Session.ID;
|
|
50
|
-
readonly agent: Agent.ID;
|
|
51
|
-
readonly messageID: SessionMessage.ID;
|
|
52
|
-
readonly callID: string;
|
|
53
|
-
readonly input: unknown;
|
|
54
|
-
result: Tool.ToolExecuteAfterEvent["result"];
|
|
55
|
-
output?: Tool.ToolExecuteAfterEvent["output"];
|
|
56
|
-
outputPaths?: ReadonlyArray<string>;
|
|
57
|
-
}
|
|
58
|
-
export interface RegisterOptions {
|
|
59
|
-
readonly group?: string;
|
|
60
|
-
/** Defaults to true. False exposes the tool directly to the provider. */
|
|
61
|
-
readonly codemode?: boolean;
|
|
62
|
-
}
|
|
20
|
+
export type ToolExecuteBeforeEvent = Tool.ToolExecuteBeforeEvent;
|
|
21
|
+
export type ToolExecuteAfterEvent = Tool.ToolExecuteAfterEvent;
|
|
22
|
+
export type RegisterOptions = Tool.RegisterOptions;
|
|
63
23
|
export interface ToolDraft {
|
|
64
24
|
add<Input extends SchemaType<any>, Output extends SchemaType<any>, Structured extends SchemaType<any> = Output>(tool: Definition<Input, Output, Structured>): void;
|
|
65
25
|
add(tool: DynamicDefinition): void;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@opencode-ai/plugin",
|
|
4
|
-
"version": "0.0.0-next-
|
|
4
|
+
"version": "0.0.0-next-15634",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {
|
|
@@ -52,10 +52,11 @@
|
|
|
52
52
|
],
|
|
53
53
|
"dependencies": {
|
|
54
54
|
"@ai-sdk/provider": "3.0.8",
|
|
55
|
-
"@opencode-ai/ai": "0.0.0-next-
|
|
56
|
-
"@opencode-ai/client": "0.0.0-next-
|
|
57
|
-
"@opencode-ai/schema": "0.0.0-next-
|
|
58
|
-
"@opencode-ai/sdk": "0.0.0-next-
|
|
55
|
+
"@opencode-ai/ai": "0.0.0-next-15634",
|
|
56
|
+
"@opencode-ai/client": "0.0.0-next-15634",
|
|
57
|
+
"@opencode-ai/schema": "0.0.0-next-15634",
|
|
58
|
+
"@opencode-ai/sdk": "0.0.0-next-15634",
|
|
59
|
+
"@standard-schema/spec": "^1.1.0",
|
|
59
60
|
"effect": "4.0.0-beta.83",
|
|
60
61
|
"zod": "4.1.8"
|
|
61
62
|
},
|