@opencode/plugin 0.0.0-reserved → 2.0.0
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/app.d.ts +5 -0
- package/dist/app.js +0 -0
- package/dist/effect/agent.d.ts +15 -0
- package/dist/effect/agent.js +0 -0
- package/dist/effect/aisdk.d.ts +20 -0
- package/dist/effect/aisdk.js +0 -0
- package/dist/effect/catalog.d.ts +33 -0
- package/dist/effect/catalog.js +2 -0
- package/dist/effect/command.d.ts +23 -0
- package/dist/effect/command.js +0 -0
- package/dist/effect/event.d.ts +3 -0
- package/dist/effect/event.js +0 -0
- package/dist/effect/index.d.ts +18 -0
- package/dist/effect/index.js +17 -0
- package/dist/effect/integration.d.ts +80 -0
- package/dist/effect/integration.js +2 -0
- package/dist/effect/mcp.d.ts +15 -0
- package/dist/effect/mcp.js +0 -0
- package/dist/effect/permission.d.ts +21 -0
- package/dist/effect/permission.js +0 -0
- package/dist/effect/plugin.d.ts +56 -0
- package/dist/effect/plugin.js +3 -0
- package/dist/effect/reference.d.ts +14 -0
- package/dist/effect/reference.js +0 -0
- package/dist/effect/registration.d.ts +13 -0
- package/dist/effect/registration.js +0 -0
- package/dist/effect/rpc.d.ts +19 -0
- package/dist/effect/rpc.js +0 -0
- package/dist/effect/session.d.ts +107 -0
- package/dist/effect/session.js +0 -0
- package/dist/effect/shell.d.ts +14 -0
- package/dist/effect/shell.js +0 -0
- package/dist/effect/skill.d.ts +15 -0
- package/dist/effect/skill.js +1 -0
- package/dist/effect/storage.d.ts +8 -0
- package/dist/effect/storage.js +0 -0
- package/dist/effect/tool.d.ts +52 -0
- package/dist/effect/tool.js +1 -0
- package/dist/effect/vcs.d.ts +41 -0
- package/dist/effect/vcs.js +0 -0
- package/dist/effect/websearch.d.ts +20 -0
- package/dist/effect/websearch.js +0 -0
- package/dist/effect/worktree.d.ts +18 -0
- package/dist/effect/worktree.js +0 -0
- package/dist/host.d.ts +12 -0
- package/dist/host.js +33 -0
- package/dist/options.d.ts +1 -0
- package/dist/options.js +0 -0
- package/dist/promise/adapter.d.ts +12 -0
- package/dist/promise/adapter.js +444 -0
- package/dist/promise/agent.d.ts +15 -0
- package/dist/promise/agent.js +0 -0
- package/dist/promise/aisdk.d.ts +20 -0
- package/dist/promise/aisdk.js +0 -0
- package/dist/promise/catalog.d.ts +33 -0
- package/dist/promise/catalog.js +0 -0
- package/dist/promise/command.d.ts +22 -0
- package/dist/promise/command.js +0 -0
- package/dist/promise/event.d.ts +3 -0
- package/dist/promise/event.js +0 -0
- package/dist/promise/index.d.ts +19 -0
- package/dist/promise/index.js +17 -0
- package/dist/promise/integration.d.ts +79 -0
- package/dist/promise/integration.js +2 -0
- package/dist/promise/mcp.d.ts +15 -0
- package/dist/promise/mcp.js +0 -0
- package/dist/promise/permission.d.ts +21 -0
- package/dist/promise/permission.js +0 -0
- package/dist/promise/plugin.d.ts +57 -0
- package/dist/promise/plugin.js +3 -0
- package/dist/promise/reference.d.ts +13 -0
- package/dist/promise/reference.js +0 -0
- package/dist/promise/registration.d.ts +12 -0
- package/dist/promise/registration.js +0 -0
- package/dist/promise/rpc.d.ts +22 -0
- package/dist/promise/rpc.js +0 -0
- package/dist/promise/session.d.ts +107 -0
- package/dist/promise/session.js +0 -0
- package/dist/promise/shell.d.ts +14 -0
- package/dist/promise/shell.js +0 -0
- package/dist/promise/skill.d.ts +15 -0
- package/dist/promise/skill.js +0 -0
- package/dist/promise/storage.d.ts +8 -0
- package/dist/promise/storage.js +0 -0
- package/dist/promise/tool.d.ts +56 -0
- package/dist/promise/tool.js +2 -0
- package/dist/promise/types.d.ts +3 -0
- package/dist/promise/types.js +0 -0
- package/dist/promise/vcs.d.ts +50 -0
- package/dist/promise/vcs.js +0 -0
- package/dist/promise/websearch.d.ts +21 -0
- package/dist/promise/websearch.js +0 -0
- package/dist/promise/worktree.d.ts +23 -0
- package/dist/promise/worktree.js +0 -0
- package/dist/rpc.d.ts +1 -0
- package/dist/rpc.js +1 -0
- package/dist/source.bun.d.ts +4 -0
- package/dist/source.bun.js +62 -0
- package/dist/source.d.ts +8 -0
- package/dist/source.js +59 -0
- package/dist/source.node.d.ts +5 -0
- package/dist/source.node.js +45 -0
- package/dist/storage.d.ts +14 -0
- package/dist/storage.js +0 -0
- package/dist/tui/context.d.ts +458 -0
- package/dist/tui/context.js +0 -0
- package/dist/tui/index.d.ts +2 -0
- package/dist/tui/index.js +2 -0
- package/dist/tui/plugin.d.ts +8 -0
- package/dist/tui/plugin.js +3 -0
- package/dist/tui/solid.d.ts +7 -0
- package/dist/tui/solid.js +16 -0
- package/dist/worktree.d.ts +18 -0
- package/dist/worktree.js +0 -0
- package/package.json +83 -11
- package/README.md +0 -5
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { WebSearch } from "@opencode/schema/websearch";
|
|
2
|
+
import type { WebSearchApi } from "@opencode/client/promise/api";
|
|
3
|
+
import type { Transform } from "./registration.js";
|
|
4
|
+
export interface WebSearchDefinition {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly name: string;
|
|
7
|
+
readonly execute: (input: WebSearch.ProviderInput, context: {
|
|
8
|
+
readonly signal: AbortSignal;
|
|
9
|
+
}) => Promise<readonly WebSearch.Result[]>;
|
|
10
|
+
}
|
|
11
|
+
export interface WebSearchDomain extends WebSearchApi {
|
|
12
|
+
readonly transform: Transform<WebSearchEditor>;
|
|
13
|
+
readonly reload: () => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export interface WebSearchEditor {
|
|
16
|
+
add(definition: WebSearchDefinition): void;
|
|
17
|
+
readonly default: {
|
|
18
|
+
get(): string | false | undefined;
|
|
19
|
+
set(selection: string | false): void;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { WorktreeApi } from "@opencode/client/promise/api";
|
|
2
|
+
import type { WorktreeCreateInput, WorktreeEntry, WorktreeRemoveInput, WorktreeResult } from "../worktree.js";
|
|
3
|
+
import type { Transform } from "./registration.js";
|
|
4
|
+
export interface WorktreeDefinition {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly create: (input: WorktreeCreateInput, context: {
|
|
7
|
+
readonly signal: AbortSignal;
|
|
8
|
+
}) => Promise<WorktreeResult>;
|
|
9
|
+
readonly remove: (input: WorktreeRemoveInput, context: {
|
|
10
|
+
readonly signal: AbortSignal;
|
|
11
|
+
}) => Promise<void>;
|
|
12
|
+
readonly list: (sourceDirectory: string, context: {
|
|
13
|
+
readonly signal: AbortSignal;
|
|
14
|
+
}) => Promise<readonly WorktreeEntry[]>;
|
|
15
|
+
}
|
|
16
|
+
export interface WorktreeEditor {
|
|
17
|
+
/** Registers an implementation and selects it as the default. Later active registrations win. */
|
|
18
|
+
add(definition: WorktreeDefinition): void;
|
|
19
|
+
}
|
|
20
|
+
export interface WorktreeDomain extends WorktreeApi {
|
|
21
|
+
readonly transform: Transform<WorktreeEditor>;
|
|
22
|
+
readonly reload: () => Promise<void>;
|
|
23
|
+
}
|
|
File without changes
|
package/dist/rpc.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Rpc } from "@opencode/schema/rpc";
|
package/dist/rpc.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Rpc } from "@opencode/schema/rpc";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import { Host } from "./host.js";
|
|
6
|
+
import { localSource } from "./source.js";
|
|
7
|
+
let generation = Date.now();
|
|
8
|
+
export async function prepareSource(entrypoint, track) {
|
|
9
|
+
const root = fileURLToPath(entrypoint);
|
|
10
|
+
const files = new Set();
|
|
11
|
+
const visit = (file, search = "") => {
|
|
12
|
+
if (file !== root && file.split(path.sep).includes("node_modules"))
|
|
13
|
+
return;
|
|
14
|
+
if (search)
|
|
15
|
+
delete require.cache[file + search];
|
|
16
|
+
if (files.has(file))
|
|
17
|
+
return;
|
|
18
|
+
files.add(file);
|
|
19
|
+
// Bun exposes ESM here too. Delete known keys even when absent: rejected
|
|
20
|
+
// evaluations are not enumerable, but deletion still invalidates them.
|
|
21
|
+
delete require.cache[file];
|
|
22
|
+
track(file);
|
|
23
|
+
if (!/\.[cm]?[jt]sx?$/.test(file))
|
|
24
|
+
return;
|
|
25
|
+
// Scan dependencies only; the normal runtime loader still owns compilation,
|
|
26
|
+
// package resolution, import attributes, and error reporting.
|
|
27
|
+
const imports = (() => {
|
|
28
|
+
try {
|
|
29
|
+
return new Bun.Transpiler({
|
|
30
|
+
loader: file.endsWith("tsx") ? "tsx" : file.endsWith("jsx") ? "jsx" : /\.[cm]?ts$/.test(file) ? "ts" : "js",
|
|
31
|
+
target: "bun",
|
|
32
|
+
}).scan(readFileSync(file, "utf8")).imports;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
})();
|
|
38
|
+
for (const item of imports) {
|
|
39
|
+
const local = item.path.startsWith("./") || item.path.startsWith("../")
|
|
40
|
+
? new URL(item.path, pathToFileURL(file))
|
|
41
|
+
: localSource(item.path, path.dirname(file));
|
|
42
|
+
if (!local)
|
|
43
|
+
continue;
|
|
44
|
+
const requested = fileURLToPath(local);
|
|
45
|
+
// Resolving a workspace symlink can erase its node_modules boundary.
|
|
46
|
+
if (requested.split(path.sep).includes("node_modules"))
|
|
47
|
+
continue;
|
|
48
|
+
try {
|
|
49
|
+
visit(item.kind === "require-call"
|
|
50
|
+
? createRequire(file).resolve(requested)
|
|
51
|
+
: Bun.resolveSync(requested, path.dirname(file)), local.search);
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// A missing local dependency may appear on the next save. Leave its
|
|
55
|
+
// actual failure (or optional fallback) to the native loader.
|
|
56
|
+
track(path.dirname(requested), true);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
visit(root);
|
|
61
|
+
return { version: String(++generation), load: () => Host.load(entrypoint) };
|
|
62
|
+
}
|
package/dist/source.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function createPluginSources(watch: (file: string) => Promise<void>): {
|
|
2
|
+
read: (entrypoint: string) => Promise<{
|
|
3
|
+
version: string;
|
|
4
|
+
module: unknown;
|
|
5
|
+
}>;
|
|
6
|
+
dispose: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function localSource(spec: string, directory: string): import("url").URL | undefined;
|
package/dist/source.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
2
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { Hash } from "@opencode/util/hash";
|
|
5
|
+
// Keep source fingerprints and import attempts together. Filesystem events
|
|
6
|
+
// should reload changed local graphs, not repeat unchanged evaluations.
|
|
7
|
+
export function createPluginSources(watch) {
|
|
8
|
+
const sources = new Map();
|
|
9
|
+
const cleanups = [];
|
|
10
|
+
const watching = new Set();
|
|
11
|
+
return {
|
|
12
|
+
read: async (entrypoint) => {
|
|
13
|
+
await Promise.all(watching);
|
|
14
|
+
const previous = sources.get(entrypoint);
|
|
15
|
+
if (previous && [...previous.files].every(([file, item]) => item.digest === digest(file, item.directory)))
|
|
16
|
+
return previous.loaded;
|
|
17
|
+
const files = new Map();
|
|
18
|
+
const track = (file, directory = false) => {
|
|
19
|
+
if (files.has(file))
|
|
20
|
+
return;
|
|
21
|
+
files.set(file, { digest: digest(file, directory), directory });
|
|
22
|
+
const pending = watch(file).finally(() => watching.delete(pending));
|
|
23
|
+
watching.add(pending);
|
|
24
|
+
// Watch setup can be interrupted while module evaluation is still pending.
|
|
25
|
+
void pending.catch(() => { });
|
|
26
|
+
};
|
|
27
|
+
track(fileURLToPath(entrypoint));
|
|
28
|
+
const { prepareSource } = await import("#plugin-source");
|
|
29
|
+
const prepared = await prepareSource(entrypoint, track);
|
|
30
|
+
if (prepared.dispose)
|
|
31
|
+
cleanups.push(prepared.dispose);
|
|
32
|
+
// Cache the attempt before evaluating it: unchanged failing modules must
|
|
33
|
+
// not repeat import-time effects on every filesystem notification.
|
|
34
|
+
const loaded = prepared.load().then((module) => ({ version: prepared.version, module }));
|
|
35
|
+
sources.set(entrypoint, { loaded, files });
|
|
36
|
+
return loaded.finally(() => Promise.all(watching));
|
|
37
|
+
},
|
|
38
|
+
dispose: () => {
|
|
39
|
+
for (const cleanup of cleanups.splice(0))
|
|
40
|
+
cleanup();
|
|
41
|
+
sources.clear();
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function digest(file, directory) {
|
|
46
|
+
try {
|
|
47
|
+
return Hash.sha256(directory ? JSON.stringify(readdirSync(file).sort()) : readFileSync(file));
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return "missing";
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function localSource(spec, directory) {
|
|
54
|
+
if (spec.startsWith("file://"))
|
|
55
|
+
return new URL(spec);
|
|
56
|
+
if (spec.startsWith("./") || spec.startsWith("../") || path.isAbsolute(spec))
|
|
57
|
+
return pathToFileURL(path.resolve(directory, spec));
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { registerHooks } from "node:module";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { localSource } from "./source.js";
|
|
5
|
+
import { Host } from "./host.js";
|
|
6
|
+
let generation = Date.now();
|
|
7
|
+
export async function prepareSource(entrypoint, track) {
|
|
8
|
+
const version = String(++generation);
|
|
9
|
+
const fresh = (specifier) => {
|
|
10
|
+
const url = new URL(specifier);
|
|
11
|
+
url.searchParams.set("__opencode_reload", version);
|
|
12
|
+
return url.href;
|
|
13
|
+
};
|
|
14
|
+
const hook = registerHooks({
|
|
15
|
+
resolve(specifier, context, nextResolve) {
|
|
16
|
+
if (!context.parentURL || new URL(context.parentURL).searchParams.get("__opencode_reload") !== version)
|
|
17
|
+
return nextResolve(specifier, context);
|
|
18
|
+
const local = specifier.startsWith("./") || specifier.startsWith("../")
|
|
19
|
+
? new URL(specifier, context.parentURL)
|
|
20
|
+
: localSource(specifier, path.dirname(fileURLToPath(context.parentURL)));
|
|
21
|
+
if (!local)
|
|
22
|
+
return nextResolve(specifier, context);
|
|
23
|
+
if (fileURLToPath(local).split(path.sep).includes("node_modules"))
|
|
24
|
+
return nextResolve(specifier, context);
|
|
25
|
+
const resolved = (() => {
|
|
26
|
+
try {
|
|
27
|
+
return nextResolve(specifier, context);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
track(path.dirname(fileURLToPath(local)), true);
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
})();
|
|
34
|
+
if (!resolved.url.startsWith("file:"))
|
|
35
|
+
return resolved;
|
|
36
|
+
const file = fileURLToPath(resolved.url);
|
|
37
|
+
if (file.split(path.sep).includes("node_modules"))
|
|
38
|
+
return resolved;
|
|
39
|
+
track(file);
|
|
40
|
+
return { ...resolved, url: fresh(resolved.url) };
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
const specifier = fresh(entrypoint);
|
|
44
|
+
return { version: specifier, load: () => Host.load(specifier), dispose: () => hook.deregister() };
|
|
45
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Schema } from "effect";
|
|
2
|
+
export interface StorageEntry {
|
|
3
|
+
readonly key: string;
|
|
4
|
+
readonly value: Schema.Json;
|
|
5
|
+
}
|
|
6
|
+
export interface StorageScanOptions {
|
|
7
|
+
readonly prefix: string;
|
|
8
|
+
readonly after?: string;
|
|
9
|
+
readonly limit?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface StorageScanResult {
|
|
12
|
+
readonly entries: readonly StorageEntry[];
|
|
13
|
+
readonly next?: string;
|
|
14
|
+
}
|
package/dist/storage.js
ADDED
|
File without changes
|