@ccpocket/bridge 1.42.1 → 1.43.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/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 +67 -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"
|
|
@@ -1662,16 +1693,16 @@ export class BridgeWebSocketServer {
|
|
|
1662
1693
|
// Resume flow: keep past history in SessionInfo and deliver it only
|
|
1663
1694
|
// via get_history(sessionId) to avoid duplicate/missed replay races.
|
|
1664
1695
|
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
1696
|
const wtMapping = this.worktreeStore.get(sessionRefId);
|
|
1674
1697
|
const effectiveProjectPath = resolvePlatformPath(wtMapping?.projectPath ?? resumeProjectPath, this.platform);
|
|
1698
|
+
const effectiveProfile = msg.profile
|
|
1699
|
+
? await this.resolveCodexResumeProfile(msg.profile, sessionRefId, effectiveProjectPath)
|
|
1700
|
+
: undefined;
|
|
1701
|
+
const additionalWritableRoots = this.normalizeAdditionalWritableRoots(msg.additionalWritableRoots, effectiveProjectPath);
|
|
1702
|
+
if (additionalWritableRoots.deniedRoot) {
|
|
1703
|
+
this.send(ws, this.buildPathNotAllowedError(additionalWritableRoots.deniedRoot));
|
|
1704
|
+
break;
|
|
1705
|
+
}
|
|
1675
1706
|
let worktreeOpts;
|
|
1676
1707
|
if (wtMapping) {
|
|
1677
1708
|
if (worktreeExists(wtMapping.worktreePath)) {
|
|
@@ -1691,7 +1722,7 @@ export class BridgeWebSocketServer {
|
|
|
1691
1722
|
.then((pastMessages) => {
|
|
1692
1723
|
const sessionId = this.sessionManager.create(effectiveProjectPath, undefined, pastMessages, worktreeOpts, "codex", {
|
|
1693
1724
|
threadId: sessionRefId,
|
|
1694
|
-
profile:
|
|
1725
|
+
profile: effectiveProfile,
|
|
1695
1726
|
approvalPolicy: codexApprovalPolicy ??
|
|
1696
1727
|
normalizeCodexApprovalPolicy(executionMode === "fullAccess" ? "never" : "on-request"),
|
|
1697
1728
|
approvalsReviewer: msg.approvalsReviewer,
|
|
@@ -1701,6 +1732,7 @@ export class BridgeWebSocketServer {
|
|
|
1701
1732
|
networkAccessEnabled: msg.networkAccessEnabled,
|
|
1702
1733
|
webSearchMode: msg.webSearchMode ??
|
|
1703
1734
|
undefined,
|
|
1735
|
+
additionalWritableRoots: additionalWritableRoots.roots,
|
|
1704
1736
|
collaborationMode: planMode
|
|
1705
1737
|
? "plan"
|
|
1706
1738
|
: "default",
|
|
@@ -3075,6 +3107,26 @@ export class BridgeWebSocketServer {
|
|
|
3075
3107
|
this.defaultCodexProfile = snapshot.defaultProfile;
|
|
3076
3108
|
return snapshot.profiles.includes(profile);
|
|
3077
3109
|
}
|
|
3110
|
+
async resolveCodexResumeProfile(requestedProfile, threadId, projectPath) {
|
|
3111
|
+
const snapshot = await this.loadCodexProfiles(projectPath);
|
|
3112
|
+
this.codexProfiles = snapshot.profiles;
|
|
3113
|
+
this.defaultCodexProfile = snapshot.defaultProfile;
|
|
3114
|
+
if (snapshot.profiles.includes(requestedProfile)) {
|
|
3115
|
+
return requestedProfile;
|
|
3116
|
+
}
|
|
3117
|
+
const fallbackProfile = snapshot.defaultProfile &&
|
|
3118
|
+
snapshot.profiles.includes(snapshot.defaultProfile)
|
|
3119
|
+
? snapshot.defaultProfile
|
|
3120
|
+
: undefined;
|
|
3121
|
+
console.warn(`[ws] Codex profile not found on resume: ${requestedProfile}; ` +
|
|
3122
|
+
(fallbackProfile
|
|
3123
|
+
? `falling back to default profile: ${fallbackProfile}`
|
|
3124
|
+
: "falling back to Codex config default"));
|
|
3125
|
+
saveCodexSessionProfile(threadId, fallbackProfile ?? null).catch((err) => {
|
|
3126
|
+
console.warn(`[ws] Failed to update Codex session profile cache: ${err}`);
|
|
3127
|
+
});
|
|
3128
|
+
return fallbackProfile;
|
|
3129
|
+
}
|
|
3078
3130
|
getActiveCodexProcess() {
|
|
3079
3131
|
const summary = this.sessionManager
|
|
3080
3132
|
.list()
|
|
@@ -3802,6 +3854,10 @@ export class BridgeWebSocketServer {
|
|
|
3802
3854
|
if (session.codexSettings.webSearchMode !== undefined) {
|
|
3803
3855
|
msg.webSearchMode = session.codexSettings.webSearchMode;
|
|
3804
3856
|
}
|
|
3857
|
+
if (session.codexSettings.additionalWritableRoots !== undefined) {
|
|
3858
|
+
msg.additionalWritableRoots =
|
|
3859
|
+
session.codexSettings.additionalWritableRoots;
|
|
3860
|
+
}
|
|
3805
3861
|
}
|
|
3806
3862
|
return msg;
|
|
3807
3863
|
}
|