opencode-add-dir 1.3.0 → 1.4.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/README.md +12 -31
- package/bin/setup.mjs +57 -42
- package/dist/index.d.ts +5 -2
- package/dist/index.js +86 -17
- package/dist/state.d.ts +1 -0
- package/dist/tui-plugin.d.ts +5 -0
- package/dist/tui.tsx +110 -0
- package/package.json +29 -4
package/README.md
CHANGED
|
@@ -31,7 +31,6 @@ Automatically adds the plugin to your global `opencode.json`.
|
|
|
31
31
|
<summary>Alternative: local file</summary>
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
# Clone and build
|
|
35
34
|
git clone https://github.com/kuzeofficial/add-dir-opencode.git
|
|
36
35
|
cd add-dir-opencode
|
|
37
36
|
bun install && bun run deploy
|
|
@@ -41,27 +40,15 @@ Bundles to `~/.config/opencode/plugins/add-dir.js`.
|
|
|
41
40
|
|
|
42
41
|
</details>
|
|
43
42
|
|
|
44
|
-
##
|
|
45
|
-
|
|
46
|
-
### Slash Command
|
|
43
|
+
## Commands
|
|
47
44
|
|
|
48
45
|
```
|
|
49
|
-
/add-dir /path/to/directory #
|
|
46
|
+
/add-dir /path/to/directory # Add for this session
|
|
50
47
|
/add-dir /path/to/directory --remember # Persist across sessions
|
|
51
|
-
/
|
|
52
|
-
/
|
|
48
|
+
/list-dir # Show added directories
|
|
49
|
+
/remove-dir /path/to/directory # Remove a directory
|
|
53
50
|
```
|
|
54
51
|
|
|
55
|
-
### LLM Tools
|
|
56
|
-
|
|
57
|
-
The agent can also call these tools directly:
|
|
58
|
-
|
|
59
|
-
| Tool | Description |
|
|
60
|
-
|------|-------------|
|
|
61
|
-
| `add_dir` | Add a directory (with optional `remember` flag) |
|
|
62
|
-
| `list_dirs` | List all added directories |
|
|
63
|
-
| `remove_dir` | Remove a directory |
|
|
64
|
-
|
|
65
52
|
## How It Works
|
|
66
53
|
|
|
67
54
|
The plugin uses a layered approach to handle permissions across all sessions, including subagents:
|
|
@@ -69,13 +56,13 @@ The plugin uses a layered approach to handle permissions across all sessions, in
|
|
|
69
56
|
| Layer | When | Scope |
|
|
70
57
|
|-------|------|-------|
|
|
71
58
|
| **Config hook** | Startup | Injects `external_directory: "allow"` rules for persisted dirs into all agents |
|
|
72
|
-
| **Session permission** | `/add-dir` | Sets `external_directory: true` on the current session
|
|
59
|
+
| **Session permission** | `/add-dir` | Sets `external_directory: true` on the current session |
|
|
73
60
|
| **tool.execute.before** | Every file tool | Detects subagent sessions accessing added dirs, grants permission before execution |
|
|
74
61
|
| **Event auto-approve** | Permission popup | Catches any remaining `external_directory` requests and auto-approves via SDK |
|
|
75
62
|
|
|
76
|
-
###
|
|
63
|
+
### Context Injection
|
|
77
64
|
|
|
78
|
-
If an added directory contains `AGENTS.md`, `CLAUDE.md`, or `.agents/AGENTS.md`, the content is automatically injected into the system prompt
|
|
65
|
+
If an added directory contains `AGENTS.md`, `CLAUDE.md`, or `.agents/AGENTS.md`, the content is automatically injected into the system prompt.
|
|
79
66
|
|
|
80
67
|
## Persistence
|
|
81
68
|
|
|
@@ -91,7 +78,7 @@ These are loaded at startup and injected into agent permission rules via the con
|
|
|
91
78
|
|
|
92
79
|
```bash
|
|
93
80
|
bun install
|
|
94
|
-
bun test #
|
|
81
|
+
bun test # 33 tests
|
|
95
82
|
bun run typecheck # Type check
|
|
96
83
|
bun run build # Build npm package
|
|
97
84
|
bun run deploy # Bundle to ~/.config/opencode/plugins/
|
|
@@ -102,24 +89,18 @@ bun run deploy # Bundle to ~/.config/opencode/plugins/
|
|
|
102
89
|
```
|
|
103
90
|
src/
|
|
104
91
|
├── index.ts # Entry point (default export)
|
|
105
|
-
├── plugin.ts # Hooks +
|
|
106
|
-
├── state.ts # Persistence
|
|
92
|
+
├── plugin.ts # Hooks + commands
|
|
93
|
+
├── state.ts # Persistence + path utils
|
|
107
94
|
├── validate.ts # Directory validation
|
|
108
95
|
├── permissions.ts # Session grants + auto-approve
|
|
109
|
-
|
|
96
|
+
├── context.ts # AGENTS.md injection
|
|
97
|
+
└── types.ts # Shared type definitions
|
|
110
98
|
```
|
|
111
99
|
|
|
112
100
|
## Debugging
|
|
113
101
|
|
|
114
|
-
Run OpenCode with logs:
|
|
115
|
-
|
|
116
102
|
```bash
|
|
117
103
|
opencode --print-logs 2>debug.log
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
Filter plugin logs:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
104
|
grep "\[add-dir\]" debug.log
|
|
124
105
|
```
|
|
125
106
|
|
package/bin/setup.mjs
CHANGED
|
@@ -9,19 +9,9 @@ const isRemove = args.includes("--remove")
|
|
|
9
9
|
|
|
10
10
|
function configDir() {
|
|
11
11
|
if (process.env.XDG_CONFIG_HOME) return join(process.env.XDG_CONFIG_HOME, "opencode")
|
|
12
|
-
if (process.platform === "darwin") return join(homedir(), ".config", "opencode")
|
|
13
12
|
return join(homedir(), ".config", "opencode")
|
|
14
13
|
}
|
|
15
14
|
|
|
16
|
-
function findConfig() {
|
|
17
|
-
const dir = configDir()
|
|
18
|
-
for (const name of ["opencode.jsonc", "opencode.json"]) {
|
|
19
|
-
const p = join(dir, name)
|
|
20
|
-
if (existsSync(p)) return p
|
|
21
|
-
}
|
|
22
|
-
return join(dir, "opencode.json")
|
|
23
|
-
}
|
|
24
|
-
|
|
25
15
|
function stripJsonComments(text) {
|
|
26
16
|
let result = ""
|
|
27
17
|
let inString = false
|
|
@@ -39,48 +29,73 @@ function stripJsonComments(text) {
|
|
|
39
29
|
return result
|
|
40
30
|
}
|
|
41
31
|
|
|
42
|
-
function
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
let config = {}
|
|
47
|
-
if (existsSync(configPath)) {
|
|
48
|
-
const raw = readFileSync(configPath, "utf-8")
|
|
49
|
-
config = JSON.parse(stripJsonComments(raw))
|
|
50
|
-
} else {
|
|
51
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
|
|
32
|
+
function findConfigFile(dir, baseName) {
|
|
33
|
+
for (const ext of [".jsonc", ".json"]) {
|
|
34
|
+
const p = join(dir, baseName + ext)
|
|
35
|
+
if (existsSync(p)) return p
|
|
52
36
|
}
|
|
37
|
+
return join(dir, baseName + ".json")
|
|
38
|
+
}
|
|
53
39
|
|
|
54
|
-
|
|
55
|
-
|
|
40
|
+
function readConfig(filePath) {
|
|
41
|
+
if (!existsSync(filePath)) return {}
|
|
42
|
+
return JSON.parse(stripJsonComments(readFileSync(filePath, "utf-8")))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function hasPlugin(plugins) {
|
|
46
|
+
return (plugins || []).some((p) => {
|
|
56
47
|
const name = Array.isArray(p) ? p[0] : p
|
|
57
48
|
return name === PKG || name.startsWith(PKG + "@")
|
|
58
49
|
})
|
|
50
|
+
}
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n")
|
|
70
|
-
console.log(`Removed ${PKG} from ${configPath}`)
|
|
71
|
-
return
|
|
72
|
-
}
|
|
52
|
+
function withoutPlugin(plugins) {
|
|
53
|
+
return (plugins || []).filter((p) => {
|
|
54
|
+
const name = Array.isArray(p) ? p[0] : p
|
|
55
|
+
return name !== PKG && !name.startsWith(PKG + "@")
|
|
56
|
+
})
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function patchConfig(filePath, config, schemaUrl) {
|
|
60
|
+
config.plugin = config.plugin || []
|
|
73
61
|
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
if (isRemove) {
|
|
63
|
+
if (!hasPlugin(config.plugin)) return false
|
|
64
|
+
config.plugin = withoutPlugin(config.plugin)
|
|
65
|
+
writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n")
|
|
66
|
+
return true
|
|
77
67
|
}
|
|
78
68
|
|
|
69
|
+
if (hasPlugin(config.plugin)) return false
|
|
79
70
|
config.plugin.push(PKG)
|
|
80
|
-
if (!config.$schema) config.$schema =
|
|
81
|
-
writeFileSync(
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
if (schemaUrl && !config.$schema) config.$schema = schemaUrl
|
|
72
|
+
writeFileSync(filePath, JSON.stringify(config, null, 2) + "\n")
|
|
73
|
+
return true
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function run() {
|
|
77
|
+
const dir = configDir()
|
|
78
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true })
|
|
79
|
+
|
|
80
|
+
const serverPath = findConfigFile(dir, "opencode")
|
|
81
|
+
const tuiPath = findConfigFile(dir, "tui")
|
|
82
|
+
|
|
83
|
+
const serverConfig = readConfig(serverPath)
|
|
84
|
+
const tuiConfig = readConfig(tuiPath)
|
|
85
|
+
|
|
86
|
+
const verb = isRemove ? "Removed" : "Added"
|
|
87
|
+
const serverChanged = patchConfig(serverPath, serverConfig, "https://opencode.ai/config.json")
|
|
88
|
+
const tuiChanged = patchConfig(tuiPath, tuiConfig)
|
|
89
|
+
|
|
90
|
+
if (serverChanged) console.log(`${verb} ${PKG} in ${serverPath}`)
|
|
91
|
+
else console.log(`${PKG} already ${isRemove ? "absent from" : "in"} ${serverPath}`)
|
|
92
|
+
|
|
93
|
+
if (tuiChanged) console.log(`${verb} ${PKG} in ${tuiPath}`)
|
|
94
|
+
else console.log(`${PKG} already ${isRemove ? "absent from" : "in"} ${tuiPath}`)
|
|
95
|
+
|
|
96
|
+
if (serverChanged || tuiChanged) {
|
|
97
|
+
console.log("Restart OpenCode to activate the plugin.")
|
|
98
|
+
}
|
|
84
99
|
}
|
|
85
100
|
|
|
86
101
|
run()
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -35,6 +35,83 @@ function matchesDirs(dirs, filepath) {
|
|
|
35
35
|
}
|
|
36
36
|
return false;
|
|
37
37
|
}
|
|
38
|
+
var PKG = "opencode-add-dir";
|
|
39
|
+
function stripJsonComments(text) {
|
|
40
|
+
let result = "";
|
|
41
|
+
let inString = false;
|
|
42
|
+
let escape = false;
|
|
43
|
+
for (let i = 0;i < text.length; i++) {
|
|
44
|
+
const ch = text[i];
|
|
45
|
+
if (escape) {
|
|
46
|
+
result += ch;
|
|
47
|
+
escape = false;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (ch === "\\" && inString) {
|
|
51
|
+
result += ch;
|
|
52
|
+
escape = true;
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (ch === '"') {
|
|
56
|
+
inString = !inString;
|
|
57
|
+
result += ch;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (inString) {
|
|
61
|
+
result += ch;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (ch === "/" && text[i + 1] === "/") {
|
|
65
|
+
while (i < text.length && text[i] !== `
|
|
66
|
+
`)
|
|
67
|
+
i++;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (ch === "/" && text[i + 1] === "*") {
|
|
71
|
+
i += 2;
|
|
72
|
+
while (i < text.length && !(text[i] === "*" && text[i + 1] === "/"))
|
|
73
|
+
i++;
|
|
74
|
+
i++;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
result += ch;
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
function configDir() {
|
|
82
|
+
return join(process.env["XDG_CONFIG_HOME"] || join(process.env["HOME"] || "~", ".config"), "opencode");
|
|
83
|
+
}
|
|
84
|
+
function findTuiConfig() {
|
|
85
|
+
const dir = configDir();
|
|
86
|
+
for (const name of ["tui.jsonc", "tui.json"]) {
|
|
87
|
+
const p = join(dir, name);
|
|
88
|
+
if (existsSync(p))
|
|
89
|
+
return p;
|
|
90
|
+
}
|
|
91
|
+
return join(dir, "tui.json");
|
|
92
|
+
}
|
|
93
|
+
function ensureTuiConfig() {
|
|
94
|
+
try {
|
|
95
|
+
const dir = configDir();
|
|
96
|
+
if (!existsSync(dir))
|
|
97
|
+
mkdirSync(dir, { recursive: true });
|
|
98
|
+
const filePath = findTuiConfig();
|
|
99
|
+
let config = {};
|
|
100
|
+
if (existsSync(filePath)) {
|
|
101
|
+
config = JSON.parse(stripJsonComments(readFileSync(filePath, "utf-8")));
|
|
102
|
+
}
|
|
103
|
+
const plugins = config.plugin ?? [];
|
|
104
|
+
const hasEntry = plugins.some((p) => {
|
|
105
|
+
const name = Array.isArray(p) ? p[0] : p;
|
|
106
|
+
return name === PKG || typeof name === "string" && name.startsWith(PKG + "@");
|
|
107
|
+
});
|
|
108
|
+
if (hasEntry)
|
|
109
|
+
return;
|
|
110
|
+
config.plugin = [...plugins, PKG];
|
|
111
|
+
writeFileSync(filePath, JSON.stringify(config, null, 2) + `
|
|
112
|
+
`);
|
|
113
|
+
} catch {}
|
|
114
|
+
}
|
|
38
115
|
|
|
39
116
|
// src/validate.ts
|
|
40
117
|
import { statSync } from "fs";
|
|
@@ -138,14 +215,11 @@ ${content}`);
|
|
|
138
215
|
|
|
139
216
|
// src/plugin.ts
|
|
140
217
|
var SENTINEL = Object.assign(new Error("__ADD_DIR_HANDLED__"), { stack: "" });
|
|
141
|
-
function log(msg, data) {
|
|
142
|
-
console.error(`[add-dir] ${msg}`, data !== undefined ? JSON.stringify(data) : "");
|
|
143
|
-
}
|
|
144
218
|
var AddDirPlugin = async ({ client, worktree, directory }) => {
|
|
145
219
|
const root = worktree || directory;
|
|
146
220
|
const dirs = loadDirs();
|
|
147
221
|
const sdk = client;
|
|
148
|
-
|
|
222
|
+
ensureTuiConfig();
|
|
149
223
|
function add(dirPath, persist) {
|
|
150
224
|
const result = validateDir(dirPath, root, [...dirs.values()].map((d) => d.path));
|
|
151
225
|
if (!result.ok)
|
|
@@ -184,18 +258,9 @@ var AddDirPlugin = async ({ client, worktree, directory }) => {
|
|
|
184
258
|
notify(sdk, sessionID, result.message);
|
|
185
259
|
}
|
|
186
260
|
const commands = {
|
|
187
|
-
"add-dir": (args, sid) =>
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
},
|
|
191
|
-
"list-dir": (_, sid) => {
|
|
192
|
-
log("list-dir", { sid });
|
|
193
|
-
notify(sdk, sid, list());
|
|
194
|
-
},
|
|
195
|
-
"remove-dir": (args, sid) => {
|
|
196
|
-
log("remove-dir", { args, sid });
|
|
197
|
-
notify(sdk, sid, remove(args));
|
|
198
|
-
}
|
|
261
|
+
"add-dir": (args, sid) => handleAdd(args, sid),
|
|
262
|
+
"list-dir": (_, sid) => notify(sdk, sid, list()),
|
|
263
|
+
"remove-dir": (args, sid) => notify(sdk, sid, remove(args))
|
|
199
264
|
};
|
|
200
265
|
return {
|
|
201
266
|
config: async (cfg) => {
|
|
@@ -234,7 +299,11 @@ var AddDirPlugin = async ({ client, worktree, directory }) => {
|
|
|
234
299
|
};
|
|
235
300
|
|
|
236
301
|
// src/index.ts
|
|
237
|
-
var
|
|
302
|
+
var plugin = {
|
|
303
|
+
id: "opencode-add-dir",
|
|
304
|
+
server: AddDirPlugin
|
|
305
|
+
};
|
|
306
|
+
var src_default = plugin;
|
|
238
307
|
export {
|
|
239
308
|
src_default as default
|
|
240
309
|
};
|
package/dist/state.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export declare function loadDirs(): Map<string, DirEntry>;
|
|
|
7
7
|
export declare function saveDirs(dirs: Map<string, DirEntry>): void;
|
|
8
8
|
export declare function isChildOf(parent: string, child: string): boolean;
|
|
9
9
|
export declare function matchesDirs(dirs: Map<string, DirEntry>, filepath: string): boolean;
|
|
10
|
+
export declare function ensureTuiConfig(): void;
|
package/dist/tui.tsx
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from "@opencode-ai/plugin/tui"
|
|
2
|
+
import { createSignal } from "solid-js"
|
|
3
|
+
|
|
4
|
+
const PLUGIN_ID = "opencode-add-dir"
|
|
5
|
+
const COMMAND_NAME = "add-dir"
|
|
6
|
+
|
|
7
|
+
function activeSessionID(api: TuiPluginApi): string | undefined {
|
|
8
|
+
const route = api.route.current
|
|
9
|
+
if (route.name !== "session" || !route.params) return
|
|
10
|
+
return route.params.sessionID as string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function ensureSession(api: TuiPluginApi): Promise<string | undefined> {
|
|
14
|
+
const existing = activeSessionID(api)
|
|
15
|
+
if (existing) return existing
|
|
16
|
+
|
|
17
|
+
const res = await api.client.session.create({})
|
|
18
|
+
if (res.error) return
|
|
19
|
+
|
|
20
|
+
api.route.navigate("session", { sessionID: res.data.id })
|
|
21
|
+
return res.data.id
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function executeAddDir(api: TuiPluginApi, dirPath: string) {
|
|
25
|
+
const sessionID = await ensureSession(api)
|
|
26
|
+
if (!sessionID) {
|
|
27
|
+
api.ui.toast({ variant: "error", message: "Failed to create session" })
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// The server plugin intercepts via command.execute.before, handles the logic,
|
|
32
|
+
// sends feedback through the session event stream, then throws SENTINEL to
|
|
33
|
+
// prevent the command template from reaching the LLM. This rejection is expected.
|
|
34
|
+
api.client.session.command({
|
|
35
|
+
sessionID,
|
|
36
|
+
command: COMMAND_NAME,
|
|
37
|
+
arguments: dirPath,
|
|
38
|
+
}).catch(() => {})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function AddDirDialog(props: { api: TuiPluginApi }) {
|
|
42
|
+
const [busy, setBusy] = createSignal(false)
|
|
43
|
+
|
|
44
|
+
async function handleConfirm(value: string) {
|
|
45
|
+
const dirPath = value.trim()
|
|
46
|
+
if (!dirPath) {
|
|
47
|
+
props.api.ui.toast({ variant: "error", message: "Please enter a directory path" })
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
setBusy(true)
|
|
52
|
+
try {
|
|
53
|
+
await executeAddDir(props.api, dirPath)
|
|
54
|
+
props.api.ui.dialog.clear()
|
|
55
|
+
} finally {
|
|
56
|
+
setBusy(false)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<props.api.ui.DialogPrompt
|
|
62
|
+
title="Add directory"
|
|
63
|
+
placeholder="/path/to/directory"
|
|
64
|
+
busy={busy()}
|
|
65
|
+
busyText="Adding directory..."
|
|
66
|
+
description={() => (
|
|
67
|
+
<box gap={0}>
|
|
68
|
+
<text fg={props.api.theme.current.textMuted}>
|
|
69
|
+
To get the full path of a project:
|
|
70
|
+
</text>
|
|
71
|
+
<text fg={props.api.theme.current.textMuted}>
|
|
72
|
+
{" "}1. Move to the project in your terminal
|
|
73
|
+
</text>
|
|
74
|
+
<text fg={props.api.theme.current.textMuted}>
|
|
75
|
+
{" "}2. Run "pwd" and copy the output
|
|
76
|
+
</text>
|
|
77
|
+
<text fg={props.api.theme.current.textMuted}>
|
|
78
|
+
{" "}3. Paste below
|
|
79
|
+
</text>
|
|
80
|
+
</box>
|
|
81
|
+
)}
|
|
82
|
+
onConfirm={handleConfirm}
|
|
83
|
+
onCancel={() => props.api.ui.dialog.clear()}
|
|
84
|
+
/>
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function showDialog(api: TuiPluginApi) {
|
|
89
|
+
api.ui.dialog.replace(() => <AddDirDialog api={api} />)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const tui: TuiPlugin = async (api) => {
|
|
93
|
+
api.command.register(() => [
|
|
94
|
+
{
|
|
95
|
+
title: "Add directory",
|
|
96
|
+
value: "add-dir.dialog",
|
|
97
|
+
description: "Add a working directory to the session",
|
|
98
|
+
category: "Directories",
|
|
99
|
+
slash: { name: COMMAND_NAME },
|
|
100
|
+
onSelect: () => showDialog(api),
|
|
101
|
+
},
|
|
102
|
+
])
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const plugin: TuiPluginModule & { id: string } = {
|
|
106
|
+
id: PLUGIN_ID,
|
|
107
|
+
tui,
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export default plugin
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-add-dir",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Add working directories to your OpenCode session with auto-approved permissions",
|
|
5
5
|
"author": "Cristian Fonseca <cfonsecacomas@gmail.com>",
|
|
6
6
|
"type": "module",
|
|
@@ -8,10 +8,20 @@
|
|
|
8
8
|
".": {
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"import": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./server": {
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./tui": {
|
|
16
|
+
"import": "./dist/tui.tsx"
|
|
11
17
|
}
|
|
12
18
|
},
|
|
13
19
|
"main": "./dist/index.js",
|
|
14
20
|
"types": "./dist/index.d.ts",
|
|
21
|
+
"oc-plugin": [
|
|
22
|
+
"server",
|
|
23
|
+
"tui"
|
|
24
|
+
],
|
|
15
25
|
"bin": {
|
|
16
26
|
"opencode-add-dir-setup": "./bin/setup.mjs"
|
|
17
27
|
},
|
|
@@ -22,8 +32,10 @@
|
|
|
22
32
|
"LICENSE"
|
|
23
33
|
],
|
|
24
34
|
"scripts": {
|
|
25
|
-
"build": "bun build
|
|
26
|
-
"
|
|
35
|
+
"build": "bun run build:server && bun run build:tui && bun x tsc --emitDeclarationOnly",
|
|
36
|
+
"build:server": "bun build ./src/index.ts --outdir ./dist --target node --format esm --external @opencode-ai/plugin",
|
|
37
|
+
"build:tui": "cp ./src/tui-plugin.tsx ./dist/tui.tsx",
|
|
38
|
+
"deploy": "bun run build:server && bun run build:tui",
|
|
27
39
|
"test": "bun test",
|
|
28
40
|
"typecheck": "bun x tsc --noEmit",
|
|
29
41
|
"prepublishOnly": "bun run typecheck && bun test && bun run build"
|
|
@@ -41,10 +53,22 @@
|
|
|
41
53
|
},
|
|
42
54
|
"license": "MIT",
|
|
43
55
|
"peerDependencies": {
|
|
44
|
-
"@opencode-ai/plugin": ">=1.0.0"
|
|
56
|
+
"@opencode-ai/plugin": ">=1.0.0",
|
|
57
|
+
"@opentui/core": ">=0.1.92",
|
|
58
|
+
"@opentui/solid": ">=0.1.92"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"@opentui/core": {
|
|
62
|
+
"optional": true
|
|
63
|
+
},
|
|
64
|
+
"@opentui/solid": {
|
|
65
|
+
"optional": true
|
|
66
|
+
}
|
|
45
67
|
},
|
|
46
68
|
"devDependencies": {
|
|
47
69
|
"@opencode-ai/plugin": "^1.1.14",
|
|
70
|
+
"@opentui/core": "0.1.95",
|
|
71
|
+
"@opentui/solid": "0.1.95",
|
|
48
72
|
"@semantic-release/changelog": "^6.0.3",
|
|
49
73
|
"@semantic-release/commit-analyzer": "^13.0.1",
|
|
50
74
|
"@semantic-release/git": "^10.0.1",
|
|
@@ -53,6 +77,7 @@
|
|
|
53
77
|
"@semantic-release/release-notes-generator": "^14.1.0",
|
|
54
78
|
"@types/bun": "latest",
|
|
55
79
|
"semantic-release": "^25.0.3",
|
|
80
|
+
"solid-js": "^1.9.12",
|
|
56
81
|
"typescript": "^5.8.3"
|
|
57
82
|
}
|
|
58
83
|
}
|