@neurocode-ai/plugin 1.18.13 → 1.18.15
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/package.json +2 -1
- package/src/example-workspace.ts +34 -0
- package/src/example.ts +18 -0
- package/src/index.ts +335 -0
- package/src/shell.ts +136 -0
- package/src/tool.ts +54 -0
- package/src/tui.ts +634 -0
- package/src/v2/effect/PLAN.md +515 -0
- package/src/v2/effect/README.md +111 -0
- package/src/v2/effect/agent.ts +14 -0
- package/src/v2/effect/aisdk.ts +18 -0
- package/src/v2/effect/catalog.ts +29 -0
- package/src/v2/effect/command.ts +13 -0
- package/src/v2/effect/context.ts +22 -0
- package/src/v2/effect/event.ts +10 -0
- package/src/v2/effect/filesystem.ts +17 -0
- package/src/v2/effect/index.ts +3 -0
- package/src/v2/effect/integration.ts +63 -0
- package/src/v2/effect/location.ts +6 -0
- package/src/v2/effect/npm.ts +11 -0
- package/src/v2/effect/path.ts +8 -0
- package/src/v2/effect/plugin.ts +16 -0
- package/src/v2/effect/reference.ts +12 -0
- package/src/v2/effect/registration.ts +15 -0
- package/src/v2/effect/skill.ts +11 -0
- package/src/v2/options.ts +1 -0
- package/src/v2/promise/README.md +103 -0
- package/src/v2/promise/agent.ts +8 -0
- package/src/v2/promise/aisdk.ts +18 -0
- package/src/v2/promise/catalog.ts +8 -0
- package/src/v2/promise/command.ts +8 -0
- package/src/v2/promise/context.ts +22 -0
- package/src/v2/promise/index.ts +12 -0
- package/src/v2/promise/integration.ts +14 -0
- package/src/v2/promise/plugin.ts +15 -0
- package/src/v2/promise/reference.ts +8 -0
- package/src/v2/promise/registration.ts +11 -0
- package/src/v2/promise/skill.ts +8 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PluginOptions } from "../options.js"
|
|
2
|
+
import type { AgentHooks } from "./agent.js"
|
|
3
|
+
import type { AISDKHooks } from "./aisdk.js"
|
|
4
|
+
import type { CatalogHooks } from "./catalog.js"
|
|
5
|
+
import type { CommandHooks } from "./command.js"
|
|
6
|
+
import type { IntegrationHooks } from "./integration.js"
|
|
7
|
+
import type { PluginDomain } from "./plugin.js"
|
|
8
|
+
import type { ReferenceHooks } from "./reference.js"
|
|
9
|
+
import type { SkillHooks } from "./skill.js"
|
|
10
|
+
import type { Reload } from "./registration.js"
|
|
11
|
+
|
|
12
|
+
export interface PluginContext {
|
|
13
|
+
readonly options: PluginOptions
|
|
14
|
+
readonly agent: AgentHooks & Reload
|
|
15
|
+
readonly aisdk: AISDKHooks
|
|
16
|
+
readonly catalog: CatalogHooks & Reload
|
|
17
|
+
readonly command: CommandHooks & Reload
|
|
18
|
+
readonly integration: IntegrationHooks & Reload
|
|
19
|
+
readonly plugin: PluginDomain
|
|
20
|
+
readonly reference: ReferenceHooks & Reload
|
|
21
|
+
readonly skill: SkillHooks & Reload
|
|
22
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Event as SDKEvent } from "@neurocode-ai/sdk/v2/types"
|
|
2
|
+
import type { Stream } from "effect"
|
|
3
|
+
|
|
4
|
+
export type EventMap = {
|
|
5
|
+
[Item in SDKEvent as Item["type"]]: Item
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface Event {
|
|
9
|
+
subscribe<Type extends keyof EventMap>(type: Type): Stream.Stream<EventMap[Type]>
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { FileSystemEntry } from "@neurocode-ai/sdk/v2/types"
|
|
2
|
+
import type { Effect } from "effect"
|
|
3
|
+
|
|
4
|
+
export interface FileSystem {
|
|
5
|
+
read(input: { readonly path: string }): Effect.Effect<{ readonly content: Uint8Array; readonly mime: string }>
|
|
6
|
+
list(input?: { readonly path?: string }): Effect.Effect<FileSystemEntry[]>
|
|
7
|
+
find(input: {
|
|
8
|
+
readonly query: string
|
|
9
|
+
readonly type?: "file" | "directory"
|
|
10
|
+
readonly limit?: number
|
|
11
|
+
}): Effect.Effect<FileSystemEntry[]>
|
|
12
|
+
glob(input: {
|
|
13
|
+
readonly pattern: string
|
|
14
|
+
readonly path?: string
|
|
15
|
+
readonly limit?: number
|
|
16
|
+
}): Effect.Effect<readonly FileSystemEntry[]>
|
|
17
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ConnectionInfo,
|
|
3
|
+
CredentialOAuth,
|
|
4
|
+
CredentialValue,
|
|
5
|
+
IntegrationEnvMethod,
|
|
6
|
+
IntegrationInputs,
|
|
7
|
+
IntegrationKeyMethod,
|
|
8
|
+
IntegrationMethod,
|
|
9
|
+
IntegrationOAuthMethod,
|
|
10
|
+
IntegrationRef,
|
|
11
|
+
} from "@neurocode-ai/sdk/v2/types"
|
|
12
|
+
import type { Effect, Scope } from "effect"
|
|
13
|
+
import type { Hooks } from "./registration.js"
|
|
14
|
+
|
|
15
|
+
export type IntegrationOAuthAuthorization = {
|
|
16
|
+
readonly url: string
|
|
17
|
+
readonly instructions: string
|
|
18
|
+
} & (
|
|
19
|
+
| {
|
|
20
|
+
readonly mode: "auto"
|
|
21
|
+
readonly callback: Effect.Effect<CredentialOAuth, unknown>
|
|
22
|
+
}
|
|
23
|
+
| {
|
|
24
|
+
readonly mode: "code"
|
|
25
|
+
readonly callback: (code: string) => Effect.Effect<CredentialOAuth, unknown>
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
export type IntegrationOAuthMethodRegistration = {
|
|
29
|
+
readonly integrationID: string
|
|
30
|
+
readonly method: IntegrationOAuthMethod
|
|
31
|
+
readonly authorize: (inputs: IntegrationInputs) => Effect.Effect<IntegrationOAuthAuthorization, unknown, Scope.Scope>
|
|
32
|
+
readonly refresh?: (credential: CredentialOAuth) => Effect.Effect<CredentialOAuth, unknown>
|
|
33
|
+
readonly label?: (credential: CredentialOAuth) => string | undefined
|
|
34
|
+
}
|
|
35
|
+
export type IntegrationMethodRegistration =
|
|
36
|
+
| IntegrationOAuthMethodRegistration
|
|
37
|
+
| {
|
|
38
|
+
readonly integrationID: string
|
|
39
|
+
readonly method: IntegrationKeyMethod
|
|
40
|
+
}
|
|
41
|
+
| {
|
|
42
|
+
readonly integrationID: string
|
|
43
|
+
readonly method: IntegrationEnvMethod
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface IntegrationDraft {
|
|
47
|
+
list(): readonly IntegrationRef[]
|
|
48
|
+
get(id: string): IntegrationRef | undefined
|
|
49
|
+
update(id: string, update: (integration: IntegrationRef) => void): void
|
|
50
|
+
remove(id: string): void
|
|
51
|
+
readonly method: {
|
|
52
|
+
list(integrationID: string): readonly IntegrationMethod[]
|
|
53
|
+
update(input: IntegrationMethodRegistration): void
|
|
54
|
+
remove(integrationID: string, method: IntegrationMethod): void
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface IntegrationHooks extends Hooks<{ transform: IntegrationDraft }> {
|
|
59
|
+
readonly connection: {
|
|
60
|
+
readonly active: (integrationID: string) => Effect.Effect<ConnectionInfo | undefined>
|
|
61
|
+
readonly resolve: (connection: ConnectionInfo) => Effect.Effect<CredentialValue | undefined, unknown>
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Effect, Scope } from "effect"
|
|
2
|
+
import type { PluginContext } from "./context.js"
|
|
3
|
+
|
|
4
|
+
export interface Plugin<R = Scope.Scope> {
|
|
5
|
+
readonly id: string
|
|
6
|
+
readonly effect: (context: PluginContext) => Effect.Effect<void, never, R>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function define<R = Scope.Scope>(plugin: Plugin<R>) {
|
|
10
|
+
return plugin
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface PluginDomain {
|
|
14
|
+
readonly add: (plugin: Plugin) => Effect.Effect<void>
|
|
15
|
+
readonly remove: (id: string) => Effect.Effect<void>
|
|
16
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ReferenceGitSource, ReferenceLocalSource } from "@neurocode-ai/sdk/v2/types"
|
|
2
|
+
import type { Hooks } from "./registration.js"
|
|
3
|
+
|
|
4
|
+
export interface ReferenceDraft {
|
|
5
|
+
add(name: string, source: ReferenceLocalSource | ReferenceGitSource): void
|
|
6
|
+
remove(name: string): void
|
|
7
|
+
list(): readonly (readonly [string, ReferenceLocalSource | ReferenceGitSource])[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ReferenceHooks = Hooks<{
|
|
11
|
+
transform: ReferenceDraft
|
|
12
|
+
}>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Effect, Scope } from "effect"
|
|
2
|
+
|
|
3
|
+
export interface Registration {
|
|
4
|
+
readonly dispose: Effect.Effect<void>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface Reload {
|
|
8
|
+
readonly reload: () => Effect.Effect<void>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type Hooks<Spec> = {
|
|
12
|
+
readonly [Name in keyof Spec]: (
|
|
13
|
+
callback: (input: Spec[Name]) => Effect.Effect<void> | void,
|
|
14
|
+
) => Effect.Effect<Registration, never, Scope.Scope>
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SkillV2Source } from "@neurocode-ai/sdk/v2/types"
|
|
2
|
+
import type { Hooks } from "./registration.js"
|
|
3
|
+
|
|
4
|
+
export interface SkillDraft {
|
|
5
|
+
source(source: SkillV2Source): void
|
|
6
|
+
list(): readonly SkillV2Source[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type SkillHooks = Hooks<{
|
|
10
|
+
transform: SkillDraft
|
|
11
|
+
}>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type PluginOptions = Readonly<Record<string, any>>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# OpenCode V2 Promise Plugin API
|
|
2
|
+
|
|
3
|
+
The Promise plugin API is the async/await equivalent of `@opencode-ai/plugin/v2/effect`. It grants plugins the same two in-process capabilities:
|
|
4
|
+
|
|
5
|
+
- `hook` installs behavior at an OpenCode extension point.
|
|
6
|
+
- `reload` reruns every transform hook for a stateful domain.
|
|
7
|
+
|
|
8
|
+
The only difference from the Effect API is the async boundary: hook callbacks, hook registration, `reload`, and `Registration.dispose` use Promises instead of Effects.
|
|
9
|
+
|
|
10
|
+
## Defining A Plugin
|
|
11
|
+
|
|
12
|
+
```ts
|
|
13
|
+
import { define } from "@opencode-ai/plugin/v2/promise"
|
|
14
|
+
|
|
15
|
+
export const Plugin = define({
|
|
16
|
+
id: "example",
|
|
17
|
+
setup: async (ctx) => {
|
|
18
|
+
await ctx.catalog.transform((catalog) => {
|
|
19
|
+
catalog.provider.update("example", (provider) => {
|
|
20
|
+
provider.name = "Example"
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
},
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Plugin setup registers hooks imperatively. It does not return a hook object.
|
|
28
|
+
|
|
29
|
+
Configuration supplied for the plugin is available as `ctx.options`.
|
|
30
|
+
|
|
31
|
+
A registration may be removed early through `dispose`:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
const registration = await ctx.catalog.transform(applyCatalog)
|
|
35
|
+
await registration.dispose()
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Transform Hooks
|
|
39
|
+
|
|
40
|
+
Transform hooks contribute to stateful domains. The draft editor is synchronous; the callback may be `async` when it needs to await other work:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
await ctx.agent.transform((agent) => {
|
|
44
|
+
agent.update("reviewer", (item) => {
|
|
45
|
+
item.description = "Reviews code for regressions"
|
|
46
|
+
item.mode = "subagent"
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Available transform hooks are namespaced by domain:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
ctx.agent.transform
|
|
55
|
+
ctx.catalog.transform
|
|
56
|
+
ctx.command.transform
|
|
57
|
+
ctx.integration.transform
|
|
58
|
+
ctx.reference.transform
|
|
59
|
+
ctx.skill.transform
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Runtime Hooks
|
|
63
|
+
|
|
64
|
+
Runtime hooks intercept live operations:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
await ctx.aisdk.sdk(async (event) => {
|
|
68
|
+
if (event.package !== "@ai-sdk/xai") return
|
|
69
|
+
const mod = await import("@ai-sdk/xai")
|
|
70
|
+
event.sdk = mod.createXai(event.options)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
await ctx.aisdk.language((event) => {
|
|
74
|
+
if (event.model.providerID !== "xai") return
|
|
75
|
+
event.language = event.sdk.responses(event.model.api.id)
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Reloading A Domain
|
|
80
|
+
|
|
81
|
+
When data captured by a transform changes, reload the affected domain:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
let data = await loadCatalog()
|
|
85
|
+
|
|
86
|
+
await ctx.catalog.transform((catalog) => {
|
|
87
|
+
applyCatalog(data, catalog)
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
data = await loadCatalog()
|
|
91
|
+
await ctx.catalog.reload()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Available reload operations are:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
ctx.agent.reload()
|
|
98
|
+
ctx.catalog.reload()
|
|
99
|
+
ctx.command.reload()
|
|
100
|
+
ctx.integration.reload()
|
|
101
|
+
ctx.reference.reload()
|
|
102
|
+
ctx.skill.reload()
|
|
103
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { LanguageModelV3 } from "@ai-sdk/provider"
|
|
2
|
+
import type { ModelV2Info } from "@neurocode-ai/sdk/v2/types"
|
|
3
|
+
import type { Hooks } from "./registration.js"
|
|
4
|
+
|
|
5
|
+
export type AISDKHooks = Hooks<{
|
|
6
|
+
sdk: {
|
|
7
|
+
readonly model: ModelV2Info
|
|
8
|
+
readonly package: string
|
|
9
|
+
readonly options: Record<string, any>
|
|
10
|
+
sdk?: any
|
|
11
|
+
}
|
|
12
|
+
language: {
|
|
13
|
+
readonly model: ModelV2Info
|
|
14
|
+
readonly sdk: any
|
|
15
|
+
readonly options: Record<string, any>
|
|
16
|
+
language?: LanguageModelV3
|
|
17
|
+
}
|
|
18
|
+
}>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PluginOptions } from "../options.js"
|
|
2
|
+
import type { AgentHooks } from "./agent.js"
|
|
3
|
+
import type { AISDKHooks } from "./aisdk.js"
|
|
4
|
+
import type { CatalogHooks } from "./catalog.js"
|
|
5
|
+
import type { CommandHooks } from "./command.js"
|
|
6
|
+
import type { IntegrationHooks } from "./integration.js"
|
|
7
|
+
import type { PluginDomain } from "./plugin.js"
|
|
8
|
+
import type { ReferenceHooks } from "./reference.js"
|
|
9
|
+
import type { SkillHooks } from "./skill.js"
|
|
10
|
+
import type { Reload } from "./registration.js"
|
|
11
|
+
|
|
12
|
+
export interface PluginContext {
|
|
13
|
+
readonly options: PluginOptions
|
|
14
|
+
readonly agent: AgentHooks & Reload
|
|
15
|
+
readonly aisdk: AISDKHooks
|
|
16
|
+
readonly catalog: CatalogHooks & Reload
|
|
17
|
+
readonly command: CommandHooks & Reload
|
|
18
|
+
readonly integration: IntegrationHooks & Reload
|
|
19
|
+
readonly plugin: PluginDomain
|
|
20
|
+
readonly reference: ReferenceHooks & Reload
|
|
21
|
+
readonly skill: SkillHooks & Reload
|
|
22
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type { PluginContext } from "./context.js"
|
|
2
|
+
export type { PluginOptions } from "../options.js"
|
|
3
|
+
export { define } from "./plugin.js"
|
|
4
|
+
export type { Plugin, PluginDomain } from "./plugin.js"
|
|
5
|
+
export type { Registration, Reload } from "./registration.js"
|
|
6
|
+
export type { AgentDraft, AgentHooks } from "./agent.js"
|
|
7
|
+
export type { AISDKHooks } from "./aisdk.js"
|
|
8
|
+
export type { CatalogDraft, CatalogHooks, CatalogProviderRecord } from "./catalog.js"
|
|
9
|
+
export type { CommandDraft, CommandHooks } from "./command.js"
|
|
10
|
+
export type { IntegrationDraft, IntegrationHooks, IntegrationMethodRegistration } from "./integration.js"
|
|
11
|
+
export type { ReferenceDraft, ReferenceHooks } from "./reference.js"
|
|
12
|
+
export type { SkillDraft, SkillHooks } from "./skill.js"
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IntegrationDraft, IntegrationMethodRegistration } from "../effect/integration.js"
|
|
2
|
+
import type { CredentialValue } from "@neurocode-ai/sdk/v2/types"
|
|
3
|
+
import type { Hooks } from "./registration.js"
|
|
4
|
+
|
|
5
|
+
export type { IntegrationDraft, IntegrationMethodRegistration }
|
|
6
|
+
|
|
7
|
+
export interface IntegrationHooks extends Hooks<{ transform: IntegrationDraft }> {
|
|
8
|
+
readonly connection: {
|
|
9
|
+
readonly active: (integrationID: string) => Promise<import("@neurocode-ai/sdk/v2/types").ConnectionInfo | undefined>
|
|
10
|
+
readonly resolve: (
|
|
11
|
+
connection: import("@neurocode-ai/sdk/v2/types").ConnectionInfo,
|
|
12
|
+
) => Promise<CredentialValue | undefined>
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PluginContext } from "./context.js"
|
|
2
|
+
|
|
3
|
+
export interface Plugin {
|
|
4
|
+
readonly id: string
|
|
5
|
+
readonly setup: (context: PluginContext) => Promise<void> | void
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function define(plugin: Plugin) {
|
|
9
|
+
return plugin
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface PluginDomain {
|
|
13
|
+
readonly add: (plugin: Plugin) => Promise<void>
|
|
14
|
+
readonly remove: (id: string) => Promise<void>
|
|
15
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface Registration {
|
|
2
|
+
readonly dispose: () => Promise<void>
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export interface Reload {
|
|
6
|
+
readonly reload: () => Promise<void>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type Hooks<Spec> = {
|
|
10
|
+
readonly [Name in keyof Spec]: (callback: (input: Spec[Name]) => Promise<void> | void) => Promise<Registration>
|
|
11
|
+
}
|