paintress 0.2.3 → 0.3.1
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 +25 -6
- package/README.zh-CN.md +25 -6
- package/dist/cli.js +105 -30
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -84,8 +84,10 @@ Canvas navigation: wheel zooms at the pointer, space / middle button / empty are
|
|
|
84
84
|
| Claude Desktop | `~/.config/Claude/claude_desktop_config.json` | `mcpServers` |
|
|
85
85
|
| Cursor | `~/.cursor/mcp.json` | `mcpServers` |
|
|
86
86
|
| VS Code | `~/.config/Code/User/mcp.json` | `servers` (with `"type": "stdio"`) |
|
|
87
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `mcpServers` |
|
|
87
88
|
| Codex | `~/.codex/config.toml` | `[mcp_servers.paintress]` |
|
|
88
89
|
| pi | `~/.pi/agent/mcp.json` | `mcpServers` |
|
|
90
|
+
| OpenCode | `~/.config/opencode/opencode.json` | `mcp.servers` (current) or `mcp` (older; `command` is an array) |
|
|
89
91
|
|
|
90
92
|
```bash
|
|
91
93
|
paintress mcp-config cursor # print the exact snippet instead of editing files
|
|
@@ -126,9 +128,15 @@ You are an agent asked to install paintress on this machine. Work through the st
|
|
|
126
128
|
Rules:
|
|
127
129
|
|
|
128
130
|
- **Any hit means reuse.** Do not install again; go to step 2.
|
|
129
|
-
- Report the resolved path and version
|
|
131
|
+
- Report the resolved path and version: `paintress --version` prints the package version (or `npm ls -g --depth=0 paintress`).
|
|
130
132
|
- Only when every check is empty do you install (step 1).
|
|
131
133
|
|
|
134
|
+
If the install succeeded but `command -v paintress` still finds nothing (some version managers need a new shell), call it by full path — do not install a second copy:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
"$(npm prefix -g)/bin/paintress" doctor
|
|
138
|
+
```
|
|
139
|
+
|
|
132
140
|
### 1. Install (only if step 0 found nothing)
|
|
133
141
|
|
|
134
142
|
```bash
|
|
@@ -152,7 +160,9 @@ paintress install --dry-run # preview the writes
|
|
|
152
160
|
paintress install <client-id> # write only the client you are running in
|
|
153
161
|
```
|
|
154
162
|
|
|
155
|
-
Client ids: `claude`, `cursor`, `vscode`, `codex`, `pi`. Use `paintress install` without arguments to cover every detected client.
|
|
163
|
+
Client ids: `claude`, `cursor`, `vscode`, `windsurf`, `codex`, `pi`, `opencode`. Use `paintress install` without arguments to cover every detected client.
|
|
164
|
+
|
|
165
|
+
OpenCode has two config layouts in the wild. `install` follows whatever the existing file already uses and falls back to the current `mcp.servers` shape for a new file; force it with `--opencode-layout legacy` or `--opencode-layout v2`.
|
|
156
166
|
|
|
157
167
|
What the write does:
|
|
158
168
|
|
|
@@ -162,14 +172,23 @@ What the write does:
|
|
|
162
172
|
- is idempotent: an identical entry reports `noop` and nothing is written;
|
|
163
173
|
- uses the bare command `paintress` when it resolves on PATH, otherwise the absolute path of the binary.
|
|
164
174
|
|
|
165
|
-
If
|
|
175
|
+
### If your client is not in that list
|
|
176
|
+
|
|
177
|
+
The entry is small and nearly the same everywhere, so adapt it by hand:
|
|
178
|
+
|
|
179
|
+
1. Find where the client keeps its MCP servers — its own docs, an `/mcp` command, or a "configure MCP servers" menu item.
|
|
180
|
+
2. Match the shape. Most clients use a `mcpServers` object holding `command` + `args`; VS Code uses `servers` with `"type": "stdio"`; OpenCode puts a single `command` **array** under `mcp.servers` (older builds: under `mcp`) with `"type": "local"`; Codex uses a TOML table.
|
|
181
|
+
3. Print the closest snippet and edit it:
|
|
166
182
|
|
|
167
183
|
```bash
|
|
168
|
-
paintress mcp-config cursor
|
|
169
|
-
paintress mcp-config vscode
|
|
170
|
-
paintress mcp-config
|
|
184
|
+
paintress mcp-config cursor # JSON with mcpServers
|
|
185
|
+
paintress mcp-config vscode # JSON with servers + type: stdio
|
|
186
|
+
paintress mcp-config opencode # JSON with mcp.servers + command array
|
|
187
|
+
paintress mcp-config codex # TOML table
|
|
171
188
|
```
|
|
172
189
|
|
|
190
|
+
To make a client first-class (so `doctor` and `install` cover it), add one spec to `src/integrations/clients.ts` — `id`, `label`, `format`, `rootPath`, optional `typeValue` / `commandForm` / `extraFields`, and `configPath(home, platform, env)` — plus one test in `test/integrations.spec.ts`. No other file needs to change.
|
|
191
|
+
|
|
173
192
|
### 3. Install the skill (recommended)
|
|
174
193
|
|
|
175
194
|
```bash
|
package/README.zh-CN.md
CHANGED
|
@@ -84,8 +84,10 @@ paintress watch demo ./demo
|
|
|
84
84
|
| Claude Desktop | `~/.config/Claude/claude_desktop_config.json` | `mcpServers` |
|
|
85
85
|
| Cursor | `~/.cursor/mcp.json` | `mcpServers` |
|
|
86
86
|
| VS Code | `~/.config/Code/User/mcp.json` | `servers`(条目需 `"type": "stdio"`) |
|
|
87
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `mcpServers` |
|
|
87
88
|
| Codex | `~/.codex/config.toml` | `[mcp_servers.paintress]` |
|
|
88
89
|
| pi | `~/.pi/agent/mcp.json` | `mcpServers` |
|
|
90
|
+
| OpenCode | `~/.config/opencode/opencode.json` | `mcp.servers`(当前版)或 `mcp`(旧版;`command` 是数组) |
|
|
89
91
|
|
|
90
92
|
```bash
|
|
91
93
|
paintress mcp-config cursor # 只打印片段,不改文件
|
|
@@ -126,9 +128,15 @@ MIT
|
|
|
126
128
|
规则:
|
|
127
129
|
|
|
128
130
|
- **命中任意一项就复用**,不要重装,直接进入第 2 步。
|
|
129
|
-
-
|
|
131
|
+
- 向用户报告解析到的路径与版本:`paintress --version` 打印包版本(或用 `npm ls -g --depth=0 paintress`)。
|
|
130
132
|
- 只有在全部检查都为空时,才执行第 1 步。
|
|
131
133
|
|
|
134
|
+
如果安装成功但 `command -v paintress` 仍然找不到(某些版本管理器需要新开 shell),用完整路径调用,**不要因此再装一份**:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
"$(npm prefix -g)/bin/paintress" doctor
|
|
138
|
+
```
|
|
139
|
+
|
|
132
140
|
### 1. 安装(仅在检测全空时)
|
|
133
141
|
|
|
134
142
|
```bash
|
|
@@ -152,7 +160,9 @@ paintress install --dry-run # 预览将要写入的内容
|
|
|
152
160
|
paintress install <client-id> # 只写当前所在的客户端
|
|
153
161
|
```
|
|
154
162
|
|
|
155
|
-
客户端 id:`claude`、`cursor`、`vscode`、`codex`、`pi`。不带参数执行 `paintress install` 会覆盖所有检测到的客户端。
|
|
163
|
+
客户端 id:`claude`、`cursor`、`vscode`、`windsurf`、`codex`、`pi`、`opencode`。不带参数执行 `paintress install` 会覆盖所有检测到的客户端。
|
|
164
|
+
|
|
165
|
+
OpenCode 现在有两套配置布局:`install` 会跟随文件里既有的布局,新文件按官方当前的 `mcp.servers`;需要强制时用 `--opencode-layout legacy` 或 `--opencode-layout v2`。
|
|
156
166
|
|
|
157
167
|
写入行为:
|
|
158
168
|
|
|
@@ -162,14 +172,23 @@ paintress install <client-id> # 只写当前所在的客户端
|
|
|
162
172
|
- 幂等:条目已一致时返回 `noop`,不写磁盘;
|
|
163
173
|
- 当 `paintress` 能在 PATH 上解析时写裸命令,否则写可执行文件的绝对路径。
|
|
164
174
|
|
|
165
|
-
如果当前 agent
|
|
175
|
+
### 如果当前 agent 不在列表里
|
|
176
|
+
|
|
177
|
+
条目很小,各家格式几乎一致,直接照抄改写即可:
|
|
178
|
+
|
|
179
|
+
1. 先找到该客户端放 MCP server 的位置——查它自己的文档、`/mcp` 命令,或「配置 MCP 服务器」菜单项。
|
|
180
|
+
2. 对照格式:多数是 `mcpServers` 对象,里面 `command` + `args`;VS Code 是 `servers` 加 `"type": "stdio"`;OpenCode 的 `command` 是**数组**,放在 `mcp.servers` 下(旧版放 `mcp` 下)并带 `"type": "local"`;Codex 是 TOML 表。
|
|
181
|
+
3. 打印最接近的片段再改:
|
|
166
182
|
|
|
167
183
|
```bash
|
|
168
|
-
paintress mcp-config cursor
|
|
169
|
-
paintress mcp-config vscode
|
|
170
|
-
paintress mcp-config
|
|
184
|
+
paintress mcp-config cursor # JSON,顶层 mcpServers
|
|
185
|
+
paintress mcp-config vscode # JSON,顶层 servers + type: stdio
|
|
186
|
+
paintress mcp-config opencode # JSON,mcp.servers + command 数组
|
|
187
|
+
paintress mcp-config codex # TOML 表
|
|
171
188
|
```
|
|
172
189
|
|
|
190
|
+
想让某个客户端成为内置支持(`doctor`、`install` 都能覆盖),只需在 `src/integrations/clients.ts` 里加一条配置:`id`、`label`、`format`、`rootPath`,以及可选的 `typeValue` / `commandForm` / `extraFields` 和 `configPath(home, platform, env)`,再在 `test/integrations.spec.ts` 加一个测试。其他文件都不用动。
|
|
191
|
+
|
|
173
192
|
### 3. 安装 skill(建议)
|
|
174
193
|
|
|
175
194
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -859,8 +859,7 @@ const CLIENTS = [
|
|
|
859
859
|
id: "claude",
|
|
860
860
|
label: "Claude Desktop",
|
|
861
861
|
format: "json",
|
|
862
|
-
|
|
863
|
-
needsType: false,
|
|
862
|
+
rootPath: ["mcpServers"],
|
|
864
863
|
configPath: (home, platform, env) => {
|
|
865
864
|
if (platform === "darwin") return `${posixHome(home)}/Library/Application Support/Claude/claude_desktop_config.json`;
|
|
866
865
|
if (platform === "win32") return `${env["APPDATA"] ?? posixHome(home)}/Claude/claude_desktop_config.json`;
|
|
@@ -871,37 +870,54 @@ const CLIENTS = [
|
|
|
871
870
|
id: "cursor",
|
|
872
871
|
label: "Cursor",
|
|
873
872
|
format: "json",
|
|
874
|
-
|
|
875
|
-
needsType: false,
|
|
873
|
+
rootPath: ["mcpServers"],
|
|
876
874
|
configPath: (home) => `${posixHome(home)}/.cursor/mcp.json`
|
|
877
875
|
},
|
|
878
876
|
{
|
|
879
877
|
id: "vscode",
|
|
880
878
|
label: "VS Code",
|
|
881
879
|
format: "json",
|
|
882
|
-
|
|
883
|
-
|
|
880
|
+
rootPath: ["servers"],
|
|
881
|
+
typeValue: "stdio",
|
|
884
882
|
configPath: (home, platform, env) => {
|
|
885
883
|
if (platform === "darwin") return `${posixHome(home)}/Library/Application Support/Code/User/mcp.json`;
|
|
886
884
|
if (platform === "win32") return `${env["APPDATA"] ?? posixHome(home)}/Code/User/mcp.json`;
|
|
887
885
|
return `${posixHome(home)}/.config/Code/User/mcp.json`;
|
|
888
886
|
}
|
|
889
887
|
},
|
|
888
|
+
{
|
|
889
|
+
id: "windsurf",
|
|
890
|
+
label: "Windsurf",
|
|
891
|
+
format: "json",
|
|
892
|
+
rootPath: ["mcpServers"],
|
|
893
|
+
configPath: (home, platform, env) => {
|
|
894
|
+
return `${platform === "win32" ? env["USERPROFILE"] ?? posixHome(home) : posixHome(home)}/.codeium/windsurf/mcp_config.json`;
|
|
895
|
+
}
|
|
896
|
+
},
|
|
890
897
|
{
|
|
891
898
|
id: "codex",
|
|
892
899
|
label: "Codex",
|
|
893
900
|
format: "toml",
|
|
894
|
-
|
|
895
|
-
needsType: false,
|
|
901
|
+
rootPath: ["mcp_servers"],
|
|
896
902
|
configPath: (home) => `${posixHome(home)}/.codex/config.toml`
|
|
897
903
|
},
|
|
898
904
|
{
|
|
899
905
|
id: "pi",
|
|
900
906
|
label: "pi",
|
|
901
907
|
format: "json",
|
|
902
|
-
|
|
903
|
-
needsType: false,
|
|
908
|
+
rootPath: ["mcpServers"],
|
|
904
909
|
configPath: (home) => `${posixHome(home)}/.pi/agent/mcp.json`
|
|
910
|
+
},
|
|
911
|
+
{
|
|
912
|
+
id: "opencode",
|
|
913
|
+
label: "OpenCode",
|
|
914
|
+
format: "json",
|
|
915
|
+
rootPath: ["mcp", "servers"],
|
|
916
|
+
typeValue: "local",
|
|
917
|
+
commandForm: "command-array",
|
|
918
|
+
configPath: (home, _platform, env) => {
|
|
919
|
+
return `${env["XDG_CONFIG_HOME"] ?? `${posixHome(home)}/.config`}/opencode/opencode.json`;
|
|
920
|
+
}
|
|
905
921
|
}
|
|
906
922
|
];
|
|
907
923
|
function findClient(id) {
|
|
@@ -953,33 +969,84 @@ function resolveLaunchCommand(opts) {
|
|
|
953
969
|
args: ["mcp"]
|
|
954
970
|
};
|
|
955
971
|
}
|
|
956
|
-
/**
|
|
957
|
-
function buildEntry(spec, launch) {
|
|
958
|
-
const
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
972
|
+
/** 单个客户端的配置条目;OpenCode 旧布局还需要 enabled: true */
|
|
973
|
+
function buildEntry(spec, launch, layout = "auto") {
|
|
974
|
+
const entry = {};
|
|
975
|
+
if (spec.typeValue !== void 0) entry["type"] = spec.typeValue;
|
|
976
|
+
if (spec.commandForm === "command-array") entry["command"] = [launch.command, ...launch.args];
|
|
977
|
+
else {
|
|
978
|
+
entry["command"] = launch.command;
|
|
979
|
+
entry["args"] = launch.args;
|
|
980
|
+
}
|
|
981
|
+
if (spec.extraFields !== void 0) Object.assign(entry, spec.extraFields);
|
|
982
|
+
if (spec.id === "opencode" && layout === "legacy") entry["enabled"] = true;
|
|
983
|
+
return entry;
|
|
984
|
+
}
|
|
985
|
+
function isRecord$1(value) {
|
|
986
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* 解析 server 表在配置里的路径。
|
|
990
|
+
*
|
|
991
|
+
* OpenCode 有两套布局:V2 把 server 放在 `mcp.servers` 下,旧布局直接放在 `mcp` 下。
|
|
992
|
+
* 已有文件按实际内容判断(避免把条目写到当前版本不读的位置),新文件用官方当前的 V2。
|
|
993
|
+
*/
|
|
994
|
+
function resolveRootPath(spec, existingRoot, layout = "auto") {
|
|
995
|
+
if (spec.id !== "opencode") return spec.rootPath;
|
|
996
|
+
if (layout === "legacy") return ["mcp"];
|
|
997
|
+
if (layout === "v2") return ["mcp", "servers"];
|
|
998
|
+
const mcp = existingRoot?.["mcp"];
|
|
999
|
+
if (isRecord$1(mcp)) {
|
|
1000
|
+
if (isRecord$1(mcp["servers"])) return ["mcp", "servers"];
|
|
1001
|
+
if (Object.values(mcp).some((v) => isRecord$1(v) && (typeof v["type"] === "string" || "command" in v))) return ["mcp"];
|
|
1002
|
+
}
|
|
1003
|
+
return ["mcp", "servers"];
|
|
966
1004
|
}
|
|
967
1005
|
/** Codex 用的 TOML 片段(改 TOML 风险高,只输出不写入) */
|
|
968
1006
|
function tomlSnippet(launch, name = "paintress") {
|
|
969
1007
|
const args = launch.args.map((a) => JSON.stringify(a)).join(", ");
|
|
970
1008
|
return `[mcp_servers.${name}]\ncommand = ${JSON.stringify(launch.command)}\nargs = [${args}]\n`;
|
|
971
1009
|
}
|
|
972
|
-
/** JSON
|
|
1010
|
+
/** JSON 客户端用的片段(含嵌套路径,OpenCode 按默认布局) */
|
|
973
1011
|
function jsonSnippet(spec, launch, name = "paintress") {
|
|
974
|
-
|
|
1012
|
+
const path = resolveRootPath(spec, null);
|
|
1013
|
+
const entry = buildEntry(spec, launch, path.length === 1 ? "legacy" : "v2");
|
|
1014
|
+
let cursor = { [name]: entry };
|
|
1015
|
+
for (const key of [...path].reverse()) cursor = { [key]: cursor };
|
|
1016
|
+
return JSON.stringify(cursor, null, 2);
|
|
975
1017
|
}
|
|
976
1018
|
// src/integrations/install.ts
|
|
977
1019
|
/**
|
|
978
1020
|
* 配置写入:解析 → 合并 → 备份 → 原子落盘。
|
|
979
1021
|
* 只动 `rootKey` 下名为 `paintress` 的那一条,其余内容与顺序保持不变(JSON 重新序列化)。
|
|
980
1022
|
*/
|
|
1023
|
+
function isRecord(value) {
|
|
1024
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1025
|
+
}
|
|
1026
|
+
/** 按路径取出 server 表(不存在或类型不对时返回空对象) */
|
|
1027
|
+
function readTable(root, path) {
|
|
1028
|
+
let cursor = root;
|
|
1029
|
+
for (const key of path) {
|
|
1030
|
+
if (!isRecord(cursor)) return {};
|
|
1031
|
+
cursor = cursor[key];
|
|
1032
|
+
}
|
|
1033
|
+
return isRecord(cursor) ? { ...cursor } : {};
|
|
1034
|
+
}
|
|
1035
|
+
/** 按路径写回 server 表,沿途缺失的层级补建,其余键原样保留 */
|
|
1036
|
+
function writeTable(root, path, table) {
|
|
1037
|
+
let cursor = root;
|
|
1038
|
+
path.forEach((key, index) => {
|
|
1039
|
+
if (index === path.length - 1) {
|
|
1040
|
+
cursor[key] = table;
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const next = isRecord(cursor[key]) ? { ...cursor[key] } : {};
|
|
1044
|
+
cursor[key] = next;
|
|
1045
|
+
cursor = next;
|
|
1046
|
+
});
|
|
1047
|
+
}
|
|
981
1048
|
/** 纯函数:把 paintress 条目并入现有配置文本 */
|
|
982
|
-
function planJsonMerge(spec, path, existing, launch) {
|
|
1049
|
+
function planJsonMerge(spec, path, existing, launch, options = {}) {
|
|
983
1050
|
const base = {
|
|
984
1051
|
spec,
|
|
985
1052
|
path,
|
|
@@ -1024,9 +1091,10 @@ function planJsonMerge(spec, path, existing, launch) {
|
|
|
1024
1091
|
detail: "配置文件不是合法 JSON,未改动"
|
|
1025
1092
|
};
|
|
1026
1093
|
}
|
|
1027
|
-
const
|
|
1028
|
-
const
|
|
1029
|
-
const
|
|
1094
|
+
const rootPath = resolveRootPath(spec, root, options.opencodeLayout ?? "auto");
|
|
1095
|
+
const layout = spec.id === "opencode" && rootPath.length === 1 ? "legacy" : "v2";
|
|
1096
|
+
const table = readTable(root, rootPath);
|
|
1097
|
+
const entry = buildEntry(spec, launch, layout);
|
|
1030
1098
|
const current = table["paintress"];
|
|
1031
1099
|
if (JSON.stringify(current) === JSON.stringify(entry)) return {
|
|
1032
1100
|
...base,
|
|
@@ -1036,7 +1104,7 @@ function planJsonMerge(spec, path, existing, launch) {
|
|
|
1036
1104
|
};
|
|
1037
1105
|
const existed = current !== void 0;
|
|
1038
1106
|
table["paintress"] = entry;
|
|
1039
|
-
root
|
|
1107
|
+
writeTable(root, rootPath, table);
|
|
1040
1108
|
return {
|
|
1041
1109
|
...base,
|
|
1042
1110
|
status: existed ? "update" : existing === null ? "create" : "update",
|
|
@@ -1076,7 +1144,8 @@ const FLAG_KEYS = /* @__PURE__ */ new Set([
|
|
|
1076
1144
|
"port",
|
|
1077
1145
|
"idle",
|
|
1078
1146
|
"daemon",
|
|
1079
|
-
"dry-run"
|
|
1147
|
+
"dry-run",
|
|
1148
|
+
"opencode-layout"
|
|
1080
1149
|
]);
|
|
1081
1150
|
const BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
1082
1151
|
"regex",
|
|
@@ -1144,9 +1213,13 @@ async function call(tool, args) {
|
|
|
1144
1213
|
}
|
|
1145
1214
|
/** 入口:返回退出码(可单测) */
|
|
1146
1215
|
async function main(argv) {
|
|
1216
|
+
if (argv[0] === "--version" || argv[0] === "-v" || argv[0] === "version") {
|
|
1217
|
+
console.log(`paintress ${VERSION}`);
|
|
1218
|
+
return 0;
|
|
1219
|
+
}
|
|
1147
1220
|
const parsed = parseArgv(argv);
|
|
1148
1221
|
if (!parsed) {
|
|
1149
|
-
console.error("用法:paintress <mcp|web|ping|status|watch|unwatch|attach|stop|info|query|get|update|insert|delete|move|batch|render|shot|validate|install|doctor|mcp-config>
|
|
1222
|
+
console.error("用法:paintress <mcp|web|ping|status|watch|unwatch|attach|stop|info|query|get|update|insert|delete|move|batch|render|shot|validate|install|doctor|mcp-config> ...(版本:paintress --version)");
|
|
1150
1223
|
return 2;
|
|
1151
1224
|
}
|
|
1152
1225
|
const { cmd, positionals, flags } = parsed;
|
|
@@ -1230,13 +1303,15 @@ async function main(argv) {
|
|
|
1230
1303
|
const unknown = ids.filter((id) => findClient(id) === void 0);
|
|
1231
1304
|
if (unknown.length > 0) throw new Error(`未知客户端:${unknown.join(", ")}(可选:${CLIENTS.map((c) => c.id).join(" / ")})`);
|
|
1232
1305
|
const dryRun = cmd === "doctor" || flags["dry-run"] === true;
|
|
1306
|
+
const layoutFlag = flagStr(flags, "opencode-layout") ?? "auto";
|
|
1307
|
+
if (layoutFlag !== "auto" && layoutFlag !== "legacy" && layoutFlag !== "v2") throw new Error(`--opencode-layout 只接受 auto / legacy / v2,收到:${layoutFlag}`);
|
|
1233
1308
|
const results = [];
|
|
1234
1309
|
for (const id of ids) {
|
|
1235
1310
|
const spec = findClient(id);
|
|
1236
1311
|
if (spec === void 0) continue;
|
|
1237
1312
|
const path = spec.configPath(home, process.platform, process.env);
|
|
1238
1313
|
const existing = readConfig(path);
|
|
1239
|
-
const plan = planJsonMerge(spec, path, existing, launch);
|
|
1314
|
+
const plan = planJsonMerge(spec, path, existing, launch, { opencodeLayout: layoutFlag });
|
|
1240
1315
|
if (cmd === "doctor") {
|
|
1241
1316
|
results.push({
|
|
1242
1317
|
client: spec.id,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "paintress",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Design-document operation layer for AI agents: read, query, edit, render",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"bin": {
|
|
25
|
-
"paintress": "
|
|
25
|
+
"paintress": "dist/cli.js"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
28
|
"dist",
|