minecodex 1.0.82 → 1.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/README.md +2 -2
- package/features/images/src/http-server.mjs +2 -1
- package/features/images/src/save-as.mjs +37 -8
- package/features/images/web/app.js +91 -80
- package/features/images/web/i18n.mjs +127 -0
- package/features/images/web/index.html +33 -33
- package/features/model-slider/README.md +7 -4
- package/features/notes/README.md +1 -1
- package/features/notes/src/http-server.mjs +31 -0
- package/features/notes/web/app.js +13 -306
- package/features/notes/web/file-icons.mjs +68 -0
- package/features/notes/web/i18n.mjs +237 -0
- package/features/notes/web/todo-drag.mjs +18 -0
- package/package.json +4 -2
- package/packages/cli/src/commands.mjs +3 -3
- package/packages/cli/src/npm-adapter.mjs +12 -4
- package/packages/cli/src/paths.mjs +36 -1
- package/packages/cli/src/platform.mjs +517 -0
- package/packages/cli/src/runtime-manager.mjs +9 -2
- package/packages/runtime-host/README.md +5 -3
- package/packages/runtime-host/src/codex-cdp.mjs +153 -0
- package/packages/runtime-host/src/codex-design-contract.mjs +116 -0
- package/packages/runtime-host/src/codex-injection.mjs +4586 -0
- package/packages/runtime-host/src/codex-runtime.mjs +63 -4930
- package/packages/runtime-host/src/host-actions.mjs +221 -0
- package/packages/runtime-host/src/main.mjs +17 -9
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
// i18n for CodexNotes web surfaces. Single source of all user-visible copy.
|
|
2
|
+
// Locale state is initialised by app.js via setLocale(); this module never touches DOM.
|
|
3
|
+
|
|
4
|
+
const SUPPORTED_LOCALES = new Set(["en", "zh-CN"]);
|
|
5
|
+
|
|
6
|
+
function normalizeLocale(value) {
|
|
7
|
+
const candidate = String(value ?? "").trim();
|
|
8
|
+
if (candidate.toLowerCase().startsWith("zh")) return "zh-CN";
|
|
9
|
+
return SUPPORTED_LOCALES.has(candidate) ? candidate : "en";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let locale = "en";
|
|
13
|
+
|
|
14
|
+
export function getLocale() {
|
|
15
|
+
return locale;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function setLocale(value) {
|
|
19
|
+
const next = normalizeLocale(value);
|
|
20
|
+
if (next === locale) return false;
|
|
21
|
+
locale = next;
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const MESSAGES = Object.freeze({
|
|
26
|
+
en: {
|
|
27
|
+
requestFailed: ({ status }) => `Request failed (${status})`,
|
|
28
|
+
temporarilyUnavailable: "CodexNotes is temporarily unavailable",
|
|
29
|
+
unavailable: "CodexNotes is unavailable",
|
|
30
|
+
retry: "Retry",
|
|
31
|
+
hostUnavailable: "Codex host is not connected",
|
|
32
|
+
hostTimeout: "Codex did not respond",
|
|
33
|
+
hostActionFailed: "Host action failed",
|
|
34
|
+
restoreTodo: "Restore Todo",
|
|
35
|
+
completeTodo: "Complete Todo",
|
|
36
|
+
edit: "Edit",
|
|
37
|
+
delete: "Delete",
|
|
38
|
+
editTodo: "Edit Todo",
|
|
39
|
+
newTodo: "New Todo",
|
|
40
|
+
todoText: "Todo text",
|
|
41
|
+
todoPlaceholder: "What do you want to remember?",
|
|
42
|
+
saveTodo: "Save Todo",
|
|
43
|
+
addTodo: "Add Todo",
|
|
44
|
+
cancel: "Cancel",
|
|
45
|
+
editPrompt: "Edit Prompt",
|
|
46
|
+
newPrompt: "New Prompt",
|
|
47
|
+
optionalTitle: "Optional title",
|
|
48
|
+
promptTitle: "Prompt title",
|
|
49
|
+
promptBody: "Prompt body",
|
|
50
|
+
promptPlaceholder: "Write a reusable prompt…",
|
|
51
|
+
savePrompt: "Save Prompt",
|
|
52
|
+
addPrompt: "Add Prompt",
|
|
53
|
+
insertPrompt: "Insert Prompt",
|
|
54
|
+
morePromptActions: "More prompt actions",
|
|
55
|
+
star: "Star",
|
|
56
|
+
unstar: "Unstar",
|
|
57
|
+
showInFolder: "Show in folder",
|
|
58
|
+
attachToChat: "Attach to chat",
|
|
59
|
+
viewAll: "View all",
|
|
60
|
+
todo: "Todo",
|
|
61
|
+
noTodo: "No Todo yet",
|
|
62
|
+
prompts: "Prompts",
|
|
63
|
+
noPrompts: "No prompts yet",
|
|
64
|
+
files: "Files",
|
|
65
|
+
pinFiles: "Pin files",
|
|
66
|
+
noPinnedFiles: "No pinned files",
|
|
67
|
+
active: "Active",
|
|
68
|
+
add: "Add",
|
|
69
|
+
nothingActive: "Nothing active",
|
|
70
|
+
completed: "Completed",
|
|
71
|
+
deleteAll: "Delete all",
|
|
72
|
+
deleteCompletedTitle: "Delete all completed Todo",
|
|
73
|
+
noCompletedTodo: "No completed Todo",
|
|
74
|
+
starred: "Starred",
|
|
75
|
+
noStarredPrompts: "No starred prompts",
|
|
76
|
+
pinnedFiles: "Pinned files",
|
|
77
|
+
loading: "Loading CodexNotes…",
|
|
78
|
+
insertedAtCaret: "Inserted at the Composer caret",
|
|
79
|
+
addedToComposer: "Added to Composer",
|
|
80
|
+
insertedFilePath: "Inserted file path",
|
|
81
|
+
filesPinned: ({ count }) => `${count} file${count === 1 ? "" : "s"} pinned`,
|
|
82
|
+
alreadyPinned: "Already pinned",
|
|
83
|
+
todoEmpty: "Todo text cannot be empty",
|
|
84
|
+
promptEmpty: "Prompt body cannot be empty",
|
|
85
|
+
editorItemMissing: "This item no longer exists.",
|
|
86
|
+
close: "Close",
|
|
87
|
+
invalidRequest: "The request is invalid",
|
|
88
|
+
invalidContentType: "The request must use JSON",
|
|
89
|
+
invalidJson: "The request body is not valid JSON",
|
|
90
|
+
bodyTooLarge: "The request is too large",
|
|
91
|
+
notFound: "The item was not found",
|
|
92
|
+
invalidOrder: "The Todo order is no longer current",
|
|
93
|
+
invalidUse: "The requested action could not be recorded",
|
|
94
|
+
fileUnavailable: "The file is unavailable",
|
|
95
|
+
fileMissing: "The source file no longer exists",
|
|
96
|
+
directoryNotAllowed: "Folders cannot be pinned; choose regular files",
|
|
97
|
+
pathNotAbsolute: "Only absolute paths can be pinned",
|
|
98
|
+
pickerUnavailable: "The system file picker is unavailable",
|
|
99
|
+
pickerFailed: "The system file picker could not be opened",
|
|
100
|
+
revealUnavailable: "Show in folder is unavailable on this platform",
|
|
101
|
+
revealFailed: "The file could not be shown in the system file manager",
|
|
102
|
+
previewUnavailable: "This file does not have an image preview",
|
|
103
|
+
previewTooLarge: "The image is too large to preview",
|
|
104
|
+
internalError: "CodexNotes could not complete the request",
|
|
105
|
+
actionNotAllowed: "This action is not available",
|
|
106
|
+
},
|
|
107
|
+
"zh-CN": {
|
|
108
|
+
requestFailed: ({ status }) => `请求失败(${status})`,
|
|
109
|
+
temporarilyUnavailable: "CodexNotes 暂时不可用",
|
|
110
|
+
unavailable: "CodexNotes 不可用",
|
|
111
|
+
retry: "重试",
|
|
112
|
+
hostUnavailable: "尚未连接 Codex 宿主",
|
|
113
|
+
hostTimeout: "Codex 未响应",
|
|
114
|
+
hostActionFailed: "宿主操作失败",
|
|
115
|
+
restoreTodo: "恢复待办",
|
|
116
|
+
completeTodo: "完成待办",
|
|
117
|
+
edit: "编辑",
|
|
118
|
+
delete: "删除",
|
|
119
|
+
editTodo: "编辑待办",
|
|
120
|
+
newTodo: "新建待办",
|
|
121
|
+
todoText: "待办内容",
|
|
122
|
+
todoPlaceholder: "你想记住什么?",
|
|
123
|
+
saveTodo: "保存待办",
|
|
124
|
+
addTodo: "添加待办",
|
|
125
|
+
cancel: "取消",
|
|
126
|
+
editPrompt: "编辑提示词",
|
|
127
|
+
newPrompt: "新建提示词",
|
|
128
|
+
optionalTitle: "可选标题",
|
|
129
|
+
promptTitle: "提示词标题",
|
|
130
|
+
promptBody: "提示词正文",
|
|
131
|
+
promptPlaceholder: "编写一条可复用的提示词…",
|
|
132
|
+
savePrompt: "保存提示词",
|
|
133
|
+
addPrompt: "添加提示词",
|
|
134
|
+
insertPrompt: "插入提示词",
|
|
135
|
+
morePromptActions: "更多提示词操作",
|
|
136
|
+
star: "收藏",
|
|
137
|
+
unstar: "取消收藏",
|
|
138
|
+
showInFolder: "在文件夹中显示",
|
|
139
|
+
attachToChat: "添加到对话",
|
|
140
|
+
viewAll: "查看全部",
|
|
141
|
+
todo: "待办",
|
|
142
|
+
noTodo: "暂无待办",
|
|
143
|
+
prompts: "提示词",
|
|
144
|
+
noPrompts: "暂无提示词",
|
|
145
|
+
files: "文件",
|
|
146
|
+
pinFiles: "固定文件",
|
|
147
|
+
noPinnedFiles: "暂无固定文件",
|
|
148
|
+
active: "进行中",
|
|
149
|
+
add: "添加",
|
|
150
|
+
nothingActive: "暂无进行中的待办",
|
|
151
|
+
completed: "已完成",
|
|
152
|
+
deleteAll: "全部删除",
|
|
153
|
+
deleteCompletedTitle: "删除全部已完成待办",
|
|
154
|
+
noCompletedTodo: "暂无已完成待办",
|
|
155
|
+
starred: "已收藏",
|
|
156
|
+
noStarredPrompts: "暂无收藏的提示词",
|
|
157
|
+
pinnedFiles: "已固定文件",
|
|
158
|
+
loading: "正在加载 CodexNotes…",
|
|
159
|
+
insertedAtCaret: "已插入到消息输入框光标处",
|
|
160
|
+
addedToComposer: "已添加到消息输入框",
|
|
161
|
+
insertedFilePath: "已插入文件路径",
|
|
162
|
+
filesPinned: ({ count }) => `已固定 ${count} 个文件`,
|
|
163
|
+
alreadyPinned: "文件已固定",
|
|
164
|
+
todoEmpty: "待办内容不能为空",
|
|
165
|
+
promptEmpty: "提示词正文不能为空",
|
|
166
|
+
editorItemMissing: "该项目已不存在。",
|
|
167
|
+
close: "关闭",
|
|
168
|
+
invalidRequest: "请求无效",
|
|
169
|
+
invalidContentType: "请求必须使用 JSON",
|
|
170
|
+
invalidJson: "请求正文不是有效的 JSON",
|
|
171
|
+
bodyTooLarge: "请求内容过大",
|
|
172
|
+
notFound: "找不到该项目",
|
|
173
|
+
invalidOrder: "待办顺序已发生变化",
|
|
174
|
+
invalidUse: "无法记录这次操作",
|
|
175
|
+
fileUnavailable: "文件不可用",
|
|
176
|
+
fileMissing: "源文件已不存在",
|
|
177
|
+
directoryNotAllowed: "不能固定文件夹,请选择普通文件",
|
|
178
|
+
pathNotAbsolute: "只能固定绝对路径",
|
|
179
|
+
pickerUnavailable: "系统文件选择器不可用",
|
|
180
|
+
pickerFailed: "无法打开系统文件选择器",
|
|
181
|
+
revealUnavailable: "当前平台不支持在文件夹中显示",
|
|
182
|
+
revealFailed: "无法在系统文件管理器中显示该文件",
|
|
183
|
+
previewUnavailable: "该文件没有图片预览",
|
|
184
|
+
previewTooLarge: "图片过大,无法预览",
|
|
185
|
+
internalError: "CodexNotes 无法完成请求",
|
|
186
|
+
actionNotAllowed: "当前操作不可用",
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
export function t(key, params = {}) {
|
|
191
|
+
const value = MESSAGES[locale]?.[key] ?? MESSAGES.en[key] ?? key;
|
|
192
|
+
return typeof value === "function" ? value(params) : value;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const ERROR_MESSAGE_KEYS = Object.freeze({
|
|
196
|
+
ACTION_NOT_ALLOWED: "actionNotAllowed",
|
|
197
|
+
BODY_TOO_LARGE: "bodyTooLarge",
|
|
198
|
+
DIRECTORY_NOT_ALLOWED: "directoryNotAllowed",
|
|
199
|
+
EMPTY_BODY: "invalidRequest",
|
|
200
|
+
FILE_MISSING: "fileMissing",
|
|
201
|
+
FILE_UNAVAILABLE: "fileUnavailable",
|
|
202
|
+
HOST_ACTION_FAILED: "hostActionFailed",
|
|
203
|
+
HOST_NOT_ALLOWED: "actionNotAllowed",
|
|
204
|
+
HOST_TIMEOUT: "hostTimeout",
|
|
205
|
+
HOST_UNAVAILABLE: "hostUnavailable",
|
|
206
|
+
INTERNAL_ERROR: "internalError",
|
|
207
|
+
INVALID_BODY: "invalidRequest",
|
|
208
|
+
INVALID_CHANGES: "invalidRequest",
|
|
209
|
+
INVALID_COMPLETED: "invalidRequest",
|
|
210
|
+
INVALID_CONTENT_TYPE: "invalidContentType",
|
|
211
|
+
INVALID_ID: "invalidRequest",
|
|
212
|
+
INVALID_JSON: "invalidJson",
|
|
213
|
+
INVALID_ORDER: "invalidOrder",
|
|
214
|
+
INVALID_PATHS: "invalidRequest",
|
|
215
|
+
INVALID_REQUEST: "invalidRequest",
|
|
216
|
+
INVALID_SURFACE: "invalidRequest",
|
|
217
|
+
INVALID_ORIGIN: "actionNotAllowed",
|
|
218
|
+
INVALID_STAR: "invalidRequest",
|
|
219
|
+
INVALID_TITLE: "invalidRequest",
|
|
220
|
+
INVALID_USE: "invalidUse",
|
|
221
|
+
NOT_FOUND: "notFound",
|
|
222
|
+
ORIGIN_NOT_ALLOWED: "actionNotAllowed",
|
|
223
|
+
PATH_NOT_ABSOLUTE: "pathNotAbsolute",
|
|
224
|
+
PICKER_FAILED: "pickerFailed",
|
|
225
|
+
PICKER_UNAVAILABLE: "pickerUnavailable",
|
|
226
|
+
PREVIEW_TOO_LARGE: "previewTooLarge",
|
|
227
|
+
PREVIEW_UNAVAILABLE: "previewUnavailable",
|
|
228
|
+
REVEAL_FAILED: "revealFailed",
|
|
229
|
+
REVEAL_UNAVAILABLE: "revealUnavailable",
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
export function localizedErrorMessage(code, fallback, params = {}) {
|
|
233
|
+
const key = ERROR_MESSAGE_KEYS[code];
|
|
234
|
+
return key ? t(key, params) : fallback;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export { SUPPORTED_LOCALES, normalizeLocale };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Todo 拖拽排序纯算法:drop 位置判定与顺序重排。
|
|
2
|
+
// 不触碰 DOM/状态,仅输入计算;app.js 的拖拽事件处理调用它们。
|
|
3
|
+
|
|
4
|
+
function todoDropPosition(event, row) {
|
|
5
|
+
const rect = row.getBoundingClientRect();
|
|
6
|
+
return event.clientY < rect.top + rect.height / 2 ? "before" : "after";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function reorderedTodoIds(ids, draggedId, targetId, position) {
|
|
10
|
+
if (!ids.includes(draggedId) || !ids.includes(targetId) || draggedId === targetId) return ids;
|
|
11
|
+
const reordered = ids.filter((id) => id !== draggedId);
|
|
12
|
+
const targetIndex = reordered.indexOf(targetId);
|
|
13
|
+
const insertAt = targetIndex + (position === "after" ? 1 : 0);
|
|
14
|
+
reordered.splice(insertAt, 0, draggedId);
|
|
15
|
+
return reordered;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { todoDropPosition, reorderedTodoIds };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minecodex",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Lightweight, local-first plugins for the Codex desktop app.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -63,9 +63,11 @@
|
|
|
63
63
|
"codex",
|
|
64
64
|
"minecodex",
|
|
65
65
|
"macos",
|
|
66
|
+
"windows",
|
|
66
67
|
"plugins"
|
|
67
68
|
],
|
|
68
69
|
"os": [
|
|
69
|
-
"darwin"
|
|
70
|
+
"darwin",
|
|
71
|
+
"win32"
|
|
70
72
|
]
|
|
71
73
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { access, readFile, rm } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { createInterface } from "node:readline/promises";
|
|
4
|
-
import { assertNodeSupported,
|
|
4
|
+
import { assertNodeSupported, createPlatformAdapter } from "./platform.mjs";
|
|
5
5
|
import { ensureConfig, ensureControlToken, readConfig } from "./config.mjs";
|
|
6
6
|
import { createControlServer } from "./control-server.mjs";
|
|
7
7
|
import { createProgressReporter } from "./progress.mjs";
|
|
@@ -81,7 +81,7 @@ function printHelp(output = console.log) {
|
|
|
81
81
|
Usage: mcx <command>
|
|
82
82
|
|
|
83
83
|
Commands:
|
|
84
|
-
mcx install Install or repair MineCodex on macOS
|
|
84
|
+
mcx install Install or repair MineCodex on macOS or Windows
|
|
85
85
|
mcx uninstall [--purge] Remove integration; preserve data unless --purge is used
|
|
86
86
|
mcx update Update to the latest stable npm release
|
|
87
87
|
mcx open Open the MineCodex plugin control panel
|
|
@@ -427,7 +427,7 @@ async function serveCommand({ paths, platform, logger }) {
|
|
|
427
427
|
|
|
428
428
|
export async function runCli(argv, {
|
|
429
429
|
paths = resolvePaths(),
|
|
430
|
-
platform =
|
|
430
|
+
platform = createPlatformAdapter(),
|
|
431
431
|
cliPath = process.argv[1],
|
|
432
432
|
output = console.log,
|
|
433
433
|
logger = console,
|
|
@@ -6,17 +6,25 @@ import { promisify } from "node:util";
|
|
|
6
6
|
|
|
7
7
|
const defaultExecFile = promisify(execFileCallback);
|
|
8
8
|
|
|
9
|
-
export function createNpmAdapter({ execFile = defaultExecFile, tempRoot = os.tmpdir() } = {}) {
|
|
9
|
+
export function createNpmAdapter({ execFile = defaultExecFile, tempRoot = os.tmpdir(), platform = process.platform } = {}) {
|
|
10
|
+
function runNpm(args) {
|
|
11
|
+
if (platform !== "win32") return execFile("npm", args);
|
|
12
|
+
// npm.cmd 需要命令解释器;字面量参数经编码传递,避免路径被当成脚本。
|
|
13
|
+
const quote = (value) => "'" + String(value).replaceAll("'", "''") + "'";
|
|
14
|
+
const script = "[Console]::OutputEncoding=[Text.Encoding]::UTF8; $ErrorActionPreference='Stop'; & npm.cmd "
|
|
15
|
+
+ args.map(quote).join(" ") + "; exit $LASTEXITCODE";
|
|
16
|
+
return execFile("powershell.exe", ["-NoProfile", "-NonInteractive", "-EncodedCommand", Buffer.from(script, "utf16le").toString("base64")]);
|
|
17
|
+
}
|
|
10
18
|
return {
|
|
11
19
|
async viewLatestVersion() {
|
|
12
|
-
const { stdout } = await
|
|
20
|
+
const { stdout } = await runNpm(["view", "minecodex", "version"]);
|
|
13
21
|
return stdout.trim();
|
|
14
22
|
},
|
|
15
23
|
|
|
16
24
|
async createRollbackArchive(packageRoot) {
|
|
17
25
|
const directory = await mkdtemp(path.join(tempRoot, "minecodex-update-"));
|
|
18
26
|
try {
|
|
19
|
-
const { stdout } = await
|
|
27
|
+
const { stdout } = await runNpm(["pack", packageRoot, "--pack-destination", directory]);
|
|
20
28
|
const archiveName = stdout.trim().split("\n").filter(Boolean).at(-1);
|
|
21
29
|
if (!archiveName) throw new Error("Could not create a rollback archive for the installed MineCodex version.");
|
|
22
30
|
return {
|
|
@@ -30,7 +38,7 @@ export function createNpmAdapter({ execFile = defaultExecFile, tempRoot = os.tmp
|
|
|
30
38
|
},
|
|
31
39
|
|
|
32
40
|
async installGlobal(spec) {
|
|
33
|
-
await
|
|
41
|
+
await runNpm(["install", "-g", spec]);
|
|
34
42
|
},
|
|
35
43
|
|
|
36
44
|
async cleanup(rollback) {
|
|
@@ -7,7 +7,42 @@ export const PACKAGE_ROOT = path.resolve(
|
|
|
7
7
|
"../../..",
|
|
8
8
|
);
|
|
9
9
|
|
|
10
|
-
export function resolvePaths({ homeDir = os.homedir() } = {}) {
|
|
10
|
+
export function resolvePaths({ homeDir = os.homedir(), platform = process.platform } = {}) {
|
|
11
|
+
if (platform === "win32") {
|
|
12
|
+
// 任何宿主上跑 win32 逻辑都得到规范的 Windows 路径(Windows node 上 path.win32 === path)。
|
|
13
|
+
const winPath = path.win32;
|
|
14
|
+
const appDataDir = process.env.APPDATA ?? winPath.join(homeDir, "AppData", "Roaming");
|
|
15
|
+
const localAppDataDir = process.env.LOCALAPPDATA ?? winPath.join(homeDir, "AppData", "Local");
|
|
16
|
+
const supportDir = winPath.join(appDataDir, "MineCodex");
|
|
17
|
+
const logsDir = winPath.join(localAppDataDir, "MineCodex", "Logs");
|
|
18
|
+
const serviceDir = winPath.join(supportDir, "service");
|
|
19
|
+
return Object.freeze({
|
|
20
|
+
homeDir,
|
|
21
|
+
packageRoot: PACKAGE_ROOT,
|
|
22
|
+
featuresRoot: path.join(PACKAGE_ROOT, "features"),
|
|
23
|
+
dashboardDir: path.join(PACKAGE_ROOT, "apps", "dashboard"),
|
|
24
|
+
runtimeEntry: winPath.join(PACKAGE_ROOT, "packages", "runtime-host", "src", "main.mjs"),
|
|
25
|
+
supportDir,
|
|
26
|
+
logsDir,
|
|
27
|
+
serviceDir,
|
|
28
|
+
// Windows 无 .app 服务包;服务入口是计划任务拉起的 cmd 脚本。
|
|
29
|
+
serviceBundleSource: null,
|
|
30
|
+
serviceAppPath: winPath.join(serviceDir, "MineCodexService.cmd"),
|
|
31
|
+
serviceManagerPath: null,
|
|
32
|
+
serviceRuntimeConfigPath: winPath.join(supportDir, "service-runtime.json"),
|
|
33
|
+
configPath: winPath.join(supportDir, "config.json"),
|
|
34
|
+
tokenPath: winPath.join(supportDir, "control-token"),
|
|
35
|
+
pidPath: winPath.join(supportDir, "service.pid"),
|
|
36
|
+
codexPidPath: winPath.join(supportDir, "codex.pid"),
|
|
37
|
+
runtimeReadyPath: winPath.join(supportDir, "runtime-ready.json"),
|
|
38
|
+
profileDir: winPath.join(localAppDataDir, "MineCodex", "codex-profile"),
|
|
39
|
+
launchAgentPath: null,
|
|
40
|
+
serviceLogPath: winPath.join(logsDir, "runtime.log"),
|
|
41
|
+
serviceErrorLogPath: winPath.join(logsDir, "runtime-error.log"),
|
|
42
|
+
notesDataDir: winPath.join(appDataDir, "CodexNotes"),
|
|
43
|
+
imagesDataDir: winPath.join(homeDir, ".codex-image-host"),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
11
46
|
const supportDir = path.join(homeDir, "Library", "Application Support", "MineCodex");
|
|
12
47
|
const logsDir = path.join(homeDir, "Library", "Logs", "MineCodex");
|
|
13
48
|
const serviceDir = path.join(supportDir, "service");
|