@opencode/plugin 2.0.27 → 2.0.29
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.
|
@@ -2,6 +2,9 @@ import type { PermissionApi } from "@opencode/client/effect/api";
|
|
|
2
2
|
import type { Agent } from "@opencode/schema/agent";
|
|
3
3
|
import type { Permission } from "@opencode/schema/permission";
|
|
4
4
|
import type { Session } from "@opencode/schema/session";
|
|
5
|
+
import type { Tool } from "@opencode/schema/tool";
|
|
6
|
+
import type { Effect } from "effect";
|
|
7
|
+
import type { AssertInput } from "../permission.js";
|
|
5
8
|
import type { Hooks } from "./registration.js";
|
|
6
9
|
export interface PermissionEvaluation {
|
|
7
10
|
readonly sessionID: Session.ID;
|
|
@@ -18,4 +21,10 @@ export interface PermissionHooks {
|
|
|
18
21
|
}
|
|
19
22
|
export type PermissionDomain = Pick<PermissionApi<unknown>, "list" | "get" | "reply"> & {
|
|
20
23
|
readonly hook: Hooks<PermissionHooks>;
|
|
24
|
+
/**
|
|
25
|
+
* Evaluates the session's permission rules and, when approval is required, prompts the user and
|
|
26
|
+
* waits for the reply. Succeeds when allowed. A deny rule or a rejection with feedback fails with a
|
|
27
|
+
* `Tool.Error` carrying the reason; a plain rejection ends the current step.
|
|
28
|
+
*/
|
|
29
|
+
readonly assert: (input: AssertInput) => Effect.Effect<void, Tool.Error>;
|
|
21
30
|
};
|
package/dist/effect/plugin.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExperimentalApi, GenerateApi, PluginApi } from "@opencode/client/effect/api";
|
|
1
|
+
import type { CredentialApi, ExperimentalApi, GenerateApi, PluginApi } from "@opencode/client/effect/api";
|
|
2
2
|
import type { Location } from "@opencode/schema/location";
|
|
3
3
|
import type { Effect, Scope } from "effect";
|
|
4
4
|
import type { PluginOptions } from "../options.js";
|
|
@@ -29,6 +29,7 @@ export interface Context {
|
|
|
29
29
|
readonly agent: AgentDomain;
|
|
30
30
|
readonly aisdk: AISDKDomain;
|
|
31
31
|
readonly command: CommandDomain;
|
|
32
|
+
readonly credential: Pick<CredentialApi<unknown>, "activate">;
|
|
32
33
|
readonly event: EventDomain;
|
|
33
34
|
readonly experimental: {
|
|
34
35
|
readonly terminal: Pick<ExperimentalApi<unknown>["persistentPty"], "read">;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export declare const AssertInput: Schema.Struct<{
|
|
3
|
+
readonly sessionID: Schema.brand<Schema.String, "SessionID"> & {
|
|
4
|
+
create: () => string & import("effect/Brand").Brand<"SessionID">;
|
|
5
|
+
descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
|
|
6
|
+
};
|
|
7
|
+
readonly agent: Schema.optional<Schema.brand<Schema.String, "Agent.ID">>;
|
|
8
|
+
readonly action: Schema.String;
|
|
9
|
+
readonly resources: Schema.$Array<Schema.String>;
|
|
10
|
+
readonly save: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Array<Schema.String>>>, Schema.optionalKey<Schema.$Array<Schema.String>>, never, never>;
|
|
11
|
+
readonly metadata: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Unknown>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Unknown>>, never, never>;
|
|
12
|
+
readonly source: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Union<readonly [Schema.Struct<{
|
|
13
|
+
readonly type: Schema.Literal<"tool">;
|
|
14
|
+
readonly messageID: Schema.String;
|
|
15
|
+
readonly id: Schema.String;
|
|
16
|
+
}>]>>>, Schema.optionalKey<Schema.Union<readonly [Schema.Struct<{
|
|
17
|
+
readonly type: Schema.Literal<"tool">;
|
|
18
|
+
readonly messageID: Schema.String;
|
|
19
|
+
readonly id: Schema.String;
|
|
20
|
+
}>]>>, never, never>;
|
|
21
|
+
}>;
|
|
22
|
+
export interface AssertInput extends Schema.Schema.Type<typeof AssertInput> {
|
|
23
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Agent } from "@opencode/schema/agent";
|
|
2
|
+
import { Permission } from "@opencode/schema/permission";
|
|
3
|
+
import { Schema } from "effect";
|
|
4
|
+
export const AssertInput = Schema.Struct({
|
|
5
|
+
sessionID: Permission.Request.fields.sessionID,
|
|
6
|
+
agent: Agent.ID.pipe(Schema.optional),
|
|
7
|
+
action: Permission.Request.fields.action,
|
|
8
|
+
resources: Permission.Request.fields.resources,
|
|
9
|
+
save: Permission.Request.fields.save,
|
|
10
|
+
metadata: Permission.Request.fields.metadata,
|
|
11
|
+
source: Permission.Request.fields.source,
|
|
12
|
+
});
|
package/dist/promise/adapter.js
CHANGED
|
@@ -2,6 +2,7 @@ import { Tool } from "@opencode/schema/tool";
|
|
|
2
2
|
import { Effect, Schema, SchemaAST, Stream } from "effect";
|
|
3
3
|
import { HttpApiEndpoint, HttpApiSchema } from "effect/http-api";
|
|
4
4
|
import { define } from "../effect/plugin.js";
|
|
5
|
+
import { AssertInput } from "../permission.js";
|
|
5
6
|
const compiledEndpoints = new WeakMap();
|
|
6
7
|
const JsonInput = Schema.fromJsonString(Schema.Unknown);
|
|
7
8
|
class ReturnedRpcError extends Error {
|
|
@@ -157,6 +158,7 @@ export function fromPromise(plugin) {
|
|
|
157
158
|
const [{ ClientApi }, { OpenCodeEvent }] = yield* Effect.promise(() => Promise.all([import("@opencode/protocol/client"), import("@opencode/protocol/groups/event")]));
|
|
158
159
|
const AgentEndpoints = ClientApi.groups["server.agent"].endpoints;
|
|
159
160
|
const CommandEndpoints = ClientApi.groups["server.command"].endpoints;
|
|
161
|
+
const CredentialEndpoints = ClientApi.groups["server.credential"].endpoints;
|
|
160
162
|
const ExperimentalEndpoints = ClientApi.groups["server.experimental"].endpoints;
|
|
161
163
|
const GenerateEndpoints = ClientApi.groups["server.generate"].endpoints;
|
|
162
164
|
const IntegrationEndpoints = ClientApi.groups["server.integration"].endpoints;
|
|
@@ -220,6 +222,9 @@ export function fromPromise(plugin) {
|
|
|
220
222
|
}))),
|
|
221
223
|
reload: () => run(host.command.reload()),
|
|
222
224
|
},
|
|
225
|
+
credential: {
|
|
226
|
+
activate: adaptApiMethod(CredentialEndpoints["credential.activate"], host.credential.activate),
|
|
227
|
+
},
|
|
223
228
|
event: {
|
|
224
229
|
subscribe: (options) => streams(host.event.subscribe().pipe(Stream.mapEffect((event) => Schema.encodeUnknownEffect(OpenCodeEvent)(event)), Stream.map((event) => event)), options),
|
|
225
230
|
},
|
|
@@ -308,6 +313,7 @@ export function fromPromise(plugin) {
|
|
|
308
313
|
list: adaptApiMethod(PermissionEndpoints["session.permission.list"], host.permission.list),
|
|
309
314
|
get: adaptApiMethod(PermissionEndpoints["session.permission.get"], host.permission.get),
|
|
310
315
|
reply: adaptApiMethod(PermissionEndpoints["session.permission.reply"], host.permission.reply),
|
|
316
|
+
assert: (input) => run(Schema.decodeUnknownEffect(AssertInput)(input).pipe(Effect.flatMap(host.permission.assert))),
|
|
311
317
|
},
|
|
312
318
|
plugin: {
|
|
313
319
|
list: adaptApiMethod(PluginEndpoints["plugin.list"], host.plugin.list),
|
|
@@ -357,7 +363,7 @@ export function fromPromise(plugin) {
|
|
|
357
363
|
}),
|
|
358
364
|
remove: editor.remove,
|
|
359
365
|
}))),
|
|
360
|
-
hook: (name, callback) => register(host.tool.hook(name, (event) =>
|
|
366
|
+
hook: (name, callback) => register(host.tool.hook(name, (event) => toolHook[name](() => Promise.resolve(callback(event))))),
|
|
361
367
|
},
|
|
362
368
|
vcs: {
|
|
363
369
|
get: adaptApiMethod(VcsEndpoints["vcs.get"], host.vcs.get),
|
|
@@ -447,8 +453,19 @@ export function fromPromise(plugin) {
|
|
|
447
453
|
function attempt(evaluate) {
|
|
448
454
|
return Effect.tryPromise({ try: evaluate, catch: (cause) => cause });
|
|
449
455
|
}
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
456
|
+
const toolError = (error) => error instanceof Tool.Error
|
|
457
|
+
? error
|
|
458
|
+
: new Tool.Error({ message: error instanceof Error ? error.message : String(error), error });
|
|
459
|
+
// Only execute.before may reject a call; a rejection fails that call alone, like an Effect hook.
|
|
460
|
+
const toolHook = {
|
|
461
|
+
"execute.before": (run) => Effect.tryPromise({ try: run, catch: toolError }),
|
|
462
|
+
"execute.after": (run) => Effect.promise(run),
|
|
463
|
+
};
|
|
464
|
+
const executePromiseTool = (tool, input, context) => Effect.tryPromise({
|
|
465
|
+
try: (signal) => tool.execute(input, {
|
|
466
|
+
...context,
|
|
467
|
+
signal,
|
|
468
|
+
progress: (update) => Effect.runPromise(context.progress(update), { signal }),
|
|
469
|
+
}),
|
|
470
|
+
catch: toolError,
|
|
471
|
+
});
|
|
@@ -2,6 +2,7 @@ import type { PermissionApi } from "@opencode/client/promise/api";
|
|
|
2
2
|
import type { Agent } from "@opencode/schema/agent";
|
|
3
3
|
import type { Permission } from "@opencode/schema/permission";
|
|
4
4
|
import type { Session } from "@opencode/schema/session";
|
|
5
|
+
import type { AssertInput } from "../permission.js";
|
|
5
6
|
import type { Hooks } from "./registration.js";
|
|
6
7
|
export interface PermissionEvaluation {
|
|
7
8
|
readonly sessionID: Session.ID;
|
|
@@ -18,4 +19,11 @@ export interface PermissionHooks {
|
|
|
18
19
|
}
|
|
19
20
|
export type PermissionDomain = Pick<PermissionApi, "list" | "get" | "reply"> & {
|
|
20
21
|
readonly hook: Hooks<PermissionHooks>;
|
|
22
|
+
/**
|
|
23
|
+
* Evaluates the session's permission rules and, when approval is required, prompts the user and
|
|
24
|
+
* waits for the reply. Resolves when allowed. A deny rule or a rejection with feedback rejects with
|
|
25
|
+
* a `Tool.Error` carrying the reason. A plain rejection rejects with an error that ends the current
|
|
26
|
+
* step; rethrow it rather than returning it as tool output.
|
|
27
|
+
*/
|
|
28
|
+
readonly assert: (input: typeof AssertInput.Encoded) => Promise<void>;
|
|
21
29
|
};
|
package/dist/promise/plugin.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { OpenCodeClient } from "@opencode/client";
|
|
2
|
-
import type { GenerateApi, PluginApi } from "@opencode/client/promise/api";
|
|
2
|
+
import type { CredentialApi, GenerateApi, PluginApi } from "@opencode/client/promise/api";
|
|
3
3
|
import type { Location } from "@opencode/schema/location";
|
|
4
4
|
import type { PluginOptions } from "../options.js";
|
|
5
5
|
import type { App } from "../app.js";
|
|
@@ -29,6 +29,7 @@ export interface Context {
|
|
|
29
29
|
readonly agent: AgentDomain;
|
|
30
30
|
readonly aisdk: AISDKDomain;
|
|
31
31
|
readonly command: CommandDomain;
|
|
32
|
+
readonly credential: Pick<CredentialApi, "activate">;
|
|
32
33
|
readonly event: EventDomain;
|
|
33
34
|
readonly experimental: {
|
|
34
35
|
readonly terminal: Pick<OpenCodeClient["experimental"]["persistentPty"], "read">;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@opencode/plugin",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.29",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"scripts": {
|
|
@@ -47,15 +47,15 @@
|
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@ai-sdk/provider": "3.0.8",
|
|
50
|
-
"@opencode/ai": "2.0.
|
|
51
|
-
"@opencode/client": "2.0.
|
|
52
|
-
"@opencode/protocol": "2.0.
|
|
53
|
-
"@opencode/schema": "2.0.
|
|
54
|
-
"@opencode/util": "2.0.
|
|
50
|
+
"@opencode/ai": "2.0.29",
|
|
51
|
+
"@opencode/client": "2.0.29",
|
|
52
|
+
"@opencode/protocol": "2.0.29",
|
|
53
|
+
"@opencode/schema": "2.0.29",
|
|
54
|
+
"@opencode/util": "2.0.29",
|
|
55
55
|
"effect": "4.0.1"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@opencode/theme": "2.0.
|
|
58
|
+
"@opencode/theme": "2.0.29",
|
|
59
59
|
"@opentui/core": ">=0.5.17",
|
|
60
60
|
"@opentui/solid": ">=0.5.17",
|
|
61
61
|
"solid-js": ">=1.9.0"
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
}
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
|
-
"@opencode/theme": "2.0.
|
|
78
|
+
"@opencode/theme": "2.0.29",
|
|
79
79
|
"@opentui/core": "0.5.17",
|
|
80
80
|
"@opentui/solid": "0.5.17",
|
|
81
81
|
"@tsconfig/bun": "1.0.9",
|