@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
|
@@ -5,6 +5,8 @@ import { createId } from "../../shared/utils/id.js";
|
|
|
5
5
|
import { nowIso } from "../../shared/utils/time.js";
|
|
6
6
|
import { buildClaudeCompatibleRawStoreRef } from "./claude-compatible-provider-registry.js";
|
|
7
7
|
const CLAUDE_PRE_TOOL_USE_TIMEOUT_MS = 90_000;
|
|
8
|
+
const CLAUDE_ASK_USER_QUESTION_TIMEOUT_MS = 600_000;
|
|
9
|
+
const CLAUDE_PLAN_APPROVAL_TIMEOUT_MS = 600_000;
|
|
8
10
|
const OPENCODE_RECONNECT_DELAY_MS = 1_500;
|
|
9
11
|
export class SessionPermissionRequestService {
|
|
10
12
|
sessionHistoryService;
|
|
@@ -70,11 +72,38 @@ export class SessionPermissionRequestService {
|
|
|
70
72
|
}
|
|
71
73
|
if (request.source.kind === "claude-pre-tool-use") {
|
|
72
74
|
const action = normalizeText(input.action);
|
|
73
|
-
if (action !== "allow" &&
|
|
75
|
+
if (action !== "allow" &&
|
|
76
|
+
action !== "allow_session" &&
|
|
77
|
+
action !== "deny" &&
|
|
78
|
+
action !== "submit") {
|
|
74
79
|
throw new AppError({
|
|
75
80
|
statusCode: 400,
|
|
76
81
|
errorCode: "INVALID_INPUT",
|
|
77
|
-
detail: "Claude
|
|
82
|
+
detail: "Claude 请求只支持 allow、allow_session、deny 或 submit",
|
|
83
|
+
field: "action"
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (request.kind === "user_input" && action !== "submit") {
|
|
87
|
+
throw new AppError({
|
|
88
|
+
statusCode: 400,
|
|
89
|
+
errorCode: "INVALID_INPUT",
|
|
90
|
+
detail: "Claude 问题请求只支持提交答案",
|
|
91
|
+
field: "action"
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (request.kind !== "user_input" && action === "submit") {
|
|
95
|
+
throw new AppError({
|
|
96
|
+
statusCode: 400,
|
|
97
|
+
errorCode: "INVALID_INPUT",
|
|
98
|
+
detail: "只有问题请求可以提交答案",
|
|
99
|
+
field: "action"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (request.kind === "plan_approval" && action === "allow_session") {
|
|
103
|
+
throw new AppError({
|
|
104
|
+
statusCode: 400,
|
|
105
|
+
errorCode: "INVALID_INPUT",
|
|
106
|
+
detail: "计划审批不支持设置整场会话默认允许",
|
|
78
107
|
field: "action"
|
|
79
108
|
});
|
|
80
109
|
}
|
|
@@ -91,7 +120,8 @@ export class SessionPermissionRequestService {
|
|
|
91
120
|
});
|
|
92
121
|
}
|
|
93
122
|
request.source.resolve({
|
|
94
|
-
action: action === "deny" ? "deny" : "allow"
|
|
123
|
+
action: action === "deny" ? "deny" : "allow",
|
|
124
|
+
answers: request.kind === "user_input" ? input.answers : undefined
|
|
95
125
|
});
|
|
96
126
|
return await this.markResolved(request, action === "deny" ? "declined" : "approved");
|
|
97
127
|
}
|
|
@@ -240,7 +270,7 @@ export class SessionPermissionRequestService {
|
|
|
240
270
|
const timer = setTimeout(() => {
|
|
241
271
|
resolvedByTimeout = true;
|
|
242
272
|
resolve({ action: "ask" });
|
|
243
|
-
},
|
|
273
|
+
}, resolveClaudeBlockingRequestTimeoutMs(normalized.kind));
|
|
244
274
|
const record = {
|
|
245
275
|
...normalized,
|
|
246
276
|
source: {
|
|
@@ -273,7 +303,11 @@ export class SessionPermissionRequestService {
|
|
|
273
303
|
accepted: true,
|
|
274
304
|
ignored: false,
|
|
275
305
|
sessionId: binding.sessionId,
|
|
276
|
-
bridgeResponse:
|
|
306
|
+
bridgeResponse: normalized.kind === "user_input"
|
|
307
|
+
? buildClaudeAskUserQuestionBridgeResponse(decision.action, decision.answers ?? {}, normalized.questions, payload.tool_input, buildClaudeDecisionReason(decision.action, normalized.title, resolvedByTimeout))
|
|
308
|
+
: normalized.kind === "plan_approval"
|
|
309
|
+
? buildClaudeExitPlanModeBridgeResponse(decision.action, payload.tool_input, buildClaudeDecisionReason(decision.action, normalized.title, resolvedByTimeout))
|
|
310
|
+
: buildClaudePreToolUseBridgeResponse(decision.action, buildClaudeDecisionReason(decision.action, normalized.title, resolvedByTimeout))
|
|
277
311
|
};
|
|
278
312
|
}
|
|
279
313
|
async handleClaudePermissionRequest(payload, provider = "claude-code") {
|
|
@@ -404,6 +438,96 @@ export class SessionPermissionRequestService {
|
|
|
404
438
|
: "CodingNS 已拒绝本次权限申请")
|
|
405
439
|
};
|
|
406
440
|
}
|
|
441
|
+
async handleClaudeElicitation(payload, provider = "claude-code") {
|
|
442
|
+
logPermissionDebug("claude_permission.elicitation.begin", {
|
|
443
|
+
provider,
|
|
444
|
+
providerSessionId: payload.session_id ?? null,
|
|
445
|
+
cwd: payload.cwd ?? null,
|
|
446
|
+
transcriptPath: payload.transcript_path ?? null,
|
|
447
|
+
title: payload.title ?? null
|
|
448
|
+
});
|
|
449
|
+
const providerSessionId = requireNonEmptyText(payload.session_id, "session_id");
|
|
450
|
+
const workspacePath = requireNonEmptyText(payload.cwd, "cwd");
|
|
451
|
+
const workspace = this.workspaceService.findWorkspaceByPath(workspacePath);
|
|
452
|
+
if (!workspace) {
|
|
453
|
+
return {
|
|
454
|
+
accepted: true,
|
|
455
|
+
ignored: true,
|
|
456
|
+
sessionId: null,
|
|
457
|
+
bridgeResponse: buildClaudePreToolUseBridgeResponse("ask", "未匹配到工作区,回退 Claude 原生征询")
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
const transcriptPath = normalizeText(payload.transcript_path) || null;
|
|
461
|
+
const binding = await this.resolveClaudeBinding(provider, providerSessionId, workspace.id, workspace.path, transcriptPath, workspace.ownerUserId ?? null).catch(() => null)
|
|
462
|
+
?? this.resolveClaudeWorkspaceSessionFallback({
|
|
463
|
+
provider,
|
|
464
|
+
providerSessionId,
|
|
465
|
+
workspaceId: workspace.id,
|
|
466
|
+
workspacePath: workspace.path,
|
|
467
|
+
transcriptPath,
|
|
468
|
+
userId: workspace.ownerUserId ?? null
|
|
469
|
+
})
|
|
470
|
+
?? (this.resolveActiveClaudeSession
|
|
471
|
+
? await this.resolveActiveClaudeSession({
|
|
472
|
+
provider,
|
|
473
|
+
providerSessionId,
|
|
474
|
+
workspaceId: workspace.id,
|
|
475
|
+
workspacePath: workspace.path,
|
|
476
|
+
transcriptPath
|
|
477
|
+
}).catch(() => null)
|
|
478
|
+
: null);
|
|
479
|
+
if (!binding) {
|
|
480
|
+
return {
|
|
481
|
+
accepted: true,
|
|
482
|
+
ignored: true,
|
|
483
|
+
sessionId: null,
|
|
484
|
+
bridgeResponse: buildClaudePreToolUseBridgeResponse("ask", "未匹配到会话绑定,回退 Claude 原生征询")
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
const now = nowIso();
|
|
488
|
+
const normalized = normalizeClaudeElicitationRequest({
|
|
489
|
+
provider,
|
|
490
|
+
sessionId: binding.sessionId,
|
|
491
|
+
providerSessionId,
|
|
492
|
+
payload,
|
|
493
|
+
createdAt: now
|
|
494
|
+
});
|
|
495
|
+
let resolvedByTimeout = false;
|
|
496
|
+
const decision = await new Promise((resolve) => {
|
|
497
|
+
const timer = setTimeout(() => {
|
|
498
|
+
resolvedByTimeout = true;
|
|
499
|
+
resolve({ action: "deny" });
|
|
500
|
+
}, CLAUDE_ASK_USER_QUESTION_TIMEOUT_MS);
|
|
501
|
+
const record = {
|
|
502
|
+
...normalized,
|
|
503
|
+
source: {
|
|
504
|
+
kind: "claude-pre-tool-use",
|
|
505
|
+
resolve,
|
|
506
|
+
timer
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
this.upsertRequest(record);
|
|
510
|
+
void this.emitEnvelope({
|
|
511
|
+
type: "session.permission_request",
|
|
512
|
+
sessionId: binding.sessionId,
|
|
513
|
+
request: this.toRequestView(record)
|
|
514
|
+
});
|
|
515
|
+
});
|
|
516
|
+
const existing = this.requestsById.get(normalized.id);
|
|
517
|
+
if (existing) {
|
|
518
|
+
await this.markResolved(existing, resolvedByTimeout ? "expired" : "approved");
|
|
519
|
+
}
|
|
520
|
+
return {
|
|
521
|
+
accepted: true,
|
|
522
|
+
ignored: false,
|
|
523
|
+
sessionId: binding.sessionId,
|
|
524
|
+
bridgeResponse: buildClaudeAskUserQuestionBridgeResponse(decision.action, decision.answers ?? {}, normalized.questions, payload, decision.action === "allow"
|
|
525
|
+
? "用户已提供补充信息"
|
|
526
|
+
: resolvedByTimeout
|
|
527
|
+
? "用户补充信息超时,回退 Claude 原生处理"
|
|
528
|
+
: "用户拒绝补充信息")
|
|
529
|
+
};
|
|
530
|
+
}
|
|
407
531
|
ingestCodexServerRequest(sessionId, providerSessionId, request) {
|
|
408
532
|
const normalized = normalizeCodexServerRequest(sessionId, providerSessionId, request);
|
|
409
533
|
if (!normalized) {
|
|
@@ -1017,7 +1141,7 @@ export function normalizeClaudePreToolUseRequest(input) {
|
|
|
1017
1141
|
cwd: normalizeText(toRecord(toolInput)?.cwd) || null,
|
|
1018
1142
|
paths: normalized.paths,
|
|
1019
1143
|
permissionProfile: null,
|
|
1020
|
-
questions:
|
|
1144
|
+
questions: normalized.questions,
|
|
1021
1145
|
actions: buildClaudeActions({
|
|
1022
1146
|
kind: normalized.kind,
|
|
1023
1147
|
command: normalized.command,
|
|
@@ -1035,6 +1159,46 @@ export function normalizeClaudePreToolUseRequest(input) {
|
|
|
1035
1159
|
}
|
|
1036
1160
|
};
|
|
1037
1161
|
}
|
|
1162
|
+
export function normalizeClaudeElicitationRequest(input) {
|
|
1163
|
+
const rawPayload = stringifyPayload(input.payload);
|
|
1164
|
+
const questions = readClaudeElicitationQuestions(input.payload);
|
|
1165
|
+
const requestKey = normalizeText(input.payload.title) ||
|
|
1166
|
+
normalizeText(input.payload.prompt) ||
|
|
1167
|
+
normalizeText(input.payload.question) ||
|
|
1168
|
+
normalizeText(input.payload.message) ||
|
|
1169
|
+
`Elicitation:${hashLike(rawPayload)}`;
|
|
1170
|
+
return {
|
|
1171
|
+
id: `permission-${createId()}`,
|
|
1172
|
+
sessionId: input.sessionId,
|
|
1173
|
+
provider: input.provider,
|
|
1174
|
+
providerSessionId: input.providerSessionId,
|
|
1175
|
+
requestKey,
|
|
1176
|
+
kind: "user_input",
|
|
1177
|
+
status: "pending",
|
|
1178
|
+
title: normalizeText(input.payload.title) || "Claude 需要你补充信息",
|
|
1179
|
+
summary: questions[0]?.question ?? "Claude 需要你补充信息后才能继续",
|
|
1180
|
+
detail: rawPayload,
|
|
1181
|
+
reason: normalizeText(input.payload.reason) || null,
|
|
1182
|
+
toolName: "Elicitation",
|
|
1183
|
+
command: null,
|
|
1184
|
+
cwd: normalizeText(input.payload.cwd) || null,
|
|
1185
|
+
paths: [],
|
|
1186
|
+
permissionProfile: null,
|
|
1187
|
+
questions,
|
|
1188
|
+
actions: [
|
|
1189
|
+
createAction("submit", "提交答案", "primary", "把补充信息交给 Claude 继续处理")
|
|
1190
|
+
],
|
|
1191
|
+
rawPayload,
|
|
1192
|
+
createdAt: input.createdAt,
|
|
1193
|
+
updatedAt: input.createdAt,
|
|
1194
|
+
resolvedAt: null,
|
|
1195
|
+
source: {
|
|
1196
|
+
kind: "claude-pre-tool-use",
|
|
1197
|
+
resolve: () => undefined,
|
|
1198
|
+
timer: null
|
|
1199
|
+
}
|
|
1200
|
+
};
|
|
1201
|
+
}
|
|
1038
1202
|
export function normalizeOpenCodePermissionRequest(input) {
|
|
1039
1203
|
const requestKey = normalizeText(input.permission.id) || createId();
|
|
1040
1204
|
const title = normalizeText(input.permission.title) || "OpenCode 请求权限";
|
|
@@ -1215,6 +1379,7 @@ export function normalizeCodexServerRequest(sessionId, providerSessionId, reques
|
|
|
1215
1379
|
question: normalizeText(question.question) || "请输入答案",
|
|
1216
1380
|
allowOther: Boolean(question.isOther),
|
|
1217
1381
|
secret: Boolean(question.isSecret),
|
|
1382
|
+
multiSelect: Boolean(question.multiSelect),
|
|
1218
1383
|
options: Array.isArray(question.options)
|
|
1219
1384
|
? question.options
|
|
1220
1385
|
.map((option) => toRecord(option))
|
|
@@ -1268,6 +1433,37 @@ function buildClaudePreToolUseBridgeResponse(action, reason) {
|
|
|
1268
1433
|
}
|
|
1269
1434
|
};
|
|
1270
1435
|
}
|
|
1436
|
+
function buildClaudeAskUserQuestionBridgeResponse(action, answers, questions, originalInput, reason) {
|
|
1437
|
+
const response = buildClaudePreToolUseBridgeResponse(action, reason);
|
|
1438
|
+
const originalInputRecord = toRecord(originalInput);
|
|
1439
|
+
if (action === "allow") {
|
|
1440
|
+
return {
|
|
1441
|
+
hookSpecificOutput: {
|
|
1442
|
+
...response.hookSpecificOutput,
|
|
1443
|
+
updatedInput: {
|
|
1444
|
+
...(originalInputRecord ?? {}),
|
|
1445
|
+
answers: buildClaudeAskUserQuestionAnswers(answers, questions)
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
return response;
|
|
1451
|
+
}
|
|
1452
|
+
function buildClaudeExitPlanModeBridgeResponse(action, originalInput, reason) {
|
|
1453
|
+
const originalInputRecord = toRecord(originalInput);
|
|
1454
|
+
const response = buildClaudePreToolUseBridgeResponse(action, reason);
|
|
1455
|
+
if (action !== "allow") {
|
|
1456
|
+
return response;
|
|
1457
|
+
}
|
|
1458
|
+
return {
|
|
1459
|
+
hookSpecificOutput: {
|
|
1460
|
+
...response.hookSpecificOutput,
|
|
1461
|
+
updatedInput: {
|
|
1462
|
+
...(originalInputRecord ?? {})
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1271
1467
|
function buildClaudePermissionRequestBridgeResponse(action, message) {
|
|
1272
1468
|
return {
|
|
1273
1469
|
hookSpecificOutput: {
|
|
@@ -1422,6 +1618,7 @@ function buildClaudeKind(toolName, toolInput) {
|
|
|
1422
1618
|
const command = normalizeText(inputRecord?.command) ||
|
|
1423
1619
|
normalizeText(inputRecord?.cmd) ||
|
|
1424
1620
|
null;
|
|
1621
|
+
const allowedPrompts = readClaudeAllowedPrompts(inputRecord);
|
|
1425
1622
|
if (normalizedToolName === "bash" || normalizedToolName === "shell") {
|
|
1426
1623
|
return {
|
|
1427
1624
|
kind: "command",
|
|
@@ -1429,7 +1626,37 @@ function buildClaudeKind(toolName, toolInput) {
|
|
|
1429
1626
|
summary: command ?? "Bash 工具需要确认",
|
|
1430
1627
|
detail: stringifyPayload(toolInput),
|
|
1431
1628
|
command,
|
|
1432
|
-
paths: []
|
|
1629
|
+
paths: [],
|
|
1630
|
+
questions: []
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
if (normalizedToolName === "askuserquestion") {
|
|
1634
|
+
const questions = readClaudeAskUserQuestionQuestions(inputRecord);
|
|
1635
|
+
return {
|
|
1636
|
+
kind: "user_input",
|
|
1637
|
+
title: "Claude 需要你回答问题",
|
|
1638
|
+
summary: questions[0]?.question ?? "Claude 需要你补充选择",
|
|
1639
|
+
detail: stringifyPayload(toolInput),
|
|
1640
|
+
command: null,
|
|
1641
|
+
paths: [],
|
|
1642
|
+
questions
|
|
1643
|
+
};
|
|
1644
|
+
}
|
|
1645
|
+
if (normalizedToolName === "exitplanmode") {
|
|
1646
|
+
const summary = normalizeText(inputRecord?.plan) ||
|
|
1647
|
+
normalizeText(inputRecord?.summary) ||
|
|
1648
|
+
normalizeText(inputRecord?.title) ||
|
|
1649
|
+
(allowedPrompts[0]
|
|
1650
|
+
? `Claude 准备按计划继续执行:${allowedPrompts[0].prompt}`
|
|
1651
|
+
: "Claude 准备退出计划模式并继续执行");
|
|
1652
|
+
return {
|
|
1653
|
+
kind: "plan_approval",
|
|
1654
|
+
title: "Claude 请求确认执行计划",
|
|
1655
|
+
summary,
|
|
1656
|
+
detail: stringifyPayload(toolInput),
|
|
1657
|
+
command: null,
|
|
1658
|
+
paths: [],
|
|
1659
|
+
questions: []
|
|
1433
1660
|
};
|
|
1434
1661
|
}
|
|
1435
1662
|
if (normalizedToolName === "edit" ||
|
|
@@ -1442,7 +1669,8 @@ function buildClaudeKind(toolName, toolInput) {
|
|
|
1442
1669
|
summary: paths[0] ?? `${toolName} 工具需要确认`,
|
|
1443
1670
|
detail: stringifyPayload(toolInput),
|
|
1444
1671
|
command: null,
|
|
1445
|
-
paths
|
|
1672
|
+
paths,
|
|
1673
|
+
questions: []
|
|
1446
1674
|
};
|
|
1447
1675
|
}
|
|
1448
1676
|
return {
|
|
@@ -1451,9 +1679,143 @@ function buildClaudeKind(toolName, toolInput) {
|
|
|
1451
1679
|
summary: toolName,
|
|
1452
1680
|
detail: stringifyPayload(toolInput),
|
|
1453
1681
|
command,
|
|
1454
|
-
paths
|
|
1682
|
+
paths,
|
|
1683
|
+
questions: []
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
function readClaudeAskUserQuestionQuestions(inputRecord) {
|
|
1687
|
+
if (!inputRecord) {
|
|
1688
|
+
return [];
|
|
1689
|
+
}
|
|
1690
|
+
const rawQuestions = Array.isArray(inputRecord.questions)
|
|
1691
|
+
? inputRecord.questions
|
|
1692
|
+
: [
|
|
1693
|
+
{
|
|
1694
|
+
...inputRecord,
|
|
1695
|
+
id: normalizeText(inputRecord.id) || "question"
|
|
1696
|
+
}
|
|
1697
|
+
];
|
|
1698
|
+
return rawQuestions
|
|
1699
|
+
.map((question, index) => normalizeClaudeAskUserQuestion(question, index))
|
|
1700
|
+
.filter((question) => question !== null);
|
|
1701
|
+
}
|
|
1702
|
+
function normalizeClaudeAskUserQuestion(value, index) {
|
|
1703
|
+
const record = toRecord(value);
|
|
1704
|
+
if (!record) {
|
|
1705
|
+
return null;
|
|
1706
|
+
}
|
|
1707
|
+
const questionText = normalizeText(record.question) ||
|
|
1708
|
+
normalizeText(record.prompt) ||
|
|
1709
|
+
normalizeText(record.message) ||
|
|
1710
|
+
"请选择一个选项";
|
|
1711
|
+
const options = readClaudeAskUserQuestionOptions(record.options ?? record.choices ?? record.answers);
|
|
1712
|
+
return {
|
|
1713
|
+
id: normalizeText(record.id) ||
|
|
1714
|
+
normalizeText(record.name) ||
|
|
1715
|
+
`question-${index + 1}`,
|
|
1716
|
+
header: normalizeText(record.header) ||
|
|
1717
|
+
normalizeText(record.title) ||
|
|
1718
|
+
`问题 ${index + 1}`,
|
|
1719
|
+
question: questionText,
|
|
1720
|
+
allowOther: readBoolean(record.allowOther) ??
|
|
1721
|
+
readBoolean(record.allow_other) ??
|
|
1722
|
+
readBoolean(record.isOther) ??
|
|
1723
|
+
readBoolean(record.allowFreeform) ??
|
|
1724
|
+
readBoolean(record.allow_freeform) ??
|
|
1725
|
+
true,
|
|
1726
|
+
secret: readBoolean(record.secret) ??
|
|
1727
|
+
readBoolean(record.isSecret) ??
|
|
1728
|
+
false,
|
|
1729
|
+
multiSelect: readBoolean(record.multiSelect) ??
|
|
1730
|
+
readBoolean(record.multi_select) ??
|
|
1731
|
+
false,
|
|
1732
|
+
options
|
|
1455
1733
|
};
|
|
1456
1734
|
}
|
|
1735
|
+
function readClaudeAskUserQuestionOptions(value) {
|
|
1736
|
+
if (!Array.isArray(value)) {
|
|
1737
|
+
return [];
|
|
1738
|
+
}
|
|
1739
|
+
return value
|
|
1740
|
+
.map((item) => {
|
|
1741
|
+
if (typeof item === "string") {
|
|
1742
|
+
const label = item.trim();
|
|
1743
|
+
return label ? { label, description: null } : null;
|
|
1744
|
+
}
|
|
1745
|
+
const record = toRecord(item);
|
|
1746
|
+
const label = normalizeText(record?.label) ||
|
|
1747
|
+
normalizeText(record?.value) ||
|
|
1748
|
+
normalizeText(record?.text) ||
|
|
1749
|
+
normalizeText(record?.title);
|
|
1750
|
+
if (!label) {
|
|
1751
|
+
return null;
|
|
1752
|
+
}
|
|
1753
|
+
return {
|
|
1754
|
+
label,
|
|
1755
|
+
description: normalizeText(record?.description) || normalizeText(record?.detail) || null
|
|
1756
|
+
};
|
|
1757
|
+
})
|
|
1758
|
+
.filter((option) => option !== null);
|
|
1759
|
+
}
|
|
1760
|
+
function readClaudeElicitationQuestions(payload) {
|
|
1761
|
+
const options = readClaudeAskUserQuestionOptions(payload.options);
|
|
1762
|
+
const questionText = normalizeText(payload.question) ||
|
|
1763
|
+
normalizeText(payload.prompt) ||
|
|
1764
|
+
normalizeText(payload.message) ||
|
|
1765
|
+
"请补充 Claude 继续执行所需的信息";
|
|
1766
|
+
return [
|
|
1767
|
+
{
|
|
1768
|
+
id: "elicitation",
|
|
1769
|
+
header: normalizeText(payload.title) || "补充信息",
|
|
1770
|
+
question: questionText,
|
|
1771
|
+
allowOther: true,
|
|
1772
|
+
secret: false,
|
|
1773
|
+
multiSelect: false,
|
|
1774
|
+
options
|
|
1775
|
+
}
|
|
1776
|
+
];
|
|
1777
|
+
}
|
|
1778
|
+
export function buildClaudeAskUserQuestionAnswers(answers, questions) {
|
|
1779
|
+
return Object.fromEntries(questions
|
|
1780
|
+
.map((question) => {
|
|
1781
|
+
const values = Array.isArray(answers[question.id])
|
|
1782
|
+
? answers[question.id].map((value) => normalizeText(value)).filter(Boolean)
|
|
1783
|
+
: [];
|
|
1784
|
+
if (values.length === 0) {
|
|
1785
|
+
return null;
|
|
1786
|
+
}
|
|
1787
|
+
return [
|
|
1788
|
+
question.question,
|
|
1789
|
+
question.multiSelect ? values.join(", ") : values[0] ?? ""
|
|
1790
|
+
];
|
|
1791
|
+
})
|
|
1792
|
+
.filter((entry) => entry !== null));
|
|
1793
|
+
}
|
|
1794
|
+
export function resolveClaudeBlockingRequestTimeoutMs(kind) {
|
|
1795
|
+
if (kind === "user_input") {
|
|
1796
|
+
return CLAUDE_ASK_USER_QUESTION_TIMEOUT_MS;
|
|
1797
|
+
}
|
|
1798
|
+
if (kind === "plan_approval") {
|
|
1799
|
+
return CLAUDE_PLAN_APPROVAL_TIMEOUT_MS;
|
|
1800
|
+
}
|
|
1801
|
+
return CLAUDE_PRE_TOOL_USE_TIMEOUT_MS;
|
|
1802
|
+
}
|
|
1803
|
+
function readClaudeAllowedPrompts(inputRecord) {
|
|
1804
|
+
if (!inputRecord || !Array.isArray(inputRecord.allowedPrompts)) {
|
|
1805
|
+
return [];
|
|
1806
|
+
}
|
|
1807
|
+
return inputRecord.allowedPrompts
|
|
1808
|
+
.map((value) => {
|
|
1809
|
+
const record = toRecord(value);
|
|
1810
|
+
const tool = normalizeText(record?.tool);
|
|
1811
|
+
const prompt = normalizeText(record?.prompt);
|
|
1812
|
+
if (!tool || !prompt) {
|
|
1813
|
+
return null;
|
|
1814
|
+
}
|
|
1815
|
+
return { tool, prompt };
|
|
1816
|
+
})
|
|
1817
|
+
.filter((item) => item !== null);
|
|
1818
|
+
}
|
|
1457
1819
|
function buildOpenCodeKind(title, metadata, pattern, fallbackToolName) {
|
|
1458
1820
|
const command = normalizeText(metadata?.command);
|
|
1459
1821
|
const toolName = normalizeText(metadata?.tool) || fallbackToolName;
|
|
@@ -1581,6 +1943,17 @@ function buildClaudeAllowedScopeKey(request) {
|
|
|
1581
1943
|
return null;
|
|
1582
1944
|
}
|
|
1583
1945
|
function buildClaudeActions(request) {
|
|
1946
|
+
if (request.kind === "user_input") {
|
|
1947
|
+
return [
|
|
1948
|
+
createAction("submit", "提交选择", "primary", "把选择结果交给 Claude 继续处理")
|
|
1949
|
+
];
|
|
1950
|
+
}
|
|
1951
|
+
if (request.kind === "plan_approval") {
|
|
1952
|
+
return [
|
|
1953
|
+
createAction("allow", "批准计划", "primary", "允许 Claude 按当前计划继续执行"),
|
|
1954
|
+
createAction("deny", "退回计划", "danger", "拒绝这次计划,要求 Claude 停在计划阶段")
|
|
1955
|
+
];
|
|
1956
|
+
}
|
|
1584
1957
|
const actions = [
|
|
1585
1958
|
createAction("allow", "允许", "primary", "只允许这一次")
|
|
1586
1959
|
];
|
|
@@ -1908,6 +2281,21 @@ function normalizeText(value) {
|
|
|
1908
2281
|
}
|
|
1909
2282
|
return null;
|
|
1910
2283
|
}
|
|
2284
|
+
function readBoolean(value) {
|
|
2285
|
+
if (typeof value === "boolean") {
|
|
2286
|
+
return value;
|
|
2287
|
+
}
|
|
2288
|
+
if (typeof value === "string") {
|
|
2289
|
+
const normalized = value.trim().toLowerCase();
|
|
2290
|
+
if (normalized === "true" || normalized === "1" || normalized === "yes") {
|
|
2291
|
+
return true;
|
|
2292
|
+
}
|
|
2293
|
+
if (normalized === "false" || normalized === "0" || normalized === "no") {
|
|
2294
|
+
return false;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
return null;
|
|
2298
|
+
}
|
|
1911
2299
|
function toRecord(value) {
|
|
1912
2300
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1913
2301
|
return null;
|