@neurocode-ai/plugin 1.18.14 → 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 CHANGED
@@ -1,54 +1,55 @@
1
- {
2
- "$schema": "https://json.schemastore.org/package.json",
3
- "name": "@neurocode-ai/plugin",
4
- "version": "1.18.14",
5
- "type": "module",
6
- "license": "MIT",
7
- "scripts": {
8
- "typecheck": "tsgo --noEmit",
9
- "build": "tsc"
10
- },
11
- "exports": {
12
- ".": "./src/index.ts",
13
- "./tool": "./src/tool.ts",
14
- "./tui": "./src/tui.ts",
15
- "./v2/effect": "./src/v2/effect/index.ts",
16
- "./v2/effect/integration": "./src/v2/effect/integration.ts",
17
- "./v2/effect/plugin": "./src/v2/effect/plugin.ts",
18
- "./v2/promise": "./src/v2/promise/index.ts"
19
- },
20
- "files": [
21
- "dist"
22
- ],
23
- "dependencies": {
24
- "@ai-sdk/provider": "3.0.8",
25
- "@neurocode-ai/sdk": "^1.0.0",
26
- "effect": "4.0.0-beta.83",
27
- "zod": "4.1.8"
28
- },
29
- "peerDependencies": {
30
- "@opentui/core": ">=0.4.5",
31
- "@opentui/keymap": ">=0.4.5",
32
- "@opentui/solid": ">=0.4.5"
33
- },
34
- "peerDependenciesMeta": {
35
- "@opentui/core": {
36
- "optional": true
37
- },
38
- "@opentui/keymap": {
39
- "optional": true
40
- },
41
- "@opentui/solid": {
42
- "optional": true
43
- }
44
- },
45
- "devDependencies": {
46
- "@opentui/core": "0.4.5",
47
- "@opentui/keymap": "0.4.5",
48
- "@opentui/solid": "0.4.5",
49
- "@tsconfig/node22": "22.0.2",
50
- "@types/node": "24.12.2",
51
- "typescript": "5.8.2",
52
- "@typescript/native-preview": "7.0.0-dev.20251207.1"
53
- }
54
- }
1
+ {
2
+ "$schema": "https://json.schemastore.org/package.json",
3
+ "name": "@neurocode-ai/plugin",
4
+ "version": "1.18.15",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "scripts": {
8
+ "typecheck": "tsgo --noEmit",
9
+ "build": "tsc"
10
+ },
11
+ "exports": {
12
+ ".": "./src/index.ts",
13
+ "./tool": "./src/tool.ts",
14
+ "./tui": "./src/tui.ts",
15
+ "./v2/effect": "./src/v2/effect/index.ts",
16
+ "./v2/effect/integration": "./src/v2/effect/integration.ts",
17
+ "./v2/effect/plugin": "./src/v2/effect/plugin.ts",
18
+ "./v2/promise": "./src/v2/promise/index.ts"
19
+ },
20
+ "files": [
21
+ "src",
22
+ "dist"
23
+ ],
24
+ "dependencies": {
25
+ "@ai-sdk/provider": "3.0.8",
26
+ "@neurocode-ai/sdk": "^1.0.0",
27
+ "effect": "4.0.0-beta.83",
28
+ "zod": "4.1.8"
29
+ },
30
+ "peerDependencies": {
31
+ "@opentui/core": "\u003e=0.4.5",
32
+ "@opentui/keymap": "\u003e=0.4.5",
33
+ "@opentui/solid": "\u003e=0.4.5"
34
+ },
35
+ "peerDependenciesMeta": {
36
+ "@opentui/core": {
37
+ "optional": true
38
+ },
39
+ "@opentui/keymap": {
40
+ "optional": true
41
+ },
42
+ "@opentui/solid": {
43
+ "optional": true
44
+ }
45
+ },
46
+ "devDependencies": {
47
+ "@opentui/core": "0.4.5",
48
+ "@opentui/keymap": "0.4.5",
49
+ "@opentui/solid": "0.4.5",
50
+ "@tsconfig/node22": "22.0.2",
51
+ "@types/node": "24.12.2",
52
+ "typescript": "5.8.2",
53
+ "@typescript/native-preview": "7.0.0-dev.20251207.1"
54
+ }
55
+ }
@@ -0,0 +1,34 @@
1
+ import type { Plugin } from "@neurocode-ai/plugin"
2
+ import { mkdir, rm } from "node:fs/promises"
3
+
4
+ export const FolderWorkspacePlugin: Plugin = async ({ experimental_workspace }) => {
5
+ experimental_workspace.register("folder", {
6
+ name: "Folder",
7
+ description: "Create a blank folder",
8
+ configure(config) {
9
+ const rand = "" + Math.random()
10
+
11
+ return {
12
+ ...config,
13
+ directory: `/tmp/folder/folder-${rand}`,
14
+ }
15
+ },
16
+ async create(config) {
17
+ if (!config.directory) return
18
+ await mkdir(config.directory, { recursive: true })
19
+ },
20
+ async remove(config) {
21
+ await rm(config.directory!, { recursive: true, force: true })
22
+ },
23
+ target(config) {
24
+ return {
25
+ type: "local",
26
+ directory: config.directory!,
27
+ }
28
+ },
29
+ })
30
+
31
+ return {}
32
+ }
33
+
34
+ export default FolderWorkspacePlugin
package/src/example.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { Plugin } from "./index.js"
2
+ import { tool } from "./tool.js"
3
+
4
+ export const ExamplePlugin: Plugin = async (_ctx) => {
5
+ return {
6
+ tool: {
7
+ mytool: tool({
8
+ description: "This is a custom tool",
9
+ args: {
10
+ foo: tool.schema.string().describe("foo"),
11
+ },
12
+ async execute(args) {
13
+ return `Hello ${args.foo}!`
14
+ },
15
+ }),
16
+ },
17
+ }
18
+ }
package/src/index.ts ADDED
@@ -0,0 +1,335 @@
1
+ import type {
2
+ Event,
3
+ createNeurocodeClient,
4
+ Project,
5
+ Model,
6
+ Provider,
7
+ Permission,
8
+ UserMessage,
9
+ Message,
10
+ Part,
11
+ Config as SDKConfig,
12
+ } from "@neurocode-ai/sdk"
13
+ import type { Provider as ProviderV2, Model as ModelV2, Auth } from "@neurocode-ai/sdk/v2"
14
+
15
+ import type { BunShell } from "./shell.js"
16
+ import { type ToolDefinition } from "./tool.js"
17
+
18
+ export * from "./tool.js"
19
+
20
+ export type ProviderContext = {
21
+ source: "env" | "config" | "custom" | "api"
22
+ info: Provider
23
+ options: Record<string, any>
24
+ }
25
+
26
+ export type WorkspaceInfo = {
27
+ id: string
28
+ type: string
29
+ name: string
30
+ branch: string | null
31
+ directory: string | null
32
+ extra: unknown | null
33
+ projectID: string
34
+ }
35
+
36
+ export type WorkspaceTarget =
37
+ | {
38
+ type: "local"
39
+ directory: string
40
+ }
41
+ | {
42
+ type: "remote"
43
+ url: string | URL
44
+ headers?: HeadersInit
45
+ }
46
+
47
+ export type WorkspaceAdapter = {
48
+ name: string
49
+ description: string
50
+ configure(config: WorkspaceInfo): WorkspaceInfo | Promise<WorkspaceInfo>
51
+ create(config: WorkspaceInfo, env: Record<string, string | undefined>, from?: WorkspaceInfo): Promise<void>
52
+ remove(config: WorkspaceInfo): Promise<void>
53
+ target(config: WorkspaceInfo): WorkspaceTarget | Promise<WorkspaceTarget>
54
+ }
55
+
56
+ export type PluginInput = {
57
+ client: ReturnType<typeof createNeurocodeClient>
58
+ project: Project
59
+ directory: string
60
+ worktree: string
61
+ experimental_workspace: {
62
+ register(type: string, adapter: WorkspaceAdapter): void
63
+ }
64
+ serverUrl: URL
65
+ $: BunShell
66
+ }
67
+
68
+ export type PluginOptions = Record<string, unknown>
69
+
70
+ export type Config = Omit<SDKConfig, "plugin"> & {
71
+ plugin?: Array<string | [string, PluginOptions]>
72
+ }
73
+
74
+ export type Plugin = (input: PluginInput, options?: PluginOptions) => Promise<Hooks>
75
+
76
+ export type PluginModule = {
77
+ id?: string
78
+ server: Plugin
79
+ tui?: never
80
+ }
81
+
82
+ type Rule = {
83
+ key: string
84
+ op: "eq" | "neq"
85
+ value: string
86
+ }
87
+
88
+ export type AuthHook = {
89
+ provider: string
90
+ loader?: (auth: () => Promise<Auth>, provider: Provider) => Promise<Record<string, any>>
91
+ methods: (
92
+ | {
93
+ type: "oauth"
94
+ label: string
95
+ prompts?: Array<
96
+ | {
97
+ type: "text"
98
+ key: string
99
+ message: string
100
+ placeholder?: string
101
+ validate?: (value: string) => string | undefined
102
+ /** @deprecated Use `when` instead */
103
+ condition?: (inputs: Record<string, string>) => boolean
104
+ when?: Rule
105
+ }
106
+ | {
107
+ type: "select"
108
+ key: string
109
+ message: string
110
+ options: Array<{
111
+ label: string
112
+ value: string
113
+ hint?: string
114
+ }>
115
+ /** @deprecated Use `when` instead */
116
+ condition?: (inputs: Record<string, string>) => boolean
117
+ when?: Rule
118
+ }
119
+ >
120
+ authorize(inputs?: Record<string, string>): Promise<AuthOAuthResult>
121
+ }
122
+ | {
123
+ type: "api"
124
+ label: string
125
+ prompts?: Array<
126
+ | {
127
+ type: "text"
128
+ key: string
129
+ message: string
130
+ placeholder?: string
131
+ validate?: (value: string) => string | undefined
132
+ /** @deprecated Use `when` instead */
133
+ condition?: (inputs: Record<string, string>) => boolean
134
+ when?: Rule
135
+ }
136
+ | {
137
+ type: "select"
138
+ key: string
139
+ message: string
140
+ options: Array<{
141
+ label: string
142
+ value: string
143
+ hint?: string
144
+ }>
145
+ /** @deprecated Use `when` instead */
146
+ condition?: (inputs: Record<string, string>) => boolean
147
+ when?: Rule
148
+ }
149
+ >
150
+ authorize?(inputs?: Record<string, string>): Promise<
151
+ | {
152
+ type: "success"
153
+ key: string
154
+ provider?: string
155
+ metadata?: Record<string, string>
156
+ }
157
+ | {
158
+ type: "failed"
159
+ }
160
+ >
161
+ }
162
+ )[]
163
+ }
164
+
165
+ export type AuthOAuthResult = { url: string; instructions: string } & (
166
+ | {
167
+ method: "auto"
168
+ callback(): Promise<
169
+ | ({
170
+ type: "success"
171
+ provider?: string
172
+ } & (
173
+ | {
174
+ refresh: string
175
+ access: string
176
+ expires: number
177
+ accountId?: string
178
+ enterpriseUrl?: string
179
+ }
180
+ | { key: string; metadata?: Record<string, string> }
181
+ ))
182
+ | {
183
+ type: "failed"
184
+ }
185
+ >
186
+ }
187
+ | {
188
+ method: "code"
189
+ callback(code: string): Promise<
190
+ | ({
191
+ type: "success"
192
+ provider?: string
193
+ } & (
194
+ | {
195
+ refresh: string
196
+ access: string
197
+ expires: number
198
+ accountId?: string
199
+ enterpriseUrl?: string
200
+ }
201
+ | { key: string; metadata?: Record<string, string> }
202
+ ))
203
+ | {
204
+ type: "failed"
205
+ }
206
+ >
207
+ }
208
+ )
209
+
210
+ export type ProviderHookContext = {
211
+ auth?: Auth
212
+ }
213
+
214
+ export type ProviderHook = {
215
+ id: string
216
+ models?: (provider: ProviderV2, ctx: ProviderHookContext) => Promise<Record<string, ModelV2>>
217
+ }
218
+
219
+ /** @deprecated Use AuthOAuthResult instead. */
220
+ export type AuthOuathResult = AuthOAuthResult
221
+
222
+ export interface Hooks {
223
+ dispose?: () => Promise<void>
224
+ event?: (input: { event: Event }) => Promise<void>
225
+ config?: (input: Config) => Promise<void>
226
+ tool?: {
227
+ [key: string]: ToolDefinition
228
+ }
229
+ auth?: AuthHook
230
+ provider?: ProviderHook
231
+ /**
232
+ * Called when a new message is received
233
+ */
234
+ "chat.message"?: (
235
+ input: {
236
+ sessionID: string
237
+ agent?: string
238
+ model?: { providerID: string; modelID: string }
239
+ messageID?: string
240
+ variant?: string
241
+ },
242
+ output: { message: UserMessage; parts: Part[] },
243
+ ) => Promise<void>
244
+ /**
245
+ * Modify parameters sent to LLM
246
+ */
247
+ "chat.params"?: (
248
+ input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
249
+ output: {
250
+ temperature: number
251
+ topP: number
252
+ topK: number
253
+ maxOutputTokens: number | undefined
254
+ options: Record<string, any>
255
+ },
256
+ ) => Promise<void>
257
+ "chat.headers"?: (
258
+ input: { sessionID: string; agent: string; model: Model; provider: ProviderContext; message: UserMessage },
259
+ output: { headers: Record<string, string> },
260
+ ) => Promise<void>
261
+ "permission.ask"?: (input: Permission, output: { status: "ask" | "deny" | "allow" }) => Promise<void>
262
+ "command.execute.before"?: (
263
+ input: { command: string; sessionID: string; arguments: string },
264
+ output: { parts: Part[] },
265
+ ) => Promise<void>
266
+ "tool.execute.before"?: (
267
+ input: { tool: string; sessionID: string; callID: string },
268
+ output: { args: any },
269
+ ) => Promise<void>
270
+ "shell.env"?: (
271
+ input: { cwd: string; sessionID?: string; callID?: string },
272
+ output: { env: Record<string, string> },
273
+ ) => Promise<void>
274
+ "tool.execute.after"?: (
275
+ input: { tool: string; sessionID: string; callID: string; args: any },
276
+ output: {
277
+ title: string
278
+ output: string
279
+ metadata: any
280
+ },
281
+ ) => Promise<void>
282
+ "experimental.chat.messages.transform"?: (
283
+ input: {},
284
+ output: {
285
+ messages: {
286
+ info: Message
287
+ parts: Part[]
288
+ }[]
289
+ },
290
+ ) => Promise<void>
291
+ "experimental.chat.system.transform"?: (
292
+ input: { sessionID?: string; model: Model },
293
+ output: {
294
+ system: string[]
295
+ },
296
+ ) => Promise<void>
297
+ "experimental.provider.small_model"?: (input: { provider: ProviderV2 }, output: { model?: ModelV2 }) => Promise<void>
298
+ /**
299
+ * Called before session compaction starts. Allows plugins to customize
300
+ * the compaction prompt.
301
+ *
302
+ * - `context`: Additional context strings appended to the default prompt
303
+ * - `prompt`: If set, replaces the default compaction prompt entirely
304
+ */
305
+ "experimental.session.compacting"?: (
306
+ input: { sessionID: string },
307
+ output: { context: string[]; prompt?: string },
308
+ ) => Promise<void>
309
+ /**
310
+ * Called after compaction succeeds and before a synthetic user
311
+ * auto-continue message is added.
312
+ *
313
+ * - `enabled`: Defaults to `true`. Set to `false` to skip the synthetic
314
+ * user "continue" turn.
315
+ */
316
+ "experimental.compaction.autocontinue"?: (
317
+ input: {
318
+ sessionID: string
319
+ agent: string
320
+ model: Model
321
+ provider: ProviderContext
322
+ message: UserMessage
323
+ overflow: boolean
324
+ },
325
+ output: { enabled: boolean },
326
+ ) => Promise<void>
327
+ "experimental.text.complete"?: (
328
+ input: { sessionID: string; messageID: string; partID: string },
329
+ output: { text: string },
330
+ ) => Promise<void>
331
+ /**
332
+ * Modify tool definitions (description and parameters) sent to LLM
333
+ */
334
+ "tool.definition"?: (input: { toolID: string }, output: { description: string; parameters: any }) => Promise<void>
335
+ }
package/src/shell.ts ADDED
@@ -0,0 +1,136 @@
1
+ export type ShellFunction = (input: Uint8Array) => Uint8Array
2
+
3
+ export type ShellExpression =
4
+ | { toString(): string }
5
+ | Array<ShellExpression>
6
+ | string
7
+ | { raw: string }
8
+ | ReadableStream
9
+
10
+ export interface BunShell {
11
+ (strings: TemplateStringsArray, ...expressions: ShellExpression[]): BunShellPromise
12
+
13
+ /**
14
+ * Perform bash-like brace expansion on the given pattern.
15
+ * @param pattern - Brace pattern to expand
16
+ */
17
+ braces(pattern: string): string[]
18
+
19
+ /**
20
+ * Escape strings for input into shell commands.
21
+ */
22
+ escape(input: string): string
23
+
24
+ /**
25
+ * Change the default environment variables for shells created by this instance.
26
+ */
27
+ env(newEnv?: Record<string, string | undefined>): BunShell
28
+
29
+ /**
30
+ * Default working directory to use for shells created by this instance.
31
+ */
32
+ cwd(newCwd?: string): BunShell
33
+
34
+ /**
35
+ * Configure the shell to not throw an exception on non-zero exit codes.
36
+ */
37
+ nothrow(): BunShell
38
+
39
+ /**
40
+ * Configure whether or not the shell should throw an exception on non-zero exit codes.
41
+ */
42
+ throws(shouldThrow: boolean): BunShell
43
+ }
44
+
45
+ export interface BunShellPromise extends Promise<BunShellOutput> {
46
+ readonly stdin: WritableStream
47
+
48
+ /**
49
+ * Change the current working directory of the shell.
50
+ */
51
+ cwd(newCwd: string): this
52
+
53
+ /**
54
+ * Set environment variables for the shell.
55
+ */
56
+ env(newEnv: Record<string, string> | undefined): this
57
+
58
+ /**
59
+ * By default, the shell will write to the current process's stdout and stderr, as well as buffering that output.
60
+ * This configures the shell to only buffer the output.
61
+ */
62
+ quiet(): this
63
+
64
+ /**
65
+ * Read from stdout as a string, line by line
66
+ * Automatically calls quiet() to disable echoing to stdout.
67
+ */
68
+ lines(): AsyncIterable<string>
69
+
70
+ /**
71
+ * Read from stdout as a string.
72
+ * Automatically calls quiet() to disable echoing to stdout.
73
+ */
74
+ text(encoding?: BufferEncoding): Promise<string>
75
+
76
+ /**
77
+ * Read from stdout as a JSON object
78
+ * Automatically calls quiet()
79
+ */
80
+ json(): Promise<any>
81
+
82
+ /**
83
+ * Read from stdout as an ArrayBuffer
84
+ * Automatically calls quiet()
85
+ */
86
+ arrayBuffer(): Promise<ArrayBuffer>
87
+
88
+ /**
89
+ * Read from stdout as a Blob
90
+ * Automatically calls quiet()
91
+ */
92
+ blob(): Promise<Blob>
93
+
94
+ /**
95
+ * Configure the shell to not throw an exception on non-zero exit codes.
96
+ */
97
+ nothrow(): this
98
+
99
+ /**
100
+ * Configure whether or not the shell should throw an exception on non-zero exit codes.
101
+ */
102
+ throws(shouldThrow: boolean): this
103
+ }
104
+
105
+ export interface BunShellOutput {
106
+ readonly stdout: Buffer
107
+ readonly stderr: Buffer
108
+ readonly exitCode: number
109
+
110
+ /**
111
+ * Read from stdout as a string
112
+ */
113
+ text(encoding?: BufferEncoding): string
114
+
115
+ /**
116
+ * Read from stdout as a JSON object
117
+ */
118
+ json(): any
119
+
120
+ /**
121
+ * Read from stdout as an ArrayBuffer
122
+ */
123
+ arrayBuffer(): ArrayBuffer
124
+
125
+ /**
126
+ * Read from stdout as an Uint8Array
127
+ */
128
+ bytes(): Uint8Array
129
+
130
+ /**
131
+ * Read from stdout as a Blob
132
+ */
133
+ blob(): Blob
134
+ }
135
+
136
+ export type BunShellError = Error & BunShellOutput
package/src/tool.ts ADDED
@@ -0,0 +1,54 @@
1
+ import { z } from "zod"
2
+
3
+ export type ToolContext = {
4
+ sessionID: string
5
+ messageID: string
6
+ agent: string
7
+ /**
8
+ * Current project directory for this session.
9
+ * Prefer this over process.cwd() when resolving relative paths.
10
+ */
11
+ directory: string
12
+ /**
13
+ * Project worktree root for this session.
14
+ * Useful for generating stable relative paths (e.g. path.relative(worktree, absPath)).
15
+ */
16
+ worktree: string
17
+ abort: AbortSignal
18
+ metadata(input: { title?: string; metadata?: { [key: string]: any } }): void
19
+ ask(input: AskInput): Promise<void>
20
+ }
21
+
22
+ type AskInput = {
23
+ permission: string
24
+ patterns: string[]
25
+ always: string[]
26
+ metadata: { [key: string]: any }
27
+ }
28
+
29
+ export type ToolAttachment = {
30
+ type: "file"
31
+ mime: string
32
+ url: string
33
+ filename?: string
34
+ }
35
+
36
+ export type ToolResult =
37
+ | string
38
+ | {
39
+ title?: string
40
+ output: string
41
+ metadata?: { [key: string]: any }
42
+ attachments?: ToolAttachment[]
43
+ }
44
+
45
+ export function tool<Args extends z.ZodRawShape>(input: {
46
+ description: string
47
+ args: Args
48
+ execute(args: z.infer<z.ZodObject<Args>>, context: ToolContext): Promise<ToolResult>
49
+ }) {
50
+ return input
51
+ }
52
+ tool.schema = z
53
+
54
+ export type ToolDefinition = ReturnType<typeof tool>