@jingyi0605/codingns 1.0.0-beta.1 → 1.0.0-beta.3
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/public/assets/AdaptiveButlerPage-CLHLiZSY.js +2 -0
- package/dist/public/assets/{App-CHsm-VrM.js → App-FYuZfAoO.js} +6 -6
- package/dist/public/assets/{BootstrapPage-Bp0KfySv.js → BootstrapPage-3xpnsG-A.js} +1 -1
- package/dist/public/assets/ConversationPage-C5_ZqhU3.js +9 -0
- package/dist/public/assets/{DesktopDetachPreviewPage-DlDSb_tf.js → DesktopDetachPreviewPage-B77MG82y.js} +1 -1
- package/dist/public/assets/{DesktopModal-Csj5AdAN.js → DesktopModal-K5bEcj38.js} +1 -1
- package/dist/public/assets/{DesktopWindowPage-CacXiWjV.js → DesktopWindowPage-DbG-RBAf.js} +1 -1
- package/dist/public/assets/{FileContextPanel-DzMUQvE5.js → FileContextPanel-C-1yOton.js} +1 -1
- package/dist/public/assets/{GitSidebar-C8IC18GH.js → GitSidebar-DFHAPT3S.js} +1 -1
- package/dist/public/assets/{MobileCreateSessionSheet-BtqR_hKc.js → MobileCreateSessionSheet-gOyAZ857.js} +1 -1
- package/dist/public/assets/{MobileSheet-Co-qPMBD.js → MobileSheet-D0MfNkTv.js} +1 -1
- package/dist/public/assets/{PluginAccessOverview-D-KXkcyj.js → PluginAccessOverview-IrYIPLg3.js} +1 -1
- package/dist/public/assets/{PluginContainerPage-BKwCIs4r.js → PluginContainerPage-b9LQVuqG.js} +1 -1
- package/dist/public/assets/{PluginDetailPage-Djv_swcO.js → PluginDetailPage-BX7gohai.js} +1 -1
- package/dist/public/assets/{PluginsListPage-DAECNoN6.js → PluginsListPage-R0SibHMi.js} +1 -1
- package/dist/public/assets/{PureConversationPage-DP1X7Hix.js → PureConversationPage-CcakFvo0.js} +1 -1
- package/dist/public/assets/{RelayConnectEntryPage-xL_IPH8a.js → RelayConnectEntryPage-cAVq_kNM.js} +1 -1
- package/dist/public/assets/{ServerSettingsModal-CyhMgk10.js → ServerSettingsModal-BJwYHdKD.js} +1 -1
- package/dist/public/assets/{SessionIndexPage-CVEz50tc.js → SessionIndexPage-CJKRHB_F.js} +1 -1
- package/dist/public/assets/SettingsPage-Csp7wEBC.js +2 -0
- package/dist/public/assets/{TerminalManagerPanel-wVnoRA8u.js → TerminalManagerPanel-2HG-NyfR.js} +1 -1
- package/dist/public/assets/{ToolFilesPage-BospXumK.js → ToolFilesPage-BAZdjNaF.js} +1 -1
- package/dist/public/assets/{ToolGitPage-B2zOeCAD.js → ToolGitPage-CGkPmgsz.js} +1 -1
- package/dist/public/assets/{ToolProcessesPage-BDShao4b.js → ToolProcessesPage-BHpS7-VH.js} +1 -1
- package/dist/public/assets/{ToolsHomePage-s4zH7D9M.js → ToolsHomePage-DDGqYwYU.js} +1 -1
- package/dist/public/assets/{WorkbenchLandingPage-D51QCU_u.js → WorkbenchLandingPage-B4aooEYJ.js} +1 -1
- package/dist/public/assets/WorkbenchLayout-DrAvGjGK.js +1083 -0
- package/dist/public/assets/{WorkbenchModal-YsyEdJ_m.js → WorkbenchModal-BK5ix8YI.js} +1 -1
- package/dist/public/assets/WorkbenchShellRoute-DpycFsbp.css +1 -0
- package/dist/public/assets/WorkbenchShellRoute-p1FvkoPN.js +1 -0
- package/dist/public/assets/{WorkspaceDebugDetailPage-CMjNLqFq.js → WorkspaceDebugDetailPage-CPgAe8dd.js} +1 -1
- package/dist/public/assets/{WorkspaceDetailPage-CKxTbPKh.js → WorkspaceDetailPage-YM85dTGg.js} +1 -1
- package/dist/public/assets/{WorkspaceHomePage-CEy4ShCu.js → WorkspaceHomePage-DPPvwM93.js} +1 -1
- package/dist/public/assets/{client-runtime-manager-BFXU9DmS.js → client-runtime-manager-Clq-8rWh.js} +1 -1
- package/dist/public/assets/{host-alias-Zb2xyVrf.js → host-alias-BxzpRYrt.js} +1 -1
- package/dist/public/assets/index-BArTKWXk.js +50 -0
- package/dist/public/assets/index-CqKepLbu.css +1 -0
- package/dist/public/assets/{login-direct-candidate-resolver-DL8DS-Si.js → login-direct-candidate-resolver-BiWwFKnk.js} +1 -1
- package/dist/public/assets/peer-host-config-sync-kTom1_pp.js +1 -0
- package/dist/public/assets/{plugin-permission-copy-DrLk22m5.js → plugin-permission-copy-1_1wViri.js} +1 -1
- package/dist/public/assets/{plugins-api-COF4oh24.js → plugins-api-C0JqR2-W.js} +1 -1
- package/dist/public/assets/{preferences-service-CEWNV1w9.js → preferences-service-DWeLWZST.js} +1 -1
- package/dist/public/assets/{relay-entry-Cmc8vTlE.js → relay-entry-ClEd3cjN.js} +1 -1
- package/dist/public/assets/{useRegisteredDebugTemplates-FdmHG2S4.js → useRegisteredDebugTemplates-wJGOYam9.js} +1 -1
- package/dist/public/assets/{workbench-navigation-ED0157V-.js → workbench-navigation-vIWt3Rv_.js} +1 -1
- package/dist/public/index.html +2 -2
- package/dist/server/modules/client/client-controller.d.ts +1 -0
- package/dist/server/modules/client/client-controller.js +4 -0
- package/dist/server/modules/client/client-controller.js.map +1 -1
- package/dist/server/modules/client/client-service.d.ts +3 -0
- package/dist/server/modules/client/client-service.js +3 -0
- package/dist/server/modules/client/client-service.js.map +1 -1
- package/dist/server/modules/client/npm-global-package-service.js +32 -7
- package/dist/server/modules/client/npm-global-package-service.js.map +1 -1
- package/dist/server/modules/peer-host/host-ws-proxy-service.js +73 -12
- package/dist/server/modules/peer-host/host-ws-proxy-service.js.map +1 -1
- package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +2 -0
- package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -1
- package/dist/server/modules/provider/provider-discovery-helper-process.js +6 -3
- package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -1
- package/dist/server/modules/provider/provider-discovery-runtime.js +4 -1
- package/dist/server/modules/provider/provider-discovery-runtime.js.map +1 -1
- package/dist/server/modules/sessions/codex-app-server-helper-process.js +84 -20
- package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
- package/dist/server/modules/sessions/session-controller.js +2 -1
- package/dist/server/modules/sessions/session-controller.js.map +1 -1
- package/dist/server/modules/sessions/session-history-service.d.ts +8 -0
- package/dist/server/modules/sessions/session-history-service.js +123 -5
- package/dist/server/modules/sessions/session-history-service.js.map +1 -1
- package/dist/server/modules/sessions/session-live-runtime-service.d.ts +27 -0
- package/dist/server/modules/sessions/session-live-runtime-service.js +457 -9
- package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
- package/dist/server/modules/sessions/session-permission-request-service.d.ts +17 -1
- package/dist/server/modules/sessions/session-permission-request-service.js +397 -9
- package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -1
- package/dist/server/modules/sessions/session-provider-config-service.js +1 -0
- package/dist/server/modules/sessions/session-provider-config-service.js.map +1 -1
- package/dist/server/modules/sessions/workspace-session-runtime-context-service.js +15 -1
- package/dist/server/modules/sessions/workspace-session-runtime-context-service.js.map +1 -1
- package/dist/server/modules/tasks/task-helper-process-handlers.d.ts +1 -0
- package/dist/server/modules/tasks/task-helper-process-handlers.js +4 -1
- package/dist/server/modules/tasks/task-helper-process-handlers.js.map +1 -1
- package/dist/server/modules/workbench/workbench-service.js +7 -4
- package/dist/server/modules/workbench/workbench-service.js.map +1 -1
- package/dist/server/routes/client.js +1 -0
- package/dist/server/routes/client.js.map +1 -1
- package/dist/server/shared/utils/peer-host-proxy-log.d.ts +3 -0
- package/dist/server/shared/utils/peer-host-proxy-log.js +48 -0
- package/dist/server/shared/utils/peer-host-proxy-log.js.map +1 -0
- package/dist/server/storage/repositories/session-send-queue-repository.d.ts +1 -0
- package/dist/server/storage/repositories/session-send-queue-repository.js +23 -0
- package/dist/server/storage/repositories/session-send-queue-repository.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/index.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/index.js +1 -0
- package/node_modules/@codingns/session-sync-core/dist/index.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +2 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +93 -12
- package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +3 -0
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +116 -2
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +19 -8
- package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.d.ts +27 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js +48 -4
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-permissions.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +53 -15
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.d.ts +1 -0
- package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js +30 -2
- package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js.map +1 -1
- package/package.json +2 -1
- package/scripts/claude-hook-bridge.cjs +167 -0
- package/dist/public/assets/AdaptiveButlerPage-BYETYaIe.js +0 -2
- package/dist/public/assets/ConversationPage-BCrNml1k.js +0 -9
- package/dist/public/assets/SettingsPage-CQNCrgaj.js +0 -2
- package/dist/public/assets/WorkbenchLayout-Bo2BbMY6.js +0 -1081
- package/dist/public/assets/WorkbenchShellRoute-D3l4aWJS.js +0 -1
- package/dist/public/assets/WorkbenchShellRoute-D5fnyF8z.css +0 -1
- package/dist/public/assets/index-BilHJjYU.js +0 -50
- package/dist/public/assets/index-OR7OITpQ.css +0 -1
- package/dist/public/assets/peer-host-config-sync-d2ZcPC5P.js +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
3
4
|
import { performance } from "node:perf_hooks";
|
|
4
|
-
import { ClaudeRuntimeAdapter, CodexRuntimeAdapter, GeminiRuntimeAdapter, KimiRuntimeAdapter, LegnaRuntimeAdapter, OpenCodeRuntimeAdapter, ProviderRuntimeService } from "@codingns/session-sync-core";
|
|
5
|
+
import { ClaudeRuntimeAdapter, CodexRuntimeAdapter, GeminiRuntimeAdapter, KimiRuntimeAdapter, LegnaRuntimeAdapter, OpenCodeRuntimeAdapter, ProviderRuntimeService, resolveCodexPermissionResolution } from "@codingns/session-sync-core";
|
|
5
6
|
import { AppError, isAppError } from "../../shared/errors/app-error.js";
|
|
6
7
|
import { createId } from "../../shared/utils/id.js";
|
|
7
8
|
import { isPerfDebugEnabled, logPerformance } from "../../shared/utils/perf-log.js";
|
|
@@ -17,6 +18,42 @@ import { ClaudeRuntimeHelperAdapter } from "./claude-runtime-helper-client.js";
|
|
|
17
18
|
import { CodexAppServerHelperClient } from "./codex-app-server-helper-client.js";
|
|
18
19
|
const OPENCODE_ORDER_DEBUG_ENABLED = /^(1|true|yes)$/i.test(process.env.CODINGNS_OPENCODE_ORDER_DEBUG?.trim() ?? "");
|
|
19
20
|
const RUNTIME_EVENT_SQLITE_BUSY_RETRY_DELAYS_MS = [100, 250, 500, 1_000, 1_500, 2_000];
|
|
21
|
+
function buildSessionRuntimePermissionStatus(input) {
|
|
22
|
+
if (input.provider !== "codex") {
|
|
23
|
+
return {
|
|
24
|
+
requestedPermissionMode: input.requestedPermissionMode,
|
|
25
|
+
effectivePermissionMode: "default",
|
|
26
|
+
effectiveSandboxMode: null,
|
|
27
|
+
effectiveApprovalPolicy: null,
|
|
28
|
+
source: "provider-non-codex",
|
|
29
|
+
summary: "当前 provider 不使用 Codex 沙箱权限映射。",
|
|
30
|
+
detail: "这份权限说明只对 Codex 会话生效,其他 provider 仍沿用各自的权限体系。"
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
const resolution = resolveCodexPermissionResolution(input.requestedPermissionMode);
|
|
34
|
+
if (resolution.effectivePermissionMode === "default") {
|
|
35
|
+
return {
|
|
36
|
+
requestedPermissionMode: input.requestedPermissionMode,
|
|
37
|
+
effectivePermissionMode: resolution.effectivePermissionMode,
|
|
38
|
+
effectiveSandboxMode: resolution.sandboxMode,
|
|
39
|
+
effectiveApprovalPolicy: resolution.approvalPolicy ? "never" : "cli-default",
|
|
40
|
+
source: "codex-cli-default",
|
|
41
|
+
summary: "当前会话跟随 Codex CLI 默认权限。",
|
|
42
|
+
detail: resolution.reasoning
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
requestedPermissionMode: input.requestedPermissionMode,
|
|
47
|
+
effectivePermissionMode: resolution.effectivePermissionMode,
|
|
48
|
+
effectiveSandboxMode: resolution.sandboxMode,
|
|
49
|
+
effectiveApprovalPolicy: resolution.approvalPolicy ? "never" : "cli-default",
|
|
50
|
+
source: "codingns-override",
|
|
51
|
+
summary: resolution.effectivePermissionMode === "acceptEdits"
|
|
52
|
+
? "当前会话已切到工作区可写权限。"
|
|
53
|
+
: "当前会话已切到完整权限。",
|
|
54
|
+
detail: resolution.reasoning
|
|
55
|
+
};
|
|
56
|
+
}
|
|
20
57
|
const RUNTIME_START_BINDING_WAIT_TIMEOUT_MS = 10_000;
|
|
21
58
|
const START_BINDING_POLL_INTERVAL_MS = 50;
|
|
22
59
|
const EXTERNAL_RUNTIME_INTERRUPT_SUPPRESSION_MS = 30_000;
|
|
@@ -51,6 +88,7 @@ export class SessionLiveRuntimeService {
|
|
|
51
88
|
queueRetryTimers = new Map();
|
|
52
89
|
pendingSendDebugTracesBySessionId = new Map();
|
|
53
90
|
runtimePersistenceQueues = new Map();
|
|
91
|
+
sessionPermissionRuntimeStates = new Map();
|
|
54
92
|
constructor(sessionHistoryService, sessionMessageAttachmentService, workspaceService, sessionChangedFileService, sessionBindingRepository, authUserRepository, sessionSendQueueRepository, sessionIndexRepository, sessionStateRepository, sessionStatusSnapshotRepository, sessionProviderConfigService, config, sessionActivityAuthorityService = new SessionActivityAuthorityService(), openCliSessionPromptService = null, workspaceSessionRuntimeContextService = null) {
|
|
55
93
|
this.sessionHistoryService = sessionHistoryService;
|
|
56
94
|
this.sessionMessageAttachmentService = sessionMessageAttachmentService;
|
|
@@ -90,6 +128,7 @@ export class SessionLiveRuntimeService {
|
|
|
90
128
|
clientRequestId: input.clientRequestId
|
|
91
129
|
});
|
|
92
130
|
try {
|
|
131
|
+
this.rememberRequestedPermissionMode(sessionId, input.runtimeOptions?.permissionMode ?? null, "start_live");
|
|
93
132
|
const capabilities = this.sessionHistoryService.getProviderCapabilitiesSnapshot(input.provider);
|
|
94
133
|
const providerBinding = this.sessionProviderConfigService.prepareSessionBinding({
|
|
95
134
|
sessionId,
|
|
@@ -449,6 +488,13 @@ export class SessionLiveRuntimeService {
|
|
|
449
488
|
});
|
|
450
489
|
return this.sessionPermissionRequestService.handleClaudePermissionRequest(resolvedPayload, provider);
|
|
451
490
|
}
|
|
491
|
+
if (hookEventName === "Elicitation") {
|
|
492
|
+
logPermissionDebug("claude_hook_event.route", {
|
|
493
|
+
hookEventName,
|
|
494
|
+
route: "handleClaudeElicitation"
|
|
495
|
+
});
|
|
496
|
+
return this.sessionPermissionRequestService.handleClaudeElicitation(resolvedPayload, provider);
|
|
497
|
+
}
|
|
452
498
|
const providerSessionId = normalizeRequiredText(resolvedPayload.session_id, "session_id");
|
|
453
499
|
const workspacePath = normalizeRequiredText(resolvedPayload.cwd, "cwd");
|
|
454
500
|
const workspace = this.workspaceService.findWorkspaceByPath(workspacePath);
|
|
@@ -527,6 +573,12 @@ export class SessionLiveRuntimeService {
|
|
|
527
573
|
this.maybeDispatchQueuedMessages(session);
|
|
528
574
|
const capabilities = await this.sessionHistoryService.getSessionCapabilities(sessionId, userId);
|
|
529
575
|
const contextUsage = await this.sessionHistoryService.getSessionContextUsage(sessionId).catch(() => null);
|
|
576
|
+
const requestedPermissionMode = this.resolveRequestedPermissionMode(sessionId);
|
|
577
|
+
const permissionStatus = buildSessionRuntimePermissionStatus({
|
|
578
|
+
provider: session.provider,
|
|
579
|
+
requestedPermissionMode
|
|
580
|
+
});
|
|
581
|
+
this.logSessionPermissionStatus(sessionId, session.provider, permissionStatus);
|
|
530
582
|
const resolution = runtimeSnapshot
|
|
531
583
|
? this.sessionActivityAuthorityService.observe(createRuntimeActivityObservation(runtimeSessionId, runtimeSnapshot))
|
|
532
584
|
: externalRuntimeSnapshot
|
|
@@ -555,7 +607,8 @@ export class SessionLiveRuntimeService {
|
|
|
555
607
|
: null,
|
|
556
608
|
updatedAt: resolution.updatedAt,
|
|
557
609
|
watchdogTriggeredAt: resolution.watchdogTriggeredAt,
|
|
558
|
-
contextUsage
|
|
610
|
+
contextUsage,
|
|
611
|
+
permissionStatus
|
|
559
612
|
};
|
|
560
613
|
}
|
|
561
614
|
if (externalRuntimeSnapshot) {
|
|
@@ -577,7 +630,8 @@ export class SessionLiveRuntimeService {
|
|
|
577
630
|
errorDetail: resolution.runningState === "failed" ? resolution.detail ?? session.lastErrorDetail : null,
|
|
578
631
|
updatedAt: resolution.updatedAt,
|
|
579
632
|
watchdogTriggeredAt: resolution.watchdogTriggeredAt,
|
|
580
|
-
contextUsage
|
|
633
|
+
contextUsage,
|
|
634
|
+
permissionStatus
|
|
581
635
|
};
|
|
582
636
|
}
|
|
583
637
|
const persistedErrorCode = resolution.runningState === "failed" ? resolution.errorCode ?? session.lastErrorCode : null;
|
|
@@ -600,7 +654,8 @@ export class SessionLiveRuntimeService {
|
|
|
600
654
|
errorDetail: persistedErrorDetail,
|
|
601
655
|
updatedAt: resolution.updatedAt,
|
|
602
656
|
watchdogTriggeredAt: resolution.watchdogTriggeredAt,
|
|
603
|
-
contextUsage
|
|
657
|
+
contextUsage,
|
|
658
|
+
permissionStatus
|
|
604
659
|
};
|
|
605
660
|
}
|
|
606
661
|
resolveLiveActivityObservation(sessionId) {
|
|
@@ -822,6 +877,48 @@ export class SessionLiveRuntimeService {
|
|
|
822
877
|
}
|
|
823
878
|
return snapshot;
|
|
824
879
|
}
|
|
880
|
+
resolveRequestedPermissionMode(sessionId) {
|
|
881
|
+
const runtimeState = this.sessionPermissionRuntimeStates.get(sessionId);
|
|
882
|
+
if (runtimeState?.requestedPermissionMode?.trim()) {
|
|
883
|
+
return runtimeState.requestedPermissionMode.trim();
|
|
884
|
+
}
|
|
885
|
+
const queuedItems = this.sessionSendQueueRepository.listBySessionId(sessionId);
|
|
886
|
+
const dispatchingItem = queuedItems.find((item) => item.status === "dispatching");
|
|
887
|
+
if (dispatchingItem?.permissionMode?.trim()) {
|
|
888
|
+
return dispatchingItem.permissionMode.trim();
|
|
889
|
+
}
|
|
890
|
+
const latestPermissionItem = [...queuedItems]
|
|
891
|
+
.reverse()
|
|
892
|
+
.find((item) => item.permissionMode?.trim());
|
|
893
|
+
if (latestPermissionItem?.permissionMode?.trim()) {
|
|
894
|
+
return latestPermissionItem.permissionMode.trim();
|
|
895
|
+
}
|
|
896
|
+
return null;
|
|
897
|
+
}
|
|
898
|
+
rememberRequestedPermissionMode(sessionId, permissionMode, source) {
|
|
899
|
+
this.sessionPermissionRuntimeStates.set(sessionId, {
|
|
900
|
+
requestedPermissionMode: permissionMode?.trim() || null,
|
|
901
|
+
updatedAt: nowIso(),
|
|
902
|
+
source
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
logSessionPermissionStatus(sessionId, provider, permissionStatus) {
|
|
906
|
+
if (!permissionStatus) {
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
const runtimeState = this.sessionPermissionRuntimeStates.get(sessionId);
|
|
910
|
+
logPermissionDebug("session_runtime.permission_status", {
|
|
911
|
+
sessionId,
|
|
912
|
+
provider,
|
|
913
|
+
requestedPermissionMode: permissionStatus.requestedPermissionMode,
|
|
914
|
+
effectivePermissionMode: permissionStatus.effectivePermissionMode,
|
|
915
|
+
effectiveSandboxMode: permissionStatus.effectiveSandboxMode,
|
|
916
|
+
effectiveApprovalPolicy: permissionStatus.effectiveApprovalPolicy,
|
|
917
|
+
source: permissionStatus.source,
|
|
918
|
+
runtimeStateSource: runtimeState?.source ?? null,
|
|
919
|
+
runtimeStateUpdatedAt: runtimeState?.updatedAt ?? null
|
|
920
|
+
});
|
|
921
|
+
}
|
|
825
922
|
demoteDeadRuntimeSnapshot(snapshot) {
|
|
826
923
|
const updatedAt = nowIso();
|
|
827
924
|
for (const userId of this.authUserRepository.listIds()) {
|
|
@@ -1115,6 +1212,7 @@ export class SessionLiveRuntimeService {
|
|
|
1115
1212
|
}
|
|
1116
1213
|
}
|
|
1117
1214
|
async startRuntimeRun(request, userId, mode, providerBinding) {
|
|
1215
|
+
this.rememberRequestedPermissionMode(request.sessionId, request.options.permissionMode ?? null, "runtime_snapshot");
|
|
1118
1216
|
this.runtimeMessageSeenSessions.delete(request.sessionId);
|
|
1119
1217
|
this.runtimeHistoryFallbackSentSessions.delete(request.sessionId);
|
|
1120
1218
|
this.clearExternalRuntimeInterruptSuppression(request.sessionId);
|
|
@@ -1153,6 +1251,7 @@ export class SessionLiveRuntimeService {
|
|
|
1153
1251
|
clientRequestId: input.clientRequestId
|
|
1154
1252
|
});
|
|
1155
1253
|
try {
|
|
1254
|
+
this.rememberRequestedPermissionMode(input.sessionId, input.runtimeOptions?.permissionMode ?? null, "send_live");
|
|
1156
1255
|
const capabilities = await this.sessionHistoryService.getSessionCapabilities(input.sessionId, input.userId);
|
|
1157
1256
|
const workspace = this.workspaceService.getWorkspaceOrThrow(session.workspaceId);
|
|
1158
1257
|
const runtimeMode = shouldStartNativeSessionOnFirstMessage(session);
|
|
@@ -1193,9 +1292,12 @@ export class SessionLiveRuntimeService {
|
|
|
1193
1292
|
const runtimeRawStoreRef = runtimeMode === "start"
|
|
1194
1293
|
? syntheticForkRawStoreRef
|
|
1195
1294
|
: await this.resolveCodexRuntimeRequestRawStoreRef(session, providerBinding);
|
|
1196
|
-
const
|
|
1197
|
-
|
|
1198
|
-
|
|
1295
|
+
const sequenceBase = resolveRuntimeSequenceBase(session, runtimeMode);
|
|
1296
|
+
const nextUserSequence = sequenceBase !== null
|
|
1297
|
+
? sequenceBase
|
|
1298
|
+
: (runtimeMode === "start"
|
|
1299
|
+
? 1
|
|
1300
|
+
: await this.resolveNextUserSequence(input.sessionId, session.messageCount));
|
|
1199
1301
|
const resolvedAttachments = persistedAttachments
|
|
1200
1302
|
?? this.persistMessageAttachments(input.sessionId, input.clientRequestId, input.runtimeOptions?.attachments ?? []);
|
|
1201
1303
|
const providerPrompt = this.sessionMessageAttachmentService.buildProviderPrompt(session.provider, input.content, resolvedAttachments.runtimeAttachments);
|
|
@@ -1219,7 +1321,17 @@ export class SessionLiveRuntimeService {
|
|
|
1219
1321
|
providerLaunchRuntimeHomeDir: providerLaunchContext.runtimeHomeDir,
|
|
1220
1322
|
providerBindingRuntimeHomeDir: providerBinding.runtimeHomeDir
|
|
1221
1323
|
});
|
|
1222
|
-
const
|
|
1324
|
+
const claudeForkBootstrap = await this.buildClaudeForkBootstrapDescriptor({
|
|
1325
|
+
session,
|
|
1326
|
+
runtimeMode,
|
|
1327
|
+
baseInstructionFilePath: input.runtimeOptions?.providerInstructionFilePath
|
|
1328
|
+
?? workspaceRuntimeContext.instructionFilePath
|
|
1329
|
+
?? providerLaunchContext.providerInstructionFilePath
|
|
1330
|
+
?? null,
|
|
1331
|
+
runtimeHomeDir: effectiveRuntimeHomeDir
|
|
1332
|
+
});
|
|
1333
|
+
const providerInstructionFilePath = resolveRuntimeInstructionFilePath(session.provider, workspace.path, claudeForkBootstrap?.instructionFilePath
|
|
1334
|
+
?? input.runtimeOptions?.providerInstructionFilePath
|
|
1223
1335
|
?? workspaceRuntimeContext.instructionFilePath
|
|
1224
1336
|
?? providerLaunchContext.providerInstructionFilePath
|
|
1225
1337
|
?? null);
|
|
@@ -1376,6 +1488,7 @@ export class SessionLiveRuntimeService {
|
|
|
1376
1488
|
runtimeAttachments: restoredAttachments
|
|
1377
1489
|
};
|
|
1378
1490
|
try {
|
|
1491
|
+
this.rememberRequestedPermissionMode(nextQueueItem.sessionId, nextQueueItem.permissionMode, "queue_dispatch");
|
|
1379
1492
|
await this.sendLiveMessageDirect({
|
|
1380
1493
|
sessionId: nextQueueItem.sessionId,
|
|
1381
1494
|
userId: nextQueueItem.userId,
|
|
@@ -1707,6 +1820,37 @@ export class SessionLiveRuntimeService {
|
|
|
1707
1820
|
writeFileSync(syntheticFilePath, `${serialized}\n`, "utf8");
|
|
1708
1821
|
return syntheticFilePath;
|
|
1709
1822
|
}
|
|
1823
|
+
async buildClaudeForkBootstrapDescriptor(input) {
|
|
1824
|
+
if (input.runtimeMode !== "start" || !shouldBootstrapClaudeForkSession(input.session)) {
|
|
1825
|
+
return null;
|
|
1826
|
+
}
|
|
1827
|
+
const messages = await Promise.resolve(this.sessionHistoryService.readAllTextHistoryMessages(input.session.sessionId)).catch(() => []);
|
|
1828
|
+
const textMessages = Array.isArray(messages)
|
|
1829
|
+
? messages.filter((message) => (message.role === "user" || message.role === "assistant")
|
|
1830
|
+
&& message.kind === "text"
|
|
1831
|
+
&& message.content.trim().length > 0)
|
|
1832
|
+
: [];
|
|
1833
|
+
if (textMessages.length === 0) {
|
|
1834
|
+
return null;
|
|
1835
|
+
}
|
|
1836
|
+
const overlay = buildClaudeForkBootstrapInstructionOverlay({
|
|
1837
|
+
sessionTitle: input.session.title,
|
|
1838
|
+
messages: textMessages
|
|
1839
|
+
});
|
|
1840
|
+
if (!overlay) {
|
|
1841
|
+
return null;
|
|
1842
|
+
}
|
|
1843
|
+
const baseInstructionContent = readInstructionFileSafe(input.baseInstructionFilePath);
|
|
1844
|
+
const targetRoot = input.runtimeHomeDir?.trim()
|
|
1845
|
+
|| path.resolve(path.dirname(this.config.databasePath), "runtime", "claude-fork-bootstrap");
|
|
1846
|
+
const targetDir = path.join(targetRoot, ".codingns-fork-bootstrap");
|
|
1847
|
+
const instructionFilePath = path.join(targetDir, `${input.session.sessionId}.md`);
|
|
1848
|
+
mkdirSync(targetDir, { recursive: true });
|
|
1849
|
+
writeFileSync(instructionFilePath, composeForkBootstrapInstructionFile(baseInstructionContent, overlay), "utf8");
|
|
1850
|
+
return {
|
|
1851
|
+
instructionFilePath
|
|
1852
|
+
};
|
|
1853
|
+
}
|
|
1710
1854
|
buildBindingSnapshot(sessionId, provider, providerSessionId, rawStoreRef) {
|
|
1711
1855
|
const pendingValue = `pending://${provider}/${sessionId}`;
|
|
1712
1856
|
return {
|
|
@@ -2445,8 +2589,30 @@ function normalizeClaudeHookEventName(value) {
|
|
|
2445
2589
|
}
|
|
2446
2590
|
function isSupportedClaudeHookEvent(value) {
|
|
2447
2591
|
return (value === "PreToolUse" ||
|
|
2592
|
+
value === "PostToolUse" ||
|
|
2593
|
+
value === "PostToolUseFailure" ||
|
|
2448
2594
|
value === "PermissionRequest" ||
|
|
2595
|
+
value === "PermissionDenied" ||
|
|
2596
|
+
value === "Elicitation" ||
|
|
2597
|
+
value === "ElicitationResult" ||
|
|
2598
|
+
value === "MessageDisplay" ||
|
|
2449
2599
|
value === "Notification" ||
|
|
2600
|
+
value === "PostToolBatch" ||
|
|
2601
|
+
value === "TaskCreated" ||
|
|
2602
|
+
value === "TaskCompleted" ||
|
|
2603
|
+
value === "TeammateIdle" ||
|
|
2604
|
+
value === "SubagentStart" ||
|
|
2605
|
+
value === "SubagentStop" ||
|
|
2606
|
+
value === "PreCompact" ||
|
|
2607
|
+
value === "PostCompact" ||
|
|
2608
|
+
value === "InstructionsLoaded" ||
|
|
2609
|
+
value === "ConfigChange" ||
|
|
2610
|
+
value === "CwdChanged" ||
|
|
2611
|
+
value === "FileChanged" ||
|
|
2612
|
+
value === "WorktreeCreate" ||
|
|
2613
|
+
value === "WorktreeRemove" ||
|
|
2614
|
+
value === "Setup" ||
|
|
2615
|
+
value === "UserPromptExpansion" ||
|
|
2450
2616
|
value === "UserPromptSubmit" ||
|
|
2451
2617
|
value === "SessionStart" ||
|
|
2452
2618
|
value === "Stop" ||
|
|
@@ -2484,6 +2650,160 @@ function mapClaudeHookToRuntimeUpdate(hookEventName, payload, timestamp) {
|
|
|
2484
2650
|
timestamp
|
|
2485
2651
|
};
|
|
2486
2652
|
}
|
|
2653
|
+
if (hookEventName === "Setup") {
|
|
2654
|
+
return {
|
|
2655
|
+
runningState: "running",
|
|
2656
|
+
detail: buildClaudeHookRunningDetail("Claude 正在执行初始化", payload),
|
|
2657
|
+
timestamp
|
|
2658
|
+
};
|
|
2659
|
+
}
|
|
2660
|
+
if (hookEventName === "UserPromptExpansion") {
|
|
2661
|
+
return {
|
|
2662
|
+
runningState: "running",
|
|
2663
|
+
detail: buildClaudeHookRunningDetail("Claude 正在展开用户指令", payload),
|
|
2664
|
+
timestamp
|
|
2665
|
+
};
|
|
2666
|
+
}
|
|
2667
|
+
if (hookEventName === "PostToolUse") {
|
|
2668
|
+
return {
|
|
2669
|
+
runningState: "running",
|
|
2670
|
+
detail: buildClaudeHookRunningDetail("Claude 已完成一次工具调用", payload),
|
|
2671
|
+
timestamp
|
|
2672
|
+
};
|
|
2673
|
+
}
|
|
2674
|
+
if (hookEventName === "PostToolUseFailure") {
|
|
2675
|
+
return {
|
|
2676
|
+
runningState: "running",
|
|
2677
|
+
detail: buildClaudeHookRunningDetail("Claude 的一次工具调用失败", payload),
|
|
2678
|
+
timestamp
|
|
2679
|
+
};
|
|
2680
|
+
}
|
|
2681
|
+
if (hookEventName === "PermissionDenied") {
|
|
2682
|
+
return {
|
|
2683
|
+
runningState: "running",
|
|
2684
|
+
detail: buildClaudeHookRunningDetail("Claude 的工具权限请求被拒绝", payload),
|
|
2685
|
+
timestamp
|
|
2686
|
+
};
|
|
2687
|
+
}
|
|
2688
|
+
if (hookEventName === "Notification") {
|
|
2689
|
+
return {
|
|
2690
|
+
runningState: "running",
|
|
2691
|
+
detail: buildClaudeHookRunningDetail("Claude 发来一条通知", payload),
|
|
2692
|
+
timestamp
|
|
2693
|
+
};
|
|
2694
|
+
}
|
|
2695
|
+
if (hookEventName === "MessageDisplay") {
|
|
2696
|
+
return {
|
|
2697
|
+
runningState: "running",
|
|
2698
|
+
detail: buildClaudeHookRunningDetail("Claude 正在展示回复内容", payload),
|
|
2699
|
+
timestamp
|
|
2700
|
+
};
|
|
2701
|
+
}
|
|
2702
|
+
if (hookEventName === "ElicitationResult") {
|
|
2703
|
+
return {
|
|
2704
|
+
runningState: "running",
|
|
2705
|
+
detail: buildClaudeHookRunningDetail("Claude 已收到补充信息结果", payload),
|
|
2706
|
+
timestamp
|
|
2707
|
+
};
|
|
2708
|
+
}
|
|
2709
|
+
if (hookEventName === "PostToolBatch") {
|
|
2710
|
+
return {
|
|
2711
|
+
runningState: "running",
|
|
2712
|
+
detail: buildClaudeHookRunningDetail("Claude 已完成一批工具调用", payload),
|
|
2713
|
+
timestamp
|
|
2714
|
+
};
|
|
2715
|
+
}
|
|
2716
|
+
if (hookEventName === "TaskCreated") {
|
|
2717
|
+
return {
|
|
2718
|
+
runningState: "running",
|
|
2719
|
+
detail: buildClaudeHookRunningDetail("Claude 新建了一个任务", payload),
|
|
2720
|
+
timestamp
|
|
2721
|
+
};
|
|
2722
|
+
}
|
|
2723
|
+
if (hookEventName === "TaskCompleted") {
|
|
2724
|
+
return {
|
|
2725
|
+
runningState: "running",
|
|
2726
|
+
detail: buildClaudeHookRunningDetail("Claude 完成了一个任务", payload),
|
|
2727
|
+
timestamp
|
|
2728
|
+
};
|
|
2729
|
+
}
|
|
2730
|
+
if (hookEventName === "SubagentStart") {
|
|
2731
|
+
return {
|
|
2732
|
+
runningState: "running",
|
|
2733
|
+
detail: buildClaudeHookRunningDetail("Claude 子任务已启动", payload),
|
|
2734
|
+
timestamp
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
if (hookEventName === "SubagentStop") {
|
|
2738
|
+
return {
|
|
2739
|
+
runningState: "running",
|
|
2740
|
+
detail: buildClaudeHookRunningDetail("Claude 子任务已结束", payload),
|
|
2741
|
+
timestamp
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
if (hookEventName === "TeammateIdle") {
|
|
2745
|
+
return {
|
|
2746
|
+
runningState: "running",
|
|
2747
|
+
detail: buildClaudeHookRunningDetail("Claude 队友任务即将空闲", payload),
|
|
2748
|
+
timestamp
|
|
2749
|
+
};
|
|
2750
|
+
}
|
|
2751
|
+
if (hookEventName === "PreCompact") {
|
|
2752
|
+
return {
|
|
2753
|
+
runningState: "running",
|
|
2754
|
+
detail: buildClaudeHookRunningDetail("Claude 正在压缩上下文", payload),
|
|
2755
|
+
timestamp
|
|
2756
|
+
};
|
|
2757
|
+
}
|
|
2758
|
+
if (hookEventName === "PostCompact") {
|
|
2759
|
+
return {
|
|
2760
|
+
runningState: "running",
|
|
2761
|
+
detail: buildClaudeHookRunningDetail("Claude 已完成上下文压缩", payload),
|
|
2762
|
+
timestamp
|
|
2763
|
+
};
|
|
2764
|
+
}
|
|
2765
|
+
if (hookEventName === "InstructionsLoaded") {
|
|
2766
|
+
return {
|
|
2767
|
+
runningState: "running",
|
|
2768
|
+
detail: buildClaudeHookRunningDetail("Claude 已加载指令文件", payload),
|
|
2769
|
+
timestamp
|
|
2770
|
+
};
|
|
2771
|
+
}
|
|
2772
|
+
if (hookEventName === "ConfigChange") {
|
|
2773
|
+
return {
|
|
2774
|
+
runningState: "running",
|
|
2775
|
+
detail: buildClaudeHookRunningDetail("Claude 检测到配置变化", payload),
|
|
2776
|
+
timestamp
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2779
|
+
if (hookEventName === "CwdChanged") {
|
|
2780
|
+
return {
|
|
2781
|
+
runningState: "running",
|
|
2782
|
+
detail: buildClaudeHookRunningDetail("Claude 已切换工作目录", payload),
|
|
2783
|
+
timestamp
|
|
2784
|
+
};
|
|
2785
|
+
}
|
|
2786
|
+
if (hookEventName === "FileChanged") {
|
|
2787
|
+
return {
|
|
2788
|
+
runningState: "running",
|
|
2789
|
+
detail: buildClaudeHookRunningDetail("Claude 检测到文件变化", payload),
|
|
2790
|
+
timestamp
|
|
2791
|
+
};
|
|
2792
|
+
}
|
|
2793
|
+
if (hookEventName === "WorktreeCreate") {
|
|
2794
|
+
return {
|
|
2795
|
+
runningState: "running",
|
|
2796
|
+
detail: buildClaudeHookRunningDetail("Claude 正在创建工作树", payload),
|
|
2797
|
+
timestamp
|
|
2798
|
+
};
|
|
2799
|
+
}
|
|
2800
|
+
if (hookEventName === "WorktreeRemove") {
|
|
2801
|
+
return {
|
|
2802
|
+
runningState: "running",
|
|
2803
|
+
detail: buildClaudeHookRunningDetail("Claude 正在移除工作树", payload),
|
|
2804
|
+
timestamp
|
|
2805
|
+
};
|
|
2806
|
+
}
|
|
2487
2807
|
if (hookEventName === "StopFailure") {
|
|
2488
2808
|
return {
|
|
2489
2809
|
runningState: "failed",
|
|
@@ -2514,6 +2834,32 @@ function mapClaudeHookToRuntimeUpdate(hookEventName, payload, timestamp) {
|
|
|
2514
2834
|
}
|
|
2515
2835
|
return null;
|
|
2516
2836
|
}
|
|
2837
|
+
function buildClaudeHookRunningDetail(base, payload) {
|
|
2838
|
+
const candidates = [
|
|
2839
|
+
normalizeOptionalText(payload.title),
|
|
2840
|
+
normalizeOptionalText(payload.message),
|
|
2841
|
+
normalizeOptionalText(payload.reason),
|
|
2842
|
+
normalizeOptionalText(payload.prompt),
|
|
2843
|
+
normalizeOptionalText(payload.path),
|
|
2844
|
+
normalizeOptionalText(payload.file_path),
|
|
2845
|
+
normalizeOptionalText(payload.worktree_path),
|
|
2846
|
+
normalizeOptionalText(payload.config_path),
|
|
2847
|
+
normalizeOptionalText(payload.rule_file),
|
|
2848
|
+
normalizeOptionalText(payload.cwd),
|
|
2849
|
+
normalizeOptionalText(payload.command_name),
|
|
2850
|
+
normalizeOptionalText(payload.notification_type),
|
|
2851
|
+
normalizeOptionalText(payload.mcp_server_name),
|
|
2852
|
+
normalizeOptionalText(payload.matcher),
|
|
2853
|
+
normalizeOptionalText(payload.trigger),
|
|
2854
|
+
normalizeOptionalText(payload.action)
|
|
2855
|
+
].filter((value) => Boolean(value));
|
|
2856
|
+
const suffix = payload.tool_name?.trim()
|
|
2857
|
+
? `(${payload.tool_name.trim()})`
|
|
2858
|
+
: candidates[0]
|
|
2859
|
+
? `:${candidates[0]}`
|
|
2860
|
+
: "";
|
|
2861
|
+
return `${base}${suffix}`;
|
|
2862
|
+
}
|
|
2517
2863
|
function resolveRuntimeSessionTitle(provider, existingTitle, content, parentTitle, forkMethod, forkSourceType) {
|
|
2518
2864
|
const normalizedExistingTitle = existingTitle.trim();
|
|
2519
2865
|
const normalizedParentTitle = parentTitle?.trim() ?? "";
|
|
@@ -2525,6 +2871,76 @@ function resolveRuntimeSessionTitle(provider, existingTitle, content, parentTitl
|
|
|
2525
2871
|
}
|
|
2526
2872
|
return buildSessionTitleFromContent(content, "继续对话");
|
|
2527
2873
|
}
|
|
2874
|
+
function shouldBootstrapClaudeForkSession(session) {
|
|
2875
|
+
if (session.provider !== "claude-code") {
|
|
2876
|
+
return false;
|
|
2877
|
+
}
|
|
2878
|
+
if (session.forkMethod !== "native_message_fork"
|
|
2879
|
+
&& session.forkMethod !== "native_session_fork") {
|
|
2880
|
+
return false;
|
|
2881
|
+
}
|
|
2882
|
+
const inheritedCount = typeof session.inheritedPrefixMessageCount === "number"
|
|
2883
|
+
? Math.max(0, session.inheritedPrefixMessageCount)
|
|
2884
|
+
: null;
|
|
2885
|
+
if (inheritedCount === null) {
|
|
2886
|
+
return false;
|
|
2887
|
+
}
|
|
2888
|
+
return session.messageCount <= inheritedCount;
|
|
2889
|
+
}
|
|
2890
|
+
function resolveRuntimeSequenceBase(session, runtimeMode) {
|
|
2891
|
+
if (runtimeMode !== "start"
|
|
2892
|
+
|| session.provider !== "claude-code"
|
|
2893
|
+
|| (session.forkMethod !== "native_message_fork"
|
|
2894
|
+
&& session.forkMethod !== "native_session_fork")
|
|
2895
|
+
|| typeof session.inheritedPrefixMessageCount !== "number") {
|
|
2896
|
+
return null;
|
|
2897
|
+
}
|
|
2898
|
+
return Math.max(0, session.inheritedPrefixMessageCount);
|
|
2899
|
+
}
|
|
2900
|
+
function buildClaudeForkBootstrapInstructionOverlay(input) {
|
|
2901
|
+
const title = input.sessionTitle.trim() || "未命名会话";
|
|
2902
|
+
const lines = [
|
|
2903
|
+
`这是一个从既有 Claude Code 会话 fork 出来的子会话,标题:${title}。`,
|
|
2904
|
+
"下面这些历史内容已经发生过,只是给你恢复上下文。",
|
|
2905
|
+
"不要把它们当成新的用户问题逐条重答,也不要重复总结。",
|
|
2906
|
+
"真正需要处理的新用户输入,会在你看到这段说明之后单独发给你。",
|
|
2907
|
+
""
|
|
2908
|
+
];
|
|
2909
|
+
let appended = 0;
|
|
2910
|
+
for (const message of input.messages) {
|
|
2911
|
+
if (message.kind !== "text") {
|
|
2912
|
+
continue;
|
|
2913
|
+
}
|
|
2914
|
+
const normalizedContent = message.content.trim();
|
|
2915
|
+
if (!normalizedContent) {
|
|
2916
|
+
continue;
|
|
2917
|
+
}
|
|
2918
|
+
lines.push(message.role === "user" ? "[历史用户]" : "[历史助手]");
|
|
2919
|
+
lines.push(normalizedContent);
|
|
2920
|
+
lines.push("");
|
|
2921
|
+
appended += 1;
|
|
2922
|
+
}
|
|
2923
|
+
if (appended === 0) {
|
|
2924
|
+
return null;
|
|
2925
|
+
}
|
|
2926
|
+
return lines.join("\n").trim();
|
|
2927
|
+
}
|
|
2928
|
+
function readInstructionFileSafe(filePath) {
|
|
2929
|
+
const normalizedPath = filePath?.trim() || null;
|
|
2930
|
+
if (!normalizedPath || !existsSync(normalizedPath)) {
|
|
2931
|
+
return null;
|
|
2932
|
+
}
|
|
2933
|
+
try {
|
|
2934
|
+
return readFileSync(normalizedPath, "utf8");
|
|
2935
|
+
}
|
|
2936
|
+
catch {
|
|
2937
|
+
return null;
|
|
2938
|
+
}
|
|
2939
|
+
}
|
|
2940
|
+
function composeForkBootstrapInstructionFile(baseInstructionContent, overlay) {
|
|
2941
|
+
const sections = [baseInstructionContent?.trim() ?? "", overlay.trim()].filter((value) => value.length > 0);
|
|
2942
|
+
return `${sections.join("\n\n")}\n`;
|
|
2943
|
+
}
|
|
2528
2944
|
function isSyntheticRuntimeSessionTitle(provider, title) {
|
|
2529
2945
|
if (provider !== "codex") {
|
|
2530
2946
|
return false;
|
|
@@ -2534,6 +2950,10 @@ function isSyntheticRuntimeSessionTitle(provider, title) {
|
|
|
2534
2950
|
}
|
|
2535
2951
|
function shouldStartNativeSessionOnFirstMessage(session) {
|
|
2536
2952
|
if (session.provider !== "codex" && session.provider !== "opencode") {
|
|
2953
|
+
if (session.provider === "claude-code"
|
|
2954
|
+
&& shouldBootstrapClaudeForkSession(session)) {
|
|
2955
|
+
return "start";
|
|
2956
|
+
}
|
|
2537
2957
|
return "continue";
|
|
2538
2958
|
}
|
|
2539
2959
|
if (session.provider === "codex" && session.providerSessionId.startsWith("rollout-")) {
|
|
@@ -2798,8 +3218,30 @@ function buildClaudeHookBridgeConfig(config, provider) {
|
|
|
2798
3218
|
command,
|
|
2799
3219
|
supportedEvents: [
|
|
2800
3220
|
"PreToolUse",
|
|
3221
|
+
"PostToolUse",
|
|
3222
|
+
"PostToolUseFailure",
|
|
3223
|
+
"PostToolBatch",
|
|
2801
3224
|
"PermissionRequest",
|
|
3225
|
+
"PermissionDenied",
|
|
3226
|
+
"Elicitation",
|
|
3227
|
+
"ElicitationResult",
|
|
3228
|
+
"MessageDisplay",
|
|
2802
3229
|
"Notification",
|
|
3230
|
+
"TaskCreated",
|
|
3231
|
+
"TaskCompleted",
|
|
3232
|
+
"TeammateIdle",
|
|
3233
|
+
"SubagentStart",
|
|
3234
|
+
"SubagentStop",
|
|
3235
|
+
"PreCompact",
|
|
3236
|
+
"PostCompact",
|
|
3237
|
+
"InstructionsLoaded",
|
|
3238
|
+
"ConfigChange",
|
|
3239
|
+
"CwdChanged",
|
|
3240
|
+
"FileChanged",
|
|
3241
|
+
"WorktreeCreate",
|
|
3242
|
+
"WorktreeRemove",
|
|
3243
|
+
"Setup",
|
|
3244
|
+
"UserPromptExpansion",
|
|
2803
3245
|
"UserPromptSubmit",
|
|
2804
3246
|
"SessionStart",
|
|
2805
3247
|
"Stop",
|
|
@@ -2809,7 +3251,13 @@ function buildClaudeHookBridgeConfig(config, provider) {
|
|
|
2809
3251
|
};
|
|
2810
3252
|
}
|
|
2811
3253
|
function resolveClaudeHookBridgeScriptPath() {
|
|
3254
|
+
const currentFilePath = fileURLToPath(import.meta.url);
|
|
3255
|
+
const currentDir = path.dirname(currentFilePath);
|
|
3256
|
+
const packageRoot = path.resolve(currentDir, "..", "..", "..", "..");
|
|
3257
|
+
const workspaceRoot = path.resolve(packageRoot, "..", "..", "..");
|
|
2812
3258
|
const candidates = [
|
|
3259
|
+
path.resolve(packageRoot, "scripts", "claude-hook-bridge.cjs"),
|
|
3260
|
+
path.resolve(workspaceRoot, "scripts", "claude-hook-bridge.cjs"),
|
|
2813
3261
|
path.resolve(process.cwd(), "scripts", "claude-hook-bridge.cjs"),
|
|
2814
3262
|
path.resolve(process.cwd(), "..", "scripts", "claude-hook-bridge.cjs"),
|
|
2815
3263
|
path.resolve(process.cwd(), "..", "..", "scripts", "claude-hook-bridge.cjs")
|