@yee94/opencode-profile 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yee
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # OpenCode Yee Profile
2
+
3
+ OpenCode V2 插件:保留原生 Build,按需使用 Explore、Oracle、Designer。无调度器、自动唤醒或模型降级链。
4
+
5
+ ## 使用
6
+
7
+ 需要 Node.js 24+、支持 `@opencode/plugin` 2.0.12 API 的 OpenCode V2。
8
+
9
+ 在 `opencode.jsonc` 中加入:
10
+
11
+ ```jsonc
12
+ {
13
+ "plugins": ["@yee94/opencode-profile@0.1.0"]
14
+ }
15
+ ```
16
+
17
+ 重新加载 OpenCode,新建 Build 会话。从 slim 迁移时,先移除旧插件条目。
18
+
19
+ | Agent | 用途 |
20
+ | --- | --- |
21
+ | Build | 主执行者,提示词、模型和权限保持原样 |
22
+ | Explore | 只读代码定位 |
23
+ | Oracle | 只读架构审查:OCP、奥卡姆剃刀、YAGNI;合理即放行 |
24
+ | Designer | UI/UX 设计与实现 |
25
+
26
+ ## 配置模型
27
+
28
+ 直接使用 OpenCode 原生配置。下面的模型 ID 为占位符,请替换为实际值:
29
+
30
+ ```jsonc
31
+ {
32
+ "model": "your-provider/main-model",
33
+ "agents": {
34
+ "explore": { "model": "your-provider/fast-model" },
35
+ "oracle": { "model": "your-provider/review-model" },
36
+ "designer": { "model": "your-provider/design-model" }
37
+ }
38
+ }
39
+ ```
40
+
41
+ 不指定子 Agent 模型时继承父会话模型;已配置的 Agent 模型会保留。当前会话的主模型在 `/models` 中选择。
42
+ 子 Agent 模型可追加 `#variant`,例如 `your-provider/review-model#high`,需模型本身支持。
43
+
44
+ 关闭某个专家时,使用插件选项:
45
+
46
+ ```jsonc
47
+ {
48
+ "plugins": [{
49
+ "package": "@yee94/opencode-profile@0.1.0",
50
+ "options": { "agents": { "oracle": false } }
51
+ }]
52
+ }
53
+ ```
54
+
55
+ ## 本地开发
56
+
57
+ ```sh
58
+ pnpm install
59
+ pnpm build
60
+ pnpm check
61
+ ```
62
+
63
+ 将 `plugins` 中的包名替换为本仓库的绝对目录路径。修改后重新构建并重新加载插件。
64
+ `pnpm smoke:host -- opencode2` 可在隔离环境验证真实宿主加载,不发模型请求。
@@ -0,0 +1,6 @@
1
+ import { Plugin } from "@opencode/plugin";
2
+
3
+ //#region src/index.d.ts
4
+ declare const _default: Plugin.Plugin;
5
+ //#endregion
6
+ export { _default as default };
package/dist/index.mjs ADDED
@@ -0,0 +1,124 @@
1
+ import { Model, Plugin } from "@opencode/plugin";
2
+ import { z } from "zod";
3
+
4
+ //#region src/options.ts
5
+ const agentNames = [
6
+ "explore",
7
+ "oracle",
8
+ "designer"
9
+ ];
10
+ const model = z.string().regex(/^[^\s/#]+\/[^\s#]+(?:#[^\s#]+)?$/, "Expected provider/model or provider/model#variant");
11
+ const agentOptions = z.union([z.literal(false), z.strictObject({ model: model.optional() })]);
12
+ const optionsSchema = z.strictObject({ agents: z.strictObject({
13
+ explore: agentOptions.optional(),
14
+ oracle: agentOptions.optional(),
15
+ designer: agentOptions.optional()
16
+ }).default({}) });
17
+ function parseOptions(input) {
18
+ const result = optionsSchema.safeParse(input ?? {});
19
+ if (!result.success) {
20
+ const problems = result.error.issues.map((issue) => `${issue.path.join(".") || "options"}: ${issue.message}`);
21
+ throw new Error(`Invalid opencode-yee-profile options:\n${problems.join("\n")}`);
22
+ }
23
+ return result.data;
24
+ }
25
+
26
+ //#endregion
27
+ //#region src/agents.ts
28
+ const specialists = {
29
+ explore: {
30
+ description: "Map unfamiliar code to file:line evidence. Skip for a known file or a single lookup.",
31
+ system: "Find the code that answers the question. Return file:line evidence and the relevant call path; stop when the question is answered, and label gaps.",
32
+ readonly: true
33
+ },
34
+ oracle: {
35
+ description: "Architecture-first review: OCP, Occam's razor, YAGNI, and justified extensibility. Focus on material structural costs, not speculative defenses or routine sign-off.",
36
+ system: "Read project conventions; assess existing layers, ownership, reuse, and real requirements. Apply Occam's razor and YAGNI: the simplest sufficient design with justified OCP extension points, not speculative frameworks. Accept reasonable trade-offs and necessary safeguards. Report only material issues with file:line evidence, costs, and minimal compatible fixes; otherwise approve and stop.",
37
+ readonly: true
38
+ },
39
+ designer: {
40
+ description: "Design and implement UI changes; use for visual or interaction decisions, not backend work.",
41
+ system: "Design and implement within the existing visual language. Make hierarchy, responsive behavior, accessibility, and interaction states intentional; verify the changed experience and report unverified states.",
42
+ readonly: false
43
+ }
44
+ };
45
+ function readOnlyPermissions() {
46
+ return [
47
+ {
48
+ action: "*",
49
+ resource: "*",
50
+ effect: "deny"
51
+ },
52
+ ...[
53
+ "read",
54
+ "glob",
55
+ "grep"
56
+ ].map((action) => ({
57
+ action,
58
+ resource: "*",
59
+ effect: "allow"
60
+ })),
61
+ {
62
+ action: "external_directory",
63
+ resource: "*",
64
+ effect: "ask"
65
+ },
66
+ {
67
+ action: "read",
68
+ resource: "*.env",
69
+ effect: "ask"
70
+ },
71
+ {
72
+ action: "read",
73
+ resource: "*.env.*",
74
+ effect: "ask"
75
+ },
76
+ {
77
+ action: "read",
78
+ resource: "*.env.example",
79
+ effect: "allow"
80
+ }
81
+ ];
82
+ }
83
+
84
+ //#endregion
85
+ //#region src/register.ts
86
+ function registerAgents(editor, options) {
87
+ const build = editor.get("build");
88
+ if (!build || build.hidden || build.mode === "subagent") throw new Error("opencode-yee-profile requires the native, visible Build primary agent. Enable Build before loading this plugin.");
89
+ editor.default("build");
90
+ for (const name of agentNames) {
91
+ const settings = options.agents[name];
92
+ if (settings === false) {
93
+ editor.remove(name);
94
+ continue;
95
+ }
96
+ const specialist = specialists[name];
97
+ editor.update(name, (agent) => {
98
+ agent.mode = "subagent";
99
+ agent.hidden = false;
100
+ agent.description = specialist.description;
101
+ agent.system = specialist.system;
102
+ if (settings?.model) agent.model = Model.Ref.parse(settings.model);
103
+ if (specialist.readonly) agent.permissions = readOnlyPermissions();
104
+ else agent.permissions = [...agent.permissions.filter((rule) => rule.action !== "subagent"), {
105
+ action: "subagent",
106
+ resource: "*",
107
+ effect: "deny"
108
+ }];
109
+ });
110
+ }
111
+ }
112
+
113
+ //#endregion
114
+ //#region src/index.ts
115
+ var src_default = Plugin.define({
116
+ id: "opencode-yee-profile",
117
+ async setup(context) {
118
+ const options = parseOptions(context.options);
119
+ await context.agent.transform((editor) => registerAgents(editor, options));
120
+ }
121
+ });
122
+
123
+ //#endregion
124
+ export { src_default as default };
package/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default } from './dist/index.mjs';
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@yee94/opencode-profile",
3
+ "version": "0.1.0",
4
+ "description": "Build-first OpenCode V2 plugin: small specialist prompts, no orchestration runtime",
5
+ "type": "module",
6
+ "main": "./dist/index.mjs",
7
+ "types": "./dist/index.d.mts",
8
+ "packageManager": "pnpm@10.28.2",
9
+ "engines": {
10
+ "node": ">=24",
11
+ "pnpm": ">=10"
12
+ },
13
+ "exports": {
14
+ ".": "./dist/index.mjs"
15
+ },
16
+ "files": [
17
+ "index.js",
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "sideEffects": false,
23
+ "scripts": {
24
+ "build": "tsdown",
25
+ "dev": "tsdown --watch",
26
+ "type-check": "tsc --noEmit",
27
+ "test": "vitest run",
28
+ "test:watch": "vitest",
29
+ "lint": "biome check .",
30
+ "lint:fix": "biome check --write .",
31
+ "format": "biome format --write .",
32
+ "check": "pnpm lint && pnpm build && pnpm type-check && pnpm test && pnpm smoke",
33
+ "smoke": "node scripts/smoke.mjs",
34
+ "smoke:host": "node scripts/host-smoke.mjs",
35
+ "prepublishOnly": "pnpm check"
36
+ },
37
+ "dependencies": {
38
+ "zod": "^4.1.13"
39
+ },
40
+ "peerDependencies": {
41
+ "@opencode/plugin": "^2.0.12"
42
+ },
43
+ "devDependencies": {
44
+ "@biomejs/biome": "2.3.13",
45
+ "@opencode/client": "2.0.12",
46
+ "@opencode/plugin": "2.0.12",
47
+ "@types/node": "^24.10.1",
48
+ "tsdown": "0.17.2",
49
+ "typescript": "5.9.3",
50
+ "vitest": "4.0.15"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "git+https://github.com/yee94/opencode-yee-profile.git"
58
+ },
59
+ "license": "MIT"
60
+ }