opencode-plan-cards-plugin 0.1.0 → 0.1.2
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/CHANGELOG.md +39 -0
- package/README.en.md +30 -10
- package/README.ja.md +30 -10
- package/README.md +30 -10
- package/README.zh-CN.md +30 -10
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +235 -0
- package/dist/index.js +8 -1
- package/package.json +18 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.1.2] - 2026-02-16
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Open-source community files:
|
|
12
|
+
- `CONTRIBUTING.md`
|
|
13
|
+
- `SECURITY.md`
|
|
14
|
+
- `CODE_OF_CONDUCT.md`
|
|
15
|
+
- GitHub Actions CI workflow (`.github/workflows/ci.yml`) for type-check and build.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Added npm package metadata: `repository`, `homepage`, `bugs`, `author`, `engines`.
|
|
20
|
+
- Replaced placeholder git clone URLs in all README variants.
|
|
21
|
+
- Added `*.tgz` to `.gitignore`.
|
|
22
|
+
- Card mode is now enabled by default for `plan` sessions after plugin installation.
|
|
23
|
+
- `/plan card off` remains available for session-level opt-out.
|
|
24
|
+
- `/plan card on` can re-enable card mode for that session.
|
|
25
|
+
- Updated multilingual README usage examples for default-on behavior.
|
|
26
|
+
- Updated setup CLI completion message to reflect default-on behavior.
|
|
27
|
+
|
|
28
|
+
## [0.1.1] - 2026-02-16
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- CLI setup command for one-command installation:
|
|
33
|
+
- `npx -y opencode-plan-cards-plugin@latest setup`
|
|
34
|
+
- Automatic `opencode.json` update with:
|
|
35
|
+
- `plugin: ["opencode-plan-cards-plugin@0.1.1"]`
|
|
36
|
+
- `agent.ask.hidden = true`
|
|
37
|
+
- Automatic backup creation before writing config.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- Added package binary entry for CLI execution.
|
|
42
|
+
- Updated multilingual README files with one-command setup guide.
|
|
43
|
+
|
|
5
44
|
## [0.1.0] - 2026-02-16
|
|
6
45
|
|
|
7
46
|
### Added
|
package/README.en.md
CHANGED
|
@@ -9,17 +9,37 @@ A plugin that enhances card-based planning interactions for original OpenCode (D
|
|
|
9
9
|
- `/plan card off`
|
|
10
10
|
- When enabled, it injects a stricter `plan` workflow: clarify first, confirm, then output a complete plan.
|
|
11
11
|
- Enhances the `question` tool definition to encourage card questions with 2–3 options and clear tradeoff descriptions.
|
|
12
|
-
-
|
|
12
|
+
- Enabled by default after installation; still controllable per session.
|
|
13
13
|
|
|
14
14
|
## Compatibility
|
|
15
15
|
|
|
16
16
|
- OpenCode: `1.2.x` (Desktop / CLI)
|
|
17
17
|
- Plugin distribution: both `file://` and npm package
|
|
18
|
+
- One-command installer: Node.js `18+`
|
|
18
19
|
|
|
19
|
-
## Installation (Method A:
|
|
20
|
+
## Installation (Method A: npm one-command setup, recommended)
|
|
20
21
|
|
|
21
22
|
```powershell
|
|
22
|
-
|
|
23
|
+
npx -y opencode-plan-cards-plugin@latest setup
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
By default this command:
|
|
27
|
+
|
|
28
|
+
- creates a backup of `~/.config/opencode/opencode.json`
|
|
29
|
+
- writes `plugin: ["opencode-plan-cards-plugin@0.1.2"]`
|
|
30
|
+
- writes `agent.ask.hidden = true`
|
|
31
|
+
|
|
32
|
+
Optional flags:
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
npx -y opencode-plan-cards-plugin@latest setup --plugin opencode-plan-cards-plugin@0.1.2
|
|
36
|
+
npx -y opencode-plan-cards-plugin@latest setup --config "C:\Users\<you>\.config\opencode\opencode.json"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Installation (Method B: Git + file://)
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
git clone https://github.com/SAKURA1175/opencode-plan-cards-plugin.git opencode-plan-cards-plugin
|
|
23
43
|
cd opencode-plan-cards-plugin
|
|
24
44
|
npm install
|
|
25
45
|
npm run build
|
|
@@ -43,7 +63,7 @@ Configure plugin in `~/.config/opencode/opencode.json`:
|
|
|
43
63
|
|
|
44
64
|
> On Windows, use `file:///` paths and encode spaces as `%20`.
|
|
45
65
|
|
|
46
|
-
## Installation (Method
|
|
66
|
+
## Installation (Method C: npm manual config)
|
|
47
67
|
|
|
48
68
|
After publishing, user config:
|
|
49
69
|
|
|
@@ -51,7 +71,7 @@ After publishing, user config:
|
|
|
51
71
|
{
|
|
52
72
|
"$schema": "https://opencode.ai/config.json",
|
|
53
73
|
"plugin": [
|
|
54
|
-
"opencode-plan-cards-plugin@0.1.
|
|
74
|
+
"opencode-plan-cards-plugin@0.1.2"
|
|
55
75
|
],
|
|
56
76
|
"agent": {
|
|
57
77
|
"ask": {
|
|
@@ -63,14 +83,14 @@ After publishing, user config:
|
|
|
63
83
|
|
|
64
84
|
## Usage
|
|
65
85
|
|
|
66
|
-
1.
|
|
67
|
-
2.
|
|
68
|
-
3. To
|
|
86
|
+
1. After install and restart, card mode is enabled by default in `plan` sessions
|
|
87
|
+
2. To disable card mode in the current session, run `/plan card off`
|
|
88
|
+
3. To re-enable card mode in the current session, run `/plan card on`
|
|
69
89
|
|
|
70
90
|
## Validation Checklist
|
|
71
91
|
|
|
72
|
-
1. Desktop: card interaction appears
|
|
73
|
-
2. CLI: same
|
|
92
|
+
1. Desktop: card interaction appears by default in `plan` sessions
|
|
93
|
+
2. CLI: same default behavior works
|
|
74
94
|
3. `/plan card off` restores default `plan` behavior
|
|
75
95
|
4. `agent.ask.hidden=true` hides ask in UI by default
|
|
76
96
|
|
package/README.ja.md
CHANGED
|
@@ -9,17 +9,37 @@
|
|
|
9
9
|
- `/plan card off`
|
|
10
10
|
- 有効化時、`plan` セッションにのみ「要件確認 → 最終確認 → 完全な実行計画出力」の制約を注入。
|
|
11
11
|
- `question` ツール定義を強化し、2〜3択 + トレードオフ説明のカード質問を促進。
|
|
12
|
-
-
|
|
12
|
+
- インストール後はデフォルトで有効。セッションごとに切り替え可能。
|
|
13
13
|
|
|
14
14
|
## 互換性
|
|
15
15
|
|
|
16
16
|
- OpenCode: `1.2.x`(Desktop / CLI)
|
|
17
17
|
- プラグイン配布形態:`file://` と npm の両対応
|
|
18
|
+
- ワンコマンド設定: Node.js `18+`
|
|
18
19
|
|
|
19
|
-
## インストール(方式 A:
|
|
20
|
+
## インストール(方式 A:npm ワンコマンド設定、推奨)
|
|
20
21
|
|
|
21
22
|
```powershell
|
|
22
|
-
|
|
23
|
+
npx -y opencode-plan-cards-plugin@latest setup
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
このコマンドは自動で以下を実行します:
|
|
27
|
+
|
|
28
|
+
- `~/.config/opencode/opencode.json` のバックアップ作成
|
|
29
|
+
- `plugin: ["opencode-plan-cards-plugin@0.1.2"]` を設定
|
|
30
|
+
- `agent.ask.hidden = true` を設定
|
|
31
|
+
|
|
32
|
+
オプション:
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
npx -y opencode-plan-cards-plugin@latest setup --plugin opencode-plan-cards-plugin@0.1.2
|
|
36
|
+
npx -y opencode-plan-cards-plugin@latest setup --config "C:\Users\<you>\.config\opencode\opencode.json"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## インストール(方式 B:Git + file://)
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
git clone https://github.com/SAKURA1175/opencode-plan-cards-plugin.git opencode-plan-cards-plugin
|
|
23
43
|
cd opencode-plan-cards-plugin
|
|
24
44
|
npm install
|
|
25
45
|
npm run build
|
|
@@ -43,7 +63,7 @@ npm run build
|
|
|
43
63
|
|
|
44
64
|
> Windows では `file:///` 形式を使用し、空白は `%20` にしてください。
|
|
45
65
|
|
|
46
|
-
## インストール(方式
|
|
66
|
+
## インストール(方式 C:npm 手動設定)
|
|
47
67
|
|
|
48
68
|
公開後、ユーザー設定:
|
|
49
69
|
|
|
@@ -51,7 +71,7 @@ npm run build
|
|
|
51
71
|
{
|
|
52
72
|
"$schema": "https://opencode.ai/config.json",
|
|
53
73
|
"plugin": [
|
|
54
|
-
"opencode-plan-cards-plugin@0.1.
|
|
74
|
+
"opencode-plan-cards-plugin@0.1.2"
|
|
55
75
|
],
|
|
56
76
|
"agent": {
|
|
57
77
|
"ask": {
|
|
@@ -63,14 +83,14 @@ npm run build
|
|
|
63
83
|
|
|
64
84
|
## 使い方
|
|
65
85
|
|
|
66
|
-
1.
|
|
67
|
-
2.
|
|
68
|
-
3.
|
|
86
|
+
1. インストール後に再起動すると、`plan` セッションではカードモードがデフォルトで有効
|
|
87
|
+
2. 現在のセッションでカードモードを無効化する場合は `/plan card off`
|
|
88
|
+
3. 現在のセッションでカードモードを再有効化する場合は `/plan card on`
|
|
69
89
|
|
|
70
90
|
## 動作確認チェックリスト
|
|
71
91
|
|
|
72
|
-
1. Desktop
|
|
73
|
-
2. CLI
|
|
92
|
+
1. Desktop:`plan` セッションでデフォルトでカード質問フローが表示される
|
|
93
|
+
2. CLI:同様にデフォルトで有効
|
|
74
94
|
3. `/plan card off` 後に標準 `plan` 挙動へ復帰
|
|
75
95
|
4. `agent.ask.hidden=true` で UI の ask を非表示化
|
|
76
96
|
|
package/README.md
CHANGED
|
@@ -14,17 +14,37 @@ Language / 语言 / 言語:
|
|
|
14
14
|
- `/plan card off`
|
|
15
15
|
- 开启后仅在 `plan` 会话注入“先澄清、再确认、再输出完整计划”的系统约束。
|
|
16
16
|
- 强化 `question` 工具描述,推动 2–3 选项 + 权衡说明的卡片提问格式。
|
|
17
|
-
-
|
|
17
|
+
- 安装后默认自动开启卡片模式,可按会话临时关闭。
|
|
18
18
|
|
|
19
19
|
## 兼容性
|
|
20
20
|
|
|
21
21
|
- OpenCode: `1.2.x`(桌面端 / CLI)
|
|
22
22
|
- 插件形态:`file://` 与 npm 包均可
|
|
23
|
+
- 一键安装器:Node.js `18+`
|
|
23
24
|
|
|
24
|
-
## 安装(方式 A:
|
|
25
|
+
## 安装(方式 A:npm 一键写配置,推荐)
|
|
25
26
|
|
|
26
27
|
```powershell
|
|
27
|
-
|
|
28
|
+
npx -y opencode-plan-cards-plugin@latest setup
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
默认会自动:
|
|
32
|
+
|
|
33
|
+
- 备份 `~/.config/opencode/opencode.json`
|
|
34
|
+
- 写入 `plugin: ["opencode-plan-cards-plugin@0.1.2"]`
|
|
35
|
+
- 写入 `agent.ask.hidden = true`
|
|
36
|
+
|
|
37
|
+
可选参数:
|
|
38
|
+
|
|
39
|
+
```powershell
|
|
40
|
+
npx -y opencode-plan-cards-plugin@latest setup --plugin opencode-plan-cards-plugin@0.1.2
|
|
41
|
+
npx -y opencode-plan-cards-plugin@latest setup --config "C:\Users\<you>\.config\opencode\opencode.json"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 安装(方式 B:Git + file://)
|
|
45
|
+
|
|
46
|
+
```powershell
|
|
47
|
+
git clone https://github.com/SAKURA1175/opencode-plan-cards-plugin.git opencode-plan-cards-plugin
|
|
28
48
|
cd opencode-plan-cards-plugin
|
|
29
49
|
npm install
|
|
30
50
|
npm run build
|
|
@@ -48,7 +68,7 @@ npm run build
|
|
|
48
68
|
|
|
49
69
|
> Windows 路径需要使用 `file:///`,空格写成 `%20`。
|
|
50
70
|
|
|
51
|
-
## 安装(方式
|
|
71
|
+
## 安装(方式 C:npm 手动配置)
|
|
52
72
|
|
|
53
73
|
发布后,用户配置:
|
|
54
74
|
|
|
@@ -56,7 +76,7 @@ npm run build
|
|
|
56
76
|
{
|
|
57
77
|
"$schema": "https://opencode.ai/config.json",
|
|
58
78
|
"plugin": [
|
|
59
|
-
"opencode-plan-cards-plugin@0.1.
|
|
79
|
+
"opencode-plan-cards-plugin@0.1.2"
|
|
60
80
|
],
|
|
61
81
|
"agent": {
|
|
62
82
|
"ask": {
|
|
@@ -68,14 +88,14 @@ npm run build
|
|
|
68
88
|
|
|
69
89
|
## 使用
|
|
70
90
|
|
|
71
|
-
1.
|
|
72
|
-
2.
|
|
73
|
-
3.
|
|
91
|
+
1. 安装并重启后,在 `plan` 会话中默认启用卡片澄清与确认流程
|
|
92
|
+
2. 需要关闭当前会话卡片模式时输入:`/plan card off`
|
|
93
|
+
3. 需要重新开启当前会话卡片模式时输入:`/plan card on`
|
|
74
94
|
|
|
75
95
|
## 验证清单
|
|
76
96
|
|
|
77
|
-
1.
|
|
78
|
-
2. CLI
|
|
97
|
+
1. 桌面端:进入 `plan` 会话后默认出现卡片问答流程
|
|
98
|
+
2. CLI:同样默认生效
|
|
79
99
|
3. `/plan card off` 后恢复原始 `plan` 行为
|
|
80
100
|
4. `agent.ask.hidden=true` 后 UI 默认不展示 ask
|
|
81
101
|
|
package/README.zh-CN.md
CHANGED
|
@@ -9,17 +9,37 @@
|
|
|
9
9
|
- `/plan card off`
|
|
10
10
|
- 开启后仅在 `plan` 会话注入“先澄清、再确认、再输出完整计划”的系统约束。
|
|
11
11
|
- 强化 `question` 工具描述,推动 2–3 选项 + 权衡说明的卡片提问格式。
|
|
12
|
-
-
|
|
12
|
+
- 安装后默认自动开启卡片模式,可按会话临时关闭。
|
|
13
13
|
|
|
14
14
|
## 兼容性
|
|
15
15
|
|
|
16
16
|
- OpenCode: `1.2.x`(桌面端 / CLI)
|
|
17
17
|
- 插件形态:`file://` 与 npm 包均可
|
|
18
|
+
- 一键安装器:Node.js `18+`
|
|
18
19
|
|
|
19
|
-
## 安装(方式 A:
|
|
20
|
+
## 安装(方式 A:npm 一键写配置,推荐)
|
|
20
21
|
|
|
21
22
|
```powershell
|
|
22
|
-
|
|
23
|
+
npx -y opencode-plan-cards-plugin@latest setup
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
默认会自动:
|
|
27
|
+
|
|
28
|
+
- 备份 `~/.config/opencode/opencode.json`
|
|
29
|
+
- 写入 `plugin: ["opencode-plan-cards-plugin@0.1.2"]`
|
|
30
|
+
- 写入 `agent.ask.hidden = true`
|
|
31
|
+
|
|
32
|
+
可选参数:
|
|
33
|
+
|
|
34
|
+
```powershell
|
|
35
|
+
npx -y opencode-plan-cards-plugin@latest setup --plugin opencode-plan-cards-plugin@0.1.2
|
|
36
|
+
npx -y opencode-plan-cards-plugin@latest setup --config "C:\Users\<you>\.config\opencode\opencode.json"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 安装(方式 B:Git + file://)
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
git clone https://github.com/SAKURA1175/opencode-plan-cards-plugin.git opencode-plan-cards-plugin
|
|
23
43
|
cd opencode-plan-cards-plugin
|
|
24
44
|
npm install
|
|
25
45
|
npm run build
|
|
@@ -43,7 +63,7 @@ npm run build
|
|
|
43
63
|
|
|
44
64
|
> Windows 路径需要使用 `file:///`,空格写成 `%20`。
|
|
45
65
|
|
|
46
|
-
## 安装(方式
|
|
66
|
+
## 安装(方式 C:npm 手动配置)
|
|
47
67
|
|
|
48
68
|
发布后,用户配置:
|
|
49
69
|
|
|
@@ -51,7 +71,7 @@ npm run build
|
|
|
51
71
|
{
|
|
52
72
|
"$schema": "https://opencode.ai/config.json",
|
|
53
73
|
"plugin": [
|
|
54
|
-
"opencode-plan-cards-plugin@0.1.
|
|
74
|
+
"opencode-plan-cards-plugin@0.1.2"
|
|
55
75
|
],
|
|
56
76
|
"agent": {
|
|
57
77
|
"ask": {
|
|
@@ -63,14 +83,14 @@ npm run build
|
|
|
63
83
|
|
|
64
84
|
## 使用
|
|
65
85
|
|
|
66
|
-
1.
|
|
67
|
-
2.
|
|
68
|
-
3.
|
|
86
|
+
1. 安装并重启后,在 `plan` 会话中默认启用卡片澄清与确认流程
|
|
87
|
+
2. 需要关闭当前会话卡片模式时输入:`/plan card off`
|
|
88
|
+
3. 需要重新开启当前会话卡片模式时输入:`/plan card on`
|
|
69
89
|
|
|
70
90
|
## 验证清单
|
|
71
91
|
|
|
72
|
-
1.
|
|
73
|
-
2. CLI
|
|
92
|
+
1. 桌面端:进入 `plan` 会话后默认出现卡片问答流程
|
|
93
|
+
2. CLI:同样默认生效
|
|
74
94
|
3. `/plan card off` 后恢复原始 `plan` 行为
|
|
75
95
|
4. `agent.ask.hidden=true` 后 UI 默认不显示 ask
|
|
76
96
|
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
const pkg = require("../package.json");
|
|
8
|
+
function usage() {
|
|
9
|
+
const defaultPlugin = `${pkg.name ?? "opencode-plan-cards-plugin"}@${pkg.version ?? "latest"}`;
|
|
10
|
+
return [
|
|
11
|
+
"Usage:",
|
|
12
|
+
" opencode-plan-cards-plugin setup [options]",
|
|
13
|
+
"",
|
|
14
|
+
"Options:",
|
|
15
|
+
" --plugin <spec> Plugin spec to inject (default: current package version)",
|
|
16
|
+
" --config <path> Path to opencode.json",
|
|
17
|
+
" --dry-run Preview changes without writing files",
|
|
18
|
+
" --no-backup Skip backup file creation",
|
|
19
|
+
" -h, --help Show help",
|
|
20
|
+
"",
|
|
21
|
+
"Example:",
|
|
22
|
+
` npx -y ${pkg.name ?? "opencode-plan-cards-plugin"}@latest setup`,
|
|
23
|
+
` npx -y ${pkg.name ?? "opencode-plan-cards-plugin"}@latest setup --plugin ${defaultPlugin}`,
|
|
24
|
+
].join("\n");
|
|
25
|
+
}
|
|
26
|
+
function parseArgs(argv) {
|
|
27
|
+
const options = {
|
|
28
|
+
dryRun: false,
|
|
29
|
+
noBackup: false,
|
|
30
|
+
help: false,
|
|
31
|
+
};
|
|
32
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
33
|
+
const arg = argv[index];
|
|
34
|
+
if (arg === "-h" || arg === "--help") {
|
|
35
|
+
options.help = true;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (arg === "--dry-run") {
|
|
39
|
+
options.dryRun = true;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (arg === "--no-backup") {
|
|
43
|
+
options.noBackup = true;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (arg === "--plugin") {
|
|
47
|
+
const value = argv[index + 1];
|
|
48
|
+
if (!value)
|
|
49
|
+
throw new Error("Missing value for --plugin");
|
|
50
|
+
options.plugin = value.trim();
|
|
51
|
+
index += 1;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (arg.startsWith("--plugin=")) {
|
|
55
|
+
options.plugin = arg.slice("--plugin=".length).trim();
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (arg === "--config") {
|
|
59
|
+
const value = argv[index + 1];
|
|
60
|
+
if (!value)
|
|
61
|
+
throw new Error("Missing value for --config");
|
|
62
|
+
options.config = value.trim();
|
|
63
|
+
index += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (arg.startsWith("--config=")) {
|
|
67
|
+
options.config = arg.slice("--config=".length).trim();
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!options.command && !arg.startsWith("-")) {
|
|
71
|
+
options.command = arg;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`Unknown argument: ${arg}`);
|
|
75
|
+
}
|
|
76
|
+
return options;
|
|
77
|
+
}
|
|
78
|
+
function resolveConfigPath(configOverride) {
|
|
79
|
+
if (configOverride && configOverride.trim()) {
|
|
80
|
+
return resolve(configOverride.trim());
|
|
81
|
+
}
|
|
82
|
+
const configRoot = process.env.XDG_CONFIG_HOME?.trim() || join(homedir(), ".config");
|
|
83
|
+
return join(configRoot, "opencode", "opencode.json");
|
|
84
|
+
}
|
|
85
|
+
function readJSONFile(filePath) {
|
|
86
|
+
if (!existsSync(filePath))
|
|
87
|
+
return {};
|
|
88
|
+
const raw = readFileSync(filePath, "utf8");
|
|
89
|
+
const normalized = raw.replace(/^\uFEFF/, "");
|
|
90
|
+
if (!normalized.trim())
|
|
91
|
+
return {};
|
|
92
|
+
let parsed;
|
|
93
|
+
try {
|
|
94
|
+
parsed = JSON.parse(normalized);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
throw new Error(`Invalid JSON in config file: ${filePath}`);
|
|
98
|
+
}
|
|
99
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
100
|
+
throw new Error(`Config root must be a JSON object: ${filePath}`);
|
|
101
|
+
}
|
|
102
|
+
return parsed;
|
|
103
|
+
}
|
|
104
|
+
function extractPackageName(spec) {
|
|
105
|
+
const trimmed = spec.trim();
|
|
106
|
+
const match = /^(@[^/\s]+\/[^@\s/]+|[^@\s/]+)(?:@.+)?$/.exec(trimmed);
|
|
107
|
+
return match?.[1];
|
|
108
|
+
}
|
|
109
|
+
function isSamePlugin(existing, targetSpec) {
|
|
110
|
+
if (existing === targetSpec)
|
|
111
|
+
return true;
|
|
112
|
+
const targetName = extractPackageName(targetSpec);
|
|
113
|
+
if (!targetName)
|
|
114
|
+
return false;
|
|
115
|
+
const existingName = extractPackageName(existing);
|
|
116
|
+
return !!existingName && existingName === targetName;
|
|
117
|
+
}
|
|
118
|
+
function upsertPlugin(config, pluginSpec) {
|
|
119
|
+
const current = config.plugin;
|
|
120
|
+
if (current !== undefined &&
|
|
121
|
+
typeof current !== "string" &&
|
|
122
|
+
!Array.isArray(current)) {
|
|
123
|
+
throw new Error('Config key "plugin" must be a string or an array');
|
|
124
|
+
}
|
|
125
|
+
const pluginList = Array.isArray(current)
|
|
126
|
+
? [...current]
|
|
127
|
+
: typeof current === "string"
|
|
128
|
+
? [current]
|
|
129
|
+
: [];
|
|
130
|
+
let matched = false;
|
|
131
|
+
let changed = !Array.isArray(current);
|
|
132
|
+
for (let index = 0; index < pluginList.length; index += 1) {
|
|
133
|
+
const value = pluginList[index];
|
|
134
|
+
if (typeof value !== "string")
|
|
135
|
+
continue;
|
|
136
|
+
if (!isSamePlugin(value, pluginSpec))
|
|
137
|
+
continue;
|
|
138
|
+
matched = true;
|
|
139
|
+
if (value !== pluginSpec) {
|
|
140
|
+
pluginList[index] = pluginSpec;
|
|
141
|
+
changed = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (!matched) {
|
|
145
|
+
pluginList.push(pluginSpec);
|
|
146
|
+
changed = true;
|
|
147
|
+
}
|
|
148
|
+
config.plugin = pluginList;
|
|
149
|
+
return changed;
|
|
150
|
+
}
|
|
151
|
+
function ensureObject(parent, key) {
|
|
152
|
+
const value = parent[key];
|
|
153
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
const next = {};
|
|
157
|
+
parent[key] = next;
|
|
158
|
+
return next;
|
|
159
|
+
}
|
|
160
|
+
function updateAskHidden(config) {
|
|
161
|
+
const agent = ensureObject(config, "agent");
|
|
162
|
+
const ask = ensureObject(agent, "ask");
|
|
163
|
+
if (ask.hidden === true)
|
|
164
|
+
return false;
|
|
165
|
+
ask.hidden = true;
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
function applySetup(config, pluginSpec) {
|
|
169
|
+
const pluginUpdated = upsertPlugin(config, pluginSpec);
|
|
170
|
+
const askHiddenUpdated = updateAskHidden(config);
|
|
171
|
+
return {
|
|
172
|
+
changed: pluginUpdated || askHiddenUpdated,
|
|
173
|
+
pluginUpdated,
|
|
174
|
+
askHiddenUpdated,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function backupPath(configPath) {
|
|
178
|
+
const stamp = new Date().toISOString().replace(/\.\d{3}Z$/, "Z").replace(/[:]/g, "-");
|
|
179
|
+
return `${configPath}.bak-${stamp}`;
|
|
180
|
+
}
|
|
181
|
+
function writeConfig(configPath, config, createBackup) {
|
|
182
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
183
|
+
let savedBackup;
|
|
184
|
+
if (createBackup && existsSync(configPath)) {
|
|
185
|
+
savedBackup = backupPath(configPath);
|
|
186
|
+
copyFileSync(configPath, savedBackup);
|
|
187
|
+
}
|
|
188
|
+
writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`, "utf8");
|
|
189
|
+
return savedBackup;
|
|
190
|
+
}
|
|
191
|
+
function run() {
|
|
192
|
+
const options = parseArgs(process.argv.slice(2));
|
|
193
|
+
if (options.help || !options.command) {
|
|
194
|
+
console.log(usage());
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (options.command !== "setup") {
|
|
198
|
+
throw new Error(`Unknown command: ${options.command}`);
|
|
199
|
+
}
|
|
200
|
+
const packageName = pkg.name ?? "opencode-plan-cards-plugin";
|
|
201
|
+
const packageVersion = pkg.version ?? "latest";
|
|
202
|
+
const pluginSpec = options.plugin?.trim() || `${packageName}@${packageVersion}`;
|
|
203
|
+
const configPath = resolveConfigPath(options.config);
|
|
204
|
+
const config = readJSONFile(configPath);
|
|
205
|
+
const result = applySetup(config, pluginSpec);
|
|
206
|
+
if (!result.changed) {
|
|
207
|
+
console.log(`No changes needed: ${configPath}`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
if (options.dryRun) {
|
|
211
|
+
console.log(`[dry-run] Config file: ${configPath}`);
|
|
212
|
+
console.log(`[dry-run] plugin updated: ${result.pluginUpdated}`);
|
|
213
|
+
console.log(`[dry-run] ask.hidden updated: ${result.askHiddenUpdated}`);
|
|
214
|
+
console.log(JSON.stringify(config, null, 2));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const savedBackup = writeConfig(configPath, config, !options.noBackup);
|
|
218
|
+
console.log(`Updated: ${configPath}`);
|
|
219
|
+
if (savedBackup) {
|
|
220
|
+
console.log(`Backup: ${savedBackup}`);
|
|
221
|
+
}
|
|
222
|
+
console.log(`Plugin: ${pluginSpec}`);
|
|
223
|
+
console.log("Done. Restart OpenCode. Card mode is enabled by default in plan sessions.");
|
|
224
|
+
console.log("Use /plan card off to disable it for the current session.");
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
run();
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
231
|
+
console.error(`Error: ${message}`);
|
|
232
|
+
console.error("");
|
|
233
|
+
console.error(usage());
|
|
234
|
+
process.exitCode = 1;
|
|
235
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const CARD_COMMAND_PATTERN = /^\/plan\s+card\s+(on|off)$/i;
|
|
2
|
+
const DEFAULT_CARD_MODE = true;
|
|
2
3
|
const cardModeBySession = new Map();
|
|
3
4
|
const lastAgentBySession = new Map();
|
|
4
5
|
const PLAN_CARD_SYSTEM_APPENDIX = `
|
|
@@ -58,6 +59,12 @@ function appendUniqueDescription(base, appendix) {
|
|
|
58
59
|
return normalized;
|
|
59
60
|
return `${base.trim()}\n\n${normalized}`;
|
|
60
61
|
}
|
|
62
|
+
function isCardModeEnabled(sessionID) {
|
|
63
|
+
const mode = cardModeBySession.get(sessionID);
|
|
64
|
+
if (mode === undefined)
|
|
65
|
+
return DEFAULT_CARD_MODE;
|
|
66
|
+
return mode;
|
|
67
|
+
}
|
|
61
68
|
function patchQuestionParameters(parameters) {
|
|
62
69
|
const questionItem = parameters?.properties?.questions?.items;
|
|
63
70
|
const questionProps = questionItem?.properties;
|
|
@@ -98,7 +105,7 @@ export const PlanCardsPlugin = async () => {
|
|
|
98
105
|
"experimental.chat.system.transform": async (input, output) => {
|
|
99
106
|
if (!input.sessionID)
|
|
100
107
|
return;
|
|
101
|
-
if (!
|
|
108
|
+
if (!isCardModeEnabled(input.sessionID))
|
|
102
109
|
return;
|
|
103
110
|
if (lastAgentBySession.get(input.sessionID) !== "plan")
|
|
104
111
|
return;
|
package/package.json
CHANGED
|
@@ -1,9 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-plan-cards-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Plan card interaction enhancement plugin for OpenCode",
|
|
5
|
+
"author": "sakura1175",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/SAKURA1175/opencode-plan-cards-plugin.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/SAKURA1175/opencode-plan-cards-plugin#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/SAKURA1175/opencode-plan-cards-plugin/issues"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18"
|
|
17
|
+
},
|
|
5
18
|
"type": "module",
|
|
6
19
|
"main": "dist/index.js",
|
|
20
|
+
"bin": {
|
|
21
|
+
"opencode-plan-cards-plugin": "dist/cli.js"
|
|
22
|
+
},
|
|
7
23
|
"types": "dist/index.d.ts",
|
|
8
24
|
"exports": {
|
|
9
25
|
".": {
|
|
@@ -26,14 +42,13 @@
|
|
|
26
42
|
"plan",
|
|
27
43
|
"cards"
|
|
28
44
|
],
|
|
29
|
-
"author": "",
|
|
30
|
-
"license": "MIT",
|
|
31
45
|
"peerDependencies": {
|
|
32
46
|
"@opencode-ai/plugin": ">=1.2.0 <2"
|
|
33
47
|
},
|
|
34
48
|
"devDependencies": {
|
|
35
49
|
"@opencode-ai/plugin": "^1.2.0",
|
|
36
50
|
"@opencode-ai/sdk": "^1.2.0",
|
|
51
|
+
"@types/node": "^22.13.10",
|
|
37
52
|
"typescript": "^5.7.3"
|
|
38
53
|
}
|
|
39
54
|
}
|