@ccpocket/bridge 1.42.1 → 1.43.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/dist/codex-process.d.ts +2 -0
- package/dist/codex-process.js +50 -0
- package/dist/codex-process.js.map +1 -1
- package/dist/parser.d.ts +3 -0
- package/dist/parser.js +12 -0
- package/dist/parser.js.map +1 -1
- package/dist/path-utils.d.ts +1 -0
- package/dist/path-utils.js +8 -0
- package/dist/path-utils.js.map +1 -1
- package/dist/session.d.ts +2 -0
- package/dist/session.js +11 -1
- package/dist/session.js.map +1 -1
- package/dist/sessions-index.d.ts +3 -0
- package/dist/sessions-index.js +65 -0
- package/dist/sessions-index.js.map +1 -1
- package/dist/websocket.d.ts +2 -0
- package/dist/websocket.js +72 -11
- package/dist/websocket.js.map +1 -1
- package/package.json +1 -1
package/dist/websocket.js
CHANGED
|
@@ -8,7 +8,7 @@ import { SessionManager, } from "./session.js";
|
|
|
8
8
|
import { SdkProcess } from "./sdk-process.js";
|
|
9
9
|
import { CodexProcess } from "./codex-process.js";
|
|
10
10
|
import { parseClientMessage, } from "./parser.js";
|
|
11
|
-
import { getAllRecentSessions, getCodexSessionHistory, getSessionHistory, findSessionsByClaudeIds, extractMessageImages, getClaudeSessionName, loadCodexSessionNames, renameClaudeSession, renameCodexSession, } from "./sessions-index.js";
|
|
11
|
+
import { getAllRecentSessions, getCodexSessionHistory, getSessionHistory, findSessionsByClaudeIds, extractMessageImages, getClaudeSessionName, loadCodexSessionNames, renameClaudeSession, renameCodexSession, saveCodexSessionProfile, } from "./sessions-index.js";
|
|
12
12
|
import { ArchiveStore } from "./archive-store.js";
|
|
13
13
|
import { WorktreeStore } from "./worktree-store.js";
|
|
14
14
|
import { listWorktrees, removeWorktree, worktreeExists, getMainBranch, } from "./worktree.js";
|
|
@@ -20,7 +20,7 @@ import { PushRelayClient } from "./push-relay.js";
|
|
|
20
20
|
import { normalizePushLocale, t } from "./push-i18n.js";
|
|
21
21
|
import { fetchAllUsage } from "./usage.js";
|
|
22
22
|
import { getPackageVersion } from "./version.js";
|
|
23
|
-
import { isPathWithinAllowedDirectory, resolvePlatformPath, } from "./path-utils.js";
|
|
23
|
+
import { isPathWithinAllowedDirectory, resolvePlatformPath, resolvePlatformPathFrom, } from "./path-utils.js";
|
|
24
24
|
// ---- Available model lists (delivered to clients via session_list) ----
|
|
25
25
|
const CLAUDE_MODELS = [
|
|
26
26
|
"claude-opus-4-7",
|
|
@@ -256,6 +256,25 @@ export class BridgeWebSocketServer {
|
|
|
256
256
|
errorCode: "path_not_allowed",
|
|
257
257
|
};
|
|
258
258
|
}
|
|
259
|
+
normalizeAdditionalWritableRoots(roots, projectPath) {
|
|
260
|
+
if (!roots || roots.length === 0)
|
|
261
|
+
return {};
|
|
262
|
+
const normalized = new Map();
|
|
263
|
+
for (const root of roots) {
|
|
264
|
+
const trimmed = root.trim();
|
|
265
|
+
if (!trimmed)
|
|
266
|
+
continue;
|
|
267
|
+
const resolved = resolvePlatformPathFrom(projectPath, trimmed, this.platform);
|
|
268
|
+
if (!this.isPathAllowed(resolved)) {
|
|
269
|
+
return { deniedRoot: root };
|
|
270
|
+
}
|
|
271
|
+
const key = this.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
272
|
+
if (!normalized.has(key)) {
|
|
273
|
+
normalized.set(key, resolved);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return { roots: [...normalized.values()] };
|
|
277
|
+
}
|
|
259
278
|
buildSessionCreatedMessage(params) {
|
|
260
279
|
const { sessionId, provider, projectPath, session, permissionMode, executionMode, planMode, approvalsReviewer, sandboxMode, slashCommands, skills, skillMetadata, apps, appMetadata, sourceSessionId, } = params;
|
|
261
280
|
const msg = {
|
|
@@ -354,6 +373,10 @@ export class BridgeWebSocketServer {
|
|
|
354
373
|
if (session.codexSettings.webSearchMode !== undefined) {
|
|
355
374
|
msg.webSearchMode = session.codexSettings.webSearchMode;
|
|
356
375
|
}
|
|
376
|
+
if (session.codexSettings.additionalWritableRoots !== undefined) {
|
|
377
|
+
msg.additionalWritableRoots =
|
|
378
|
+
session.codexSettings.additionalWritableRoots;
|
|
379
|
+
}
|
|
357
380
|
}
|
|
358
381
|
return msg;
|
|
359
382
|
}
|
|
@@ -508,6 +531,13 @@ export class BridgeWebSocketServer {
|
|
|
508
531
|
break;
|
|
509
532
|
}
|
|
510
533
|
}
|
|
534
|
+
const additionalWritableRoots = provider === "codex"
|
|
535
|
+
? this.normalizeAdditionalWritableRoots(msg.additionalWritableRoots, projectPath)
|
|
536
|
+
: {};
|
|
537
|
+
if (additionalWritableRoots.deniedRoot) {
|
|
538
|
+
this.send(ws, this.buildPathNotAllowedError(additionalWritableRoots.deniedRoot));
|
|
539
|
+
break;
|
|
540
|
+
}
|
|
511
541
|
const cached = provider === "claude"
|
|
512
542
|
? this.sessionManager.getCachedCommands(projectPath)
|
|
513
543
|
: undefined;
|
|
@@ -553,6 +583,7 @@ export class BridgeWebSocketServer {
|
|
|
553
583
|
networkAccessEnabled: msg.networkAccessEnabled,
|
|
554
584
|
webSearchMode: msg.webSearchMode ??
|
|
555
585
|
undefined,
|
|
586
|
+
additionalWritableRoots: additionalWritableRoots.roots,
|
|
556
587
|
threadId: msg.sessionId,
|
|
557
588
|
collaborationMode: planMode
|
|
558
589
|
? "plan"
|
|
@@ -927,6 +958,11 @@ export class BridgeWebSocketServer {
|
|
|
927
958
|
if (newCollaboration !== currentCollaboration) {
|
|
928
959
|
process.setCollaborationMode(newCollaboration);
|
|
929
960
|
}
|
|
961
|
+
session.codexSettings = {
|
|
962
|
+
...(session.codexSettings ?? {}),
|
|
963
|
+
approvalPolicy: newApproval,
|
|
964
|
+
approvalsReviewer: newReviewer,
|
|
965
|
+
};
|
|
930
966
|
session.lastActivityAt = new Date();
|
|
931
967
|
this.broadcast({
|
|
932
968
|
type: "system",
|
|
@@ -1662,16 +1698,16 @@ export class BridgeWebSocketServer {
|
|
|
1662
1698
|
// Resume flow: keep past history in SessionInfo and deliver it only
|
|
1663
1699
|
// via get_history(sessionId) to avoid duplicate/missed replay races.
|
|
1664
1700
|
if (provider === "codex") {
|
|
1665
|
-
if (msg.profile &&
|
|
1666
|
-
!(await this.validateCodexProfile(msg.profile, resumeProjectPath))) {
|
|
1667
|
-
this.send(ws, {
|
|
1668
|
-
type: "error",
|
|
1669
|
-
message: `Codex profile not found: ${msg.profile}`,
|
|
1670
|
-
});
|
|
1671
|
-
break;
|
|
1672
|
-
}
|
|
1673
1701
|
const wtMapping = this.worktreeStore.get(sessionRefId);
|
|
1674
1702
|
const effectiveProjectPath = resolvePlatformPath(wtMapping?.projectPath ?? resumeProjectPath, this.platform);
|
|
1703
|
+
const effectiveProfile = msg.profile
|
|
1704
|
+
? await this.resolveCodexResumeProfile(msg.profile, sessionRefId, effectiveProjectPath)
|
|
1705
|
+
: undefined;
|
|
1706
|
+
const additionalWritableRoots = this.normalizeAdditionalWritableRoots(msg.additionalWritableRoots, effectiveProjectPath);
|
|
1707
|
+
if (additionalWritableRoots.deniedRoot) {
|
|
1708
|
+
this.send(ws, this.buildPathNotAllowedError(additionalWritableRoots.deniedRoot));
|
|
1709
|
+
break;
|
|
1710
|
+
}
|
|
1675
1711
|
let worktreeOpts;
|
|
1676
1712
|
if (wtMapping) {
|
|
1677
1713
|
if (worktreeExists(wtMapping.worktreePath)) {
|
|
@@ -1691,7 +1727,7 @@ export class BridgeWebSocketServer {
|
|
|
1691
1727
|
.then((pastMessages) => {
|
|
1692
1728
|
const sessionId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", {
|
|
1693
1729
|
threadId: sessionRefId,
|
|
1694
|
-
profile:
|
|
1730
|
+
profile: effectiveProfile,
|
|
1695
1731
|
approvalPolicy: codexApprovalPolicy ??
|
|
1696
1732
|
normalizeCodexApprovalPolicy(executionMode === "fullAccess" ? "never" : "on-request"),
|
|
1697
1733
|
approvalsReviewer: msg.approvalsReviewer,
|
|
@@ -1701,6 +1737,7 @@ export class BridgeWebSocketServer {
|
|
|
1701
1737
|
networkAccessEnabled: msg.networkAccessEnabled,
|
|
1702
1738
|
webSearchMode: msg.webSearchMode ??
|
|
1703
1739
|
undefined,
|
|
1740
|
+
additionalWritableRoots: additionalWritableRoots.roots,
|
|
1704
1741
|
collaborationMode: planMode
|
|
1705
1742
|
? "plan"
|
|
1706
1743
|
: "default",
|
|
@@ -3075,6 +3112,26 @@ export class BridgeWebSocketServer {
|
|
|
3075
3112
|
this.defaultCodexProfile = snapshot.defaultProfile;
|
|
3076
3113
|
return snapshot.profiles.includes(profile);
|
|
3077
3114
|
}
|
|
3115
|
+
async resolveCodexResumeProfile(requestedProfile, threadId, projectPath) {
|
|
3116
|
+
const snapshot = await this.loadCodexProfiles(projectPath);
|
|
3117
|
+
this.codexProfiles = snapshot.profiles;
|
|
3118
|
+
this.defaultCodexProfile = snapshot.defaultProfile;
|
|
3119
|
+
if (snapshot.profiles.includes(requestedProfile)) {
|
|
3120
|
+
return requestedProfile;
|
|
3121
|
+
}
|
|
3122
|
+
const fallbackProfile = snapshot.defaultProfile &&
|
|
3123
|
+
snapshot.profiles.includes(snapshot.defaultProfile)
|
|
3124
|
+
? snapshot.defaultProfile
|
|
3125
|
+
: undefined;
|
|
3126
|
+
console.warn(`[ws] Codex profile not found on resume: ${requestedProfile}; ` +
|
|
3127
|
+
(fallbackProfile
|
|
3128
|
+
? `falling back to default profile: ${fallbackProfile}`
|
|
3129
|
+
: "falling back to Codex config default"));
|
|
3130
|
+
saveCodexSessionProfile(threadId, fallbackProfile ?? null).catch((err) => {
|
|
3131
|
+
console.warn(`[ws] Failed to update Codex session profile cache: ${err}`);
|
|
3132
|
+
});
|
|
3133
|
+
return fallbackProfile;
|
|
3134
|
+
}
|
|
3078
3135
|
getActiveCodexProcess() {
|
|
3079
3136
|
const summary = this.sessionManager
|
|
3080
3137
|
.list()
|
|
@@ -3802,6 +3859,10 @@ export class BridgeWebSocketServer {
|
|
|
3802
3859
|
if (session.codexSettings.webSearchMode !== undefined) {
|
|
3803
3860
|
msg.webSearchMode = session.codexSettings.webSearchMode;
|
|
3804
3861
|
}
|
|
3862
|
+
if (session.codexSettings.additionalWritableRoots !== undefined) {
|
|
3863
|
+
msg.additionalWritableRoots =
|
|
3864
|
+
session.codexSettings.additionalWritableRoots;
|
|
3865
|
+
}
|
|
3805
3866
|
}
|
|
3806
3867
|
return msg;
|
|
3807
3868
|
}
|