codeksei 0.1.0 → 0.1.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/LICENSE +661 -661
- package/README.en.md +109 -47
- package/README.md +79 -58
- package/bin/cyberboss.js +1 -1
- package/package.json +86 -86
- package/scripts/open_shared_wechat_thread.sh +77 -77
- package/scripts/open_wechat_thread.sh +108 -108
- package/scripts/shared-common.js +144 -144
- package/scripts/shared-open.js +14 -14
- package/scripts/shared-start.js +5 -5
- package/scripts/shared-status.js +27 -27
- package/scripts/show_shared_status.sh +45 -45
- package/scripts/start_shared_app_server.sh +52 -52
- package/scripts/start_shared_wechat.sh +94 -94
- package/scripts/timeline-screenshot.sh +14 -14
- package/src/adapters/channel/weixin/account-store.js +99 -99
- package/src/adapters/channel/weixin/api-v2.js +50 -50
- package/src/adapters/channel/weixin/api.js +169 -169
- package/src/adapters/channel/weixin/context-token-store.js +84 -84
- package/src/adapters/channel/weixin/index.js +618 -604
- package/src/adapters/channel/weixin/legacy.js +579 -566
- package/src/adapters/channel/weixin/media-mime.js +22 -22
- package/src/adapters/channel/weixin/media-receive.js +370 -370
- package/src/adapters/channel/weixin/media-send.js +102 -102
- package/src/adapters/channel/weixin/message-utils-v2.js +282 -282
- package/src/adapters/channel/weixin/message-utils.js +199 -199
- package/src/adapters/channel/weixin/redact.js +41 -41
- package/src/adapters/channel/weixin/reminder-queue-store.js +101 -101
- package/src/adapters/channel/weixin/sync-buffer-store.js +35 -35
- package/src/adapters/runtime/codex/events.js +215 -215
- package/src/adapters/runtime/codex/index.js +109 -104
- package/src/adapters/runtime/codex/message-utils.js +95 -95
- package/src/adapters/runtime/codex/model-catalog.js +106 -106
- package/src/adapters/runtime/codex/protocol-leak-monitor.js +75 -75
- package/src/adapters/runtime/codex/rpc-client.js +339 -339
- package/src/adapters/runtime/codex/session-store.js +286 -286
- package/src/app/channel-send-file-cli.js +57 -57
- package/src/app/diary-write-cli.js +236 -88
- package/src/app/note-sync-cli.js +2 -2
- package/src/app/reminder-write-cli.js +215 -210
- package/src/app/review-cli.js +7 -5
- package/src/app/system-checkin-poller.js +64 -64
- package/src/app/system-send-cli.js +129 -129
- package/src/app/timeline-event-cli.js +28 -25
- package/src/app/timeline-screenshot-cli.js +103 -100
- package/src/core/app.js +1763 -1763
- package/src/core/branding.js +2 -1
- package/src/core/command-registry.js +381 -369
- package/src/core/config.js +30 -14
- package/src/core/default-targets.js +163 -163
- package/src/core/durable-note-schema.js +9 -8
- package/src/core/instructions-template.js +17 -16
- package/src/core/note-sync.js +8 -7
- package/src/core/path-utils.js +54 -0
- package/src/core/project-radar.js +11 -10
- package/src/core/review.js +48 -50
- package/src/core/stream-delivery.js +1162 -983
- package/src/core/system-message-dispatcher.js +68 -68
- package/src/core/system-message-queue-store.js +128 -128
- package/src/core/thread-state-store.js +96 -96
- package/src/core/timeline-screenshot-queue-store.js +134 -134
- package/src/core/timezone.js +436 -0
- package/src/core/workspace-bootstrap.js +9 -1
- package/src/index.js +148 -146
- package/src/integrations/timeline/index.js +130 -74
- package/src/integrations/timeline/state-sync.js +240 -0
- package/templates/weixin-instructions.md +12 -38
- package/templates/weixin-operations.md +29 -31
package/src/core/config.js
CHANGED
|
@@ -8,12 +8,19 @@ const {
|
|
|
8
8
|
resolveAppHome,
|
|
9
9
|
resolveStateDir,
|
|
10
10
|
} = require("./branding");
|
|
11
|
+
const { resolveCrossPlatformPathFromRoot } = require("./path-utils");
|
|
12
|
+
const { resolveTimezoneConfig } = require("./timezone");
|
|
11
13
|
|
|
12
14
|
function readConfig() {
|
|
13
15
|
const argv = process.argv.slice(2);
|
|
14
16
|
const mode = argv[0] || "";
|
|
15
17
|
const stateDir = resolveStateDir({ env: process.env });
|
|
16
18
|
const workspaceRoot = readPrefixedEnv(process.env, "WORKSPACE_ROOT") || process.cwd();
|
|
19
|
+
const timelineStateDir = readPrefixedEnv(process.env, "TIMELINE_STATE_DIR") || stateDir;
|
|
20
|
+
const timezoneConfig = resolveTimezoneConfig({
|
|
21
|
+
explicitTimezone: readPrefixedEnv(process.env, "TIMEZONE"),
|
|
22
|
+
timelineStateDir,
|
|
23
|
+
});
|
|
17
24
|
const appHome = resolveAppHome({
|
|
18
25
|
env: process.env,
|
|
19
26
|
fallbackRoot: path.resolve(__dirname, "..", ".."),
|
|
@@ -27,8 +34,12 @@ function readConfig() {
|
|
|
27
34
|
cyberbossHome: appHome,
|
|
28
35
|
workspaceId: readPrefixedEnv(process.env, "WORKSPACE_ID") || "default",
|
|
29
36
|
workspaceRoot,
|
|
37
|
+
timezone: timezoneConfig.timezone,
|
|
38
|
+
timezoneSource: timezoneConfig.source,
|
|
39
|
+
timezoneExplicit: timezoneConfig.explicit,
|
|
40
|
+
timelineStateTimezone: timezoneConfig.timelineStateTimezone,
|
|
30
41
|
diaryDir: readPrefixedEnv(process.env, "DIARY_DIR") || path.join(stateDir, "diary"),
|
|
31
|
-
timelineStateDir
|
|
42
|
+
timelineStateDir,
|
|
32
43
|
userName: readPrefixedEnv(process.env, "USER_NAME") || "用户",
|
|
33
44
|
userGender: readPrefixedEnv(process.env, "USER_GENDER") || "female",
|
|
34
45
|
allowedUserIds: readPrefixedListEnv(process.env, "ALLOWED_USER_IDS"),
|
|
@@ -47,10 +58,15 @@ function readConfig() {
|
|
|
47
58
|
accountsDir: path.join(stateDir, "accounts"),
|
|
48
59
|
logDir: path.join(stateDir, "logs"),
|
|
49
60
|
reminderQueueFile: path.join(stateDir, "reminder-queue.json"),
|
|
50
|
-
systemMessageQueueFile: path.join(stateDir, "system-message-queue.json"),
|
|
51
|
-
timelineScreenshotQueueFile: path.join(stateDir, "timeline-screenshot-queue.json"),
|
|
52
|
-
weixinInstructionsFile:
|
|
61
|
+
systemMessageQueueFile: path.join(stateDir, "system-message-queue.json"),
|
|
62
|
+
timelineScreenshotQueueFile: path.join(stateDir, "timeline-screenshot-queue.json"),
|
|
63
|
+
weixinInstructionsFile: readPrefixedEnv(process.env, "WEIXIN_INSTRUCTIONS_FILE")
|
|
64
|
+
|| path.resolve(__dirname, "..", "..", "templates", "weixin-instructions.md"),
|
|
65
|
+
weixinInstructionsOverlayFile: readPrefixedEnv(process.env, "WEIXIN_INSTRUCTIONS_OVERLAY_FILE")
|
|
66
|
+
|| path.join(stateDir, "weixin-instructions.local.md"),
|
|
53
67
|
weixinOperationsFile: path.resolve(__dirname, "..", "..", "templates", "weixin-operations.md"),
|
|
68
|
+
weixinOperationsOverlayFile: readPrefixedEnv(process.env, "WEIXIN_OPERATIONS_OVERLAY_FILE")
|
|
69
|
+
|| path.join(stateDir, "weixin-operations.local.md"),
|
|
54
70
|
syncBufferDir: path.join(stateDir, "sync-buffers"),
|
|
55
71
|
codexEndpoint: readPrefixedEnv(process.env, "CODEX_ENDPOINT"),
|
|
56
72
|
codexCommand: readPrefixedEnv(process.env, "CODEX_COMMAND"),
|
|
@@ -59,11 +75,11 @@ function readConfig() {
|
|
|
59
75
|
workspaceBootstrapConfigFile: readPrefixedEnv(process.env, "WORKSPACE_BOOTSTRAP_CONFIG")
|
|
60
76
|
|| path.join(stateDir, "workspace-bootstrap.json"),
|
|
61
77
|
projectRadarConfigFile: readPrefixedEnv(process.env, "PROJECT_RADAR_CONFIG")
|
|
62
|
-
||
|
|
78
|
+
|| resolveCrossPlatformPathFromRoot(workspaceRoot, ".codex", "code-projects.json"),
|
|
63
79
|
durableNoteSchemaConfigFile: readPrefixedEnv(process.env, "DURABLE_NOTE_SCHEMA_CONFIG")
|
|
64
|
-
||
|
|
80
|
+
|| resolveCrossPlatformPathFromRoot(workspaceRoot, ".codex", "durable-note-schema.json"),
|
|
65
81
|
reviewSchemaConfigFile: readPrefixedEnv(process.env, "REVIEW_SCHEMA_CONFIG")
|
|
66
|
-
||
|
|
82
|
+
|| resolveCrossPlatformPathFromRoot(workspaceRoot, ".codex", "review-schema.json"),
|
|
67
83
|
reviewSemanticMode: readPrefixedEnv(process.env, "REVIEW_SEMANTIC_MODE") || "hybrid",
|
|
68
84
|
reviewSemanticModel: readPrefixedEnv(process.env, "REVIEW_SEMANTIC_MODEL"),
|
|
69
85
|
reviewSemanticTimeoutMs: readPrefixedIntEnv(process.env, "REVIEW_SEMANTIC_TIMEOUT_MS") || 120000,
|
|
@@ -72,13 +88,13 @@ function readConfig() {
|
|
|
72
88
|
startWithCheckin: (mode === "start" && hasArgFlag(argv, "--checkin")) || readPrefixedBoolEnv(process.env, "ENABLE_CHECKIN"),
|
|
73
89
|
};
|
|
74
90
|
}
|
|
75
|
-
|
|
76
|
-
function normalizeWeixinReplyMode(value) {
|
|
77
|
-
return String(value || "").trim().toLowerCase() === "settled" ? "settled" : "stream";
|
|
78
|
-
}
|
|
79
|
-
|
|
91
|
+
|
|
92
|
+
function normalizeWeixinReplyMode(value) {
|
|
93
|
+
return String(value || "").trim().toLowerCase() === "settled" ? "settled" : "stream";
|
|
94
|
+
}
|
|
95
|
+
|
|
80
96
|
function hasArgFlag(argv, flag) {
|
|
81
97
|
return Array.isArray(argv) && argv.some((item) => String(item || "").trim() === flag);
|
|
82
98
|
}
|
|
83
|
-
|
|
84
|
-
module.exports = { readConfig };
|
|
99
|
+
|
|
100
|
+
module.exports = { readConfig };
|
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
const { loadPersistedContextTokens } = require("../adapters/channel/weixin/context-token-store");
|
|
2
|
-
|
|
3
|
-
function resolvePreferredSenderId({
|
|
4
|
-
config,
|
|
5
|
-
accountId,
|
|
6
|
-
explicitUser = "",
|
|
7
|
-
sessionStore = null,
|
|
8
|
-
}) {
|
|
9
|
-
const normalizedExplicitUser = normalizeText(explicitUser);
|
|
10
|
-
if (normalizedExplicitUser) {
|
|
11
|
-
return normalizedExplicitUser;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const configuredUsers = Array.isArray(config?.allowedUserIds)
|
|
15
|
-
? config.allowedUserIds.map((value) => normalizeText(value)).filter(Boolean)
|
|
16
|
-
: [];
|
|
17
|
-
if (configuredUsers.length) {
|
|
18
|
-
return configuredUsers[0];
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const bindingCandidates = collectBindingSenderIds({ config, accountId, sessionStore });
|
|
22
|
-
if (bindingCandidates.length === 1) {
|
|
23
|
-
return bindingCandidates[0];
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const persistedUserIds = Object.keys(loadPersistedContextTokens(config, accountId) || {})
|
|
27
|
-
.map((value) => normalizeText(value))
|
|
28
|
-
.filter(Boolean);
|
|
29
|
-
if (persistedUserIds.length === 1) {
|
|
30
|
-
return persistedUserIds[0];
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return "";
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function resolvePreferredWorkspaceRoot({
|
|
37
|
-
config,
|
|
38
|
-
accountId,
|
|
39
|
-
senderId = "",
|
|
40
|
-
explicitWorkspace = "",
|
|
41
|
-
sessionStore = null,
|
|
42
|
-
}) {
|
|
43
|
-
const normalizedExplicitWorkspace = normalizeText(explicitWorkspace);
|
|
44
|
-
if (normalizedExplicitWorkspace) {
|
|
45
|
-
return normalizedExplicitWorkspace;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const normalizedSenderId = normalizeText(senderId);
|
|
49
|
-
const normalizedAccountId = normalizeText(accountId);
|
|
50
|
-
const store = sessionStore && typeof sessionStore.getBinding === "function"
|
|
51
|
-
? sessionStore
|
|
52
|
-
: null;
|
|
53
|
-
|
|
54
|
-
if (store && normalizedSenderId && normalizedAccountId) {
|
|
55
|
-
const bindingKey = store.buildBindingKey({
|
|
56
|
-
workspaceId: config.workspaceId,
|
|
57
|
-
accountId: normalizedAccountId,
|
|
58
|
-
senderId: normalizedSenderId,
|
|
59
|
-
});
|
|
60
|
-
const activeWorkspaceRoot = normalizeText(store.getActiveWorkspaceRoot(bindingKey));
|
|
61
|
-
if (activeWorkspaceRoot) {
|
|
62
|
-
return activeWorkspaceRoot;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const binding = store.getBinding(bindingKey);
|
|
66
|
-
const boundWorkspaceRoots = collectWorkspaceRoots(binding);
|
|
67
|
-
if (boundWorkspaceRoots.length === 1) {
|
|
68
|
-
return boundWorkspaceRoots[0];
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const globalWorkspaceCandidates = collectBindingWorkspaceRoots({ config, accountId, sessionStore: store });
|
|
73
|
-
if (globalWorkspaceCandidates.length === 1) {
|
|
74
|
-
return globalWorkspaceCandidates[0];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return normalizeText(config?.workspaceRoot);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function collectBindingSenderIds({ config, accountId, sessionStore }) {
|
|
81
|
-
const store = sessionStore && typeof sessionStore.getBinding === "function"
|
|
82
|
-
? sessionStore
|
|
83
|
-
: null;
|
|
84
|
-
if (!store) {
|
|
85
|
-
return [];
|
|
86
|
-
}
|
|
87
|
-
const normalizedAccountId = normalizeText(accountId);
|
|
88
|
-
if (!normalizedAccountId) {
|
|
89
|
-
return [];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const senderIds = new Set();
|
|
93
|
-
for (const binding of Object.values(store.state?.bindings || {})) {
|
|
94
|
-
const bindingAccountId = normalizeText(binding?.accountId);
|
|
95
|
-
const bindingWorkspaceId = normalizeText(binding?.workspaceId);
|
|
96
|
-
const senderId = normalizeText(binding?.senderId);
|
|
97
|
-
if (!senderId || bindingAccountId !== normalizedAccountId) {
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
if (bindingWorkspaceId && bindingWorkspaceId !== normalizeText(config?.workspaceId)) {
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
senderIds.add(senderId);
|
|
104
|
-
}
|
|
105
|
-
return Array.from(senderIds).sort((left, right) => left.localeCompare(right));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function collectBindingWorkspaceRoots({ config, accountId, sessionStore }) {
|
|
109
|
-
const store = sessionStore && typeof sessionStore.getBinding === "function"
|
|
110
|
-
? sessionStore
|
|
111
|
-
: null;
|
|
112
|
-
if (!store) {
|
|
113
|
-
return [];
|
|
114
|
-
}
|
|
115
|
-
const normalizedAccountId = normalizeText(accountId);
|
|
116
|
-
const workspaceRoots = new Set();
|
|
117
|
-
|
|
118
|
-
for (const binding of Object.values(store.state?.bindings || {})) {
|
|
119
|
-
const bindingAccountId = normalizeText(binding?.accountId);
|
|
120
|
-
const bindingWorkspaceId = normalizeText(binding?.workspaceId);
|
|
121
|
-
if (bindingAccountId !== normalizedAccountId) {
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
if (bindingWorkspaceId && bindingWorkspaceId !== normalizeText(config?.workspaceId)) {
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
for (const workspaceRoot of collectWorkspaceRoots(binding)) {
|
|
128
|
-
workspaceRoots.add(workspaceRoot);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return Array.from(workspaceRoots).sort((left, right) => left.localeCompare(right));
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function collectWorkspaceRoots(binding) {
|
|
136
|
-
const workspaceRoots = new Set();
|
|
137
|
-
const activeWorkspaceRoot = normalizeText(binding?.activeWorkspaceRoot);
|
|
138
|
-
if (activeWorkspaceRoot) {
|
|
139
|
-
workspaceRoots.add(activeWorkspaceRoot);
|
|
140
|
-
}
|
|
141
|
-
for (const workspaceRoot of Object.keys(binding?.threadIdByWorkspaceRoot || {})) {
|
|
142
|
-
const normalizedWorkspaceRoot = normalizeText(workspaceRoot);
|
|
143
|
-
if (normalizedWorkspaceRoot) {
|
|
144
|
-
workspaceRoots.add(normalizedWorkspaceRoot);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
for (const workspaceRoot of Object.keys(binding?.codexParamsByWorkspaceRoot || {})) {
|
|
148
|
-
const normalizedWorkspaceRoot = normalizeText(workspaceRoot);
|
|
149
|
-
if (normalizedWorkspaceRoot) {
|
|
150
|
-
workspaceRoots.add(normalizedWorkspaceRoot);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
return Array.from(workspaceRoots).sort((left, right) => left.localeCompare(right));
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function normalizeText(value) {
|
|
157
|
-
return typeof value === "string" ? value.trim() : "";
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
module.exports = {
|
|
161
|
-
resolvePreferredSenderId,
|
|
162
|
-
resolvePreferredWorkspaceRoot,
|
|
163
|
-
};
|
|
1
|
+
const { loadPersistedContextTokens } = require("../adapters/channel/weixin/context-token-store");
|
|
2
|
+
|
|
3
|
+
function resolvePreferredSenderId({
|
|
4
|
+
config,
|
|
5
|
+
accountId,
|
|
6
|
+
explicitUser = "",
|
|
7
|
+
sessionStore = null,
|
|
8
|
+
}) {
|
|
9
|
+
const normalizedExplicitUser = normalizeText(explicitUser);
|
|
10
|
+
if (normalizedExplicitUser) {
|
|
11
|
+
return normalizedExplicitUser;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const configuredUsers = Array.isArray(config?.allowedUserIds)
|
|
15
|
+
? config.allowedUserIds.map((value) => normalizeText(value)).filter(Boolean)
|
|
16
|
+
: [];
|
|
17
|
+
if (configuredUsers.length) {
|
|
18
|
+
return configuredUsers[0];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const bindingCandidates = collectBindingSenderIds({ config, accountId, sessionStore });
|
|
22
|
+
if (bindingCandidates.length === 1) {
|
|
23
|
+
return bindingCandidates[0];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const persistedUserIds = Object.keys(loadPersistedContextTokens(config, accountId) || {})
|
|
27
|
+
.map((value) => normalizeText(value))
|
|
28
|
+
.filter(Boolean);
|
|
29
|
+
if (persistedUserIds.length === 1) {
|
|
30
|
+
return persistedUserIds[0];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolvePreferredWorkspaceRoot({
|
|
37
|
+
config,
|
|
38
|
+
accountId,
|
|
39
|
+
senderId = "",
|
|
40
|
+
explicitWorkspace = "",
|
|
41
|
+
sessionStore = null,
|
|
42
|
+
}) {
|
|
43
|
+
const normalizedExplicitWorkspace = normalizeText(explicitWorkspace);
|
|
44
|
+
if (normalizedExplicitWorkspace) {
|
|
45
|
+
return normalizedExplicitWorkspace;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const normalizedSenderId = normalizeText(senderId);
|
|
49
|
+
const normalizedAccountId = normalizeText(accountId);
|
|
50
|
+
const store = sessionStore && typeof sessionStore.getBinding === "function"
|
|
51
|
+
? sessionStore
|
|
52
|
+
: null;
|
|
53
|
+
|
|
54
|
+
if (store && normalizedSenderId && normalizedAccountId) {
|
|
55
|
+
const bindingKey = store.buildBindingKey({
|
|
56
|
+
workspaceId: config.workspaceId,
|
|
57
|
+
accountId: normalizedAccountId,
|
|
58
|
+
senderId: normalizedSenderId,
|
|
59
|
+
});
|
|
60
|
+
const activeWorkspaceRoot = normalizeText(store.getActiveWorkspaceRoot(bindingKey));
|
|
61
|
+
if (activeWorkspaceRoot) {
|
|
62
|
+
return activeWorkspaceRoot;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const binding = store.getBinding(bindingKey);
|
|
66
|
+
const boundWorkspaceRoots = collectWorkspaceRoots(binding);
|
|
67
|
+
if (boundWorkspaceRoots.length === 1) {
|
|
68
|
+
return boundWorkspaceRoots[0];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const globalWorkspaceCandidates = collectBindingWorkspaceRoots({ config, accountId, sessionStore: store });
|
|
73
|
+
if (globalWorkspaceCandidates.length === 1) {
|
|
74
|
+
return globalWorkspaceCandidates[0];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return normalizeText(config?.workspaceRoot);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function collectBindingSenderIds({ config, accountId, sessionStore }) {
|
|
81
|
+
const store = sessionStore && typeof sessionStore.getBinding === "function"
|
|
82
|
+
? sessionStore
|
|
83
|
+
: null;
|
|
84
|
+
if (!store) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
const normalizedAccountId = normalizeText(accountId);
|
|
88
|
+
if (!normalizedAccountId) {
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const senderIds = new Set();
|
|
93
|
+
for (const binding of Object.values(store.state?.bindings || {})) {
|
|
94
|
+
const bindingAccountId = normalizeText(binding?.accountId);
|
|
95
|
+
const bindingWorkspaceId = normalizeText(binding?.workspaceId);
|
|
96
|
+
const senderId = normalizeText(binding?.senderId);
|
|
97
|
+
if (!senderId || bindingAccountId !== normalizedAccountId) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (bindingWorkspaceId && bindingWorkspaceId !== normalizeText(config?.workspaceId)) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
senderIds.add(senderId);
|
|
104
|
+
}
|
|
105
|
+
return Array.from(senderIds).sort((left, right) => left.localeCompare(right));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function collectBindingWorkspaceRoots({ config, accountId, sessionStore }) {
|
|
109
|
+
const store = sessionStore && typeof sessionStore.getBinding === "function"
|
|
110
|
+
? sessionStore
|
|
111
|
+
: null;
|
|
112
|
+
if (!store) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
const normalizedAccountId = normalizeText(accountId);
|
|
116
|
+
const workspaceRoots = new Set();
|
|
117
|
+
|
|
118
|
+
for (const binding of Object.values(store.state?.bindings || {})) {
|
|
119
|
+
const bindingAccountId = normalizeText(binding?.accountId);
|
|
120
|
+
const bindingWorkspaceId = normalizeText(binding?.workspaceId);
|
|
121
|
+
if (bindingAccountId !== normalizedAccountId) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (bindingWorkspaceId && bindingWorkspaceId !== normalizeText(config?.workspaceId)) {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
for (const workspaceRoot of collectWorkspaceRoots(binding)) {
|
|
128
|
+
workspaceRoots.add(workspaceRoot);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return Array.from(workspaceRoots).sort((left, right) => left.localeCompare(right));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function collectWorkspaceRoots(binding) {
|
|
136
|
+
const workspaceRoots = new Set();
|
|
137
|
+
const activeWorkspaceRoot = normalizeText(binding?.activeWorkspaceRoot);
|
|
138
|
+
if (activeWorkspaceRoot) {
|
|
139
|
+
workspaceRoots.add(activeWorkspaceRoot);
|
|
140
|
+
}
|
|
141
|
+
for (const workspaceRoot of Object.keys(binding?.threadIdByWorkspaceRoot || {})) {
|
|
142
|
+
const normalizedWorkspaceRoot = normalizeText(workspaceRoot);
|
|
143
|
+
if (normalizedWorkspaceRoot) {
|
|
144
|
+
workspaceRoots.add(normalizedWorkspaceRoot);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
for (const workspaceRoot of Object.keys(binding?.codexParamsByWorkspaceRoot || {})) {
|
|
148
|
+
const normalizedWorkspaceRoot = normalizeText(workspaceRoot);
|
|
149
|
+
if (normalizedWorkspaceRoot) {
|
|
150
|
+
workspaceRoots.add(normalizedWorkspaceRoot);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return Array.from(workspaceRoots).sort((left, right) => left.localeCompare(right));
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function normalizeText(value) {
|
|
157
|
+
return typeof value === "string" ? value.trim() : "";
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
module.exports = {
|
|
161
|
+
resolvePreferredSenderId,
|
|
162
|
+
resolvePreferredWorkspaceRoot,
|
|
163
|
+
};
|
|
@@ -3,6 +3,11 @@ const path = require("path");
|
|
|
3
3
|
|
|
4
4
|
const { listTrackedProjects } = require("./project-radar");
|
|
5
5
|
const { appendSection, findSectionRange, resolveNoteSyncTarget } = require("./note-sync");
|
|
6
|
+
const {
|
|
7
|
+
normalizeDisplayPath,
|
|
8
|
+
resolveCrossPlatformPath,
|
|
9
|
+
resolveCrossPlatformPathFromRoot,
|
|
10
|
+
} = require("./path-utils");
|
|
6
11
|
|
|
7
12
|
function loadDurableNoteSchemaConfig(config = {}) {
|
|
8
13
|
const filePath = normalizeText(config.durableNoteSchemaConfigFile);
|
|
@@ -26,7 +31,7 @@ function loadDurableNoteSchemaConfig(config = {}) {
|
|
|
26
31
|
}
|
|
27
32
|
|
|
28
33
|
function resolveDurableNoteProfile(config = {}) {
|
|
29
|
-
const workspaceRoot =
|
|
34
|
+
const workspaceRoot = resolveCrossPlatformPath(String(config.workspaceRoot || process.cwd()));
|
|
30
35
|
const schemaConfig = loadDurableNoteSchemaConfig(config);
|
|
31
36
|
const workspaceProfile = selectWorkspaceProfile(schemaConfig.workspaces, workspaceRoot);
|
|
32
37
|
const projectDefaults = normalizeFamily(workspaceProfile?.projectDefaults);
|
|
@@ -285,10 +290,10 @@ function resolveWorkspaceNotePath(workspaceRoot, targetPath) {
|
|
|
285
290
|
if (!normalizedTargetPath) {
|
|
286
291
|
return "";
|
|
287
292
|
}
|
|
288
|
-
if (path.isAbsolute(normalizedTargetPath)) {
|
|
289
|
-
return
|
|
293
|
+
if (path.isAbsolute(normalizedTargetPath) || path.win32.isAbsolute(normalizedTargetPath)) {
|
|
294
|
+
return resolveCrossPlatformPath(normalizedTargetPath);
|
|
290
295
|
}
|
|
291
|
-
return
|
|
296
|
+
return resolveCrossPlatformPathFromRoot(workspaceRoot, ...normalizedTargetPath.split("/"));
|
|
292
297
|
}
|
|
293
298
|
|
|
294
299
|
function listAvailableScopes(profile) {
|
|
@@ -299,10 +304,6 @@ function normalizeText(value) {
|
|
|
299
304
|
return typeof value === "string" ? value.trim() : "";
|
|
300
305
|
}
|
|
301
306
|
|
|
302
|
-
function normalizeDisplayPath(targetPath) {
|
|
303
|
-
return normalizeText(targetPath).replace(/\\/g, "/");
|
|
304
|
-
}
|
|
305
|
-
|
|
306
307
|
function normalizeLineEnding(value) {
|
|
307
308
|
return String(value || "").replace(/\r\n/g, "\n");
|
|
308
309
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
function resolveUserPronoun(gender) {
|
|
2
|
-
const normalized = String(gender || "").trim().toLowerCase();
|
|
3
|
-
if (normalized === "male" || normalized === "man" || normalized === "m" || normalized === "男") {
|
|
4
|
-
return "他";
|
|
5
|
-
}
|
|
6
|
-
if (normalized === "neutral" || normalized === "nonbinary" || normalized === "nb" || normalized === "ta") {
|
|
7
|
-
return "TA";
|
|
8
|
-
}
|
|
9
|
-
return "她";
|
|
10
|
-
}
|
|
11
|
-
|
|
1
|
+
function resolveUserPronoun(gender) {
|
|
2
|
+
const normalized = String(gender || "").trim().toLowerCase();
|
|
3
|
+
if (normalized === "male" || normalized === "man" || normalized === "m" || normalized === "男") {
|
|
4
|
+
return "他";
|
|
5
|
+
}
|
|
6
|
+
if (normalized === "neutral" || normalized === "nonbinary" || normalized === "nb" || normalized === "ta") {
|
|
7
|
+
return "TA";
|
|
8
|
+
}
|
|
9
|
+
return "她";
|
|
10
|
+
}
|
|
11
|
+
|
|
12
12
|
function renderInstructionTemplate(template, config = {}) {
|
|
13
13
|
const userName = String(config?.userName || "").trim() || "用户";
|
|
14
14
|
const pronoun = resolveUserPronoun(config?.userGender);
|
|
@@ -21,11 +21,12 @@ function renderInstructionTemplate(template, config = {}) {
|
|
|
21
21
|
).trim();
|
|
22
22
|
return String(template || "")
|
|
23
23
|
.replaceAll("{{USER_NAME}}", userName)
|
|
24
|
+
.replaceAll("{{CODEKSEI_HOME}}", codekseiHome)
|
|
24
25
|
.replaceAll("{{CYBERBOSS_HOME}}", codekseiHome)
|
|
25
26
|
.replaceAll("她", pronoun);
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
module.exports = {
|
|
29
|
-
renderInstructionTemplate,
|
|
30
|
-
resolveUserPronoun,
|
|
31
|
-
};
|
|
28
|
+
|
|
29
|
+
module.exports = {
|
|
30
|
+
renderInstructionTemplate,
|
|
31
|
+
resolveUserPronoun,
|
|
32
|
+
};
|
package/src/core/note-sync.js
CHANGED
|
@@ -4,6 +4,11 @@ const {
|
|
|
4
4
|
PRIMARY_NOTE_SYNC_MARKER_PREFIX,
|
|
5
5
|
LEGACY_NOTE_SYNC_MARKER_PREFIX,
|
|
6
6
|
} = require("./branding");
|
|
7
|
+
const {
|
|
8
|
+
normalizeDisplayPath,
|
|
9
|
+
resolveCrossPlatformPath,
|
|
10
|
+
resolveCrossPlatformPathFromRoot,
|
|
11
|
+
} = require("./path-utils");
|
|
7
12
|
|
|
8
13
|
const { listTrackedProjects } = require("./project-radar");
|
|
9
14
|
|
|
@@ -42,11 +47,11 @@ function resolveNoteSyncTarget(config = {}, options = {}) {
|
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
function resolveNotePath(workspaceRoot, targetPath) {
|
|
45
|
-
if (path.isAbsolute(targetPath)) {
|
|
46
|
-
return
|
|
50
|
+
if (path.isAbsolute(targetPath) || path.win32.isAbsolute(targetPath)) {
|
|
51
|
+
return resolveCrossPlatformPath(targetPath);
|
|
47
52
|
}
|
|
48
53
|
const baseRoot = normalizeText(workspaceRoot) || process.cwd();
|
|
49
|
-
return
|
|
54
|
+
return resolveCrossPlatformPathFromRoot(baseRoot, targetPath);
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
function syncNoteFile(options = {}) {
|
|
@@ -397,10 +402,6 @@ function normalizeComparableText(value) {
|
|
|
397
402
|
return normalizeParagraphText(value).replace(/\s+/gu, " ").toLowerCase();
|
|
398
403
|
}
|
|
399
404
|
|
|
400
|
-
function normalizeDisplayPath(targetPath) {
|
|
401
|
-
return normalizeText(targetPath).replace(/\\/g, "/");
|
|
402
|
-
}
|
|
403
|
-
|
|
404
405
|
function normalizeFileEnding(value) {
|
|
405
406
|
return String(value || "").replace(/\r\n/g, "\n");
|
|
406
407
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
|
|
3
|
+
function normalizeText(value) {
|
|
4
|
+
return typeof value === "string" ? value.trim() : "";
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function normalizeDisplayPath(targetPath) {
|
|
8
|
+
return normalizeText(targetPath).replace(/\\/g, "/");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function isCrossPlatformAbsolutePath(targetPath) {
|
|
12
|
+
const normalized = normalizeText(targetPath);
|
|
13
|
+
if (!normalized) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
return path.isAbsolute(normalized) || path.win32.isAbsolute(normalized);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function resolveCrossPlatformPath(targetPath) {
|
|
20
|
+
const normalized = normalizeText(targetPath);
|
|
21
|
+
if (!normalized) {
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
if (isCrossPlatformAbsolutePath(normalized)) {
|
|
25
|
+
return normalizeDisplayPath(normalized);
|
|
26
|
+
}
|
|
27
|
+
return normalizeDisplayPath(path.resolve(normalized));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function resolveCrossPlatformPathFromRoot(rootPath, ...segments) {
|
|
31
|
+
const normalizedRoot = normalizeText(rootPath);
|
|
32
|
+
const normalizedSegments = segments
|
|
33
|
+
.flat()
|
|
34
|
+
.map((segment) => normalizeText(segment))
|
|
35
|
+
.filter(Boolean);
|
|
36
|
+
|
|
37
|
+
if (!normalizedRoot) {
|
|
38
|
+
return resolveCrossPlatformPath(path.join(...normalizedSegments));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// CI often runs on Linux even when users configure Windows absolute roots.
|
|
42
|
+
// Preserve those roots instead of reinterpreting `E:/...` as `<cwd>/E:/...`.
|
|
43
|
+
if (path.win32.isAbsolute(normalizedRoot) && !path.isAbsolute(normalizedRoot)) {
|
|
44
|
+
return normalizeDisplayPath(path.win32.resolve(normalizedRoot, ...normalizedSegments));
|
|
45
|
+
}
|
|
46
|
+
return normalizeDisplayPath(path.resolve(normalizedRoot, ...normalizedSegments));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = {
|
|
50
|
+
isCrossPlatformAbsolutePath,
|
|
51
|
+
normalizeDisplayPath,
|
|
52
|
+
resolveCrossPlatformPath,
|
|
53
|
+
resolveCrossPlatformPathFromRoot,
|
|
54
|
+
};
|
|
@@ -1,12 +1,17 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
2
|
const path = require("path");
|
|
3
3
|
const { spawnSync } = require("child_process");
|
|
4
|
+
const {
|
|
5
|
+
normalizeDisplayPath,
|
|
6
|
+
resolveCrossPlatformPath,
|
|
7
|
+
resolveCrossPlatformPathFromRoot,
|
|
8
|
+
} = require("./path-utils");
|
|
4
9
|
|
|
5
10
|
function loadProjectRadarConfig(config = {}) {
|
|
6
|
-
const workspaceRoot =
|
|
7
|
-
const configFile =
|
|
11
|
+
const workspaceRoot = resolveCrossPlatformPath(String(config.workspaceRoot || process.cwd()));
|
|
12
|
+
const configFile = resolveCrossPlatformPath(String(
|
|
8
13
|
config.projectRadarConfigFile || path.join(workspaceRoot, ".codex", "code-projects.json")
|
|
9
|
-
))
|
|
14
|
+
));
|
|
10
15
|
|
|
11
16
|
let raw = "";
|
|
12
17
|
try {
|
|
@@ -196,7 +201,7 @@ function buildMissingRepoFacts(repoRoot) {
|
|
|
196
201
|
function buildWorkspaceFileInfo(root, relativePath, kind) {
|
|
197
202
|
const normalizedRelativePath = normalizeRelativePath(relativePath);
|
|
198
203
|
const absolutePath = normalizedRelativePath
|
|
199
|
-
?
|
|
204
|
+
? resolveCrossPlatformPathFromRoot(root, ...normalizedRelativePath.split("/"))
|
|
200
205
|
: "";
|
|
201
206
|
return {
|
|
202
207
|
kind,
|
|
@@ -218,9 +223,9 @@ function normalizeProjectEntry(entry, workspaceRoot) {
|
|
|
218
223
|
slug,
|
|
219
224
|
title: normalizeText(project.title) || slug,
|
|
220
225
|
aliases: normalizeAliases(project.aliases),
|
|
221
|
-
repoRoot:
|
|
226
|
+
repoRoot: resolveCrossPlatformPath(repoRoot),
|
|
222
227
|
notePath,
|
|
223
|
-
noteAbsolutePath:
|
|
228
|
+
noteAbsolutePath: resolveCrossPlatformPathFromRoot(workspaceRoot, ...notePath.split("/")),
|
|
224
229
|
overviewFiles: normalizeRelativePathList(project.overviewFiles),
|
|
225
230
|
graphReportPath: normalizeRelativePath(project.graphReportPath),
|
|
226
231
|
timelineLabel: normalizeText(project.timelineLabel),
|
|
@@ -383,10 +388,6 @@ function normalizeCommandStderr(value) {
|
|
|
383
388
|
return String(value || "").replace(/\r\n/g, "\n").trim();
|
|
384
389
|
}
|
|
385
390
|
|
|
386
|
-
function normalizeDisplayPath(targetPath) {
|
|
387
|
-
return normalizeText(targetPath).replace(/\\/g, "/");
|
|
388
|
-
}
|
|
389
|
-
|
|
390
391
|
function normalizeText(value) {
|
|
391
392
|
return typeof value === "string" ? value.trim() : "";
|
|
392
393
|
}
|