xling 0.0.2 → 0.2.4
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 +229 -1
- package/dist/base-BlaKDtDu.d.ts +43 -0
- package/dist/base-BlaKDtDu.d.ts.map +1 -0
- package/dist/base-Cm9xh6sW.js +69 -0
- package/dist/base-Cm9xh6sW.js.map +1 -0
- package/dist/claude-l3zomoHg.js +209 -0
- package/dist/claude-l3zomoHg.js.map +1 -0
- package/dist/claudeDefault-Fk1-kHLE.js +19 -0
- package/dist/claudeDefault-Fk1-kHLE.js.map +1 -0
- package/dist/codex-CR8xqNrZ.js +85 -0
- package/dist/codex-CR8xqNrZ.js.map +1 -0
- package/dist/commands/settings/get.d.ts +24 -0
- package/dist/commands/settings/get.d.ts.map +1 -0
- package/dist/commands/settings/get.js +118 -0
- package/dist/commands/settings/get.js.map +1 -0
- package/dist/commands/settings/inspect.d.ts +19 -0
- package/dist/commands/settings/inspect.d.ts.map +1 -0
- package/dist/commands/settings/inspect.js +88 -0
- package/dist/commands/settings/inspect.js.map +1 -0
- package/dist/commands/settings/list.d.ts +25 -0
- package/dist/commands/settings/list.d.ts.map +1 -0
- package/dist/commands/settings/list.js +147 -0
- package/dist/commands/settings/list.js.map +1 -0
- package/dist/commands/settings/set.d.ts +22 -0
- package/dist/commands/settings/set.d.ts.map +1 -0
- package/dist/commands/settings/set.js +83 -0
- package/dist/commands/settings/set.js.map +1 -0
- package/dist/commands/settings/switch.d.ts +27 -0
- package/dist/commands/settings/switch.d.ts.map +1 -0
- package/dist/commands/settings/switch.js +164 -0
- package/dist/commands/settings/switch.js.map +1 -0
- package/dist/dispatcher-JXm3OqRQ.js +76 -0
- package/dist/dispatcher-JXm3OqRQ.js.map +1 -0
- package/dist/domain/interfaces.d.ts +3 -0
- package/dist/domain/interfaces.js +1 -0
- package/dist/domain/types.d.ts +2 -0
- package/dist/domain/types.js +1 -0
- package/dist/domain/validators.d.ts +82 -0
- package/dist/domain/validators.d.ts.map +1 -0
- package/dist/domain/validators.js +58 -0
- package/dist/domain/validators.js.map +1 -0
- package/dist/editor-D4qoje1V.js +32 -0
- package/dist/editor-D4qoje1V.js.map +1 -0
- package/dist/errors-CAZ5k5YT.js +89 -0
- package/dist/errors-CAZ5k5YT.js.map +1 -0
- package/dist/format-Cqecj3RS.js +229 -0
- package/dist/format-Cqecj3RS.js.map +1 -0
- package/dist/fsStore-i-3731TM.js +122 -0
- package/dist/fsStore-i-3731TM.js.map +1 -0
- package/dist/gemini-aNNm-QGE.js +52 -0
- package/dist/gemini-aNNm-QGE.js.map +1 -0
- package/dist/interfaces-CriQW6hF.d.ts +41 -0
- package/dist/interfaces-CriQW6hF.d.ts.map +1 -0
- package/dist/run.d.ts +1 -0
- package/dist/run.js +15 -0
- package/dist/run.js.map +1 -0
- package/dist/services/settings/adapters/base.d.ts +4 -0
- package/dist/services/settings/adapters/base.js +5 -0
- package/dist/services/settings/adapters/claude.d.ts +43 -0
- package/dist/services/settings/adapters/claude.d.ts.map +1 -0
- package/dist/services/settings/adapters/claude.js +9 -0
- package/dist/services/settings/adapters/codex.d.ts +45 -0
- package/dist/services/settings/adapters/codex.d.ts.map +1 -0
- package/dist/services/settings/adapters/codex.js +6 -0
- package/dist/services/settings/adapters/gemini.d.ts +32 -0
- package/dist/services/settings/adapters/gemini.d.ts.map +1 -0
- package/dist/services/settings/adapters/gemini.js +6 -0
- package/dist/services/settings/dispatcher.d.ts +36 -0
- package/dist/services/settings/dispatcher.d.ts.map +1 -0
- package/dist/services/settings/dispatcher.js +12 -0
- package/dist/services/settings/fsStore.d.ts +46 -0
- package/dist/services/settings/fsStore.d.ts.map +1 -0
- package/dist/services/settings/fsStore.js +4 -0
- package/dist/services/settings/templates/claudeDefault.d.ts +20 -0
- package/dist/services/settings/templates/claudeDefault.d.ts.map +1 -0
- package/dist/services/settings/templates/claudeDefault.js +3 -0
- package/dist/types-BfNSo2rs.d.ts +71 -0
- package/dist/types-BfNSo2rs.d.ts.map +1 -0
- package/dist/utils/editor.d.ts +6 -0
- package/dist/utils/editor.d.ts.map +1 -0
- package/dist/utils/editor.js +4 -0
- package/dist/utils/errors.d.ts +61 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +3 -0
- package/dist/utils/format.d.ts +20 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +3 -0
- package/dist/utils/logger.d.ts +32 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +46 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +66 -6
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
//#region src/utils/errors.ts
|
|
2
|
+
/**
|
|
3
|
+
* 自定义错误类型
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 基础错误类
|
|
7
|
+
*/
|
|
8
|
+
var XlingError = class extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "XlingError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* 不支持的工具错误
|
|
16
|
+
*/
|
|
17
|
+
var UnsupportedToolError = class extends XlingError {
|
|
18
|
+
constructor(tool) {
|
|
19
|
+
super(`Unsupported tool: ${tool}`);
|
|
20
|
+
this.name = "UnsupportedToolError";
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* 无效的 scope 错误
|
|
25
|
+
*/
|
|
26
|
+
var InvalidScopeError = class extends XlingError {
|
|
27
|
+
constructor(scope) {
|
|
28
|
+
super(`Invalid scope: ${scope}`);
|
|
29
|
+
this.name = "InvalidScopeError";
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* 配置文件不存在错误
|
|
34
|
+
*/
|
|
35
|
+
var ConfigFileNotFoundError = class extends XlingError {
|
|
36
|
+
constructor(path) {
|
|
37
|
+
super(`Config file not found: ${path}`);
|
|
38
|
+
this.name = "ConfigFileNotFoundError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* 配置文件解析错误
|
|
43
|
+
*/
|
|
44
|
+
var ConfigParseError = class extends XlingError {
|
|
45
|
+
constructor(path, reason) {
|
|
46
|
+
super(`Failed to parse config file ${path}: ${reason}`);
|
|
47
|
+
this.name = "ConfigParseError";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Profile 不存在错误
|
|
52
|
+
*/
|
|
53
|
+
var ProfileNotFoundError = class extends XlingError {
|
|
54
|
+
constructor(profile) {
|
|
55
|
+
super(`Profile not found: ${profile}`);
|
|
56
|
+
this.name = "ProfileNotFoundError";
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Settings 变体不存在错误
|
|
61
|
+
*/
|
|
62
|
+
var SettingsVariantNotFoundError = class extends XlingError {
|
|
63
|
+
constructor(variant) {
|
|
64
|
+
super(`Settings variant not found: ${variant}`);
|
|
65
|
+
this.name = "SettingsVariantNotFoundError";
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* 文件写入错误
|
|
70
|
+
*/
|
|
71
|
+
var FileWriteError = class extends XlingError {
|
|
72
|
+
constructor(path, reason) {
|
|
73
|
+
super(`Failed to write file ${path}: ${reason}`);
|
|
74
|
+
this.name = "FileWriteError";
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* 编辑器启动错误
|
|
79
|
+
*/
|
|
80
|
+
var EditorLaunchError = class extends XlingError {
|
|
81
|
+
constructor(editor, reason) {
|
|
82
|
+
super(`Failed to launch editor ${editor}: ${reason}`);
|
|
83
|
+
this.name = "EditorLaunchError";
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
//#endregion
|
|
88
|
+
export { InvalidScopeError as a, UnsupportedToolError as c, FileWriteError as i, XlingError as l, ConfigParseError as n, ProfileNotFoundError as o, EditorLaunchError as r, SettingsVariantNotFoundError as s, ConfigFileNotFoundError as t };
|
|
89
|
+
//# sourceMappingURL=errors-CAZ5k5YT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors-CAZ5k5YT.js","names":[],"sources":["../src/utils/errors.ts"],"sourcesContent":["/**\n * 自定义错误类型\n */\n\n/**\n * 基础错误类\n */\nexport class XlingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"XlingError\";\n }\n}\n\n/**\n * 不支持的工具错误\n */\nexport class UnsupportedToolError extends XlingError {\n constructor(tool: string) {\n super(`Unsupported tool: ${tool}`);\n this.name = \"UnsupportedToolError\";\n }\n}\n\n/**\n * 无效的 scope 错误\n */\nexport class InvalidScopeError extends XlingError {\n constructor(scope: string) {\n super(`Invalid scope: ${scope}`);\n this.name = \"InvalidScopeError\";\n }\n}\n\n/**\n * 配置文件不存在错误\n */\nexport class ConfigFileNotFoundError extends XlingError {\n constructor(path: string) {\n super(`Config file not found: ${path}`);\n this.name = \"ConfigFileNotFoundError\";\n }\n}\n\n/**\n * 配置文件解析错误\n */\nexport class ConfigParseError extends XlingError {\n constructor(path: string, reason: string) {\n super(`Failed to parse config file ${path}: ${reason}`);\n this.name = \"ConfigParseError\";\n }\n}\n\n/**\n * Profile 不存在错误\n */\nexport class ProfileNotFoundError extends XlingError {\n constructor(profile: string) {\n super(`Profile not found: ${profile}`);\n this.name = \"ProfileNotFoundError\";\n }\n}\n\n/**\n * Settings 变体不存在错误\n */\nexport class SettingsVariantNotFoundError extends XlingError {\n constructor(variant: string) {\n super(`Settings variant not found: ${variant}`);\n this.name = \"SettingsVariantNotFoundError\";\n }\n}\n\n/**\n * 文件写入错误\n */\nexport class FileWriteError extends XlingError {\n constructor(path: string, reason: string) {\n super(`Failed to write file ${path}: ${reason}`);\n this.name = \"FileWriteError\";\n }\n}\n\n/**\n * 编辑器启动错误\n */\nexport class EditorLaunchError extends XlingError {\n constructor(editor: string, reason: string) {\n super(`Failed to launch editor ${editor}: ${reason}`);\n this.name = \"EditorLaunchError\";\n }\n}\n"],"mappings":";;;;;;;AAOA,IAAa,aAAb,cAAgC,MAAM;CACpC,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO;;;;;;AAOhB,IAAa,uBAAb,cAA0C,WAAW;CACnD,YAAY,MAAc;AACxB,QAAM,qBAAqB,OAAO;AAClC,OAAK,OAAO;;;;;;AAOhB,IAAa,oBAAb,cAAuC,WAAW;CAChD,YAAY,OAAe;AACzB,QAAM,kBAAkB,QAAQ;AAChC,OAAK,OAAO;;;;;;AAOhB,IAAa,0BAAb,cAA6C,WAAW;CACtD,YAAY,MAAc;AACxB,QAAM,0BAA0B,OAAO;AACvC,OAAK,OAAO;;;;;;AAOhB,IAAa,mBAAb,cAAsC,WAAW;CAC/C,YAAY,MAAc,QAAgB;AACxC,QAAM,+BAA+B,KAAK,IAAI,SAAS;AACvD,OAAK,OAAO;;;;;;AAOhB,IAAa,uBAAb,cAA0C,WAAW;CACnD,YAAY,SAAiB;AAC3B,QAAM,sBAAsB,UAAU;AACtC,OAAK,OAAO;;;;;;AAOhB,IAAa,+BAAb,cAAkD,WAAW;CAC3D,YAAY,SAAiB;AAC3B,QAAM,+BAA+B,UAAU;AAC/C,OAAK,OAAO;;;;;;AAOhB,IAAa,iBAAb,cAAoC,WAAW;CAC7C,YAAY,MAAc,QAAgB;AACxC,QAAM,wBAAwB,KAAK,IAAI,SAAS;AAChD,OAAK,OAAO;;;;;;AAOhB,IAAa,oBAAb,cAAuC,WAAW;CAChD,YAAY,QAAgB,QAAgB;AAC1C,QAAM,2BAA2B,OAAO,IAAI,SAAS;AACrD,OAAK,OAAO"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import Table from "cli-table3";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/format.ts
|
|
4
|
+
/**
|
|
5
|
+
* 输出格式化工具
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* 格式化为 JSON 字符串
|
|
9
|
+
*/
|
|
10
|
+
function formatJson(data, pretty = true) {
|
|
11
|
+
return JSON.stringify(data, null, pretty ? 2 : 0);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 格式化为表格
|
|
15
|
+
*/
|
|
16
|
+
function formatTable(data) {
|
|
17
|
+
const table = new Table({
|
|
18
|
+
head: ["Key", "Value"],
|
|
19
|
+
colWidths: [30, 50],
|
|
20
|
+
wordWrap: true
|
|
21
|
+
});
|
|
22
|
+
for (const [key, value] of Object.entries(data)) table.push([key, formatValue(value)]);
|
|
23
|
+
return table.toString();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 格式化 settings 文件清单
|
|
27
|
+
*/
|
|
28
|
+
function formatFilesTable(files) {
|
|
29
|
+
const table = new Table({
|
|
30
|
+
head: [
|
|
31
|
+
"Variant",
|
|
32
|
+
"File",
|
|
33
|
+
"Status",
|
|
34
|
+
"Size",
|
|
35
|
+
"Updated"
|
|
36
|
+
],
|
|
37
|
+
colWidths: [
|
|
38
|
+
15,
|
|
39
|
+
40,
|
|
40
|
+
12,
|
|
41
|
+
12,
|
|
42
|
+
26
|
|
43
|
+
],
|
|
44
|
+
wordWrap: true
|
|
45
|
+
});
|
|
46
|
+
for (const file of files) table.push([
|
|
47
|
+
file.variant,
|
|
48
|
+
file.path,
|
|
49
|
+
formatStatus(file),
|
|
50
|
+
formatBytes(file.size),
|
|
51
|
+
formatTimestamp(file.lastModified)
|
|
52
|
+
]);
|
|
53
|
+
return table.toString();
|
|
54
|
+
}
|
|
55
|
+
function formatDiff(currentValue, nextValue) {
|
|
56
|
+
const current = JSON.stringify(currentValue ?? {}, null, 2);
|
|
57
|
+
const next = JSON.stringify(nextValue ?? {}, null, 2);
|
|
58
|
+
if (current === next) return null;
|
|
59
|
+
const hunks = buildUnifiedHunks(buildDiffParts(current.split("\n"), next.split("\n")));
|
|
60
|
+
const lines = ["--- current", "+++ variant"];
|
|
61
|
+
for (const hunk of hunks) {
|
|
62
|
+
lines.push(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`);
|
|
63
|
+
lines.push(...hunk.lines);
|
|
64
|
+
}
|
|
65
|
+
return lines.map(colorizeDiffLine).join("\n");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 格式化单个值
|
|
69
|
+
*/
|
|
70
|
+
function formatValue(value) {
|
|
71
|
+
if (value === null) return "null";
|
|
72
|
+
if (value === void 0) return "undefined";
|
|
73
|
+
if (typeof value === "string") return value;
|
|
74
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
75
|
+
if (Array.isArray(value)) return JSON.stringify(value);
|
|
76
|
+
if (typeof value === "object") return JSON.stringify(value, null, 2);
|
|
77
|
+
return String(value);
|
|
78
|
+
}
|
|
79
|
+
function formatStatus(file) {
|
|
80
|
+
if (file.active) return file.exists ? "active" : "missing";
|
|
81
|
+
return file.exists ? "available" : "missing";
|
|
82
|
+
}
|
|
83
|
+
function formatBytes(size) {
|
|
84
|
+
if (typeof size !== "number") return "-";
|
|
85
|
+
const units = [
|
|
86
|
+
"B",
|
|
87
|
+
"KB",
|
|
88
|
+
"MB",
|
|
89
|
+
"GB"
|
|
90
|
+
];
|
|
91
|
+
let value = size;
|
|
92
|
+
let unitIndex = 0;
|
|
93
|
+
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
94
|
+
value /= 1024;
|
|
95
|
+
unitIndex++;
|
|
96
|
+
}
|
|
97
|
+
return `${value >= 10 || value % 1 === 0 ? value.toFixed(0) : value.toFixed(1)} ${units[unitIndex]}`;
|
|
98
|
+
}
|
|
99
|
+
function formatTimestamp(date) {
|
|
100
|
+
if (!date) return "-";
|
|
101
|
+
return new Intl.DateTimeFormat(void 0, {
|
|
102
|
+
dateStyle: "medium",
|
|
103
|
+
timeStyle: "short"
|
|
104
|
+
}).format(date);
|
|
105
|
+
}
|
|
106
|
+
const ANSI = {
|
|
107
|
+
reset: "\x1B[0m",
|
|
108
|
+
red: "\x1B[31m",
|
|
109
|
+
green: "\x1B[32m",
|
|
110
|
+
yellow: "\x1B[33m",
|
|
111
|
+
cyan: "\x1B[36m",
|
|
112
|
+
dim: "\x1B[90m",
|
|
113
|
+
bold: "\x1B[1m"
|
|
114
|
+
};
|
|
115
|
+
function supportsColor() {
|
|
116
|
+
if (process.env.NO_COLOR) return false;
|
|
117
|
+
if (process.env.FORCE_COLOR === "0") return false;
|
|
118
|
+
return Boolean(process.stdout?.isTTY);
|
|
119
|
+
}
|
|
120
|
+
function colorizeDiffLine(line) {
|
|
121
|
+
if (!supportsColor()) return line;
|
|
122
|
+
if (line.startsWith("@@")) return `${ANSI.cyan}${ANSI.bold}${line}${ANSI.reset}`;
|
|
123
|
+
if (line.startsWith("---") || line.startsWith("+++")) return `${ANSI.yellow}${line}${ANSI.reset}`;
|
|
124
|
+
if (line.startsWith("+")) return `${ANSI.green}${line}${ANSI.reset}`;
|
|
125
|
+
if (line.startsWith("-")) return `${ANSI.red}${line}${ANSI.reset}`;
|
|
126
|
+
if (line.startsWith(" ")) return `${ANSI.dim}${line}${ANSI.reset}`;
|
|
127
|
+
return line;
|
|
128
|
+
}
|
|
129
|
+
function buildDiffParts(oldLines, newLines) {
|
|
130
|
+
const m = oldLines.length;
|
|
131
|
+
const n = newLines.length;
|
|
132
|
+
const dp = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }, () => 0));
|
|
133
|
+
for (let i$1 = m - 1; i$1 >= 0; i$1--) for (let j$1 = n - 1; j$1 >= 0; j$1--) if (oldLines[i$1] === newLines[j$1]) dp[i$1][j$1] = dp[i$1 + 1][j$1 + 1] + 1;
|
|
134
|
+
else dp[i$1][j$1] = Math.max(dp[i$1 + 1][j$1], dp[i$1][j$1 + 1]);
|
|
135
|
+
const parts = [];
|
|
136
|
+
const push = (type, value) => {
|
|
137
|
+
const last = parts[parts.length - 1];
|
|
138
|
+
if (last && last.type === type) last.lines.push(value);
|
|
139
|
+
else parts.push({
|
|
140
|
+
type,
|
|
141
|
+
lines: [value]
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
let i = 0;
|
|
145
|
+
let j = 0;
|
|
146
|
+
while (i < m && j < n) if (oldLines[i] === newLines[j]) {
|
|
147
|
+
push("equal", oldLines[i]);
|
|
148
|
+
i++;
|
|
149
|
+
j++;
|
|
150
|
+
} else if (dp[i + 1][j] >= dp[i][j + 1]) {
|
|
151
|
+
push("delete", oldLines[i]);
|
|
152
|
+
i++;
|
|
153
|
+
} else {
|
|
154
|
+
push("insert", newLines[j]);
|
|
155
|
+
j++;
|
|
156
|
+
}
|
|
157
|
+
while (i < m) push("delete", oldLines[i++]);
|
|
158
|
+
while (j < n) push("insert", newLines[j++]);
|
|
159
|
+
return parts;
|
|
160
|
+
}
|
|
161
|
+
function buildUnifiedHunks(parts) {
|
|
162
|
+
const context = 3;
|
|
163
|
+
const hunks = [];
|
|
164
|
+
let oldLine = 1;
|
|
165
|
+
let newLine = 1;
|
|
166
|
+
let currentHunk = null;
|
|
167
|
+
let contextBuffer = [];
|
|
168
|
+
const startHunk = () => {
|
|
169
|
+
currentHunk = {
|
|
170
|
+
oldStart: Math.max(oldLine - contextBuffer.length, 1),
|
|
171
|
+
newStart: Math.max(newLine - contextBuffer.length, 1),
|
|
172
|
+
oldLines: contextBuffer.length,
|
|
173
|
+
newLines: contextBuffer.length,
|
|
174
|
+
lines: contextBuffer.map((line) => ` ${line}`)
|
|
175
|
+
};
|
|
176
|
+
contextBuffer = [];
|
|
177
|
+
};
|
|
178
|
+
const closeHunk = () => {
|
|
179
|
+
if (currentHunk) {
|
|
180
|
+
hunks.push(currentHunk);
|
|
181
|
+
currentHunk = null;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
for (const part of parts) {
|
|
185
|
+
if (part.type === "equal") {
|
|
186
|
+
if (currentHunk !== null) {
|
|
187
|
+
const active$1 = currentHunk;
|
|
188
|
+
const leading = part.lines.slice(0, context);
|
|
189
|
+
for (const line of leading) {
|
|
190
|
+
active$1.lines.push(` ${line}`);
|
|
191
|
+
active$1.oldLines++;
|
|
192
|
+
active$1.newLines++;
|
|
193
|
+
}
|
|
194
|
+
oldLine += leading.length;
|
|
195
|
+
newLine += leading.length;
|
|
196
|
+
if (part.lines.length > context) {
|
|
197
|
+
closeHunk();
|
|
198
|
+
contextBuffer = part.lines.slice(part.lines.length - context);
|
|
199
|
+
oldLine += part.lines.length - leading.length;
|
|
200
|
+
newLine += part.lines.length - leading.length;
|
|
201
|
+
} else contextBuffer = [...leading].slice(-context);
|
|
202
|
+
} else {
|
|
203
|
+
contextBuffer.push(...part.lines);
|
|
204
|
+
if (contextBuffer.length > context) contextBuffer.splice(0, contextBuffer.length - context);
|
|
205
|
+
oldLine += part.lines.length;
|
|
206
|
+
newLine += part.lines.length;
|
|
207
|
+
}
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
if (!currentHunk) startHunk();
|
|
211
|
+
if (!currentHunk) throw new Error("Failed to initialize diff hunk");
|
|
212
|
+
const active = currentHunk;
|
|
213
|
+
for (const line of part.lines) if (part.type === "delete") {
|
|
214
|
+
active.lines.push(`-${line}`);
|
|
215
|
+
active.oldLines++;
|
|
216
|
+
oldLine++;
|
|
217
|
+
} else {
|
|
218
|
+
active.lines.push(`+${line}`);
|
|
219
|
+
active.newLines++;
|
|
220
|
+
newLine++;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
closeHunk();
|
|
224
|
+
return hunks;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
//#endregion
|
|
228
|
+
export { formatTable as i, formatFilesTable as n, formatJson as r, formatDiff as t };
|
|
229
|
+
//# sourceMappingURL=format-Cqecj3RS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-Cqecj3RS.js","names":["lines: string[]","dp: number[][]","i","j","parts: DiffPart[]","hunks: Hunk[]","currentHunk: Hunk | null","contextBuffer: string[]","active: Hunk"],"sources":["../src/utils/format.ts"],"sourcesContent":["/**\n * 输出格式化工具\n */\n\nimport Table from \"cli-table3\";\nimport type { SettingsFileEntry } from \"@/domain/types.ts\";\n\n/**\n * 格式化为 JSON 字符串\n */\nexport function formatJson(data: unknown, pretty = true): string {\n return JSON.stringify(data, null, pretty ? 2 : 0);\n}\n\n/**\n * 格式化为表格\n */\nexport function formatTable(data: Record<string, unknown>): string {\n const table = new Table({\n head: [\"Key\", \"Value\"],\n colWidths: [30, 50],\n wordWrap: true,\n });\n\n for (const [key, value] of Object.entries(data)) {\n table.push([key, formatValue(value)]);\n }\n\n return table.toString();\n}\n\n/**\n * 格式化 settings 文件清单\n */\nexport function formatFilesTable(files: SettingsFileEntry[]): string {\n const table = new Table({\n head: [\"Variant\", \"File\", \"Status\", \"Size\", \"Updated\"],\n colWidths: [15, 40, 12, 12, 26],\n wordWrap: true,\n });\n\n for (const file of files) {\n table.push([\n file.variant,\n file.path,\n formatStatus(file),\n formatBytes(file.size),\n formatTimestamp(file.lastModified),\n ]);\n }\n\n return table.toString();\n}\n\nexport function formatDiff(\n currentValue: unknown,\n nextValue: unknown,\n): string | null {\n const current = JSON.stringify(currentValue ?? {}, null, 2);\n const next = JSON.stringify(nextValue ?? {}, null, 2);\n\n if (current === next) {\n return null;\n }\n\n const parts = buildDiffParts(current.split(\"\\n\"), next.split(\"\\n\"));\n const hunks = buildUnifiedHunks(parts);\n\n const lines: string[] = [\"--- current\", \"+++ variant\"];\n for (const hunk of hunks) {\n lines.push(\n `@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`,\n );\n lines.push(...hunk.lines);\n }\n\n return lines.map(colorizeDiffLine).join(\"\\n\");\n}\n\n/**\n * 格式化单个值\n */\nfunction formatValue(value: unknown): string {\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\")\n return String(value);\n if (Array.isArray(value)) return JSON.stringify(value);\n if (typeof value === \"object\") return JSON.stringify(value, null, 2);\n return String(value);\n}\n\nfunction formatStatus(file: SettingsFileEntry): string {\n if (file.active) {\n return file.exists ? \"active\" : \"missing\";\n }\n return file.exists ? \"available\" : \"missing\";\n}\n\nfunction formatBytes(size?: number): string {\n if (typeof size !== \"number\") {\n return \"-\";\n }\n\n const units = [\"B\", \"KB\", \"MB\", \"GB\"];\n let value = size;\n let unitIndex = 0;\n\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex++;\n }\n\n const formatted =\n value >= 10 || value % 1 === 0 ? value.toFixed(0) : value.toFixed(1);\n return `${formatted} ${units[unitIndex]}`;\n}\n\nfunction formatTimestamp(date?: Date): string {\n if (!date) {\n return \"-\";\n }\n\n return new Intl.DateTimeFormat(undefined, {\n dateStyle: \"medium\",\n timeStyle: \"short\",\n }).format(date);\n}\n\nconst ANSI = {\n reset: \"\\x1b[0m\",\n red: \"\\x1b[31m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n cyan: \"\\x1b[36m\",\n dim: \"\\x1b[90m\",\n bold: \"\\x1b[1m\",\n};\n\nfunction supportsColor(): boolean {\n if (process.env.NO_COLOR) return false;\n if (process.env.FORCE_COLOR === \"0\") return false;\n return Boolean(process.stdout?.isTTY);\n}\n\nfunction colorizeDiffLine(line: string): string {\n if (!supportsColor()) {\n return line;\n }\n\n if (line.startsWith(\"@@\")) {\n return `${ANSI.cyan}${ANSI.bold}${line}${ANSI.reset}`;\n }\n if (line.startsWith(\"---\") || line.startsWith(\"+++\")) {\n return `${ANSI.yellow}${line}${ANSI.reset}`;\n }\n if (line.startsWith(\"+\")) {\n return `${ANSI.green}${line}${ANSI.reset}`;\n }\n if (line.startsWith(\"-\")) {\n return `${ANSI.red}${line}${ANSI.reset}`;\n }\n if (line.startsWith(\" \")) {\n return `${ANSI.dim}${line}${ANSI.reset}`;\n }\n return line;\n}\n\ntype DiffPart = {\n type: \"equal\" | \"insert\" | \"delete\";\n lines: string[];\n};\n\ntype Hunk = {\n oldStart: number;\n newStart: number;\n oldLines: number;\n newLines: number;\n lines: string[];\n};\n\nfunction buildDiffParts(oldLines: string[], newLines: string[]): DiffPart[] {\n const m = oldLines.length;\n const n = newLines.length;\n const dp: number[][] = Array.from({ length: m + 1 }, () =>\n Array.from({ length: n + 1 }, () => 0),\n );\n\n for (let i = m - 1; i >= 0; i--) {\n for (let j = n - 1; j >= 0; j--) {\n if (oldLines[i] === newLines[j]) {\n dp[i][j] = dp[i + 1][j + 1] + 1;\n } else {\n dp[i][j] = Math.max(dp[i + 1][j], dp[i][j + 1]);\n }\n }\n }\n\n const parts: DiffPart[] = [];\n const push = (type: DiffPart[\"type\"], value: string) => {\n const last = parts[parts.length - 1];\n if (last && last.type === type) {\n last.lines.push(value);\n } else {\n parts.push({ type, lines: [value] });\n }\n };\n\n let i = 0;\n let j = 0;\n\n while (i < m && j < n) {\n if (oldLines[i] === newLines[j]) {\n push(\"equal\", oldLines[i]);\n i++;\n j++;\n } else if (dp[i + 1][j] >= dp[i][j + 1]) {\n push(\"delete\", oldLines[i]);\n i++;\n } else {\n push(\"insert\", newLines[j]);\n j++;\n }\n }\n\n while (i < m) {\n push(\"delete\", oldLines[i++]);\n }\n while (j < n) {\n push(\"insert\", newLines[j++]);\n }\n\n return parts;\n}\n\nfunction buildUnifiedHunks(parts: DiffPart[]): Hunk[] {\n const context = 3;\n const hunks: Hunk[] = [];\n let oldLine = 1;\n let newLine = 1;\n let currentHunk: Hunk | null = null;\n let contextBuffer: string[] = [];\n\n const startHunk = () => {\n const oldStart = Math.max(oldLine - contextBuffer.length, 1);\n const newStart = Math.max(newLine - contextBuffer.length, 1);\n currentHunk = {\n oldStart,\n newStart,\n oldLines: contextBuffer.length,\n newLines: contextBuffer.length,\n lines: contextBuffer.map((line) => ` ${line}`),\n };\n contextBuffer = [];\n };\n\n const closeHunk = () => {\n if (currentHunk) {\n hunks.push(currentHunk);\n currentHunk = null;\n }\n };\n\n for (const part of parts) {\n if (part.type === \"equal\") {\n if (currentHunk !== null) {\n const active: Hunk = currentHunk;\n const leading = part.lines.slice(0, context);\n for (const line of leading) {\n active.lines.push(` ${line}`);\n active.oldLines++;\n active.newLines++;\n }\n oldLine += leading.length;\n newLine += leading.length;\n\n if (part.lines.length > context) {\n closeHunk();\n contextBuffer = part.lines.slice(part.lines.length - context);\n oldLine += part.lines.length - leading.length;\n newLine += part.lines.length - leading.length;\n } else {\n contextBuffer = [...leading].slice(-context);\n }\n } else {\n contextBuffer.push(...part.lines);\n if (contextBuffer.length > context) {\n contextBuffer.splice(0, contextBuffer.length - context);\n }\n oldLine += part.lines.length;\n newLine += part.lines.length;\n }\n continue;\n }\n\n if (!currentHunk) {\n startHunk();\n }\n\n if (!currentHunk) {\n throw new Error(\"Failed to initialize diff hunk\");\n }\n\n const active: Hunk = currentHunk;\n for (const line of part.lines) {\n if (part.type === \"delete\") {\n active.lines.push(`-${line}`);\n active.oldLines++;\n oldLine++;\n } else {\n active.lines.push(`+${line}`);\n active.newLines++;\n newLine++;\n }\n }\n }\n\n closeHunk();\n return hunks;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { i as FileWriteError, n as ConfigParseError, t as ConfigFileNotFoundError } from "./errors-CAZ5k5YT.js";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import * as os from "os";
|
|
5
|
+
import * as toml from "@iarna/toml";
|
|
6
|
+
|
|
7
|
+
//#region src/services/settings/fsStore.ts
|
|
8
|
+
/**
|
|
9
|
+
* 文件系统存储工具
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* 解析 ~ 为用户主目录
|
|
13
|
+
*/
|
|
14
|
+
function resolveHome(filepath) {
|
|
15
|
+
if (filepath.startsWith("~/") || filepath === "~") return path.join(os.homedir(), filepath.slice(1));
|
|
16
|
+
return filepath;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 确保目录存在
|
|
20
|
+
*/
|
|
21
|
+
function ensureDir(dirPath) {
|
|
22
|
+
const resolvedPath = resolveHome(dirPath);
|
|
23
|
+
if (!fs.existsSync(resolvedPath)) fs.mkdirSync(resolvedPath, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 读取 JSON 文件
|
|
27
|
+
*/
|
|
28
|
+
function readJSON(filepath) {
|
|
29
|
+
const resolvedPath = resolveHome(filepath);
|
|
30
|
+
if (!fs.existsSync(resolvedPath)) throw new ConfigFileNotFoundError(resolvedPath);
|
|
31
|
+
try {
|
|
32
|
+
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
33
|
+
return JSON.parse(content);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
throw new ConfigParseError(resolvedPath, error.message);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* 写入 JSON 文件
|
|
40
|
+
*/
|
|
41
|
+
function writeJSON(filepath, data, backup = true) {
|
|
42
|
+
const resolvedPath = resolveHome(filepath);
|
|
43
|
+
ensureDir(path.dirname(resolvedPath));
|
|
44
|
+
if (backup && fs.existsSync(resolvedPath)) {
|
|
45
|
+
const backupPath = `${resolvedPath}.bak`;
|
|
46
|
+
fs.copyFileSync(resolvedPath, backupPath);
|
|
47
|
+
}
|
|
48
|
+
try {
|
|
49
|
+
const tempPath = `${resolvedPath}.tmp`;
|
|
50
|
+
fs.writeFileSync(tempPath, JSON.stringify(data, null, 2), "utf-8");
|
|
51
|
+
fs.renameSync(tempPath, resolvedPath);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
throw new FileWriteError(resolvedPath, error.message);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* 读取 TOML 文件
|
|
58
|
+
*/
|
|
59
|
+
function readTOML(filepath) {
|
|
60
|
+
const resolvedPath = resolveHome(filepath);
|
|
61
|
+
if (!fs.existsSync(resolvedPath)) throw new ConfigFileNotFoundError(resolvedPath);
|
|
62
|
+
try {
|
|
63
|
+
const content = fs.readFileSync(resolvedPath, "utf-8");
|
|
64
|
+
return toml.parse(content);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
throw new ConfigParseError(resolvedPath, error.message);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* 写入 TOML 文件
|
|
71
|
+
*/
|
|
72
|
+
function writeTOML(filepath, data, backup = true) {
|
|
73
|
+
const resolvedPath = resolveHome(filepath);
|
|
74
|
+
ensureDir(path.dirname(resolvedPath));
|
|
75
|
+
if (backup && fs.existsSync(resolvedPath)) {
|
|
76
|
+
const backupPath = `${resolvedPath}.bak`;
|
|
77
|
+
fs.copyFileSync(resolvedPath, backupPath);
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const tempPath = `${resolvedPath}.tmp`;
|
|
81
|
+
fs.writeFileSync(tempPath, toml.stringify(data), "utf-8");
|
|
82
|
+
fs.renameSync(tempPath, resolvedPath);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
throw new FileWriteError(resolvedPath, error.message);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 深度合并对象
|
|
89
|
+
*/
|
|
90
|
+
function deepMerge(target, source) {
|
|
91
|
+
const result = { ...target };
|
|
92
|
+
for (const key in source) if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
93
|
+
const sourceValue = source[key];
|
|
94
|
+
const targetValue = result[key];
|
|
95
|
+
if (typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) result[key] = deepMerge(targetValue, sourceValue);
|
|
96
|
+
else result[key] = sourceValue;
|
|
97
|
+
}
|
|
98
|
+
return result;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* 检查文件是否存在
|
|
102
|
+
*/
|
|
103
|
+
function fileExists(filepath) {
|
|
104
|
+
const resolvedPath = resolveHome(filepath);
|
|
105
|
+
return fs.existsSync(resolvedPath);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 获取文件信息
|
|
109
|
+
*/
|
|
110
|
+
function getFileInfo(filepath) {
|
|
111
|
+
const resolvedPath = resolveHome(filepath);
|
|
112
|
+
if (!fs.existsSync(resolvedPath)) return null;
|
|
113
|
+
const stats = fs.statSync(resolvedPath);
|
|
114
|
+
return {
|
|
115
|
+
size: stats.size,
|
|
116
|
+
lastModified: stats.mtime
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
//#endregion
|
|
121
|
+
export { readJSON as a, writeJSON as c, getFileInfo as i, writeTOML as l, ensureDir as n, readTOML as o, fileExists as r, resolveHome as s, deepMerge as t };
|
|
122
|
+
//# sourceMappingURL=fsStore-i-3731TM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fsStore-i-3731TM.js","names":[],"sources":["../src/services/settings/fsStore.ts"],"sourcesContent":["/**\n * 文件系统存储工具\n */\n\nimport * as fs from \"fs\";\nimport * as path from \"path\";\nimport * as os from \"os\";\nimport * as toml from \"@iarna/toml\";\nimport {\n ConfigFileNotFoundError,\n ConfigParseError,\n FileWriteError,\n} from \"@/utils/errors.ts\";\n\n/**\n * 解析 ~ 为用户主目录\n */\nexport function resolveHome(filepath: string): string {\n if (filepath.startsWith(\"~/\") || filepath === \"~\") {\n return path.join(os.homedir(), filepath.slice(1));\n }\n return filepath;\n}\n\n/**\n * 确保目录存在\n */\nexport function ensureDir(dirPath: string): void {\n const resolvedPath = resolveHome(dirPath);\n if (!fs.existsSync(resolvedPath)) {\n fs.mkdirSync(resolvedPath, { recursive: true });\n }\n}\n\n/**\n * 读取 JSON 文件\n */\nexport function readJSON(filepath: string): Record<string, unknown> {\n const resolvedPath = resolveHome(filepath);\n\n if (!fs.existsSync(resolvedPath)) {\n throw new ConfigFileNotFoundError(resolvedPath);\n }\n\n try {\n const content = fs.readFileSync(resolvedPath, \"utf-8\");\n return JSON.parse(content);\n } catch (error) {\n throw new ConfigParseError(resolvedPath, (error as Error).message);\n }\n}\n\n/**\n * 写入 JSON 文件\n */\nexport function writeJSON(\n filepath: string,\n data: Record<string, unknown>,\n backup = true,\n): void {\n const resolvedPath = resolveHome(filepath);\n\n // 确保目录存在\n ensureDir(path.dirname(resolvedPath));\n\n // 备份现有文件\n if (backup && fs.existsSync(resolvedPath)) {\n const backupPath = `${resolvedPath}.bak`;\n fs.copyFileSync(resolvedPath, backupPath);\n }\n\n try {\n // 原子写入:先写临时文件,再重命名\n const tempPath = `${resolvedPath}.tmp`;\n fs.writeFileSync(tempPath, JSON.stringify(data, null, 2), \"utf-8\");\n fs.renameSync(tempPath, resolvedPath);\n } catch (error) {\n throw new FileWriteError(resolvedPath, (error as Error).message);\n }\n}\n\n/**\n * 读取 TOML 文件\n */\nexport function readTOML(filepath: string): Record<string, unknown> {\n const resolvedPath = resolveHome(filepath);\n\n if (!fs.existsSync(resolvedPath)) {\n throw new ConfigFileNotFoundError(resolvedPath);\n }\n\n try {\n const content = fs.readFileSync(resolvedPath, \"utf-8\");\n return toml.parse(content) as Record<string, unknown>;\n } catch (error) {\n throw new ConfigParseError(resolvedPath, (error as Error).message);\n }\n}\n\n/**\n * 写入 TOML 文件\n */\nexport function writeTOML(\n filepath: string,\n data: Record<string, unknown>,\n backup = true,\n): void {\n const resolvedPath = resolveHome(filepath);\n\n // 确保目录存在\n ensureDir(path.dirname(resolvedPath));\n\n // 备份现有文件\n if (backup && fs.existsSync(resolvedPath)) {\n const backupPath = `${resolvedPath}.bak`;\n fs.copyFileSync(resolvedPath, backupPath);\n }\n\n try {\n // 原子写入\n const tempPath = `${resolvedPath}.tmp`;\n fs.writeFileSync(tempPath, toml.stringify(data as any), \"utf-8\");\n fs.renameSync(tempPath, resolvedPath);\n } catch (error) {\n throw new FileWriteError(resolvedPath, (error as Error).message);\n }\n}\n\n/**\n * 深度合并对象\n */\nexport function deepMerge(\n target: Record<string, unknown>,\n source: Record<string, unknown>,\n): Record<string, unknown> {\n const result = { ...target };\n\n for (const key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n const sourceValue = source[key];\n const targetValue = result[key];\n\n if (\n typeof sourceValue === \"object\" &&\n sourceValue !== null &&\n !Array.isArray(sourceValue) &&\n typeof targetValue === \"object\" &&\n targetValue !== null &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(\n targetValue as Record<string, unknown>,\n sourceValue as Record<string, unknown>,\n );\n } else {\n result[key] = sourceValue;\n }\n }\n }\n\n return result;\n}\n\n/**\n * 检查文件是否存在\n */\nexport function fileExists(filepath: string): boolean {\n const resolvedPath = resolveHome(filepath);\n return fs.existsSync(resolvedPath);\n}\n\n/**\n * 获取文件信息\n */\nexport function getFileInfo(filepath: string) {\n const resolvedPath = resolveHome(filepath);\n if (!fs.existsSync(resolvedPath)) {\n return null;\n }\n\n const stats = fs.statSync(resolvedPath);\n return {\n size: stats.size,\n lastModified: stats.mtime,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { t as BaseAdapter } from "./base-Cm9xh6sW.js";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as os from "os";
|
|
4
|
+
|
|
5
|
+
//#region src/services/settings/adapters/gemini.ts
|
|
6
|
+
/**
|
|
7
|
+
* Gemini CLI 配置适配器
|
|
8
|
+
*
|
|
9
|
+
* 配置文件路径:
|
|
10
|
+
* - user: ~/.gemini/settings.json
|
|
11
|
+
* - project: <cwd>/.gemini/settings.json
|
|
12
|
+
* - system: 平台相关路径
|
|
13
|
+
*/
|
|
14
|
+
var GeminiAdapter = class extends BaseAdapter {
|
|
15
|
+
toolId = "gemini";
|
|
16
|
+
/**
|
|
17
|
+
* 解析配置文件路径
|
|
18
|
+
*/
|
|
19
|
+
resolvePath(scope) {
|
|
20
|
+
switch (scope) {
|
|
21
|
+
case "user": return "~/.gemini/settings.json";
|
|
22
|
+
case "project": return ".gemini/settings.json";
|
|
23
|
+
case "system": return this.getSystemConfigPath();
|
|
24
|
+
default: throw new Error(`Unsupported scope for Gemini: ${scope}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 验证 scope 是否有效
|
|
29
|
+
*/
|
|
30
|
+
validateScope(scope) {
|
|
31
|
+
return [
|
|
32
|
+
"user",
|
|
33
|
+
"project",
|
|
34
|
+
"system"
|
|
35
|
+
].includes(scope);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 获取系统级配置路径(跨平台)
|
|
39
|
+
*/
|
|
40
|
+
getSystemConfigPath() {
|
|
41
|
+
switch (os.platform()) {
|
|
42
|
+
case "darwin": return "/Library/Application Support/Gemini/settings.json";
|
|
43
|
+
case "win32": return path.join(process.env.PROGRAMDATA || "C:\\ProgramData", "Gemini", "settings.json");
|
|
44
|
+
case "linux": return "/etc/gemini/settings.json";
|
|
45
|
+
default: return "/etc/gemini/settings.json";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
export { GeminiAdapter as t };
|
|
52
|
+
//# sourceMappingURL=gemini-aNNm-QGE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-aNNm-QGE.js","names":[],"sources":["../src/services/settings/adapters/gemini.ts"],"sourcesContent":["/**\n * Gemini CLI 适配器\n */\n\nimport type { Scope } from \"@/domain/types.ts\";\nimport { BaseAdapter } from \"./base.ts\";\nimport * as os from \"os\";\nimport * as path from \"path\";\n\n/**\n * Gemini CLI 配置适配器\n *\n * 配置文件路径:\n * - user: ~/.gemini/settings.json\n * - project: <cwd>/.gemini/settings.json\n * - system: 平台相关路径\n */\nexport class GeminiAdapter extends BaseAdapter {\n readonly toolId = \"gemini\" as const;\n\n /**\n * 解析配置文件路径\n */\n resolvePath(scope: Scope): string {\n switch (scope) {\n case \"user\":\n return \"~/.gemini/settings.json\";\n case \"project\":\n return \".gemini/settings.json\";\n case \"system\":\n return this.getSystemConfigPath();\n default:\n throw new Error(`Unsupported scope for Gemini: ${scope}`);\n }\n }\n\n /**\n * 验证 scope 是否有效\n */\n validateScope(scope: Scope): boolean {\n return [\"user\", \"project\", \"system\"].includes(scope);\n }\n\n /**\n * 获取系统级配置路径(跨平台)\n */\n private getSystemConfigPath(): string {\n const platform = os.platform();\n\n switch (platform) {\n case \"darwin\": // macOS\n return \"/Library/Application Support/Gemini/settings.json\";\n case \"win32\": // Windows\n return path.join(\n process.env.PROGRAMDATA || \"C:\\\\ProgramData\",\n \"Gemini\",\n \"settings.json\",\n );\n case \"linux\":\n return \"/etc/gemini/settings.json\";\n default:\n return \"/etc/gemini/settings.json\";\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,IAAa,gBAAb,cAAmC,YAAY;CAC7C,AAAS,SAAS;;;;CAKlB,YAAY,OAAsB;AAChC,UAAQ,OAAR;GACE,KAAK,OACH,QAAO;GACT,KAAK,UACH,QAAO;GACT,KAAK,SACH,QAAO,KAAK,qBAAqB;GACnC,QACE,OAAM,IAAI,MAAM,iCAAiC,QAAQ;;;;;;CAO/D,cAAc,OAAuB;AACnC,SAAO;GAAC;GAAQ;GAAW;GAAS,CAAC,SAAS,MAAM;;;;;CAMtD,AAAQ,sBAA8B;AAGpC,UAFiB,GAAG,UAAU,EAE9B;GACE,KAAK,SACH,QAAO;GACT,KAAK,QACH,QAAO,KAAK,KACV,QAAQ,IAAI,eAAe,mBAC3B,UACA,gBACD;GACH,KAAK,QACH,QAAO;GACT,QACE,QAAO"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { d as ToolId, i as Scope, l as SettingsResult, n as InspectResult, s as SettingsListData, t as EditOptions, u as SwitchOptions } from "./types-BfNSo2rs.js";
|
|
2
|
+
|
|
3
|
+
//#region src/domain/interfaces.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Settings 适配器接口
|
|
7
|
+
* 所有工具适配器必须实现此接口(LSP 原则)
|
|
8
|
+
*/
|
|
9
|
+
interface SettingsAdapter {
|
|
10
|
+
/**
|
|
11
|
+
* 工具标识符
|
|
12
|
+
*/
|
|
13
|
+
readonly toolId: ToolId;
|
|
14
|
+
/**
|
|
15
|
+
* 列出指定 scope 的所有配置
|
|
16
|
+
*/
|
|
17
|
+
list(scope: Scope): Promise<SettingsListData>;
|
|
18
|
+
/**
|
|
19
|
+
* 切换 profile(可选,仅 Codex 支持)
|
|
20
|
+
*/
|
|
21
|
+
switchProfile?(scope: Scope, profile: string, options?: SwitchOptions): Promise<SettingsResult>;
|
|
22
|
+
/**
|
|
23
|
+
* 打开配置文件供编辑(可选)
|
|
24
|
+
*/
|
|
25
|
+
edit?(scope: Scope, options: EditOptions): Promise<SettingsResult>;
|
|
26
|
+
/**
|
|
27
|
+
* 检查配置文件状态
|
|
28
|
+
*/
|
|
29
|
+
inspect?(scope: Scope): Promise<InspectResult>;
|
|
30
|
+
/**
|
|
31
|
+
* 解析配置文件路径
|
|
32
|
+
*/
|
|
33
|
+
resolvePath(scope: Scope): string;
|
|
34
|
+
/**
|
|
35
|
+
* 验证 scope 是否有效
|
|
36
|
+
*/
|
|
37
|
+
validateScope(scope: Scope): boolean;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { SettingsAdapter as t };
|
|
41
|
+
//# sourceMappingURL=interfaces-CriQW6hF.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interfaces-CriQW6hF.d.ts","names":[],"sources":["../src/domain/interfaces.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAiCW,UAfM,eAAA,CAeN;EAEG;;;EAMC,SAAA,MAAA,EAnBI,MAmBJ;EAAgB;;;EAKb,IAAA,CAAA,KAAA,EAnBJ,KAmBI,CAAA,EAnBI,OAmBJ,CAnBY,gBAmBZ,CAAA;EAAgB;;;EAUX,aAAA,EAAA,KAAA,EAvBZ,KAuBY,EAAA,OAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EArBT,aAqBS,CAAA,EApBlB,OAoBkB,CApBV,cAoBU,CAAA;EAAK;;;eAfb,gBAAgB,cAAc,QAAQ;;;;kBAKnC,QAAQ,QAAQ;;;;qBAKb;;;;uBAKE"}
|
package/dist/run.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/run.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execute } from "@oclif/core";
|
|
3
|
+
|
|
4
|
+
//#region src/run.ts
|
|
5
|
+
/**
|
|
6
|
+
* xling CLI 入口点
|
|
7
|
+
*/
|
|
8
|
+
await execute({
|
|
9
|
+
development: false,
|
|
10
|
+
dir: import.meta.url
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { };
|
|
15
|
+
//# sourceMappingURL=run.js.map
|
package/dist/run.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","names":[],"sources":["../src/run.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * xling CLI 入口点\n */\n\nimport { execute } from \"@oclif/core\";\n\nawait execute({ development: false, dir: import.meta.url });\n"],"mappings":";;;;;;;AAQA,MAAM,QAAQ;CAAE,aAAa;CAAO,KAAK,OAAO,KAAK;CAAK,CAAC"}
|