@ccpocket/bridge 1.45.3 → 1.46.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 +17 -0
- package/dist/codex-process.js +121 -19
- package/dist/codex-process.js.map +1 -1
- package/dist/parser.d.ts +17 -0
- package/dist/parser.js.map +1 -1
- package/dist/session.d.ts +2 -0
- package/dist/session.js +6 -1
- package/dist/session.js.map +1 -1
- package/dist/websocket.js +21 -2
- package/dist/websocket.js.map +1 -1
- package/package.json +1 -1
package/dist/codex-process.d.ts
CHANGED
|
@@ -40,6 +40,23 @@ export interface CodexAppMetadata {
|
|
|
40
40
|
isAccessible: boolean;
|
|
41
41
|
isEnabled: boolean;
|
|
42
42
|
}
|
|
43
|
+
/** Plugin metadata returned by the Codex `plugin/list` RPC. */
|
|
44
|
+
export interface CodexPluginMetadata {
|
|
45
|
+
id: string;
|
|
46
|
+
name: string;
|
|
47
|
+
path: string;
|
|
48
|
+
marketplaceName: string;
|
|
49
|
+
marketplacePath?: string;
|
|
50
|
+
installed: boolean;
|
|
51
|
+
enabled: boolean;
|
|
52
|
+
displayName?: string;
|
|
53
|
+
shortDescription?: string;
|
|
54
|
+
longDescription?: string;
|
|
55
|
+
defaultPrompt?: string;
|
|
56
|
+
brandColor?: string;
|
|
57
|
+
composerIcon?: string;
|
|
58
|
+
composerIconUrl?: string;
|
|
59
|
+
}
|
|
43
60
|
export interface CodexThreadSummary {
|
|
44
61
|
id: string;
|
|
45
62
|
preview: string;
|
package/dist/codex-process.js
CHANGED
|
@@ -370,7 +370,7 @@ export class CodexProcess extends EventEmitter {
|
|
|
370
370
|
const pending = this.resolvePendingApproval(toolUseId);
|
|
371
371
|
if (!pending) {
|
|
372
372
|
// Fallback: McpElicitation lives in pendingUserInputs
|
|
373
|
-
if (this.approveUserInput(toolUseId, "
|
|
373
|
+
if (this.approveUserInput(toolUseId, "Allow for this session"))
|
|
374
374
|
return;
|
|
375
375
|
console.log("[codex-process] approveAlways() called but no pending permission requests");
|
|
376
376
|
return;
|
|
@@ -398,7 +398,7 @@ export class CodexProcess extends EventEmitter {
|
|
|
398
398
|
return;
|
|
399
399
|
}
|
|
400
400
|
this.pendingApprovals.delete(pending.toolUseId);
|
|
401
|
-
this.respondToServerRequest(pending.requestId, buildApprovalResponse(pending,
|
|
401
|
+
this.respondToServerRequest(pending.requestId, buildApprovalResponse(pending, resolveApprovalRejectDecision(pending)));
|
|
402
402
|
this.emitToolResult(pending.toolUseId, "Rejected");
|
|
403
403
|
if (this.pendingApprovals.size === 0) {
|
|
404
404
|
this.setStatus("running");
|
|
@@ -491,7 +491,7 @@ export class CodexProcess extends EventEmitter {
|
|
|
491
491
|
if (!pending)
|
|
492
492
|
return false;
|
|
493
493
|
this.pendingUserInputs.delete(pending.toolUseId);
|
|
494
|
-
this.respondToServerRequest(pending.requestId, buildUserInputResponse(pending, result));
|
|
494
|
+
this.respondToServerRequest(pending.requestId, buildUserInputResponse(pending, resolveUserInputRejectResult(pending, result)));
|
|
495
495
|
this.emitToolResult(pending.toolUseId, "Rejected");
|
|
496
496
|
if (this.pendingApprovals.size === 0 && this.pendingUserInputs.size === 0) {
|
|
497
497
|
this.setStatus("running");
|
|
@@ -759,6 +759,13 @@ export class CodexProcess extends EventEmitter {
|
|
|
759
759
|
async _fetchCompletionEntitiesInternal(projectPath) {
|
|
760
760
|
const TIMEOUT_MS = 10_000;
|
|
761
761
|
try {
|
|
762
|
+
const requestOrNull = (method, params) => Promise.race([
|
|
763
|
+
this.request(method, params).catch((err) => {
|
|
764
|
+
console.log(`[codex-process] ${method} failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
|
|
765
|
+
return null;
|
|
766
|
+
}),
|
|
767
|
+
new Promise((resolve) => setTimeout(() => resolve(null), TIMEOUT_MS)),
|
|
768
|
+
]);
|
|
762
769
|
const skillsResult = (await Promise.race([
|
|
763
770
|
this.request("skills/list", { cwds: [projectPath] }),
|
|
764
771
|
new Promise((resolve) => setTimeout(() => resolve(null), TIMEOUT_MS)),
|
|
@@ -772,6 +779,15 @@ export class CodexProcess extends EventEmitter {
|
|
|
772
779
|
}),
|
|
773
780
|
new Promise((resolve) => setTimeout(() => resolve(null), TIMEOUT_MS)),
|
|
774
781
|
]));
|
|
782
|
+
const pluginsResult = await requestOrNull("plugin/list", { cwds: [projectPath] });
|
|
783
|
+
const optionalString = (value) => typeof value === "string" ? value : undefined;
|
|
784
|
+
const optionalFirstString = (value) => {
|
|
785
|
+
if (typeof value === "string")
|
|
786
|
+
return value;
|
|
787
|
+
if (!Array.isArray(value))
|
|
788
|
+
return undefined;
|
|
789
|
+
return value.find((entry) => typeof entry === "string");
|
|
790
|
+
};
|
|
775
791
|
const skills = [];
|
|
776
792
|
const skillMetadata = [];
|
|
777
793
|
if (skillsResult?.data) {
|
|
@@ -808,6 +824,30 @@ export class CodexProcess extends EventEmitter {
|
|
|
808
824
|
isEnabled: app.isEnabled ?? true,
|
|
809
825
|
}));
|
|
810
826
|
this._apps = appMetadata;
|
|
827
|
+
const pluginMetadata = [];
|
|
828
|
+
for (const marketplace of pluginsResult?.marketplaces ?? []) {
|
|
829
|
+
for (const plugin of marketplace.plugins ?? []) {
|
|
830
|
+
if (!plugin.installed || !plugin.enabled)
|
|
831
|
+
continue;
|
|
832
|
+
pluginMetadata.push({
|
|
833
|
+
id: plugin.id,
|
|
834
|
+
name: plugin.name,
|
|
835
|
+
path: `plugin://${plugin.id}`,
|
|
836
|
+
marketplaceName: marketplace.name,
|
|
837
|
+
marketplacePath: marketplace.path ?? undefined,
|
|
838
|
+
installed: plugin.installed,
|
|
839
|
+
enabled: plugin.enabled,
|
|
840
|
+
displayName: optionalString(plugin.interface?.displayName),
|
|
841
|
+
shortDescription: optionalString(plugin.interface?.shortDescription),
|
|
842
|
+
longDescription: optionalString(plugin.interface?.longDescription),
|
|
843
|
+
defaultPrompt: optionalFirstString(plugin.interface?.defaultPrompt),
|
|
844
|
+
brandColor: optionalString(plugin.interface?.brandColor),
|
|
845
|
+
composerIcon: optionalString(plugin.interface?.composerIcon),
|
|
846
|
+
composerIconUrl: optionalString(plugin.interface?.composerIconUrl),
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
const plugins = pluginMetadata.map((plugin) => plugin.name);
|
|
811
851
|
if (this.stopped)
|
|
812
852
|
return;
|
|
813
853
|
const signature = JSON.stringify({
|
|
@@ -815,13 +855,17 @@ export class CodexProcess extends EventEmitter {
|
|
|
815
855
|
skillMetadata,
|
|
816
856
|
apps: appMetadata.map((app) => app.id),
|
|
817
857
|
appMetadata,
|
|
858
|
+
plugins,
|
|
859
|
+
pluginMetadata,
|
|
818
860
|
});
|
|
819
861
|
if (signature === this._lastCompletionEntitiesSignature) {
|
|
820
862
|
return;
|
|
821
863
|
}
|
|
822
864
|
this._lastCompletionEntitiesSignature = signature;
|
|
823
|
-
if (skills.length > 0 ||
|
|
824
|
-
|
|
865
|
+
if (skills.length > 0 ||
|
|
866
|
+
appMetadata.length > 0 ||
|
|
867
|
+
pluginMetadata.length > 0) {
|
|
868
|
+
console.log(`[codex-process] completion entities loaded: ${skills.length} skills, ${appMetadata.length} apps, ${pluginMetadata.length} plugins`);
|
|
825
869
|
this.emitMessage({
|
|
826
870
|
type: "system",
|
|
827
871
|
subtype: "supported_commands",
|
|
@@ -829,6 +873,8 @@ export class CodexProcess extends EventEmitter {
|
|
|
829
873
|
skillMetadata,
|
|
830
874
|
apps: appMetadata.map((app) => app.id),
|
|
831
875
|
appMetadata,
|
|
876
|
+
plugins,
|
|
877
|
+
pluginMetadata,
|
|
832
878
|
});
|
|
833
879
|
}
|
|
834
880
|
}
|
|
@@ -1783,6 +1829,16 @@ function buildApprovalResponse(pending, decision) {
|
|
|
1783
1829
|
decision,
|
|
1784
1830
|
};
|
|
1785
1831
|
}
|
|
1832
|
+
function resolveApprovalRejectDecision(pending) {
|
|
1833
|
+
const availableDecisions = pending.input.availableDecisions;
|
|
1834
|
+
if (!Array.isArray(availableDecisions))
|
|
1835
|
+
return "decline";
|
|
1836
|
+
const decisions = new Set(availableDecisions.filter((entry) => typeof entry === "string"));
|
|
1837
|
+
if (decisions.has("cancel") && !decisions.has("decline")) {
|
|
1838
|
+
return "cancel";
|
|
1839
|
+
}
|
|
1840
|
+
return "decline";
|
|
1841
|
+
}
|
|
1786
1842
|
function buildUserInputResponse(pending, rawResult) {
|
|
1787
1843
|
if (pending.kind === "questions") {
|
|
1788
1844
|
return {
|
|
@@ -1791,6 +1847,18 @@ function buildUserInputResponse(pending, rawResult) {
|
|
|
1791
1847
|
}
|
|
1792
1848
|
return buildElicitationResponse(pending, rawResult);
|
|
1793
1849
|
}
|
|
1850
|
+
function resolveUserInputRejectResult(pending, fallback) {
|
|
1851
|
+
if (pending.kind !== "elicitation_approval")
|
|
1852
|
+
return fallback;
|
|
1853
|
+
const availableDecisions = pending.input.availableDecisions;
|
|
1854
|
+
if (!Array.isArray(availableDecisions))
|
|
1855
|
+
return fallback;
|
|
1856
|
+
const decisions = new Set(availableDecisions.filter((entry) => typeof entry === "string"));
|
|
1857
|
+
if (decisions.has("cancel") && !decisions.has("decline")) {
|
|
1858
|
+
return "Cancel";
|
|
1859
|
+
}
|
|
1860
|
+
return fallback;
|
|
1861
|
+
}
|
|
1794
1862
|
function extractWritableRootsFromConfigRead(response) {
|
|
1795
1863
|
if (!response || typeof response !== "object")
|
|
1796
1864
|
return [];
|
|
@@ -2410,8 +2478,9 @@ function createElicitationInput(params) {
|
|
|
2410
2478
|
}
|
|
2411
2479
|
const schema = asRecord(params.requestedSchema);
|
|
2412
2480
|
const elicitationMeta = asRecord(params._meta);
|
|
2413
|
-
if (
|
|
2481
|
+
if (isApprovalActionElicitation(schema, elicitationMeta)) {
|
|
2414
2482
|
const questionId = "approval";
|
|
2483
|
+
const isToolApproval = isToolApprovalElicitation(elicitationMeta);
|
|
2415
2484
|
return {
|
|
2416
2485
|
kind: "elicitation_approval",
|
|
2417
2486
|
questions: [{ id: questionId, question: message }],
|
|
@@ -2420,12 +2489,13 @@ function createElicitationInput(params) {
|
|
|
2420
2489
|
serverName,
|
|
2421
2490
|
message,
|
|
2422
2491
|
_meta: elicitationMeta ?? null,
|
|
2492
|
+
availableDecisions: buildApprovalActionElicitationAvailableDecisions(elicitationMeta, isToolApproval),
|
|
2423
2493
|
questions: [
|
|
2424
2494
|
{
|
|
2425
2495
|
id: questionId,
|
|
2426
2496
|
header: "Approve app tool call?",
|
|
2427
2497
|
question: message,
|
|
2428
|
-
options:
|
|
2498
|
+
options: buildApprovalActionElicitationOptions(elicitationMeta, isToolApproval),
|
|
2429
2499
|
multiSelect: false,
|
|
2430
2500
|
isOther: false,
|
|
2431
2501
|
isSecret: false,
|
|
@@ -2504,10 +2574,8 @@ function createElicitationInput(params) {
|
|
|
2504
2574
|
},
|
|
2505
2575
|
};
|
|
2506
2576
|
}
|
|
2507
|
-
function
|
|
2508
|
-
|
|
2509
|
-
return false;
|
|
2510
|
-
return isEmptyObjectSchema(schema);
|
|
2577
|
+
function isApprovalActionElicitation(schema, meta) {
|
|
2578
|
+
return isEmptyObjectSchema(schema) && !isToolSuggestionElicitation(meta);
|
|
2511
2579
|
}
|
|
2512
2580
|
function isEmptyObjectSchema(schema) {
|
|
2513
2581
|
if (!schema)
|
|
@@ -2517,29 +2585,63 @@ function isEmptyObjectSchema(schema) {
|
|
|
2517
2585
|
const properties = asRecord(schema.properties);
|
|
2518
2586
|
return properties != null && Object.keys(properties).length === 0;
|
|
2519
2587
|
}
|
|
2520
|
-
function
|
|
2588
|
+
function isToolApprovalElicitation(meta) {
|
|
2589
|
+
return meta?.codex_approval_kind === "mcp_tool_call";
|
|
2590
|
+
}
|
|
2591
|
+
function isToolSuggestionElicitation(meta) {
|
|
2592
|
+
return meta?.codex_approval_kind === "tool_suggestion";
|
|
2593
|
+
}
|
|
2594
|
+
function buildApprovalActionElicitationOptions(meta, isToolApproval) {
|
|
2521
2595
|
const persistModes = extractPersistModes(meta);
|
|
2522
2596
|
const options = [
|
|
2523
|
-
{
|
|
2597
|
+
{
|
|
2598
|
+
label: "Allow",
|
|
2599
|
+
description: isToolApproval
|
|
2600
|
+
? "Run the tool and continue."
|
|
2601
|
+
: "Allow this request and continue.",
|
|
2602
|
+
},
|
|
2524
2603
|
];
|
|
2525
2604
|
if (persistModes.has("session")) {
|
|
2526
2605
|
options.push({
|
|
2527
2606
|
label: "Allow for this session",
|
|
2528
|
-
description:
|
|
2607
|
+
description: isToolApproval
|
|
2608
|
+
? "Run the tool and remember this choice for this session."
|
|
2609
|
+
: "Allow this request and remember this choice for this session.",
|
|
2529
2610
|
});
|
|
2530
2611
|
}
|
|
2531
2612
|
if (persistModes.has("always")) {
|
|
2532
2613
|
options.push({
|
|
2533
2614
|
label: "Always allow",
|
|
2534
|
-
description:
|
|
2615
|
+
description: isToolApproval
|
|
2616
|
+
? "Run the tool and remember this choice for future tool calls."
|
|
2617
|
+
: "Allow this request and remember this choice for future requests.",
|
|
2535
2618
|
});
|
|
2536
2619
|
}
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2620
|
+
if (!isToolApproval) {
|
|
2621
|
+
options.push({
|
|
2622
|
+
label: "Deny",
|
|
2623
|
+
description: "Decline this request and continue.",
|
|
2624
|
+
});
|
|
2625
|
+
}
|
|
2626
|
+
options.push(isToolApproval
|
|
2627
|
+
? {
|
|
2628
|
+
label: "Cancel",
|
|
2629
|
+
description: "Cancel this tool call.",
|
|
2630
|
+
}
|
|
2631
|
+
: {
|
|
2632
|
+
label: "Cancel",
|
|
2633
|
+
description: "Cancel this request.",
|
|
2634
|
+
});
|
|
2541
2635
|
return options;
|
|
2542
2636
|
}
|
|
2637
|
+
function buildApprovalActionElicitationAvailableDecisions(meta, isToolApproval) {
|
|
2638
|
+
const persistModes = extractPersistModes(meta);
|
|
2639
|
+
return [
|
|
2640
|
+
"accept",
|
|
2641
|
+
...(persistModes.has("session") ? ["acceptForSession"] : []),
|
|
2642
|
+
isToolApproval ? "cancel" : "decline",
|
|
2643
|
+
];
|
|
2644
|
+
}
|
|
2543
2645
|
function extractPersistModes(meta) {
|
|
2544
2646
|
const persist = meta?.persist;
|
|
2545
2647
|
const modes = new Set();
|