@agentclientprotocol/codex-acp 1.0.0 → 1.0.2
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/README.md +5 -2
- package/dist/index.js +1056 -237
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3343,6 +3343,9 @@ var CLIENT_METHODS = {
|
|
|
3343
3343
|
elicitation_create: "elicitation/create",
|
|
3344
3344
|
elicitation_complete: "elicitation/complete"
|
|
3345
3345
|
};
|
|
3346
|
+
var PROTOCOL_METHODS = {
|
|
3347
|
+
cancel_request: "$/cancel_request"
|
|
3348
|
+
};
|
|
3346
3349
|
var PROTOCOL_VERSION = 1;
|
|
3347
3350
|
|
|
3348
3351
|
// node_modules/zod/v4/classic/external.js
|
|
@@ -18935,6 +18938,17 @@ var zFileSystemCapabilities = object({
|
|
|
18935
18938
|
writeTextFile: boolean2().optional().default(false),
|
|
18936
18939
|
_meta: record(string2(), unknown()).nullish()
|
|
18937
18940
|
});
|
|
18941
|
+
var zBooleanConfigOptionCapabilities = object({
|
|
18942
|
+
_meta: record(string2(), unknown()).nullish()
|
|
18943
|
+
});
|
|
18944
|
+
var zSessionConfigOptionsCapabilities = object({
|
|
18945
|
+
boolean: defaultOnError(zBooleanConfigOptionCapabilities.nullish(), () => void 0),
|
|
18946
|
+
_meta: record(string2(), unknown()).nullish()
|
|
18947
|
+
});
|
|
18948
|
+
var zClientSessionCapabilities = object({
|
|
18949
|
+
configOptions: defaultOnError(zSessionConfigOptionsCapabilities.nullish(), () => void 0),
|
|
18950
|
+
_meta: record(string2(), unknown()).nullish()
|
|
18951
|
+
});
|
|
18938
18952
|
var zPlanCapabilities = object({
|
|
18939
18953
|
_meta: record(string2(), unknown()).nullish()
|
|
18940
18954
|
});
|
|
@@ -18971,6 +18985,7 @@ var zClientNesCapabilities = object({
|
|
|
18971
18985
|
var zClientCapabilities = object({
|
|
18972
18986
|
fs: zFileSystemCapabilities.optional().default({ readTextFile: false, writeTextFile: false }),
|
|
18973
18987
|
terminal: boolean2().optional().default(false),
|
|
18988
|
+
session: defaultOnError(zClientSessionCapabilities.nullish(), () => void 0),
|
|
18974
18989
|
plan: defaultOnError(zPlanCapabilities.nullish(), () => void 0),
|
|
18975
18990
|
auth: zAuthCapabilities.optional().default({ terminal: false }),
|
|
18976
18991
|
elicitation: defaultOnError(zElicitationCapabilities.nullish(), () => void 0),
|
|
@@ -19515,6 +19530,19 @@ function ndJsonStream(output, input) {
|
|
|
19515
19530
|
}
|
|
19516
19531
|
|
|
19517
19532
|
// node_modules/@agentclientprotocol/sdk/dist/jsonrpc.js
|
|
19533
|
+
var CANCEL_REQUEST_METHOD = "$/cancel_request";
|
|
19534
|
+
function isRecord(value) {
|
|
19535
|
+
return typeof value === "object" && value !== null;
|
|
19536
|
+
}
|
|
19537
|
+
function isJsonRpcId(value) {
|
|
19538
|
+
return value === null || typeof value === "string" || typeof value === "number" && Number.isFinite(value);
|
|
19539
|
+
}
|
|
19540
|
+
function cancelRequestId(params) {
|
|
19541
|
+
if (!isRecord(params) || !isJsonRpcId(params["requestId"])) {
|
|
19542
|
+
return void 0;
|
|
19543
|
+
}
|
|
19544
|
+
return params["requestId"];
|
|
19545
|
+
}
|
|
19518
19546
|
var Handled = {
|
|
19519
19547
|
/**
|
|
19520
19548
|
* Marks a message as handled.
|
|
@@ -19561,13 +19589,40 @@ function errorToResult(error51) {
|
|
|
19561
19589
|
return RequestError.internalError({ details }).toResult();
|
|
19562
19590
|
}
|
|
19563
19591
|
}
|
|
19592
|
+
function requestCancelledError(reason) {
|
|
19593
|
+
if (reason instanceof RequestError && reason.code === -32800) {
|
|
19594
|
+
return reason;
|
|
19595
|
+
}
|
|
19596
|
+
return RequestError.requestCancelled(reason);
|
|
19597
|
+
}
|
|
19598
|
+
function errorToRequestResult(error51, signal) {
|
|
19599
|
+
const requestCancelled = abortErrorToRequestCancelled(error51, signal);
|
|
19600
|
+
return requestCancelled ? requestCancelled.toResult() : errorToResult(error51);
|
|
19601
|
+
}
|
|
19602
|
+
function abortErrorToRequestCancelled(error51, signal) {
|
|
19603
|
+
if (!signal.aborted || !isAbortError(error51)) {
|
|
19604
|
+
return void 0;
|
|
19605
|
+
}
|
|
19606
|
+
return requestCancelledError(signal.reason);
|
|
19607
|
+
}
|
|
19608
|
+
function isAbortError(error51) {
|
|
19609
|
+
if (typeof error51 !== "object" || error51 === null) {
|
|
19610
|
+
return false;
|
|
19611
|
+
}
|
|
19612
|
+
const maybeAbortError = error51;
|
|
19613
|
+
return maybeAbortError.name === "AbortError" || maybeAbortError.code === "ABORT_ERR";
|
|
19614
|
+
}
|
|
19564
19615
|
var RequestResponder = class {
|
|
19565
19616
|
id;
|
|
19566
19617
|
sendResult;
|
|
19618
|
+
signal;
|
|
19619
|
+
finishRequest;
|
|
19567
19620
|
didRespond = false;
|
|
19568
|
-
constructor(id, sendResult) {
|
|
19621
|
+
constructor(id, sendResult, signal = new AbortController().signal, finishRequest) {
|
|
19569
19622
|
this.id = id;
|
|
19570
19623
|
this.sendResult = sendResult;
|
|
19624
|
+
this.signal = signal;
|
|
19625
|
+
this.finishRequest = finishRequest;
|
|
19571
19626
|
}
|
|
19572
19627
|
/**
|
|
19573
19628
|
* Whether this request has already received a response.
|
|
@@ -19596,7 +19651,9 @@ var RequestResponder = class {
|
|
|
19596
19651
|
return rejectedPromise(new Error("JSON-RPC request already responded"));
|
|
19597
19652
|
}
|
|
19598
19653
|
this.didRespond = true;
|
|
19599
|
-
return this.sendResult(result)
|
|
19654
|
+
return this.sendResult(result).finally(() => {
|
|
19655
|
+
this.finishRequest?.();
|
|
19656
|
+
});
|
|
19600
19657
|
}
|
|
19601
19658
|
};
|
|
19602
19659
|
var HandlerRegistration = class {
|
|
@@ -19636,8 +19693,8 @@ var ConnectionContext = class {
|
|
|
19636
19693
|
/**
|
|
19637
19694
|
* Sends a request over the connection.
|
|
19638
19695
|
*/
|
|
19639
|
-
sendRequest(method, params, mapResponse) {
|
|
19640
|
-
return this.connection.sendRequest(method, params, mapResponse);
|
|
19696
|
+
sendRequest(method, params, mapResponse, options) {
|
|
19697
|
+
return this.connection.sendRequest(method, params, mapResponse, options);
|
|
19641
19698
|
}
|
|
19642
19699
|
/**
|
|
19643
19700
|
* Sends a notification over the connection.
|
|
@@ -19645,6 +19702,12 @@ var ConnectionContext = class {
|
|
|
19645
19702
|
sendNotification(method, params) {
|
|
19646
19703
|
return this.connection.sendNotification(method, params);
|
|
19647
19704
|
}
|
|
19705
|
+
/**
|
|
19706
|
+
* Sends a protocol-level request cancellation notification.
|
|
19707
|
+
*/
|
|
19708
|
+
sendCancelRequest(requestId) {
|
|
19709
|
+
return this.connection.sendCancelRequest(requestId);
|
|
19710
|
+
}
|
|
19648
19711
|
/**
|
|
19649
19712
|
* Registers a handler that can be disposed independently.
|
|
19650
19713
|
*/
|
|
@@ -19666,6 +19729,7 @@ var ConnectionContext = class {
|
|
|
19666
19729
|
};
|
|
19667
19730
|
var Connection = class {
|
|
19668
19731
|
pendingResponses = /* @__PURE__ */ new Map();
|
|
19732
|
+
incomingRequests = /* @__PURE__ */ new Map();
|
|
19669
19733
|
nextRequestId = 0;
|
|
19670
19734
|
staticHandlers = [];
|
|
19671
19735
|
dynamicHandlers = /* @__PURE__ */ new Set();
|
|
@@ -19763,13 +19827,15 @@ var Connection = class {
|
|
|
19763
19827
|
* `mapResponse` can convert the raw result before the returned promise
|
|
19764
19828
|
* resolves.
|
|
19765
19829
|
*/
|
|
19766
|
-
sendRequest(method, params, mapResponse) {
|
|
19830
|
+
sendRequest(method, params, mapResponse, options = {}) {
|
|
19767
19831
|
if (this.abortController.signal.aborted) {
|
|
19768
19832
|
return rejectedPromise(this.closedReason());
|
|
19769
19833
|
}
|
|
19770
19834
|
const id = this.nextRequestId++;
|
|
19835
|
+
let cancel = () => {
|
|
19836
|
+
};
|
|
19771
19837
|
const responsePromise = new Promise((resolve, reject) => {
|
|
19772
|
-
|
|
19838
|
+
const pendingResponse = {
|
|
19773
19839
|
resolve: (response) => {
|
|
19774
19840
|
try {
|
|
19775
19841
|
const value = mapResponse ? mapResponse(response) : response;
|
|
@@ -19779,14 +19845,45 @@ var Connection = class {
|
|
|
19779
19845
|
}
|
|
19780
19846
|
},
|
|
19781
19847
|
reject
|
|
19848
|
+
};
|
|
19849
|
+
cancel = () => {
|
|
19850
|
+
if (pendingResponse.cancellationSent) {
|
|
19851
|
+
return;
|
|
19852
|
+
}
|
|
19853
|
+
pendingResponse.cancellationSent = true;
|
|
19854
|
+
pendingResponse.cleanup?.();
|
|
19855
|
+
void this.sendCancelRequest(id).catch(() => {
|
|
19856
|
+
});
|
|
19857
|
+
};
|
|
19858
|
+
options.cancellationSignal?.addEventListener("abort", cancel, {
|
|
19859
|
+
once: true
|
|
19782
19860
|
});
|
|
19861
|
+
pendingResponse.cleanup = () => {
|
|
19862
|
+
options.cancellationSignal?.removeEventListener("abort", cancel);
|
|
19863
|
+
};
|
|
19864
|
+
this.pendingResponses.set(id, pendingResponse);
|
|
19783
19865
|
});
|
|
19784
19866
|
responsePromise.catch(() => {
|
|
19785
19867
|
});
|
|
19786
|
-
|
|
19868
|
+
const requestSent = this.sendMessage({
|
|
19869
|
+
jsonrpc: "2.0",
|
|
19870
|
+
id,
|
|
19871
|
+
method,
|
|
19872
|
+
params
|
|
19787
19873
|
});
|
|
19874
|
+
void requestSent.catch(() => {
|
|
19875
|
+
});
|
|
19876
|
+
if (options.cancellationSignal?.aborted) {
|
|
19877
|
+
cancel();
|
|
19878
|
+
}
|
|
19788
19879
|
return responsePromise;
|
|
19789
19880
|
}
|
|
19881
|
+
/**
|
|
19882
|
+
* Sends a protocol-level request cancellation notification.
|
|
19883
|
+
*/
|
|
19884
|
+
sendCancelRequest(requestId) {
|
|
19885
|
+
return this.sendNotification(CANCEL_REQUEST_METHOD, { requestId });
|
|
19886
|
+
}
|
|
19790
19887
|
/**
|
|
19791
19888
|
* Sends a JSON-RPC notification.
|
|
19792
19889
|
*/
|
|
@@ -19804,11 +19901,16 @@ var Connection = class {
|
|
|
19804
19901
|
return;
|
|
19805
19902
|
}
|
|
19806
19903
|
const closeError = error51 ?? new Error("ACP connection closed");
|
|
19904
|
+
this.abortController.abort(closeError);
|
|
19807
19905
|
for (const pendingResponse of this.pendingResponses.values()) {
|
|
19906
|
+
pendingResponse.cleanup?.();
|
|
19808
19907
|
pendingResponse.reject(closeError);
|
|
19809
19908
|
}
|
|
19810
19909
|
this.pendingResponses.clear();
|
|
19811
|
-
this.
|
|
19910
|
+
for (const controller of this.incomingRequests.values()) {
|
|
19911
|
+
controller.abort(closeError);
|
|
19912
|
+
}
|
|
19913
|
+
this.incomingRequests.clear();
|
|
19812
19914
|
void this.receiveReader?.cancel(closeError).catch(() => {
|
|
19813
19915
|
});
|
|
19814
19916
|
}
|
|
@@ -19869,6 +19971,9 @@ var Connection = class {
|
|
|
19869
19971
|
return;
|
|
19870
19972
|
}
|
|
19871
19973
|
if ("method" in message) {
|
|
19974
|
+
if (!("id" in message)) {
|
|
19975
|
+
this.handleProtocolNotification(message);
|
|
19976
|
+
}
|
|
19872
19977
|
void this.processIncomingMessage(this.toIncomingMessage(message)).catch((error51) => this.close(error51));
|
|
19873
19978
|
} else if ("id" in message) {
|
|
19874
19979
|
this.handleResponse(message);
|
|
@@ -19909,7 +20014,7 @@ var Connection = class {
|
|
|
19909
20014
|
return;
|
|
19910
20015
|
}
|
|
19911
20016
|
if (current.kind === "request" && !current.responder.responded) {
|
|
19912
|
-
await current.responder.respondWithResult(
|
|
20017
|
+
await current.responder.respondWithResult(errorToRequestResult(error51, current.responder.signal));
|
|
19913
20018
|
} else {
|
|
19914
20019
|
const response = errorToResult(error51);
|
|
19915
20020
|
if ("error" in response) {
|
|
@@ -19920,16 +20025,24 @@ var Connection = class {
|
|
|
19920
20025
|
}
|
|
19921
20026
|
toIncomingMessage(message) {
|
|
19922
20027
|
if ("id" in message) {
|
|
20028
|
+
const abortController = new AbortController();
|
|
20029
|
+
this.incomingRequests.set(message.id, abortController);
|
|
20030
|
+
const finishRequest = () => {
|
|
20031
|
+
if (this.incomingRequests.get(message.id) === abortController) {
|
|
20032
|
+
this.incomingRequests.delete(message.id);
|
|
20033
|
+
}
|
|
20034
|
+
};
|
|
19923
20035
|
return {
|
|
19924
20036
|
kind: "request",
|
|
19925
20037
|
method: message.method,
|
|
19926
20038
|
params: message.params,
|
|
19927
20039
|
raw: message,
|
|
20040
|
+
signal: abortController.signal,
|
|
19928
20041
|
responder: new RequestResponder(message.id, (result) => this.sendMessage({
|
|
19929
20042
|
jsonrpc: "2.0",
|
|
19930
20043
|
id: message.id,
|
|
19931
20044
|
...result
|
|
19932
|
-
}))
|
|
20045
|
+
}), abortController.signal, finishRequest)
|
|
19933
20046
|
};
|
|
19934
20047
|
}
|
|
19935
20048
|
return {
|
|
@@ -19942,6 +20055,8 @@ var Connection = class {
|
|
|
19942
20055
|
handleResponse(response) {
|
|
19943
20056
|
const pendingResponse = this.pendingResponses.get(response.id);
|
|
19944
20057
|
if (pendingResponse) {
|
|
20058
|
+
this.pendingResponses.delete(response.id);
|
|
20059
|
+
pendingResponse.cleanup?.();
|
|
19945
20060
|
if ("result" in response) {
|
|
19946
20061
|
pendingResponse.resolve(response.result);
|
|
19947
20062
|
} else if ("error" in response) {
|
|
@@ -19950,11 +20065,24 @@ var Connection = class {
|
|
|
19950
20065
|
} else {
|
|
19951
20066
|
pendingResponse.reject(RequestError.invalidRequest(response));
|
|
19952
20067
|
}
|
|
19953
|
-
this.pendingResponses.delete(response.id);
|
|
19954
20068
|
} else {
|
|
19955
20069
|
console.error("Got response to unknown request", response.id);
|
|
19956
20070
|
}
|
|
19957
20071
|
}
|
|
20072
|
+
handleProtocolNotification(message) {
|
|
20073
|
+
if (message.method !== CANCEL_REQUEST_METHOD) {
|
|
20074
|
+
return;
|
|
20075
|
+
}
|
|
20076
|
+
const requestId = cancelRequestId(message.params);
|
|
20077
|
+
if (requestId === void 0) {
|
|
20078
|
+
return;
|
|
20079
|
+
}
|
|
20080
|
+
const controller = this.incomingRequests.get(requestId);
|
|
20081
|
+
if (!controller || controller.signal.aborted) {
|
|
20082
|
+
return;
|
|
20083
|
+
}
|
|
20084
|
+
controller.abort(RequestError.requestCancelled({ requestId }));
|
|
20085
|
+
}
|
|
19958
20086
|
closedReason() {
|
|
19959
20087
|
return this.abortController.signal.reason ?? new Error("ACP connection closed");
|
|
19960
20088
|
}
|
|
@@ -20095,6 +20223,12 @@ var RequestError = class _RequestError extends Error {
|
|
|
20095
20223
|
static internalError(data, additionalMessage) {
|
|
20096
20224
|
return new _RequestError(-32603, `Internal error${additionalMessage ? `: ${additionalMessage}` : ""}`, data);
|
|
20097
20225
|
}
|
|
20226
|
+
/**
|
|
20227
|
+
* Execution of the request was aborted.
|
|
20228
|
+
*/
|
|
20229
|
+
static requestCancelled(data, additionalMessage) {
|
|
20230
|
+
return new _RequestError(-32800, `Request cancelled${additionalMessage ? `: ${additionalMessage}` : ""}`, data);
|
|
20231
|
+
}
|
|
20098
20232
|
/**
|
|
20099
20233
|
* Authentication required.
|
|
20100
20234
|
*/
|
|
@@ -20210,6 +20344,9 @@ var methods = {
|
|
|
20210
20344
|
create: CLIENT_METHODS.elicitation_create,
|
|
20211
20345
|
complete: CLIENT_METHODS.elicitation_complete
|
|
20212
20346
|
}
|
|
20347
|
+
},
|
|
20348
|
+
protocol: {
|
|
20349
|
+
cancelRequest: PROTOCOL_METHODS.cancel_request
|
|
20213
20350
|
}
|
|
20214
20351
|
};
|
|
20215
20352
|
var startActiveSession = /* @__PURE__ */ Symbol("startActiveSession");
|
|
@@ -20224,8 +20361,8 @@ var AcpContext = class {
|
|
|
20224
20361
|
return this.cx;
|
|
20225
20362
|
}
|
|
20226
20363
|
/** @internal */
|
|
20227
|
-
sendRequest(method, params, mapResponse) {
|
|
20228
|
-
return this.cx.sendRequest(method, params, mapResponse);
|
|
20364
|
+
sendRequest(method, params, mapResponse, options) {
|
|
20365
|
+
return this.cx.sendRequest(method, params, mapResponse, options);
|
|
20229
20366
|
}
|
|
20230
20367
|
/** @internal */
|
|
20231
20368
|
sendNotification(method, params) {
|
|
@@ -20244,9 +20381,9 @@ var AgentContext = class _AgentContext extends AcpContext {
|
|
|
20244
20381
|
static create(cx) {
|
|
20245
20382
|
return new _AgentContext(cx);
|
|
20246
20383
|
}
|
|
20247
|
-
request(method, params) {
|
|
20384
|
+
request(method, params, options) {
|
|
20248
20385
|
const spec = clientRequestSpecsByMethod[method];
|
|
20249
|
-
return this.sendRequest(method, params, spec?.mapResponse);
|
|
20386
|
+
return this.sendRequest(method, params, spec?.mapResponse, options);
|
|
20250
20387
|
}
|
|
20251
20388
|
notify(method, params) {
|
|
20252
20389
|
return this.sendNotification(method, params);
|
|
@@ -20261,8 +20398,8 @@ var ClientContext = class _ClientContext extends AcpContext {
|
|
|
20261
20398
|
return new _ClientContext(cx);
|
|
20262
20399
|
}
|
|
20263
20400
|
/** @internal */
|
|
20264
|
-
[startActiveSession](params) {
|
|
20265
|
-
return this.sendRequest(AGENT_METHODS.session_new, params, (response) => this.attachSession(response));
|
|
20401
|
+
[startActiveSession](params, options) {
|
|
20402
|
+
return this.sendRequest(AGENT_METHODS.session_new, params, (response) => this.attachSession(response), options);
|
|
20266
20403
|
}
|
|
20267
20404
|
buildSession(cwdOrRequest) {
|
|
20268
20405
|
if (typeof cwdOrRequest === "string") {
|
|
@@ -20296,9 +20433,9 @@ var ClientContext = class _ClientContext extends AcpContext {
|
|
|
20296
20433
|
closeRegistration
|
|
20297
20434
|
]);
|
|
20298
20435
|
}
|
|
20299
|
-
request(method, params) {
|
|
20436
|
+
request(method, params, options) {
|
|
20300
20437
|
const spec = agentRequestSpecsByMethod[method];
|
|
20301
|
-
return this.sendRequest(method, params, spec?.mapResponse);
|
|
20438
|
+
return this.sendRequest(method, params, spec?.mapResponse, options);
|
|
20302
20439
|
}
|
|
20303
20440
|
notify(method, params) {
|
|
20304
20441
|
return this.sendNotification(method, params);
|
|
@@ -20475,8 +20612,8 @@ var SessionBuilder = class _SessionBuilder {
|
|
|
20475
20612
|
* Call `dispose()` on the returned session when you no longer need update
|
|
20476
20613
|
* routing, or use `withSession(...)` to scope disposal automatically.
|
|
20477
20614
|
*/
|
|
20478
|
-
async start() {
|
|
20479
|
-
return this.cx[startActiveSession](this.toRequest());
|
|
20615
|
+
async start(options) {
|
|
20616
|
+
return this.cx[startActiveSession](this.toRequest(), options);
|
|
20480
20617
|
}
|
|
20481
20618
|
/**
|
|
20482
20619
|
* Starts the session, runs `op`, and disposes the active-session update
|
|
@@ -20538,12 +20675,12 @@ var ActiveSession = class _ActiveSession {
|
|
|
20538
20675
|
* `PromptResponse`, and the same completion is also queued as a `stop`
|
|
20539
20676
|
* message for `nextUpdate()`.
|
|
20540
20677
|
*/
|
|
20541
|
-
prompt(prompt) {
|
|
20678
|
+
prompt(prompt, options) {
|
|
20542
20679
|
this.updates.clearErrors();
|
|
20543
20680
|
const response = this.cx.request(AGENT_METHODS.session_prompt, {
|
|
20544
20681
|
sessionId: this.sessionId,
|
|
20545
20682
|
prompt: this.promptBlocks(prompt)
|
|
20546
|
-
});
|
|
20683
|
+
}, options);
|
|
20547
20684
|
void response.then((value) => {
|
|
20548
20685
|
this.updates.enqueue({
|
|
20549
20686
|
kind: "stop",
|
|
@@ -20627,12 +20764,12 @@ function notificationSpec(method, params) {
|
|
|
20627
20764
|
}
|
|
20628
20765
|
function registerAppRequest(builder, spec, context, handler) {
|
|
20629
20766
|
builder.onReceiveRequest(spec.method, (params) => parseParams(spec.params, params), async (params, responder, cx) => {
|
|
20630
|
-
const response = await handler(context(params, cx));
|
|
20767
|
+
const response = await handler(context(params, cx, responder.signal));
|
|
20631
20768
|
await responder.respond(spec.mapResponse ? spec.mapResponse(response) : response);
|
|
20632
20769
|
});
|
|
20633
20770
|
}
|
|
20634
20771
|
function registerAppNotification(builder, spec, context, handler) {
|
|
20635
|
-
builder.onReceiveNotification(spec.method, (params) => parseParams(spec.params, params), (params, cx) => handler(context(params, cx)));
|
|
20772
|
+
builder.onReceiveNotification(spec.method, (params) => parseParams(spec.params, params), (params, cx) => handler(context(params, cx, cx.signal)));
|
|
20636
20773
|
}
|
|
20637
20774
|
function specsByMethod(specs) {
|
|
20638
20775
|
const byMethod = {};
|
|
@@ -20691,15 +20828,17 @@ var agentRequestSpecsByMethod = specsByMethod(agentRequestSpecs);
|
|
|
20691
20828
|
var agentNotificationSpecsByMethod = specsByMethod(agentNotificationSpecs);
|
|
20692
20829
|
var clientRequestSpecsByMethod = specsByMethod(clientRequestSpecs);
|
|
20693
20830
|
var clientNotificationSpecsByMethod = specsByMethod(clientNotificationSpecs);
|
|
20694
|
-
function agentHandlerContext(params, client) {
|
|
20831
|
+
function agentHandlerContext(params, client, signal) {
|
|
20695
20832
|
return {
|
|
20696
20833
|
params,
|
|
20834
|
+
signal,
|
|
20697
20835
|
client
|
|
20698
20836
|
};
|
|
20699
20837
|
}
|
|
20700
|
-
function clientHandlerContext(params, agent2) {
|
|
20838
|
+
function clientHandlerContext(params, agent2, signal) {
|
|
20701
20839
|
return {
|
|
20702
20840
|
params,
|
|
20841
|
+
signal,
|
|
20703
20842
|
agent: agent2
|
|
20704
20843
|
};
|
|
20705
20844
|
}
|
|
@@ -20818,11 +20957,11 @@ var AgentApp = class {
|
|
|
20818
20957
|
return this.notification(spec, handlerOrParams);
|
|
20819
20958
|
}
|
|
20820
20959
|
request(spec, handler) {
|
|
20821
|
-
registerAppRequest(this.builder, spec, (params, cx) => agentHandlerContext(params, AgentContext.create(cx)), handler);
|
|
20960
|
+
registerAppRequest(this.builder, spec, (params, cx, signal) => agentHandlerContext(params, AgentContext.create(cx), signal), handler);
|
|
20822
20961
|
return this;
|
|
20823
20962
|
}
|
|
20824
20963
|
notification(spec, handler) {
|
|
20825
|
-
registerAppNotification(this.builder, spec, (params, cx) => agentHandlerContext(params, AgentContext.create(cx)), handler);
|
|
20964
|
+
registerAppNotification(this.builder, spec, (params, cx, signal) => agentHandlerContext(params, AgentContext.create(cx), signal), handler);
|
|
20826
20965
|
return this;
|
|
20827
20966
|
}
|
|
20828
20967
|
connectConnection(target, options = {}) {
|
|
@@ -20915,11 +21054,11 @@ var ClientApp = class {
|
|
|
20915
21054
|
return this.notification(spec, handlerOrParams);
|
|
20916
21055
|
}
|
|
20917
21056
|
request(spec, handler) {
|
|
20918
|
-
registerAppRequest(this.builder, spec, (params, cx) => clientHandlerContext(params, ClientContext.create(cx)), handler);
|
|
21057
|
+
registerAppRequest(this.builder, spec, (params, cx, signal) => clientHandlerContext(params, ClientContext.create(cx), signal), handler);
|
|
20919
21058
|
return this;
|
|
20920
21059
|
}
|
|
20921
21060
|
notification(spec, handler) {
|
|
20922
|
-
registerAppNotification(this.builder, spec, (params, cx) => clientHandlerContext(params, ClientContext.create(cx)), handler);
|
|
21061
|
+
registerAppNotification(this.builder, spec, (params, cx, signal) => clientHandlerContext(params, ClientContext.create(cx), signal), handler);
|
|
20923
21062
|
return this;
|
|
20924
21063
|
}
|
|
20925
21064
|
connectConnection(target) {
|
|
@@ -21844,6 +21983,34 @@ function createWebSearchCompleteUpdate(item) {
|
|
|
21844
21983
|
rawInput: item
|
|
21845
21984
|
};
|
|
21846
21985
|
}
|
|
21986
|
+
function createCollabAgentToolCallUpdate(item) {
|
|
21987
|
+
return {
|
|
21988
|
+
sessionUpdate: "tool_call",
|
|
21989
|
+
toolCallId: item.id,
|
|
21990
|
+
kind: "other",
|
|
21991
|
+
title: item.tool,
|
|
21992
|
+
status: toAcpStatus(item.status),
|
|
21993
|
+
rawInput: createCollabAgentToolCallRawInput(item)
|
|
21994
|
+
};
|
|
21995
|
+
}
|
|
21996
|
+
function createCollabAgentToolCallCompleteUpdate(item) {
|
|
21997
|
+
return {
|
|
21998
|
+
sessionUpdate: "tool_call_update",
|
|
21999
|
+
toolCallId: item.id,
|
|
22000
|
+
title: item.tool,
|
|
22001
|
+
status: toAcpStatus(item.status),
|
|
22002
|
+
rawInput: createCollabAgentToolCallRawInput(item)
|
|
22003
|
+
};
|
|
22004
|
+
}
|
|
22005
|
+
function createCollabAgentToolCallRawInput(item) {
|
|
22006
|
+
return {
|
|
22007
|
+
prompt: item.prompt,
|
|
22008
|
+
senderThreadId: item.senderThreadId,
|
|
22009
|
+
receiverThreadIds: item.receiverThreadIds,
|
|
22010
|
+
agentsStates: item.agentsStates,
|
|
22011
|
+
status: item.status
|
|
22012
|
+
};
|
|
22013
|
+
}
|
|
21847
22014
|
function formatWebSearchTitle(item) {
|
|
21848
22015
|
const action = item.action;
|
|
21849
22016
|
if (!action) {
|
|
@@ -22295,6 +22462,7 @@ var CodexEventHandler = class {
|
|
|
22295
22462
|
case "mcpServer/startupStatus/updated":
|
|
22296
22463
|
case "serverRequest/resolved":
|
|
22297
22464
|
case "model/verification":
|
|
22465
|
+
case "model/safetyBuffering/updated":
|
|
22298
22466
|
case "windows/worldWritableWarning":
|
|
22299
22467
|
case "thread/realtime/started":
|
|
22300
22468
|
case "thread/realtime/itemAdded":
|
|
@@ -22316,6 +22484,7 @@ var CodexEventHandler = class {
|
|
|
22316
22484
|
case "remoteControl/status/changed":
|
|
22317
22485
|
case "app/list/updated":
|
|
22318
22486
|
case "thread/settings/updated":
|
|
22487
|
+
case "externalAgentConfig/import/progress":
|
|
22319
22488
|
case "process/outputDelta":
|
|
22320
22489
|
case "process/exited":
|
|
22321
22490
|
return null;
|
|
@@ -22375,15 +22544,24 @@ ${event.details}` : "";
|
|
|
22375
22544
|
};
|
|
22376
22545
|
}
|
|
22377
22546
|
createThreadGoalUpdatedEvent(event) {
|
|
22547
|
+
const goalSnapshot = this.createThreadGoalSnapshot(event);
|
|
22548
|
+
if (this.sameThreadGoalSnapshot(this.sessionState.currentGoal, goalSnapshot)) {
|
|
22549
|
+
return null;
|
|
22550
|
+
}
|
|
22551
|
+
this.sessionState.currentGoal = goalSnapshot;
|
|
22378
22552
|
const status = this.formatThreadGoalStatus(event.goal.status);
|
|
22379
|
-
const objective =
|
|
22553
|
+
const objective = goalSnapshot.objective;
|
|
22380
22554
|
const text = objective.includes("\n") ? `Goal updated (${status}):
|
|
22381
22555
|
${objective}` : `Goal updated (${status}): ${objective}`;
|
|
22382
22556
|
return {
|
|
22383
22557
|
sessionUpdate: "agent_message_chunk",
|
|
22384
22558
|
content: {
|
|
22385
22559
|
type: "text",
|
|
22386
|
-
text
|
|
22560
|
+
text: `
|
|
22561
|
+
|
|
22562
|
+
${text}
|
|
22563
|
+
|
|
22564
|
+
`
|
|
22387
22565
|
}
|
|
22388
22566
|
};
|
|
22389
22567
|
}
|
|
@@ -22404,14 +22582,28 @@ ${objective}` : `Goal updated (${status}): ${objective}`;
|
|
|
22404
22582
|
}
|
|
22405
22583
|
}
|
|
22406
22584
|
createThreadGoalClearedEvent(_event) {
|
|
22585
|
+
if (this.sessionState.currentGoal === null) {
|
|
22586
|
+
return null;
|
|
22587
|
+
}
|
|
22588
|
+
this.sessionState.currentGoal = null;
|
|
22407
22589
|
return {
|
|
22408
22590
|
sessionUpdate: "agent_message_chunk",
|
|
22409
22591
|
content: {
|
|
22410
22592
|
type: "text",
|
|
22411
|
-
text: "
|
|
22593
|
+
text: "\n\nGoal cleared.\n\n"
|
|
22412
22594
|
}
|
|
22413
22595
|
};
|
|
22414
22596
|
}
|
|
22597
|
+
createThreadGoalSnapshot(event) {
|
|
22598
|
+
return {
|
|
22599
|
+
objective: event.goal.objective.trim(),
|
|
22600
|
+
status: event.goal.status,
|
|
22601
|
+
tokenBudget: event.goal.tokenBudget
|
|
22602
|
+
};
|
|
22603
|
+
}
|
|
22604
|
+
sameThreadGoalSnapshot(left, right) {
|
|
22605
|
+
return left !== null && left !== void 0 && left.objective === right.objective && left.status === right.status && left.tokenBudget === right.tokenBudget;
|
|
22606
|
+
}
|
|
22415
22607
|
createReasoningDeltaEvent(event) {
|
|
22416
22608
|
this.seenReasoningDeltaItemIds.add(event.itemId);
|
|
22417
22609
|
return this.createAgentThoughtEvent(event.delta);
|
|
@@ -22455,6 +22647,7 @@ ${objective}` : `Goal updated (${status}): ${objective}`;
|
|
|
22455
22647
|
this.activeImageGenerationItems.add(event.item.id);
|
|
22456
22648
|
return createImageGenerationStartUpdate(event.item);
|
|
22457
22649
|
case "collabAgentToolCall":
|
|
22650
|
+
return createCollabAgentToolCallUpdate(event.item);
|
|
22458
22651
|
case "subAgentActivity":
|
|
22459
22652
|
case "sleep":
|
|
22460
22653
|
case "userMessage":
|
|
@@ -22504,12 +22697,13 @@ ${objective}` : `Goal updated (${status}): ${objective}`;
|
|
|
22504
22697
|
return this.createCompletedReasoningEvent(event.item);
|
|
22505
22698
|
case "webSearch":
|
|
22506
22699
|
return createWebSearchCompleteUpdate(event.item);
|
|
22700
|
+
case "collabAgentToolCall":
|
|
22701
|
+
return createCollabAgentToolCallCompleteUpdate(event.item);
|
|
22507
22702
|
case "exitedReviewMode":
|
|
22508
22703
|
return this.createExitedReviewModeEvent(event.item);
|
|
22509
22704
|
case "contextCompaction":
|
|
22510
22705
|
return this.createContextCompactedEvent();
|
|
22511
22706
|
//ignored types
|
|
22512
|
-
case "collabAgentToolCall":
|
|
22513
22707
|
case "subAgentActivity":
|
|
22514
22708
|
case "sleep":
|
|
22515
22709
|
case "userMessage":
|
|
@@ -22668,8 +22862,12 @@ ${event.stdin}
|
|
|
22668
22862
|
}
|
|
22669
22863
|
async createErrorEvent(params) {
|
|
22670
22864
|
const error51 = params.error.codexErrorInfo;
|
|
22671
|
-
if (error51
|
|
22672
|
-
this.failure = RequestError.
|
|
22865
|
+
if (error51 === "usageLimitExceeded") {
|
|
22866
|
+
this.failure = RequestError.internalError(
|
|
22867
|
+
this.createTurnErrorData(params.error)
|
|
22868
|
+
);
|
|
22869
|
+
} else if (this.isAuthenticationRequiredError(error51)) {
|
|
22870
|
+
this.failure = this.sessionState.authConfigured ? RequestError.internalError(this.createTurnErrorData(params.error)) : RequestError.authRequired(this.createTurnErrorData(params.error), params.error.message);
|
|
22673
22871
|
}
|
|
22674
22872
|
return {
|
|
22675
22873
|
sessionUpdate: "agent_message_chunk",
|
|
@@ -22681,6 +22879,9 @@ ${event.stdin}
|
|
|
22681
22879
|
}
|
|
22682
22880
|
};
|
|
22683
22881
|
}
|
|
22882
|
+
isAuthenticationRequiredError(error51) {
|
|
22883
|
+
return error51 === "unauthorized" || this.getHttpStatusCode(error51) === 401;
|
|
22884
|
+
}
|
|
22684
22885
|
getHttpStatusCode(error51) {
|
|
22685
22886
|
if (error51 !== null && typeof error51 === "object") {
|
|
22686
22887
|
if ("httpConnectionFailed" in error51) {
|
|
@@ -22695,6 +22896,18 @@ ${event.stdin}
|
|
|
22695
22896
|
}
|
|
22696
22897
|
return null;
|
|
22697
22898
|
}
|
|
22899
|
+
createTurnErrorData(error51) {
|
|
22900
|
+
const data = {
|
|
22901
|
+
message: error51.additionalDetails ?? error51.message
|
|
22902
|
+
};
|
|
22903
|
+
if (error51.codexErrorInfo !== null) {
|
|
22904
|
+
data.codexErrorInfo = error51.codexErrorInfo;
|
|
22905
|
+
}
|
|
22906
|
+
if (error51.additionalDetails !== null) {
|
|
22907
|
+
data.additionalDetails = error51.additionalDetails;
|
|
22908
|
+
}
|
|
22909
|
+
return data;
|
|
22910
|
+
}
|
|
22698
22911
|
handleTokenUsageUpdated(params) {
|
|
22699
22912
|
this.sessionState.lastTokenUsage = toTokenCount(params.tokenUsage.last);
|
|
22700
22913
|
this.sessionState.totalTokenUsage = toTokenCount(params.tokenUsage.total);
|
|
@@ -22774,15 +22987,21 @@ function permissionOption(optionId, name, kind, codexMeta) {
|
|
|
22774
22987
|
var CodexApprovalHandler = class {
|
|
22775
22988
|
connection;
|
|
22776
22989
|
sessionState;
|
|
22777
|
-
|
|
22990
|
+
cancellationSignal;
|
|
22991
|
+
constructor(connection, sessionState, cancellationSignal) {
|
|
22778
22992
|
this.connection = connection;
|
|
22779
22993
|
this.sessionState = sessionState;
|
|
22994
|
+
this.cancellationSignal = cancellationSignal;
|
|
22780
22995
|
}
|
|
22781
22996
|
async handleCommandExecution(params) {
|
|
22782
22997
|
try {
|
|
22783
22998
|
const sessionId = this.sessionState.sessionId;
|
|
22784
22999
|
const acpRequest = this.buildCommandPermissionRequest(sessionId, params);
|
|
22785
|
-
const response = await this.connection.request(
|
|
23000
|
+
const response = await this.connection.request(
|
|
23001
|
+
methods.client.session.requestPermission,
|
|
23002
|
+
acpRequest,
|
|
23003
|
+
this.requestOptions()
|
|
23004
|
+
);
|
|
22786
23005
|
return this.convertCommandResponse(params, response);
|
|
22787
23006
|
} catch (error51) {
|
|
22788
23007
|
logger.error("Error requesting command execution permission", error51);
|
|
@@ -22793,7 +23012,11 @@ var CodexApprovalHandler = class {
|
|
|
22793
23012
|
try {
|
|
22794
23013
|
const sessionId = this.sessionState.sessionId;
|
|
22795
23014
|
const acpRequest = this.buildFileChangePermissionRequest(sessionId, params);
|
|
22796
|
-
const response = await this.connection.request(
|
|
23015
|
+
const response = await this.connection.request(
|
|
23016
|
+
methods.client.session.requestPermission,
|
|
23017
|
+
acpRequest,
|
|
23018
|
+
this.requestOptions()
|
|
23019
|
+
);
|
|
22797
23020
|
return this.convertFileChangeResponse(params, response);
|
|
22798
23021
|
} catch (error51) {
|
|
22799
23022
|
logger.error("Error requesting file change permission", error51);
|
|
@@ -22804,13 +23027,20 @@ var CodexApprovalHandler = class {
|
|
|
22804
23027
|
try {
|
|
22805
23028
|
const sessionId = this.sessionState.sessionId;
|
|
22806
23029
|
const acpRequest = this.buildPermissionsRequest(sessionId, params);
|
|
22807
|
-
const response = await this.connection.request(
|
|
23030
|
+
const response = await this.connection.request(
|
|
23031
|
+
methods.client.session.requestPermission,
|
|
23032
|
+
acpRequest,
|
|
23033
|
+
this.requestOptions()
|
|
23034
|
+
);
|
|
22808
23035
|
return this.convertPermissionsResponse(params, response);
|
|
22809
23036
|
} catch (error51) {
|
|
22810
23037
|
logger.error("Error requesting permissions", error51);
|
|
22811
23038
|
return this.rejectPermissionsResponse();
|
|
22812
23039
|
}
|
|
22813
23040
|
}
|
|
23041
|
+
requestOptions() {
|
|
23042
|
+
return this.cancellationSignal ? { cancellationSignal: this.cancellationSignal } : void 0;
|
|
23043
|
+
}
|
|
22814
23044
|
buildCommandPermissionRequest(sessionId, params) {
|
|
22815
23045
|
const options = this.buildCommandOptions(params).map(({ option }) => option);
|
|
22816
23046
|
return {
|
|
@@ -23095,6 +23325,7 @@ function buildToolApprovalOptions(persistOptions) {
|
|
|
23095
23325
|
var CodexElicitationHandler = class {
|
|
23096
23326
|
connection;
|
|
23097
23327
|
sessionState;
|
|
23328
|
+
cancellationSignal;
|
|
23098
23329
|
// In Rust, the MCP elicitation handler receives ElicitationRequestEvent directly from the MCP
|
|
23099
23330
|
// protocol layer, where id is set to "mcp_tool_call_approval_<call_id>" — the call ID is extracted
|
|
23100
23331
|
// by stripping that prefix.
|
|
@@ -23111,9 +23342,10 @@ var CodexElicitationHandler = class {
|
|
|
23111
23342
|
// call's elicitation before starting the next, so there is at most one pending approval per
|
|
23112
23343
|
// (threadId, serverName).
|
|
23113
23344
|
pendingMcpApprovals = /* @__PURE__ */ new Map();
|
|
23114
|
-
constructor(connection, sessionState) {
|
|
23345
|
+
constructor(connection, sessionState, cancellationSignal) {
|
|
23115
23346
|
this.connection = connection;
|
|
23116
23347
|
this.sessionState = sessionState;
|
|
23348
|
+
this.cancellationSignal = cancellationSignal;
|
|
23117
23349
|
}
|
|
23118
23350
|
handleNotification(notification) {
|
|
23119
23351
|
switch (notification.method) {
|
|
@@ -23133,7 +23365,11 @@ var CodexElicitationHandler = class {
|
|
|
23133
23365
|
async handleElicitation(params) {
|
|
23134
23366
|
try {
|
|
23135
23367
|
const { request, correlatedCallId } = this.buildPermissionRequest(params);
|
|
23136
|
-
const response = await this.connection.request(
|
|
23368
|
+
const response = await this.connection.request(
|
|
23369
|
+
methods.client.session.requestPermission,
|
|
23370
|
+
request,
|
|
23371
|
+
this.requestOptions()
|
|
23372
|
+
);
|
|
23137
23373
|
if (correlatedCallId !== void 0 && response.outcome.outcome !== "cancelled") {
|
|
23138
23374
|
const optionId = response.outcome.optionId;
|
|
23139
23375
|
if (optionId !== McpApprovalOptionId.Decline) {
|
|
@@ -23149,6 +23385,9 @@ var CodexElicitationHandler = class {
|
|
|
23149
23385
|
return { action: "cancel", content: null, _meta: null };
|
|
23150
23386
|
}
|
|
23151
23387
|
}
|
|
23388
|
+
requestOptions() {
|
|
23389
|
+
return this.cancellationSignal ? { cancellationSignal: this.cancellationSignal } : void 0;
|
|
23390
|
+
}
|
|
23152
23391
|
buildPermissionRequest(params) {
|
|
23153
23392
|
const sessionId = this.sessionState.sessionId;
|
|
23154
23393
|
const messageContent = {
|
|
@@ -23158,7 +23397,7 @@ var CodexElicitationHandler = class {
|
|
|
23158
23397
|
const meta3 = params._meta;
|
|
23159
23398
|
const isToolApproval = isMcpToolCallApproval(meta3);
|
|
23160
23399
|
const options = isToolApproval ? buildToolApprovalOptions(parsePersistOptions(meta3)) : ELICITATION_OPTIONS;
|
|
23161
|
-
if (params.mode === "form") {
|
|
23400
|
+
if (params.mode === "form" || params.mode === "openai/form") {
|
|
23162
23401
|
const correlatedCallId = isToolApproval ? this.popPendingApproval(params.threadId, params.serverName) : void 0;
|
|
23163
23402
|
if (correlatedCallId !== void 0) {
|
|
23164
23403
|
return {
|
|
@@ -23259,6 +23498,8 @@ var CodexElicitationHandler = class {
|
|
|
23259
23498
|
};
|
|
23260
23499
|
|
|
23261
23500
|
// src/CodexAuthMethod.ts
|
|
23501
|
+
var CODEX_API_KEY_ENV_VAR = "CODEX_API_KEY";
|
|
23502
|
+
var OPENAI_API_KEY_ENV_VAR = "OPENAI_API_KEY";
|
|
23262
23503
|
var ApiKeyAuthMethod = {
|
|
23263
23504
|
id: "api-key",
|
|
23264
23505
|
name: "API Key",
|
|
@@ -23285,8 +23526,11 @@ var GatewayAuthMethod = {
|
|
|
23285
23526
|
}
|
|
23286
23527
|
}
|
|
23287
23528
|
};
|
|
23288
|
-
function getCodexAuthMethods(clientCapabilities) {
|
|
23289
|
-
const authMethods = [ApiKeyAuthMethod
|
|
23529
|
+
function getCodexAuthMethods(clientCapabilities, env = process.env) {
|
|
23530
|
+
const authMethods = [ApiKeyAuthMethod];
|
|
23531
|
+
if (!env["NO_BROWSER"]) {
|
|
23532
|
+
authMethods.push(ChatGptAuthMethod);
|
|
23533
|
+
}
|
|
23290
23534
|
const supportsGatewayAuth = clientCapabilities?.auth?._meta?.["gateway"] === true;
|
|
23291
23535
|
if (supportsGatewayAuth) {
|
|
23292
23536
|
authMethods.push(GatewayAuthMethod);
|
|
@@ -24038,7 +24282,7 @@ var package_default = {
|
|
|
24038
24282
|
publishConfig: {
|
|
24039
24283
|
access: "public"
|
|
24040
24284
|
},
|
|
24041
|
-
version: "1.0.
|
|
24285
|
+
version: "1.0.2",
|
|
24042
24286
|
description: "",
|
|
24043
24287
|
main: "dist/index.js",
|
|
24044
24288
|
bin: {
|
|
@@ -24096,8 +24340,8 @@ var package_default = {
|
|
|
24096
24340
|
vitest: "^4.0.10"
|
|
24097
24341
|
},
|
|
24098
24342
|
dependencies: {
|
|
24099
|
-
"@agentclientprotocol/sdk": "^0.
|
|
24100
|
-
"@openai/codex": "^0.
|
|
24343
|
+
"@agentclientprotocol/sdk": "^1.0.0",
|
|
24344
|
+
"@openai/codex": "^0.142.4",
|
|
24101
24345
|
diff: "^8.0.3",
|
|
24102
24346
|
open: "^11.0.0",
|
|
24103
24347
|
"vscode-jsonrpc": "^8.2.1",
|
|
@@ -24142,17 +24386,15 @@ var CodexAcpClient = class {
|
|
|
24142
24386
|
}
|
|
24143
24387
|
switch (authRequest.methodId) {
|
|
24144
24388
|
case "api-key": {
|
|
24145
|
-
|
|
24146
|
-
|
|
24147
|
-
await this.codexClient.accountLogin({
|
|
24148
|
-
type: "apiKey",
|
|
24149
|
-
apiKey: authRequest._meta["api-key"].apiKey
|
|
24150
|
-
});
|
|
24151
|
-
this.gatewayConfig = null;
|
|
24152
|
-
const result = await loginCompletedPromise;
|
|
24153
|
-
return result.success;
|
|
24389
|
+
const apiKey = authRequest._meta?.["api-key"]?.apiKey ?? this.readApiKeyFromEnv();
|
|
24390
|
+
return await this.authenticateWithApiKey(apiKey);
|
|
24154
24391
|
}
|
|
24155
24392
|
case "chat-gpt": {
|
|
24393
|
+
const accountResponse = await this.codexClient.accountRead({ refreshToken: true });
|
|
24394
|
+
if (accountResponse.account?.type === "chatgpt") {
|
|
24395
|
+
this.gatewayConfig = null;
|
|
24396
|
+
return true;
|
|
24397
|
+
}
|
|
24156
24398
|
const loginCompletedPromise = this.awaitNextLoginCompleted();
|
|
24157
24399
|
const loginResponse = await this.codexClient.accountLogin({ type: "chatgpt" });
|
|
24158
24400
|
if (loginResponse.type == "chatgpt") {
|
|
@@ -24186,6 +24428,28 @@ var CodexAcpClient = class {
|
|
|
24186
24428
|
this.gatewayConfig = null;
|
|
24187
24429
|
return false;
|
|
24188
24430
|
}
|
|
24431
|
+
async authenticateWithApiKey(apiKey) {
|
|
24432
|
+
const loginCompletedPromise = this.awaitNextLoginCompleted();
|
|
24433
|
+
await this.codexClient.accountLogin({
|
|
24434
|
+
type: "apiKey",
|
|
24435
|
+
apiKey
|
|
24436
|
+
});
|
|
24437
|
+
this.gatewayConfig = null;
|
|
24438
|
+
const result = await loginCompletedPromise;
|
|
24439
|
+
return result.success;
|
|
24440
|
+
}
|
|
24441
|
+
readApiKeyFromEnv() {
|
|
24442
|
+
for (const envVar of [CODEX_API_KEY_ENV_VAR, OPENAI_API_KEY_ENV_VAR]) {
|
|
24443
|
+
const value = process.env[envVar]?.trim();
|
|
24444
|
+
if (value) {
|
|
24445
|
+
return value;
|
|
24446
|
+
}
|
|
24447
|
+
}
|
|
24448
|
+
throw RequestError.internalError(
|
|
24449
|
+
{ envVars: [CODEX_API_KEY_ENV_VAR, OPENAI_API_KEY_ENV_VAR] },
|
|
24450
|
+
`${CODEX_API_KEY_ENV_VAR} or ${OPENAI_API_KEY_ENV_VAR} is not set`
|
|
24451
|
+
);
|
|
24452
|
+
}
|
|
24189
24453
|
async getAuthenticationStatus() {
|
|
24190
24454
|
const modelProvider = await this.getCurrentModelProvider();
|
|
24191
24455
|
if (modelProvider) {
|
|
@@ -24208,7 +24472,7 @@ var CodexAcpClient = class {
|
|
|
24208
24472
|
case "chatgpt":
|
|
24209
24473
|
return {
|
|
24210
24474
|
type: "chat-gpt",
|
|
24211
|
-
email: account.email
|
|
24475
|
+
email: account.email ?? ""
|
|
24212
24476
|
};
|
|
24213
24477
|
case "amazonBedrock":
|
|
24214
24478
|
return {
|
|
@@ -24223,7 +24487,7 @@ var CodexAcpClient = class {
|
|
|
24223
24487
|
return sessionModelProvider;
|
|
24224
24488
|
}
|
|
24225
24489
|
const settingsModelProvider = await this.codexClient.configRead({ includeLayers: false });
|
|
24226
|
-
return settingsModelProvider
|
|
24490
|
+
return settingsModelProvider?.config?.model_provider ?? null;
|
|
24227
24491
|
}
|
|
24228
24492
|
async logout() {
|
|
24229
24493
|
const accountUpdatedPromise = this.awaitNextAccountUpdated();
|
|
@@ -24237,6 +24501,9 @@ var CodexAcpClient = class {
|
|
|
24237
24501
|
const response = await this.codexClient.accountRead({ refreshToken: false });
|
|
24238
24502
|
return response.requiresOpenaiAuth && !response.account;
|
|
24239
24503
|
}
|
|
24504
|
+
hasGatewayAuth() {
|
|
24505
|
+
return this.gatewayConfig !== null;
|
|
24506
|
+
}
|
|
24240
24507
|
async getAccount() {
|
|
24241
24508
|
return this.codexClient.accountRead({ refreshToken: false });
|
|
24242
24509
|
}
|
|
@@ -24246,7 +24513,7 @@ var CodexAcpClient = class {
|
|
|
24246
24513
|
const response = await this.codexClient.threadResume({
|
|
24247
24514
|
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
|
|
24248
24515
|
cwd: request.cwd,
|
|
24249
|
-
modelProvider: this.getResumeModelProvider(),
|
|
24516
|
+
modelProvider: await this.getResumeModelProvider(),
|
|
24250
24517
|
threadId: request.sessionId
|
|
24251
24518
|
});
|
|
24252
24519
|
onSubscribed?.();
|
|
@@ -24256,6 +24523,7 @@ var CodexAcpClient = class {
|
|
|
24256
24523
|
sessionId: request.sessionId,
|
|
24257
24524
|
currentModelId,
|
|
24258
24525
|
models: codexModels,
|
|
24526
|
+
modelProvider: response.modelProvider,
|
|
24259
24527
|
currentServiceTier: response.serviceTier ?? null,
|
|
24260
24528
|
additionalDirectories
|
|
24261
24529
|
};
|
|
@@ -24266,7 +24534,7 @@ var CodexAcpClient = class {
|
|
|
24266
24534
|
const response = await this.codexClient.threadResume({
|
|
24267
24535
|
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
|
|
24268
24536
|
cwd: request.cwd,
|
|
24269
|
-
modelProvider: this.getResumeModelProvider(),
|
|
24537
|
+
modelProvider: await this.getResumeModelProvider(),
|
|
24270
24538
|
threadId: request.sessionId
|
|
24271
24539
|
});
|
|
24272
24540
|
onSubscribed?.();
|
|
@@ -24280,6 +24548,7 @@ var CodexAcpClient = class {
|
|
|
24280
24548
|
sessionId: request.sessionId,
|
|
24281
24549
|
currentModelId,
|
|
24282
24550
|
models: codexModels,
|
|
24551
|
+
modelProvider: response.modelProvider,
|
|
24283
24552
|
currentServiceTier: response.serviceTier ?? null,
|
|
24284
24553
|
thread: historyResponse.thread,
|
|
24285
24554
|
additionalDirectories
|
|
@@ -24302,6 +24571,7 @@ var CodexAcpClient = class {
|
|
|
24302
24571
|
sessionId: response.thread.id,
|
|
24303
24572
|
currentModelId,
|
|
24304
24573
|
models: codexModels,
|
|
24574
|
+
modelProvider: response.modelProvider,
|
|
24305
24575
|
currentServiceTier: response.serviceTier ?? null,
|
|
24306
24576
|
additionalDirectories
|
|
24307
24577
|
};
|
|
@@ -24326,6 +24596,28 @@ var CodexAcpClient = class {
|
|
|
24326
24596
|
async runCompact(sessionId) {
|
|
24327
24597
|
await this.codexClient.runCompact({ threadId: sessionId });
|
|
24328
24598
|
}
|
|
24599
|
+
async setGoal(sessionId, objective, onTurnStarted) {
|
|
24600
|
+
return await this.codexClient.runGoalSet({
|
|
24601
|
+
threadId: sessionId,
|
|
24602
|
+
objective,
|
|
24603
|
+
status: "active"
|
|
24604
|
+
}, onTurnStarted);
|
|
24605
|
+
}
|
|
24606
|
+
async setGoalStatus(sessionId, status) {
|
|
24607
|
+
await this.codexClient.runGoalSet({
|
|
24608
|
+
threadId: sessionId,
|
|
24609
|
+
status
|
|
24610
|
+
});
|
|
24611
|
+
}
|
|
24612
|
+
async resumeGoal(sessionId, onTurnStarted) {
|
|
24613
|
+
return await this.codexClient.runGoalSet({
|
|
24614
|
+
threadId: sessionId,
|
|
24615
|
+
status: "active"
|
|
24616
|
+
}, onTurnStarted);
|
|
24617
|
+
}
|
|
24618
|
+
async clearGoal(sessionId) {
|
|
24619
|
+
await this.codexClient.runGoalClear({ threadId: sessionId });
|
|
24620
|
+
}
|
|
24329
24621
|
async awaitMcpServerStartup(serverNames, afterVersion) {
|
|
24330
24622
|
return await this.codexClient.awaitMcpServerStartup(serverNames, afterVersion);
|
|
24331
24623
|
}
|
|
@@ -24372,8 +24664,8 @@ var CodexAcpClient = class {
|
|
|
24372
24664
|
getModelProvider() {
|
|
24373
24665
|
return this.gatewayConfig?.modelProvider ?? this.modelProvider;
|
|
24374
24666
|
}
|
|
24375
|
-
getResumeModelProvider() {
|
|
24376
|
-
return this.
|
|
24667
|
+
async getResumeModelProvider() {
|
|
24668
|
+
return await this.getCurrentModelProvider() ?? "openai";
|
|
24377
24669
|
}
|
|
24378
24670
|
async refreshSkills(cwd, additionalRoots) {
|
|
24379
24671
|
if (!cwd) {
|
|
@@ -24417,11 +24709,18 @@ var CodexAcpClient = class {
|
|
|
24417
24709
|
* Falls back to model defaults if parameters are missing or unsupported.
|
|
24418
24710
|
*/
|
|
24419
24711
|
createModelId(availableModels, modelId, reasoningEffort) {
|
|
24420
|
-
const selectedModel = availableModels.find((m) => m.id === modelId)
|
|
24421
|
-
if (
|
|
24712
|
+
const selectedModel = availableModels.find((m) => m.id === modelId);
|
|
24713
|
+
if (selectedModel) {
|
|
24714
|
+
return ModelId.create(selectedModel.id, reasoningEffort ?? selectedModel.defaultReasoningEffort);
|
|
24715
|
+
}
|
|
24716
|
+
if (modelId) {
|
|
24717
|
+
return ModelId.create(modelId, reasoningEffort ?? "medium");
|
|
24718
|
+
}
|
|
24719
|
+
const defaultModel = availableModels.find((m) => m.isDefault);
|
|
24720
|
+
if (!defaultModel) {
|
|
24422
24721
|
throw new Error(`Model selection failed: No model found for ID "${modelId}" and no default model is defined.`);
|
|
24423
24722
|
}
|
|
24424
|
-
return ModelId.create(
|
|
24723
|
+
return ModelId.create(defaultModel.id, reasoningEffort ?? defaultModel.defaultReasoningEffort);
|
|
24425
24724
|
}
|
|
24426
24725
|
async subscribeToSessionEvents(sessionId, eventHandler, approvalHandler, elicitationHandler) {
|
|
24427
24726
|
this.codexClient.onServerNotification(sessionId, (event) => {
|
|
@@ -24545,11 +24844,6 @@ var CodexAcpClient = class {
|
|
|
24545
24844
|
"vscode",
|
|
24546
24845
|
"exec",
|
|
24547
24846
|
"appServer",
|
|
24548
|
-
"subAgent",
|
|
24549
|
-
"subAgentReview",
|
|
24550
|
-
"subAgentCompact",
|
|
24551
|
-
"subAgentThreadSpawn",
|
|
24552
|
-
"subAgentOther",
|
|
24553
24847
|
"unknown"
|
|
24554
24848
|
];
|
|
24555
24849
|
const requestedCwd = request.cwd?.trim() ?? null;
|
|
@@ -24568,23 +24862,19 @@ var CodexAcpClient = class {
|
|
|
24568
24862
|
modelProviders,
|
|
24569
24863
|
sourceKinds
|
|
24570
24864
|
});
|
|
24571
|
-
|
|
24572
|
-
const diagnostics = await this.runSessionListDiagnostics();
|
|
24573
|
-
logger.log("Session list diagnostics", diagnostics);
|
|
24574
|
-
}
|
|
24575
|
-
let sessions = listResponse.data.map((thread) => ({
|
|
24865
|
+
const mapThreadToSession = (thread) => ({
|
|
24576
24866
|
sessionId: thread.id,
|
|
24577
24867
|
cwd: thread.cwd,
|
|
24578
24868
|
title: (thread.name ?? thread.preview) || null,
|
|
24579
24869
|
updatedAt: new Date(thread.updatedAt * 1e3).toISOString()
|
|
24580
|
-
})
|
|
24870
|
+
});
|
|
24871
|
+
if (listResponse.data.length === 0) {
|
|
24872
|
+
const diagnostics = await this.runSessionListDiagnostics();
|
|
24873
|
+
logger.log("Session list diagnostics", diagnostics);
|
|
24874
|
+
}
|
|
24875
|
+
let sessions = listResponse.data.map(mapThreadToSession);
|
|
24581
24876
|
if (requestedCwd) {
|
|
24582
|
-
const filtered = listResponse.data.filter(filterByCwd).map(
|
|
24583
|
-
sessionId: thread.id,
|
|
24584
|
-
cwd: thread.cwd,
|
|
24585
|
-
title: (thread.name ?? thread.preview) || null,
|
|
24586
|
-
updatedAt: new Date(thread.updatedAt * 1e3).toISOString()
|
|
24587
|
-
}));
|
|
24877
|
+
const filtered = listResponse.data.filter(filterByCwd).map(mapThreadToSession);
|
|
24588
24878
|
if (filtered.length > 0 || path4.isAbsolute(requestedCwd)) {
|
|
24589
24879
|
sessions = filtered;
|
|
24590
24880
|
} else {
|
|
@@ -24640,7 +24930,7 @@ function buildPromptItems(prompt) {
|
|
|
24640
24930
|
case "text":
|
|
24641
24931
|
return { type: "text", text: block.text, text_elements: [] };
|
|
24642
24932
|
case "image": {
|
|
24643
|
-
const url2 = block.uri
|
|
24933
|
+
const url2 = isSupportedImageUrl(block.uri) ? block.uri : imageDataUrl(block);
|
|
24644
24934
|
return { type: "image", url: url2 };
|
|
24645
24935
|
}
|
|
24646
24936
|
case "resource_link":
|
|
@@ -24671,9 +24961,23 @@ ${context}`, text_elements: [] };
|
|
|
24671
24961
|
}
|
|
24672
24962
|
}).filter((block) => block !== null);
|
|
24673
24963
|
}
|
|
24964
|
+
function imageDataUrl(block) {
|
|
24965
|
+
return `data:${block.mimeType};base64,${block.data}`;
|
|
24966
|
+
}
|
|
24674
24967
|
function isImageMimeType(mimeType) {
|
|
24675
24968
|
return mimeType?.startsWith("image/") ?? false;
|
|
24676
24969
|
}
|
|
24970
|
+
function isSupportedImageUrl(uri) {
|
|
24971
|
+
if (!uri) {
|
|
24972
|
+
return false;
|
|
24973
|
+
}
|
|
24974
|
+
try {
|
|
24975
|
+
const protocol = new URL(uri).protocol;
|
|
24976
|
+
return protocol === "http:" || protocol === "https:" || protocol === "data:";
|
|
24977
|
+
} catch {
|
|
24978
|
+
return false;
|
|
24979
|
+
}
|
|
24980
|
+
}
|
|
24677
24981
|
function formatUriAsLink(name, uri) {
|
|
24678
24982
|
if (name && name.length > 0) {
|
|
24679
24983
|
return `[@${name}](${uri})`;
|
|
@@ -24778,6 +25082,18 @@ function findSupportedEffort(options, effort) {
|
|
|
24778
25082
|
return options.find((o) => o.reasoningEffort === effort)?.reasoningEffort;
|
|
24779
25083
|
}
|
|
24780
25084
|
function createModelConfigOption(availableModels, currentBaseModelId) {
|
|
25085
|
+
const options = availableModels.map((model) => ({
|
|
25086
|
+
value: model.id,
|
|
25087
|
+
name: model.displayName,
|
|
25088
|
+
description: model.description
|
|
25089
|
+
}));
|
|
25090
|
+
if (!availableModels.some((model) => model.id === currentBaseModelId)) {
|
|
25091
|
+
options.unshift({
|
|
25092
|
+
value: currentBaseModelId,
|
|
25093
|
+
name: currentBaseModelId,
|
|
25094
|
+
description: null
|
|
25095
|
+
});
|
|
25096
|
+
}
|
|
24781
25097
|
return {
|
|
24782
25098
|
id: MODEL_CONFIG_ID,
|
|
24783
25099
|
name: "Model",
|
|
@@ -24785,11 +25101,7 @@ function createModelConfigOption(availableModels, currentBaseModelId) {
|
|
|
24785
25101
|
category: "model",
|
|
24786
25102
|
type: "select",
|
|
24787
25103
|
currentValue: currentBaseModelId,
|
|
24788
|
-
options
|
|
24789
|
-
value: model.id,
|
|
24790
|
-
name: model.displayName,
|
|
24791
|
-
description: model.description
|
|
24792
|
-
}))
|
|
25104
|
+
options
|
|
24793
25105
|
};
|
|
24794
25106
|
}
|
|
24795
25107
|
function createReasoningEffortConfigOption(supportedReasoningEfforts, currentEffort) {
|
|
@@ -24813,27 +25125,35 @@ var CodexCommands = class {
|
|
|
24813
25125
|
connection;
|
|
24814
25126
|
codexAcpClient;
|
|
24815
25127
|
runWithProcessCheck;
|
|
24816
|
-
|
|
25128
|
+
onLogout;
|
|
25129
|
+
constructor(connection, codexAcpClient, runWithProcessCheck, onLogout = () => {
|
|
25130
|
+
}) {
|
|
24817
25131
|
this.connection = connection;
|
|
24818
25132
|
this.codexAcpClient = codexAcpClient;
|
|
24819
25133
|
this.runWithProcessCheck = runWithProcessCheck;
|
|
25134
|
+
this.onLogout = onLogout;
|
|
24820
25135
|
}
|
|
24821
|
-
async publish(
|
|
25136
|
+
async publish(sessionState) {
|
|
24822
25137
|
try {
|
|
24823
|
-
const skillsResponse = await this.runWithProcessCheck(() => this.codexAcpClient.listSkills());
|
|
25138
|
+
const skillsResponse = await this.runWithProcessCheck(() => this.codexAcpClient.listSkills(this.createSkillsListParams(sessionState)));
|
|
24824
25139
|
const availableCommands = this.buildAvailableCommands(skillsResponse?.data ?? []);
|
|
24825
25140
|
if (availableCommands.length === 0) {
|
|
24826
25141
|
return;
|
|
24827
25142
|
}
|
|
24828
|
-
const session = new ACPSessionConnection(this.connection, sessionId);
|
|
25143
|
+
const session = new ACPSessionConnection(this.connection, sessionState.sessionId);
|
|
24829
25144
|
await session.update({
|
|
24830
25145
|
sessionUpdate: "available_commands_update",
|
|
24831
25146
|
availableCommands
|
|
24832
25147
|
});
|
|
24833
25148
|
} catch (err) {
|
|
24834
|
-
logger.error(`Failed to publish available commands for session ${sessionId}`, err);
|
|
25149
|
+
logger.error(`Failed to publish available commands for session ${sessionState.sessionId}`, err);
|
|
24835
25150
|
}
|
|
24836
25151
|
}
|
|
25152
|
+
createSkillsListParams(sessionState) {
|
|
25153
|
+
return {
|
|
25154
|
+
cwds: [sessionState.cwd, ...sessionState.additionalDirectories]
|
|
25155
|
+
};
|
|
25156
|
+
}
|
|
24837
25157
|
buildAvailableCommands(skillsEntries) {
|
|
24838
25158
|
const commands = /* @__PURE__ */ new Map();
|
|
24839
25159
|
for (const builtin of this.getBuiltinCommands()) {
|
|
@@ -24893,6 +25213,11 @@ var CodexCommands = class {
|
|
|
24893
25213
|
description: "Summarize conversation to avoid hitting the context limit.",
|
|
24894
25214
|
input: null
|
|
24895
25215
|
},
|
|
25216
|
+
{
|
|
25217
|
+
name: "goal",
|
|
25218
|
+
description: "Set, pause, resume, or clear a task goal.",
|
|
25219
|
+
input: { hint: "[<objective>|clear|pause|resume]" }
|
|
25220
|
+
},
|
|
24896
25221
|
{
|
|
24897
25222
|
name: "logout",
|
|
24898
25223
|
description: "Sign out of Codex. This option is available when you are logged in via ChatGPT.",
|
|
@@ -24914,7 +25239,7 @@ var CodexCommands = class {
|
|
|
24914
25239
|
rest: commandText.slice(name.length).trim()
|
|
24915
25240
|
};
|
|
24916
25241
|
}
|
|
24917
|
-
async tryHandleCommand(prompt, sessionState) {
|
|
25242
|
+
async tryHandleCommand(prompt, sessionState, options = {}) {
|
|
24918
25243
|
const command = this.parseCommand(prompt);
|
|
24919
25244
|
if (command === null) return { handled: false };
|
|
24920
25245
|
const commandName = command.name;
|
|
@@ -24925,9 +25250,12 @@ var CodexCommands = class {
|
|
|
24925
25250
|
await this.runWithProcessCheck(() => this.codexAcpClient.runCompact(sessionId));
|
|
24926
25251
|
return { handled: true };
|
|
24927
25252
|
}
|
|
25253
|
+
case "goal": {
|
|
25254
|
+
return await this.runGoalCommand(sessionState, command.rest, options);
|
|
25255
|
+
}
|
|
24928
25256
|
case "review": {
|
|
24929
25257
|
const target = this.buildReviewTarget(command.rest);
|
|
24930
|
-
const turnCompleted = await this.runReviewCommand(sessionState, target);
|
|
25258
|
+
const turnCompleted = await this.runReviewCommand(sessionState, target, options);
|
|
24931
25259
|
return { handled: true, turnCompleted };
|
|
24932
25260
|
}
|
|
24933
25261
|
case "review-branch": {
|
|
@@ -24938,7 +25266,7 @@ var CodexCommands = class {
|
|
|
24938
25266
|
const turnCompleted = await this.runReviewCommand(sessionState, {
|
|
24939
25267
|
type: "baseBranch",
|
|
24940
25268
|
branch: command.rest
|
|
24941
|
-
});
|
|
25269
|
+
}, options);
|
|
24942
25270
|
return { handled: true, turnCompleted };
|
|
24943
25271
|
}
|
|
24944
25272
|
case "review-commit": {
|
|
@@ -24950,7 +25278,7 @@ var CodexCommands = class {
|
|
|
24950
25278
|
type: "commit",
|
|
24951
25279
|
sha: command.rest,
|
|
24952
25280
|
title: null
|
|
24953
|
-
});
|
|
25281
|
+
}, options);
|
|
24954
25282
|
return { handled: true, turnCompleted };
|
|
24955
25283
|
}
|
|
24956
25284
|
case "status": {
|
|
@@ -24964,6 +25292,7 @@ var CodexCommands = class {
|
|
|
24964
25292
|
}
|
|
24965
25293
|
case "logout": {
|
|
24966
25294
|
await this.runWithProcessCheck(() => this.codexAcpClient.logout());
|
|
25295
|
+
await this.onLogout();
|
|
24967
25296
|
const session = new ACPSessionConnection(this.connection, sessionId);
|
|
24968
25297
|
await session.update({
|
|
24969
25298
|
sessionUpdate: "agent_message_chunk",
|
|
@@ -24972,7 +25301,7 @@ var CodexCommands = class {
|
|
|
24972
25301
|
return { handled: true };
|
|
24973
25302
|
}
|
|
24974
25303
|
case "skills": {
|
|
24975
|
-
const response = await this.runWithProcessCheck(() => this.codexAcpClient.listSkills());
|
|
25304
|
+
const response = await this.runWithProcessCheck(() => this.codexAcpClient.listSkills(this.createSkillsListParams(sessionState)));
|
|
24976
25305
|
const skills = (response?.data ?? []).flatMap((entry) => entry.skills);
|
|
24977
25306
|
const lines = skills.map((skill) => {
|
|
24978
25307
|
const description = skill.shortDescription ?? skill.description ?? "";
|
|
@@ -25008,15 +25337,75 @@ var CodexCommands = class {
|
|
|
25008
25337
|
return { handled: true };
|
|
25009
25338
|
}
|
|
25010
25339
|
}
|
|
25011
|
-
async runReviewCommand(sessionState, target) {
|
|
25340
|
+
async runReviewCommand(sessionState, target, options) {
|
|
25341
|
+
options.onTurnStartPending?.();
|
|
25012
25342
|
return await this.runWithProcessCheck(() => this.codexAcpClient.runReview(
|
|
25013
25343
|
sessionState.sessionId,
|
|
25014
25344
|
target,
|
|
25015
|
-
(turnId) => {
|
|
25016
|
-
sessionState
|
|
25345
|
+
(turnId, threadId) => {
|
|
25346
|
+
this.handleCommandTurnStarted(sessionState, options, turnId, threadId);
|
|
25017
25347
|
}
|
|
25018
25348
|
));
|
|
25019
25349
|
}
|
|
25350
|
+
async runGoalCommand(sessionState, rest, options) {
|
|
25351
|
+
const sessionId = sessionState.sessionId;
|
|
25352
|
+
const argument = rest.trim();
|
|
25353
|
+
if (argument.length === 0) {
|
|
25354
|
+
await this.sendCommandUsageMessage("goal", "[<objective>|clear|pause|resume]", sessionId);
|
|
25355
|
+
return { handled: true };
|
|
25356
|
+
}
|
|
25357
|
+
switch (argument.toLowerCase()) {
|
|
25358
|
+
case "pause":
|
|
25359
|
+
await this.runWithProcessCheck(() => this.codexAcpClient.setGoalStatus(sessionId, "paused"));
|
|
25360
|
+
return { handled: true };
|
|
25361
|
+
case "resume":
|
|
25362
|
+
options.onTurnStartPending?.();
|
|
25363
|
+
return this.createGoalCommandResult(await this.runWithProcessCheck(() => this.codexAcpClient.resumeGoal(
|
|
25364
|
+
sessionId,
|
|
25365
|
+
(turnId) => {
|
|
25366
|
+
this.handleCommandTurnStarted(sessionState, options, turnId, sessionId);
|
|
25367
|
+
}
|
|
25368
|
+
)));
|
|
25369
|
+
case "clear":
|
|
25370
|
+
await this.runWithProcessCheck(() => this.codexAcpClient.clearGoal(sessionId));
|
|
25371
|
+
return { handled: true };
|
|
25372
|
+
}
|
|
25373
|
+
if (argument.length > 4e3) {
|
|
25374
|
+
const session = new ACPSessionConnection(this.connection, sessionId);
|
|
25375
|
+
await session.update({
|
|
25376
|
+
sessionUpdate: "agent_message_chunk",
|
|
25377
|
+
content: {
|
|
25378
|
+
type: "text",
|
|
25379
|
+
text: 'Command "/goal" requires goal text of at most 4000 characters.'
|
|
25380
|
+
}
|
|
25381
|
+
});
|
|
25382
|
+
return { handled: true };
|
|
25383
|
+
}
|
|
25384
|
+
options.onTurnStartPending?.();
|
|
25385
|
+
return this.createGoalCommandResult(await this.runWithProcessCheck(() => this.codexAcpClient.setGoal(
|
|
25386
|
+
sessionId,
|
|
25387
|
+
argument,
|
|
25388
|
+
(turnId) => {
|
|
25389
|
+
this.handleCommandTurnStarted(sessionState, options, turnId, sessionId);
|
|
25390
|
+
}
|
|
25391
|
+
)));
|
|
25392
|
+
}
|
|
25393
|
+
handleCommandTurnStarted(sessionState, options, turnId, threadId) {
|
|
25394
|
+
if (options.onTurnStarted) {
|
|
25395
|
+
options.onTurnStarted(turnId, threadId);
|
|
25396
|
+
} else {
|
|
25397
|
+
sessionState.currentTurnId = turnId;
|
|
25398
|
+
}
|
|
25399
|
+
}
|
|
25400
|
+
createGoalCommandResult(turnCompleted) {
|
|
25401
|
+
if (turnCompleted === null) {
|
|
25402
|
+
return { handled: true };
|
|
25403
|
+
}
|
|
25404
|
+
return {
|
|
25405
|
+
handled: true,
|
|
25406
|
+
turnCompleted
|
|
25407
|
+
};
|
|
25408
|
+
}
|
|
25020
25409
|
buildReviewTarget(instructions) {
|
|
25021
25410
|
if (instructions.length === 0) {
|
|
25022
25411
|
return { type: "uncommittedChanges" };
|
|
@@ -25484,15 +25873,16 @@ function createFunctionCallUpdate(item) {
|
|
|
25484
25873
|
if (!toolCallId || !name) {
|
|
25485
25874
|
return null;
|
|
25486
25875
|
}
|
|
25876
|
+
const isExecCommand = name === "exec_command";
|
|
25487
25877
|
const args = parseFunctionArguments(item["arguments"]);
|
|
25488
|
-
const command =
|
|
25489
|
-
const cwd =
|
|
25878
|
+
const command = isExecCommand ? commandFromFunctionArguments(args) : null;
|
|
25879
|
+
const cwd = isExecCommand ? cwdFromFunctionArguments(args) : "";
|
|
25490
25880
|
const commandAction = command ? inferCommandAction(command, cwd) : null;
|
|
25491
25881
|
if (commandAction) {
|
|
25492
25882
|
return {
|
|
25493
25883
|
update: createCommandActionEvent(toolCallId, "inProgress", cwd, commandAction),
|
|
25494
25884
|
usesTerminal: false,
|
|
25495
|
-
isExecCommand
|
|
25885
|
+
isExecCommand
|
|
25496
25886
|
};
|
|
25497
25887
|
}
|
|
25498
25888
|
const update = {
|
|
@@ -25504,12 +25894,12 @@ function createFunctionCallUpdate(item) {
|
|
|
25504
25894
|
rawInput: rawInputForFunctionCall(name, args)
|
|
25505
25895
|
};
|
|
25506
25896
|
if (!functionCallUsesTerminal(item)) {
|
|
25507
|
-
return { update, usesTerminal: false, isExecCommand
|
|
25897
|
+
return { update, usesTerminal: false, isExecCommand };
|
|
25508
25898
|
}
|
|
25509
25899
|
return {
|
|
25510
25900
|
update: withTerminalContent(update, toolCallId, cwd),
|
|
25511
25901
|
usesTerminal: true,
|
|
25512
|
-
isExecCommand
|
|
25902
|
+
isExecCommand
|
|
25513
25903
|
};
|
|
25514
25904
|
}
|
|
25515
25905
|
function createFunctionCallOutputUpdate(item, terminalOutputMode, terminalToolCallIds, execToolCallIds) {
|
|
@@ -26023,7 +26413,7 @@ function sedFileArguments(args) {
|
|
|
26023
26413
|
return files;
|
|
26024
26414
|
}
|
|
26025
26415
|
function looksLikeSedRangeScript(arg) {
|
|
26026
|
-
return /^(\d+|\$)?(,(\d+|\$))?[pd]$/.test(arg)
|
|
26416
|
+
return /^(\d+|\$)?(,(\d+|\$))?[pd]$/.test(arg);
|
|
26027
26417
|
}
|
|
26028
26418
|
function headTailFileArguments(args) {
|
|
26029
26419
|
const files = [];
|
|
@@ -26238,7 +26628,8 @@ var CodexAcpServer = class _CodexAcpServer {
|
|
|
26238
26628
|
this.availableCommands = new CodexCommands(
|
|
26239
26629
|
connection,
|
|
26240
26630
|
codexAcpClient,
|
|
26241
|
-
(operation) => this.runWithProcessCheck(operation)
|
|
26631
|
+
(operation) => this.runWithProcessCheck(operation),
|
|
26632
|
+
() => this.refreshSessionsAuthState(null)
|
|
26242
26633
|
);
|
|
26243
26634
|
}
|
|
26244
26635
|
async initialize(_params) {
|
|
@@ -26322,6 +26713,7 @@ var CodexAcpServer = class _CodexAcpServer {
|
|
|
26322
26713
|
async handleError(e) {
|
|
26323
26714
|
if (e.message.includes("log out") || e.message.includes("cloud requirements")) {
|
|
26324
26715
|
await this.runWithProcessCheck(() => this.codexAcpClient.logout());
|
|
26716
|
+
await this.refreshSessionsAuthState(null);
|
|
26325
26717
|
throw RequestError.internalError(`${e.message}
|
|
26326
26718
|
|
|
26327
26719
|
You have been logged out. Please try again.`);
|
|
@@ -26407,9 +26799,10 @@ You have been logged out. Please try again.`);
|
|
|
26407
26799
|
sessionMetadata = await this.runWithProcessCheck(() => this.codexAcpClient.newSession(request));
|
|
26408
26800
|
}
|
|
26409
26801
|
const { sessionId, currentModelId, models } = sessionMetadata;
|
|
26410
|
-
|
|
26802
|
+
const authProvider = sessionMetadata.modelProvider ?? this.codexAcpClient.getModelProvider();
|
|
26803
|
+
let authState;
|
|
26411
26804
|
try {
|
|
26412
|
-
|
|
26805
|
+
authState = await this.getAuthStateForProvider(authProvider);
|
|
26413
26806
|
} catch (err) {
|
|
26414
26807
|
if (resumeSubscribed && requestedSessionGeneration !== null) {
|
|
26415
26808
|
await this.cleanupStaleSessionOpen(sessionId, requestedSessionGeneration);
|
|
@@ -26436,7 +26829,9 @@ You have been logged out. Please try again.`);
|
|
|
26436
26829
|
totalTokenUsage: null,
|
|
26437
26830
|
modelContextWindow: null,
|
|
26438
26831
|
rateLimits: null,
|
|
26439
|
-
account,
|
|
26832
|
+
account: authState.account,
|
|
26833
|
+
authConfigured: authState.authConfigured,
|
|
26834
|
+
authProvider,
|
|
26440
26835
|
cwd: request.cwd,
|
|
26441
26836
|
additionalDirectories: sessionMetadata.additionalDirectories,
|
|
26442
26837
|
fastModeEnabled: sessionMetadata.currentServiceTier === "fast",
|
|
@@ -26453,17 +26848,38 @@ You have been logged out. Please try again.`);
|
|
|
26453
26848
|
});
|
|
26454
26849
|
this.publishMcpStartupStatusAsync(sessionId);
|
|
26455
26850
|
}
|
|
26456
|
-
this.publishAvailableCommandsAsync(
|
|
26851
|
+
this.publishAvailableCommandsAsync(sessionState);
|
|
26457
26852
|
const sessionModelState = this.createModelState(models, currentModelId);
|
|
26458
26853
|
const sessionModeState = sessionState.agentMode.toSessionModeState();
|
|
26459
26854
|
return [sessionId, sessionModelState, sessionModeState];
|
|
26460
26855
|
}
|
|
26461
|
-
async
|
|
26462
|
-
if (this.
|
|
26463
|
-
return
|
|
26856
|
+
async getAuthStateForProvider(authProvider) {
|
|
26857
|
+
if (!this.authProviderUsesOpenAiAccount(authProvider)) {
|
|
26858
|
+
return {
|
|
26859
|
+
account: null,
|
|
26860
|
+
authConfigured: true
|
|
26861
|
+
};
|
|
26464
26862
|
}
|
|
26465
26863
|
const accountResponse = await this.runWithProcessCheck(() => this.codexAcpClient.getAccount());
|
|
26466
|
-
return
|
|
26864
|
+
return {
|
|
26865
|
+
account: accountResponse.account,
|
|
26866
|
+
authConfigured: accountResponse.account !== null || !accountResponse.requiresOpenaiAuth
|
|
26867
|
+
};
|
|
26868
|
+
}
|
|
26869
|
+
authProviderUsesOpenAiAccount(authProvider) {
|
|
26870
|
+
return authProvider === null || authProvider === "openai";
|
|
26871
|
+
}
|
|
26872
|
+
authProvidersMatch(a, b) {
|
|
26873
|
+
if (this.authProviderUsesOpenAiAccount(a) && this.authProviderUsesOpenAiAccount(b)) {
|
|
26874
|
+
return true;
|
|
26875
|
+
}
|
|
26876
|
+
return a === b;
|
|
26877
|
+
}
|
|
26878
|
+
getAuthProviderForAuthenticateRequest(request) {
|
|
26879
|
+
if (isCodexAuthRequest(request) && request.methodId === "gateway") {
|
|
26880
|
+
return "custom-gateway";
|
|
26881
|
+
}
|
|
26882
|
+
return null;
|
|
26467
26883
|
}
|
|
26468
26884
|
async loadSession(params) {
|
|
26469
26885
|
logger.log("Loading session...", { sessionId: params.sessionId });
|
|
@@ -26592,14 +27008,26 @@ You have been logged out. Please try again.`);
|
|
|
26592
27008
|
logger.log("Authenticate request failed");
|
|
26593
27009
|
throw RequestError.invalidParams();
|
|
26594
27010
|
}
|
|
27011
|
+
await this.refreshSessionsAuthState(this.getAuthProviderForAuthenticateRequest(_params));
|
|
26595
27012
|
logger.log("Authenticate request completed");
|
|
26596
27013
|
return {};
|
|
26597
27014
|
}
|
|
26598
27015
|
async logout(_params) {
|
|
26599
27016
|
logger.log("Logout request received");
|
|
26600
27017
|
await this.runWithProcessCheck(() => this.codexAcpClient.logout());
|
|
27018
|
+
await this.refreshSessionsAuthState(null);
|
|
26601
27019
|
logger.log("Logout request completed");
|
|
26602
27020
|
}
|
|
27021
|
+
async refreshSessionsAuthState(authProvider) {
|
|
27022
|
+
if (this.sessions.size === 0) return;
|
|
27023
|
+
const sessionsToRefresh = [...this.sessions.values()].filter((sessionState) => this.authProvidersMatch(sessionState.authProvider, authProvider));
|
|
27024
|
+
if (sessionsToRefresh.length === 0) return;
|
|
27025
|
+
const authState = await this.getAuthStateForProvider(authProvider);
|
|
27026
|
+
for (const sessionState of sessionsToRefresh) {
|
|
27027
|
+
sessionState.account = authState.account;
|
|
27028
|
+
sessionState.authConfigured = authState.authConfigured;
|
|
27029
|
+
}
|
|
27030
|
+
}
|
|
26603
27031
|
async setSessionMode(_params) {
|
|
26604
27032
|
logger.log("Set session mode requested", {
|
|
26605
27033
|
sessionId: _params.sessionId,
|
|
@@ -26657,6 +27085,10 @@ You have been logged out. Please try again.`);
|
|
|
26657
27085
|
applyModelChange(sessionState, value) {
|
|
26658
27086
|
const model = sessionState.availableModels.find((m) => m.id === value);
|
|
26659
27087
|
if (!model) {
|
|
27088
|
+
const currentModel = ModelId.fromString(sessionState.currentModelId).model;
|
|
27089
|
+
if (value === currentModel) {
|
|
27090
|
+
return;
|
|
27091
|
+
}
|
|
26660
27092
|
throw RequestError.invalidParams();
|
|
26661
27093
|
}
|
|
26662
27094
|
const currentEffort = ModelId.fromString(sessionState.currentModelId).effort;
|
|
@@ -26715,12 +27147,19 @@ You have been logged out. Please try again.`);
|
|
|
26715
27147
|
}
|
|
26716
27148
|
createSessionConfigOptions(sessionState) {
|
|
26717
27149
|
const currentModelId = ModelId.fromString(sessionState.currentModelId);
|
|
26718
|
-
|
|
27150
|
+
const configOptions = [
|
|
26719
27151
|
sessionState.agentMode.toConfigOption(),
|
|
26720
|
-
createModelConfigOption(sessionState.availableModels, currentModelId.model)
|
|
26721
|
-
createReasoningEffortConfigOption(sessionState.supportedReasoningEfforts, currentModelId.effort),
|
|
26722
|
-
createFastModeConfigOption(sessionState.fastModeEnabled)
|
|
27152
|
+
createModelConfigOption(sessionState.availableModels, currentModelId.model)
|
|
26723
27153
|
];
|
|
27154
|
+
if (sessionState.supportedReasoningEfforts.length > 0) {
|
|
27155
|
+
configOptions.push(
|
|
27156
|
+
createReasoningEffortConfigOption(sessionState.supportedReasoningEfforts, currentModelId.effort)
|
|
27157
|
+
);
|
|
27158
|
+
}
|
|
27159
|
+
if (sessionState.currentModelSupportsFast) {
|
|
27160
|
+
configOptions.push(createFastModeConfigOption(sessionState.fastModeEnabled));
|
|
27161
|
+
}
|
|
27162
|
+
return configOptions;
|
|
26724
27163
|
}
|
|
26725
27164
|
createSessionConfigOptionsResponse(sessionState) {
|
|
26726
27165
|
if (!this.isSessionConfigEnabled()) {
|
|
@@ -26733,8 +27172,8 @@ You have been logged out. Please try again.`);
|
|
|
26733
27172
|
isSessionConfigEnabled() {
|
|
26734
27173
|
return !isJetBrains2026_1Client(this.clientInfo);
|
|
26735
27174
|
}
|
|
26736
|
-
publishAvailableCommandsAsync(
|
|
26737
|
-
void this.availableCommands.publish(
|
|
27175
|
+
publishAvailableCommandsAsync(sessionState) {
|
|
27176
|
+
void this.availableCommands.publish(sessionState);
|
|
26738
27177
|
}
|
|
26739
27178
|
findCurrentModel(models, currentModelId) {
|
|
26740
27179
|
const modelId = ModelId.fromString(currentModelId);
|
|
@@ -26777,9 +27216,10 @@ You have been logged out. Please try again.`);
|
|
|
26777
27216
|
throw err;
|
|
26778
27217
|
}
|
|
26779
27218
|
const { sessionId, currentModelId, models, thread } = sessionMetadata;
|
|
26780
|
-
|
|
27219
|
+
const authProvider = sessionMetadata.modelProvider ?? this.codexAcpClient.getModelProvider();
|
|
27220
|
+
let authState;
|
|
26781
27221
|
try {
|
|
26782
|
-
|
|
27222
|
+
authState = await this.getAuthStateForProvider(authProvider);
|
|
26783
27223
|
} catch (err) {
|
|
26784
27224
|
if (subscribed) {
|
|
26785
27225
|
await this.cleanupStaleSessionOpen(request.sessionId, requestedSessionGeneration);
|
|
@@ -26805,7 +27245,9 @@ You have been logged out. Please try again.`);
|
|
|
26805
27245
|
totalTokenUsage: null,
|
|
26806
27246
|
modelContextWindow: null,
|
|
26807
27247
|
rateLimits: null,
|
|
26808
|
-
account,
|
|
27248
|
+
account: authState.account,
|
|
27249
|
+
authConfigured: authState.authConfigured,
|
|
27250
|
+
authProvider,
|
|
26809
27251
|
cwd: request.cwd,
|
|
26810
27252
|
additionalDirectories: sessionMetadata.additionalDirectories,
|
|
26811
27253
|
fastModeEnabled: sessionMetadata.currentServiceTier === "fast",
|
|
@@ -26822,7 +27264,7 @@ You have been logged out. Please try again.`);
|
|
|
26822
27264
|
});
|
|
26823
27265
|
this.publishMcpStartupStatusAsync(sessionId);
|
|
26824
27266
|
}
|
|
26825
|
-
await this.availableCommands.publish(
|
|
27267
|
+
await this.availableCommands.publish(sessionState);
|
|
26826
27268
|
const sessionModelState = this.createModelState(models, currentModelId);
|
|
26827
27269
|
const sessionModeState = sessionState.agentMode.toSessionModeState();
|
|
26828
27270
|
return {
|
|
@@ -26881,7 +27323,7 @@ You have been logged out. Please try again.`);
|
|
|
26881
27323
|
case "dynamicToolCall":
|
|
26882
27324
|
return [await createDynamicToolCallUpdate(item)];
|
|
26883
27325
|
case "collabAgentToolCall":
|
|
26884
|
-
return [
|
|
27326
|
+
return [createCollabAgentToolCallUpdate(item)];
|
|
26885
27327
|
case "webSearch":
|
|
26886
27328
|
return [this.createWebSearchUpdate(item)];
|
|
26887
27329
|
case "imageView":
|
|
@@ -26918,22 +27360,6 @@ You have been logged out. Please try again.`);
|
|
|
26918
27360
|
content: { type: "text", text }
|
|
26919
27361
|
}));
|
|
26920
27362
|
}
|
|
26921
|
-
createCollabAgentToolCallUpdate(item) {
|
|
26922
|
-
return {
|
|
26923
|
-
sessionUpdate: "tool_call",
|
|
26924
|
-
toolCallId: item.id,
|
|
26925
|
-
kind: "other",
|
|
26926
|
-
title: `collab.${item.tool}`,
|
|
26927
|
-
status: this.toAcpToolCallStatus(item.status),
|
|
26928
|
-
rawInput: {
|
|
26929
|
-
prompt: item.prompt,
|
|
26930
|
-
senderThreadId: item.senderThreadId,
|
|
26931
|
-
receiverThreadIds: item.receiverThreadIds,
|
|
26932
|
-
agentsStates: item.agentsStates,
|
|
26933
|
-
status: item.status
|
|
26934
|
-
}
|
|
26935
|
-
};
|
|
26936
|
-
}
|
|
26937
27363
|
createWebSearchUpdate(item) {
|
|
26938
27364
|
return {
|
|
26939
27365
|
sessionUpdate: "tool_call",
|
|
@@ -26975,16 +27401,6 @@ ${item.text}`
|
|
|
26975
27401
|
}
|
|
26976
27402
|
};
|
|
26977
27403
|
}
|
|
26978
|
-
toAcpToolCallStatus(status) {
|
|
26979
|
-
switch (status) {
|
|
26980
|
-
case "inProgress":
|
|
26981
|
-
return "in_progress";
|
|
26982
|
-
case "completed":
|
|
26983
|
-
return "completed";
|
|
26984
|
-
case "failed":
|
|
26985
|
-
return "failed";
|
|
26986
|
-
}
|
|
26987
|
-
}
|
|
26988
27404
|
userInputToContentBlocks(input) {
|
|
26989
27405
|
switch (input.type) {
|
|
26990
27406
|
case "text":
|
|
@@ -27080,16 +27496,33 @@ ${item.text}`
|
|
|
27080
27496
|
const closeSignal = new Promise((resolve) => {
|
|
27081
27497
|
resolveCloseSignal = resolve;
|
|
27082
27498
|
});
|
|
27499
|
+
let resolveCancelSignal = () => {
|
|
27500
|
+
};
|
|
27501
|
+
const cancelSignal = new Promise((resolve) => {
|
|
27502
|
+
resolveCancelSignal = resolve;
|
|
27503
|
+
});
|
|
27504
|
+
const abortController = new AbortController();
|
|
27083
27505
|
let completed = false;
|
|
27084
27506
|
let closeRequested = false;
|
|
27085
27507
|
const activePrompt = {
|
|
27086
27508
|
completion,
|
|
27087
27509
|
closeSignal,
|
|
27510
|
+
cancelSignal,
|
|
27511
|
+
signal: abortController.signal,
|
|
27512
|
+
currentTurn: null,
|
|
27513
|
+
requestCancel: () => {
|
|
27514
|
+
if (abortController.signal.aborted) {
|
|
27515
|
+
return;
|
|
27516
|
+
}
|
|
27517
|
+
abortController.abort();
|
|
27518
|
+
resolveCancelSignal(null);
|
|
27519
|
+
},
|
|
27088
27520
|
requestClose: () => {
|
|
27089
27521
|
if (closeRequested) {
|
|
27090
27522
|
return;
|
|
27091
27523
|
}
|
|
27092
27524
|
closeRequested = true;
|
|
27525
|
+
activePrompt.requestCancel();
|
|
27093
27526
|
resolveCloseSignal(null);
|
|
27094
27527
|
},
|
|
27095
27528
|
complete: () => {
|
|
@@ -27106,6 +27539,40 @@ ${item.text}`
|
|
|
27106
27539
|
this.activePrompts.set(sessionId, activePrompt);
|
|
27107
27540
|
return activePrompt;
|
|
27108
27541
|
}
|
|
27542
|
+
cancelBeforeTurnStarted(activePrompt) {
|
|
27543
|
+
return activePrompt.cancelSignal.then(() => {
|
|
27544
|
+
if (activePrompt.currentTurn === null) {
|
|
27545
|
+
return null;
|
|
27546
|
+
}
|
|
27547
|
+
return new Promise(() => {
|
|
27548
|
+
});
|
|
27549
|
+
});
|
|
27550
|
+
}
|
|
27551
|
+
observePromptRequestCancellation(signal, sessionState, activePrompt) {
|
|
27552
|
+
if (!signal) {
|
|
27553
|
+
return () => {
|
|
27554
|
+
};
|
|
27555
|
+
}
|
|
27556
|
+
const onAbort = () => {
|
|
27557
|
+
if (this.activePrompts.get(sessionState.sessionId) !== activePrompt) {
|
|
27558
|
+
return;
|
|
27559
|
+
}
|
|
27560
|
+
logger.log("Prompt request cancelled", { sessionId: sessionState.sessionId });
|
|
27561
|
+
activePrompt.requestCancel();
|
|
27562
|
+
const turn = activePrompt.currentTurn;
|
|
27563
|
+
if (!turn) {
|
|
27564
|
+
return;
|
|
27565
|
+
}
|
|
27566
|
+
void this.requestTurnInterrupt(turn, "Cancel");
|
|
27567
|
+
};
|
|
27568
|
+
if (signal.aborted) {
|
|
27569
|
+
onAbort();
|
|
27570
|
+
return () => {
|
|
27571
|
+
};
|
|
27572
|
+
}
|
|
27573
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
27574
|
+
return () => signal.removeEventListener("abort", onAbort);
|
|
27575
|
+
}
|
|
27109
27576
|
createPendingTurnStart() {
|
|
27110
27577
|
let resolve = () => {
|
|
27111
27578
|
};
|
|
@@ -27114,25 +27581,39 @@ ${item.text}`
|
|
|
27114
27581
|
});
|
|
27115
27582
|
return { promise: promise2, resolve };
|
|
27116
27583
|
}
|
|
27117
|
-
|
|
27584
|
+
async interruptPromptTurn(turn, requestName) {
|
|
27118
27585
|
this.codexAcpClient.markTurnStale({
|
|
27119
|
-
threadId:
|
|
27120
|
-
turnId
|
|
27586
|
+
threadId: turn.threadId,
|
|
27587
|
+
turnId: turn.turnId
|
|
27121
27588
|
});
|
|
27122
|
-
|
|
27123
|
-
|
|
27124
|
-
|
|
27125
|
-
})).catch((err) => {
|
|
27126
|
-
logger.error(`Close - late turnInterrupt failed`, err);
|
|
27127
|
-
}).finally(() => {
|
|
27589
|
+
try {
|
|
27590
|
+
await this.requestTurnInterrupt(turn, requestName);
|
|
27591
|
+
} finally {
|
|
27128
27592
|
this.codexAcpClient.resolveTurnInterrupted({
|
|
27129
|
-
threadId:
|
|
27130
|
-
turnId
|
|
27593
|
+
threadId: turn.threadId,
|
|
27594
|
+
turnId: turn.turnId
|
|
27131
27595
|
});
|
|
27132
|
-
}
|
|
27596
|
+
}
|
|
27597
|
+
}
|
|
27598
|
+
async requestTurnInterrupt(turn, requestName) {
|
|
27599
|
+
try {
|
|
27600
|
+
await this.runWithProcessCheck(() => this.codexAcpClient.turnInterrupt({
|
|
27601
|
+
threadId: turn.threadId,
|
|
27602
|
+
turnId: turn.turnId
|
|
27603
|
+
}));
|
|
27604
|
+
logger.log(`${requestName} - turnInterrupt succeeded`, {
|
|
27605
|
+
sessionId: turn.threadId,
|
|
27606
|
+
currentTurnId: turn.turnId
|
|
27607
|
+
});
|
|
27608
|
+
} catch (err) {
|
|
27609
|
+
logger.error(`${requestName} - turnInterrupt failed`, err);
|
|
27610
|
+
}
|
|
27133
27611
|
}
|
|
27134
|
-
|
|
27135
|
-
|
|
27612
|
+
interruptLateStartedTurn(turn) {
|
|
27613
|
+
void this.interruptPromptTurn(turn, "Close");
|
|
27614
|
+
}
|
|
27615
|
+
promptShouldStop(sessionId, activePrompt) {
|
|
27616
|
+
return activePrompt.signal.aborted || this.activePrompts.get(sessionId) !== activePrompt || this.sessionIsClosing(sessionId);
|
|
27136
27617
|
}
|
|
27137
27618
|
async interruptSessionTurn(sessionState, requestName, resolveInterruptedTurn) {
|
|
27138
27619
|
const turnId = await this.getInterruptibleTurnId(sessionState, requestName);
|
|
@@ -27188,7 +27669,7 @@ ${item.text}`
|
|
|
27188
27669
|
}
|
|
27189
27670
|
return turnId;
|
|
27190
27671
|
}
|
|
27191
|
-
async prompt(params) {
|
|
27672
|
+
async prompt(params, signal) {
|
|
27192
27673
|
logger.log("Prompt received", {
|
|
27193
27674
|
sessionId: params.sessionId,
|
|
27194
27675
|
prompt: params.prompt
|
|
@@ -27198,10 +27679,18 @@ ${item.text}`
|
|
|
27198
27679
|
sessionState.lastTokenUsage = null;
|
|
27199
27680
|
const activePrompt = this.trackActivePrompt(params.sessionId);
|
|
27200
27681
|
let pendingTurnStart = null;
|
|
27682
|
+
const ensurePendingTurnStart = () => {
|
|
27683
|
+
if (pendingTurnStart === null) {
|
|
27684
|
+
pendingTurnStart = this.createPendingTurnStart();
|
|
27685
|
+
this.pendingTurnStarts.set(params.sessionId, pendingTurnStart);
|
|
27686
|
+
}
|
|
27687
|
+
return pendingTurnStart;
|
|
27688
|
+
};
|
|
27689
|
+
const disposePromptRequestCancellation = this.observePromptRequestCancellation(signal, sessionState, activePrompt);
|
|
27201
27690
|
try {
|
|
27202
27691
|
const eventHandler = new CodexEventHandler(this.connection, sessionState);
|
|
27203
|
-
const approvalHandler = new CodexApprovalHandler(this.connection, sessionState);
|
|
27204
|
-
const elicitationHandler = new CodexElicitationHandler(this.connection, sessionState);
|
|
27692
|
+
const approvalHandler = new CodexApprovalHandler(this.connection, sessionState, activePrompt.signal);
|
|
27693
|
+
const elicitationHandler = new CodexElicitationHandler(this.connection, sessionState, activePrompt.signal);
|
|
27205
27694
|
await this.codexAcpClient.subscribeToSessionEvents(
|
|
27206
27695
|
params.sessionId,
|
|
27207
27696
|
(event) => {
|
|
@@ -27211,28 +27700,43 @@ ${item.text}`
|
|
|
27211
27700
|
approvalHandler,
|
|
27212
27701
|
elicitationHandler
|
|
27213
27702
|
);
|
|
27214
|
-
|
|
27703
|
+
if (activePrompt.signal.aborted) {
|
|
27704
|
+
return this.cancelledPromptResponse(sessionState);
|
|
27705
|
+
}
|
|
27706
|
+
const commandPromise = this.availableCommands.tryHandleCommand(params.prompt, sessionState, {
|
|
27707
|
+
onTurnStartPending: () => {
|
|
27708
|
+
ensurePendingTurnStart();
|
|
27709
|
+
},
|
|
27710
|
+
onTurnStarted: (turnId, threadId) => {
|
|
27711
|
+
const turn = { threadId, turnId };
|
|
27712
|
+
activePrompt.currentTurn = turn;
|
|
27713
|
+
if (this.promptShouldStop(params.sessionId, activePrompt)) {
|
|
27714
|
+
this.interruptLateStartedTurn(turn);
|
|
27715
|
+
return;
|
|
27716
|
+
}
|
|
27717
|
+
sessionState.currentTurnId = turnId;
|
|
27718
|
+
pendingTurnStart?.resolve(turnId);
|
|
27719
|
+
}
|
|
27720
|
+
});
|
|
27721
|
+
void commandPromise.catch((err) => {
|
|
27722
|
+
if (this.activePrompts.get(params.sessionId) !== activePrompt) {
|
|
27723
|
+
logger.error(`Command for cancelled prompt ${params.sessionId} failed after prompt returned`, err);
|
|
27724
|
+
}
|
|
27725
|
+
});
|
|
27726
|
+
const commandResult = await Promise.race([
|
|
27727
|
+
commandPromise,
|
|
27728
|
+
activePrompt.closeSignal,
|
|
27729
|
+
this.cancelBeforeTurnStarted(activePrompt)
|
|
27730
|
+
]);
|
|
27731
|
+
if (commandResult === null) {
|
|
27732
|
+
return this.cancelledPromptResponse(sessionState);
|
|
27733
|
+
}
|
|
27215
27734
|
if (commandResult.handled) {
|
|
27216
27735
|
logger.log("Prompt handled by a command");
|
|
27217
27736
|
await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
|
|
27218
27737
|
if (commandResult.turnCompleted?.turn.status === "interrupted") {
|
|
27219
|
-
|
|
27220
|
-
|
|
27221
|
-
sessionId: params.sessionId,
|
|
27222
|
-
update: {
|
|
27223
|
-
sessionUpdate: "agent_message_chunk",
|
|
27224
|
-
content: {
|
|
27225
|
-
type: "text",
|
|
27226
|
-
text: "*Conversation interrupted*"
|
|
27227
|
-
}
|
|
27228
|
-
}
|
|
27229
|
-
});
|
|
27230
|
-
}
|
|
27231
|
-
return {
|
|
27232
|
-
stopReason: "cancelled",
|
|
27233
|
-
usage: this.buildPromptUsage(sessionState.lastTokenUsage),
|
|
27234
|
-
_meta: this.buildQuotaMeta(sessionState)
|
|
27235
|
-
};
|
|
27738
|
+
await this.notifyConversationInterrupted(params.sessionId);
|
|
27739
|
+
return this.cancelledPromptResponse(sessionState);
|
|
27236
27740
|
}
|
|
27237
27741
|
const error52 = eventHandler.getFailure();
|
|
27238
27742
|
if (error52) {
|
|
@@ -27245,11 +27749,7 @@ ${item.text}`
|
|
|
27245
27749
|
};
|
|
27246
27750
|
}
|
|
27247
27751
|
if (this.sessionIsClosing(params.sessionId)) {
|
|
27248
|
-
return
|
|
27249
|
-
stopReason: "cancelled",
|
|
27250
|
-
usage: this.buildPromptUsage(sessionState.lastTokenUsage),
|
|
27251
|
-
_meta: this.buildQuotaMeta(sessionState)
|
|
27252
|
-
};
|
|
27752
|
+
return this.cancelledPromptResponse(sessionState);
|
|
27253
27753
|
}
|
|
27254
27754
|
const modelId = ModelId.fromString(sessionState.currentModelId);
|
|
27255
27755
|
const modelLacksReasoning = sessionState.supportedReasoningEfforts.length > 0 && sessionState.supportedReasoningEfforts.every((e) => e.reasoningEffort === "none");
|
|
@@ -27268,8 +27768,7 @@ ${item.text}`
|
|
|
27268
27768
|
sessionState.fastModeEnabled,
|
|
27269
27769
|
sessionState.currentModelSupportsFast
|
|
27270
27770
|
);
|
|
27271
|
-
|
|
27272
|
-
this.pendingTurnStarts.set(params.sessionId, pendingTurnStart);
|
|
27771
|
+
ensurePendingTurnStart();
|
|
27273
27772
|
const sendPromptPromise = this.runWithProcessCheck(
|
|
27274
27773
|
() => this.codexAcpClient.sendPrompt(
|
|
27275
27774
|
params,
|
|
@@ -27280,51 +27779,35 @@ ${item.text}`
|
|
|
27280
27779
|
sessionState.cwd,
|
|
27281
27780
|
sessionState.additionalDirectories,
|
|
27282
27781
|
(turnId) => {
|
|
27283
|
-
|
|
27284
|
-
|
|
27782
|
+
const turn = { threadId: params.sessionId, turnId };
|
|
27783
|
+
activePrompt.currentTurn = turn;
|
|
27784
|
+
if (this.promptShouldStop(params.sessionId, activePrompt)) {
|
|
27785
|
+
this.interruptLateStartedTurn(turn);
|
|
27285
27786
|
return;
|
|
27286
27787
|
}
|
|
27287
27788
|
sessionState.currentTurnId = turnId;
|
|
27288
27789
|
pendingTurnStart?.resolve(turnId);
|
|
27289
27790
|
},
|
|
27290
|
-
() => this.
|
|
27791
|
+
() => this.promptShouldStop(params.sessionId, activePrompt)
|
|
27291
27792
|
)
|
|
27292
27793
|
);
|
|
27293
27794
|
void sendPromptPromise.catch((err) => {
|
|
27294
27795
|
if (this.activePrompts.get(params.sessionId) !== activePrompt) {
|
|
27295
|
-
logger.error(`Prompt for
|
|
27796
|
+
logger.error(`Prompt for cancelled session ${params.sessionId} failed after prompt returned`, err);
|
|
27296
27797
|
}
|
|
27297
27798
|
});
|
|
27298
27799
|
const turnCompleted = await Promise.race([
|
|
27299
27800
|
sendPromptPromise,
|
|
27300
|
-
activePrompt.closeSignal
|
|
27801
|
+
activePrompt.closeSignal,
|
|
27802
|
+
this.cancelBeforeTurnStarted(activePrompt)
|
|
27301
27803
|
]);
|
|
27302
27804
|
if (turnCompleted === null) {
|
|
27303
|
-
return
|
|
27304
|
-
stopReason: "cancelled",
|
|
27305
|
-
usage: this.buildPromptUsage(sessionState.lastTokenUsage),
|
|
27306
|
-
_meta: this.buildQuotaMeta(sessionState)
|
|
27307
|
-
};
|
|
27805
|
+
return this.cancelledPromptResponse(sessionState);
|
|
27308
27806
|
}
|
|
27309
27807
|
await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
|
|
27310
27808
|
if (turnCompleted.turn.status === "interrupted") {
|
|
27311
|
-
|
|
27312
|
-
|
|
27313
|
-
sessionId: params.sessionId,
|
|
27314
|
-
update: {
|
|
27315
|
-
sessionUpdate: "agent_message_chunk",
|
|
27316
|
-
content: {
|
|
27317
|
-
type: "text",
|
|
27318
|
-
text: "*Conversation interrupted*"
|
|
27319
|
-
}
|
|
27320
|
-
}
|
|
27321
|
-
});
|
|
27322
|
-
}
|
|
27323
|
-
return {
|
|
27324
|
-
stopReason: "cancelled",
|
|
27325
|
-
usage: this.buildPromptUsage(sessionState.lastTokenUsage),
|
|
27326
|
-
_meta: this.buildQuotaMeta(sessionState)
|
|
27327
|
-
};
|
|
27809
|
+
await this.notifyConversationInterrupted(params.sessionId);
|
|
27810
|
+
return this.cancelledPromptResponse(sessionState);
|
|
27328
27811
|
}
|
|
27329
27812
|
const error51 = eventHandler.getFailure();
|
|
27330
27813
|
if (error51) {
|
|
@@ -27340,14 +27823,38 @@ ${item.text}`
|
|
|
27340
27823
|
throw err;
|
|
27341
27824
|
} finally {
|
|
27342
27825
|
logger.log("Prompt completed", { sessionId: params.sessionId });
|
|
27826
|
+
disposePromptRequestCancellation();
|
|
27343
27827
|
sessionState.currentTurnId = null;
|
|
27344
|
-
|
|
27828
|
+
const registeredPendingTurnStart = this.pendingTurnStarts.get(params.sessionId);
|
|
27829
|
+
if (registeredPendingTurnStart !== void 0) {
|
|
27345
27830
|
this.pendingTurnStarts.delete(params.sessionId);
|
|
27831
|
+
registeredPendingTurnStart.resolve(null);
|
|
27346
27832
|
}
|
|
27347
|
-
pendingTurnStart?.resolve(null);
|
|
27348
27833
|
activePrompt.complete();
|
|
27349
27834
|
}
|
|
27350
27835
|
}
|
|
27836
|
+
cancelledPromptResponse(sessionState) {
|
|
27837
|
+
return {
|
|
27838
|
+
stopReason: "cancelled",
|
|
27839
|
+
usage: this.buildPromptUsage(sessionState.lastTokenUsage),
|
|
27840
|
+
_meta: this.buildQuotaMeta(sessionState)
|
|
27841
|
+
};
|
|
27842
|
+
}
|
|
27843
|
+
async notifyConversationInterrupted(sessionId) {
|
|
27844
|
+
if (this.sessionIsClosing(sessionId) || !this.sessions.has(sessionId)) {
|
|
27845
|
+
return;
|
|
27846
|
+
}
|
|
27847
|
+
await this.connection.notify(methods.client.session.update, {
|
|
27848
|
+
sessionId,
|
|
27849
|
+
update: {
|
|
27850
|
+
sessionUpdate: "agent_message_chunk",
|
|
27851
|
+
content: {
|
|
27852
|
+
type: "text",
|
|
27853
|
+
text: "*Conversation interrupted*"
|
|
27854
|
+
}
|
|
27855
|
+
}
|
|
27856
|
+
});
|
|
27857
|
+
}
|
|
27351
27858
|
buildQuotaMeta(sessionState) {
|
|
27352
27859
|
const lastTokenUsage = sessionState.lastTokenUsage;
|
|
27353
27860
|
const modelName = sessionState.currentModelId.replace(/\[.*?]$/, "");
|
|
@@ -27454,6 +27961,7 @@ var CommandExecutionApprovalRequest = new import_node2.RequestType("item/command
|
|
|
27454
27961
|
var FileChangeApprovalRequest = new import_node2.RequestType("item/fileChange/requestApproval");
|
|
27455
27962
|
var PermissionsApprovalRequest = new import_node2.RequestType("item/permissions/requestApproval");
|
|
27456
27963
|
var McpServerElicitationRequest = new import_node2.RequestType("mcpServer/elicitation/request");
|
|
27964
|
+
var GOAL_RUNTIME_EFFECTS_GRACE_MS = 1e3;
|
|
27457
27965
|
var CodexAppServerClient = class {
|
|
27458
27966
|
connection;
|
|
27459
27967
|
approvalHandlers = /* @__PURE__ */ new Map();
|
|
@@ -27464,6 +27972,10 @@ var CodexAppServerClient = class {
|
|
|
27464
27972
|
pendingTurnCompletionResolvers = /* @__PURE__ */ new Map();
|
|
27465
27973
|
pendingCompactionCompletionResolvers = /* @__PURE__ */ new Map();
|
|
27466
27974
|
turnCompletionCaptures = /* @__PURE__ */ new Map();
|
|
27975
|
+
turnRoutingCaptures = /* @__PURE__ */ new Map();
|
|
27976
|
+
threadStatusCaptures = /* @__PURE__ */ new Map();
|
|
27977
|
+
threadGoalUpdateCaptures = /* @__PURE__ */ new Map();
|
|
27978
|
+
threadGoalClearedCaptures = /* @__PURE__ */ new Map();
|
|
27467
27979
|
staleTurnIds = /* @__PURE__ */ new Map();
|
|
27468
27980
|
constructor(connection) {
|
|
27469
27981
|
this.connection = connection;
|
|
@@ -27484,15 +27996,21 @@ var CodexAppServerClient = class {
|
|
|
27484
27996
|
if (isCompactionCompletedNotification(serverNotification)) {
|
|
27485
27997
|
this.recordCompactionCompleted(serverNotification);
|
|
27486
27998
|
}
|
|
27999
|
+
if (isThreadStatusChangedNotification(serverNotification)) {
|
|
28000
|
+
this.recordThreadStatusChanged(serverNotification.params);
|
|
28001
|
+
}
|
|
28002
|
+
if (isThreadGoalUpdatedNotification(serverNotification)) {
|
|
28003
|
+
this.recordThreadGoalUpdated(serverNotification.params);
|
|
28004
|
+
}
|
|
28005
|
+
if (isThreadGoalClearedNotification(serverNotification)) {
|
|
28006
|
+
this.recordThreadGoalCleared(serverNotification.params);
|
|
28007
|
+
}
|
|
27487
28008
|
const routing = extractTurnRouting(serverNotification);
|
|
27488
|
-
|
|
27489
|
-
|
|
27490
|
-
|
|
27491
|
-
|
|
27492
|
-
|
|
27493
|
-
for (const callback of this.codexEventHandlers) {
|
|
27494
|
-
callback({ eventType: "notification", ...serverNotification });
|
|
27495
|
-
}
|
|
28009
|
+
if (this.handleStaleTurnNotification(serverNotification, routing)) {
|
|
28010
|
+
return;
|
|
28011
|
+
}
|
|
28012
|
+
this.recordTurnRouting(routing);
|
|
28013
|
+
if (this.handleStaleTurnNotification(serverNotification, routing)) {
|
|
27496
28014
|
return;
|
|
27497
28015
|
}
|
|
27498
28016
|
this.notify(serverNotification);
|
|
@@ -27583,7 +28101,7 @@ var CodexAppServerClient = class {
|
|
|
27583
28101
|
});
|
|
27584
28102
|
try {
|
|
27585
28103
|
const reviewStarted = await this.reviewStart(params);
|
|
27586
|
-
onTurnStarted?.(reviewStarted.turn.id);
|
|
28104
|
+
onTurnStarted?.(reviewStarted.turn.id, reviewStarted.reviewThreadId);
|
|
27587
28105
|
const earlyCompletion = capturedCompletions.find((event) => event.turn.id === reviewStarted.turn.id);
|
|
27588
28106
|
releaseCapture();
|
|
27589
28107
|
if (earlyCompletion) {
|
|
@@ -27594,6 +28112,174 @@ var CodexAppServerClient = class {
|
|
|
27594
28112
|
releaseCapture();
|
|
27595
28113
|
}
|
|
27596
28114
|
}
|
|
28115
|
+
async runGoalSet(params, onTurnStarted, runtimeEffectsGraceMs = GOAL_RUNTIME_EFFECTS_GRACE_MS) {
|
|
28116
|
+
let goalTurnId = null;
|
|
28117
|
+
const capturedCompletions = [];
|
|
28118
|
+
let resolveGoalTurnCompleted = () => {
|
|
28119
|
+
};
|
|
28120
|
+
const goalTurnCompleted = new Promise((resolve) => {
|
|
28121
|
+
resolveGoalTurnCompleted = resolve;
|
|
28122
|
+
});
|
|
28123
|
+
const releaseCompletionCapture = this.captureTurnCompletions(params.threadId, (event) => {
|
|
28124
|
+
capturedCompletions.push(event);
|
|
28125
|
+
if (goalTurnId === event.turn.id) {
|
|
28126
|
+
resolveGoalTurnCompleted(event);
|
|
28127
|
+
}
|
|
28128
|
+
});
|
|
28129
|
+
let resolveGoalTurnStarted = () => {
|
|
28130
|
+
};
|
|
28131
|
+
const goalTurnStarted = new Promise((resolve) => {
|
|
28132
|
+
resolveGoalTurnStarted = resolve;
|
|
28133
|
+
});
|
|
28134
|
+
let resolveGoalUpdateHandled = () => {
|
|
28135
|
+
};
|
|
28136
|
+
const matchingGoalUpdateHandled = new Promise((resolve) => {
|
|
28137
|
+
resolveGoalUpdateHandled = () => resolve(null);
|
|
28138
|
+
});
|
|
28139
|
+
let goalUpdateHandled = false;
|
|
28140
|
+
let expectedGoal = null;
|
|
28141
|
+
const noGoalTurnStarted = this.createNoGoalTurnStartedPromise(runtimeEffectsGraceMs);
|
|
28142
|
+
const capturedGoalUpdates = [];
|
|
28143
|
+
const releaseRoutingCapture = this.captureTurnRoutings(params.threadId, (turnId) => {
|
|
28144
|
+
if (!goalUpdateHandled || goalTurnId !== null) {
|
|
28145
|
+
return;
|
|
28146
|
+
}
|
|
28147
|
+
goalTurnId = turnId;
|
|
28148
|
+
onTurnStarted?.(turnId);
|
|
28149
|
+
resolveGoalTurnStarted(turnId);
|
|
28150
|
+
});
|
|
28151
|
+
const releaseGoalUpdateCapture = this.captureThreadGoalUpdates(params.threadId, (event) => {
|
|
28152
|
+
capturedGoalUpdates.push(event);
|
|
28153
|
+
if (expectedGoal !== null && goalsMatch(event.goal, expectedGoal)) {
|
|
28154
|
+
goalUpdateHandled = true;
|
|
28155
|
+
resolveGoalUpdateHandled();
|
|
28156
|
+
noGoalTurnStarted.goalUpdated();
|
|
28157
|
+
}
|
|
28158
|
+
});
|
|
28159
|
+
const releaseStatusCapture = this.captureThreadStatuses(params.threadId, (status) => {
|
|
28160
|
+
if (!goalUpdateHandled || goalTurnId !== null) {
|
|
28161
|
+
return;
|
|
28162
|
+
}
|
|
28163
|
+
noGoalTurnStarted.threadStatusChanged(status);
|
|
28164
|
+
});
|
|
28165
|
+
try {
|
|
28166
|
+
const goalSetResponse = await this.threadGoalSet(params);
|
|
28167
|
+
expectedGoal = goalSetResponse.goal;
|
|
28168
|
+
if (capturedGoalUpdates.some((event) => goalsMatch(event.goal, expectedGoal))) {
|
|
28169
|
+
goalUpdateHandled = true;
|
|
28170
|
+
resolveGoalUpdateHandled();
|
|
28171
|
+
noGoalTurnStarted.goalUpdated();
|
|
28172
|
+
}
|
|
28173
|
+
if (expectedGoal.status !== "active") {
|
|
28174
|
+
await matchingGoalUpdateHandled;
|
|
28175
|
+
return null;
|
|
28176
|
+
}
|
|
28177
|
+
const turnId = goalTurnId ?? await Promise.race([goalTurnStarted, noGoalTurnStarted.promise]);
|
|
28178
|
+
noGoalTurnStarted.release();
|
|
28179
|
+
releaseRoutingCapture();
|
|
28180
|
+
releaseStatusCapture();
|
|
28181
|
+
releaseGoalUpdateCapture();
|
|
28182
|
+
if (turnId === null) {
|
|
28183
|
+
return null;
|
|
28184
|
+
}
|
|
28185
|
+
const earlyCompletion = capturedCompletions.find((event) => event.turn.id === turnId);
|
|
28186
|
+
if (earlyCompletion) {
|
|
28187
|
+
return earlyCompletion;
|
|
28188
|
+
}
|
|
28189
|
+
return await goalTurnCompleted;
|
|
28190
|
+
} finally {
|
|
28191
|
+
noGoalTurnStarted.release();
|
|
28192
|
+
releaseCompletionCapture();
|
|
28193
|
+
releaseRoutingCapture();
|
|
28194
|
+
releaseStatusCapture();
|
|
28195
|
+
releaseGoalUpdateCapture();
|
|
28196
|
+
}
|
|
28197
|
+
}
|
|
28198
|
+
async runGoalClear(params) {
|
|
28199
|
+
let goalClearedHandled = false;
|
|
28200
|
+
let resolveGoalClearedHandled = () => {
|
|
28201
|
+
};
|
|
28202
|
+
const matchingGoalClearedHandled = new Promise((resolve) => {
|
|
28203
|
+
resolveGoalClearedHandled = () => resolve();
|
|
28204
|
+
});
|
|
28205
|
+
const releaseGoalClearedCapture = this.captureThreadGoalClears(params.threadId, () => {
|
|
28206
|
+
goalClearedHandled = true;
|
|
28207
|
+
resolveGoalClearedHandled();
|
|
28208
|
+
});
|
|
28209
|
+
try {
|
|
28210
|
+
const response = await this.threadGoalClear(params);
|
|
28211
|
+
if (!response.cleared || goalClearedHandled) {
|
|
28212
|
+
return;
|
|
28213
|
+
}
|
|
28214
|
+
await matchingGoalClearedHandled;
|
|
28215
|
+
} finally {
|
|
28216
|
+
releaseGoalClearedCapture();
|
|
28217
|
+
}
|
|
28218
|
+
}
|
|
28219
|
+
createNoGoalTurnStartedPromise(runtimeEffectsGraceMs) {
|
|
28220
|
+
let released = false;
|
|
28221
|
+
let resolved = false;
|
|
28222
|
+
let goalUpdated = false;
|
|
28223
|
+
let activeAfterGoalUpdate = false;
|
|
28224
|
+
let timeout = null;
|
|
28225
|
+
let resolveNoGoalTurnStarted = () => {
|
|
28226
|
+
};
|
|
28227
|
+
const clearTimer = () => {
|
|
28228
|
+
if (timeout !== null) {
|
|
28229
|
+
clearTimeout(timeout);
|
|
28230
|
+
timeout = null;
|
|
28231
|
+
}
|
|
28232
|
+
};
|
|
28233
|
+
const resolveNoTurn = () => {
|
|
28234
|
+
if (released || resolved) {
|
|
28235
|
+
return;
|
|
28236
|
+
}
|
|
28237
|
+
resolved = true;
|
|
28238
|
+
clearTimer();
|
|
28239
|
+
resolveNoGoalTurnStarted();
|
|
28240
|
+
};
|
|
28241
|
+
const scheduleNoTurnTimer = () => {
|
|
28242
|
+
if (released || resolved || !goalUpdated || activeAfterGoalUpdate || timeout !== null) {
|
|
28243
|
+
return;
|
|
28244
|
+
}
|
|
28245
|
+
timeout = setTimeout(resolveNoTurn, runtimeEffectsGraceMs);
|
|
28246
|
+
};
|
|
28247
|
+
const release = () => {
|
|
28248
|
+
if (released) {
|
|
28249
|
+
return;
|
|
28250
|
+
}
|
|
28251
|
+
released = true;
|
|
28252
|
+
clearTimer();
|
|
28253
|
+
};
|
|
28254
|
+
const promise2 = new Promise((resolve) => {
|
|
28255
|
+
resolveNoGoalTurnStarted = () => {
|
|
28256
|
+
resolve(null);
|
|
28257
|
+
};
|
|
28258
|
+
});
|
|
28259
|
+
const handleGoalUpdated = () => {
|
|
28260
|
+
goalUpdated = true;
|
|
28261
|
+
scheduleNoTurnTimer();
|
|
28262
|
+
};
|
|
28263
|
+
const handleThreadStatusChanged = (status) => {
|
|
28264
|
+
if (!goalUpdated || released || resolved) {
|
|
28265
|
+
return;
|
|
28266
|
+
}
|
|
28267
|
+
if (status.type === "active") {
|
|
28268
|
+
activeAfterGoalUpdate = true;
|
|
28269
|
+
clearTimer();
|
|
28270
|
+
return;
|
|
28271
|
+
}
|
|
28272
|
+
if (activeAfterGoalUpdate) {
|
|
28273
|
+
resolveNoTurn();
|
|
28274
|
+
}
|
|
28275
|
+
};
|
|
28276
|
+
return {
|
|
28277
|
+
promise: promise2,
|
|
28278
|
+
release,
|
|
28279
|
+
goalUpdated: handleGoalUpdated,
|
|
28280
|
+
threadStatusChanged: handleThreadStatusChanged
|
|
28281
|
+
};
|
|
28282
|
+
}
|
|
27597
28283
|
async runCompact(params) {
|
|
27598
28284
|
const compactionCompleted = this.awaitCompactionCompleted(params.threadId);
|
|
27599
28285
|
await this.threadCompactStart(params);
|
|
@@ -27634,6 +28320,12 @@ var CodexAppServerClient = class {
|
|
|
27634
28320
|
async threadCompactStart(params) {
|
|
27635
28321
|
return await this.sendRequest({ method: "thread/compact/start", params });
|
|
27636
28322
|
}
|
|
28323
|
+
async threadGoalSet(params) {
|
|
28324
|
+
return await this.sendRequest({ method: "thread/goal/set", params });
|
|
28325
|
+
}
|
|
28326
|
+
async threadGoalClear(params) {
|
|
28327
|
+
return await this.sendRequest({ method: "thread/goal/clear", params });
|
|
28328
|
+
}
|
|
27637
28329
|
async listMcpServerStatus(params) {
|
|
27638
28330
|
return await this.sendRequest({ method: "mcpServerStatus/list", params });
|
|
27639
28331
|
}
|
|
@@ -27765,6 +28457,57 @@ var CodexAppServerClient = class {
|
|
|
27765
28457
|
resolve(event);
|
|
27766
28458
|
}
|
|
27767
28459
|
}
|
|
28460
|
+
recordThreadStatusChanged(event) {
|
|
28461
|
+
const captures = this.threadStatusCaptures.get(event.threadId);
|
|
28462
|
+
if (!captures) {
|
|
28463
|
+
return;
|
|
28464
|
+
}
|
|
28465
|
+
for (const capture of captures) {
|
|
28466
|
+
capture(event.status);
|
|
28467
|
+
}
|
|
28468
|
+
}
|
|
28469
|
+
recordThreadGoalUpdated(event) {
|
|
28470
|
+
const captures = this.threadGoalUpdateCaptures.get(event.threadId);
|
|
28471
|
+
if (!captures) {
|
|
28472
|
+
return;
|
|
28473
|
+
}
|
|
28474
|
+
for (const capture of captures) {
|
|
28475
|
+
capture(event);
|
|
28476
|
+
}
|
|
28477
|
+
}
|
|
28478
|
+
recordThreadGoalCleared(event) {
|
|
28479
|
+
const captures = this.threadGoalClearedCaptures.get(event.threadId);
|
|
28480
|
+
if (!captures) {
|
|
28481
|
+
return;
|
|
28482
|
+
}
|
|
28483
|
+
for (const capture of captures) {
|
|
28484
|
+
capture();
|
|
28485
|
+
}
|
|
28486
|
+
}
|
|
28487
|
+
recordTurnRouting(routing) {
|
|
28488
|
+
if (routing.threadId === null || routing.turnId === null) {
|
|
28489
|
+
return;
|
|
28490
|
+
}
|
|
28491
|
+
const captures = this.turnRoutingCaptures.get(routing.threadId);
|
|
28492
|
+
if (!captures) {
|
|
28493
|
+
return;
|
|
28494
|
+
}
|
|
28495
|
+
for (const capture of captures) {
|
|
28496
|
+
capture(routing.turnId);
|
|
28497
|
+
}
|
|
28498
|
+
}
|
|
28499
|
+
handleStaleTurnNotification(notification, routing) {
|
|
28500
|
+
if (!this.isStaleTurn(routing.threadId, routing.turnId)) {
|
|
28501
|
+
return false;
|
|
28502
|
+
}
|
|
28503
|
+
if (isTurnCompletedNotification(notification) && routing.threadId !== null && routing.turnId !== null) {
|
|
28504
|
+
this.clearStaleTurn(routing.threadId, routing.turnId);
|
|
28505
|
+
}
|
|
28506
|
+
for (const callback of this.codexEventHandlers) {
|
|
28507
|
+
callback({ eventType: "notification", ...notification });
|
|
28508
|
+
}
|
|
28509
|
+
return true;
|
|
28510
|
+
}
|
|
27768
28511
|
isStaleTurn(threadId, turnId) {
|
|
27769
28512
|
if (threadId === null || turnId === null) {
|
|
27770
28513
|
return false;
|
|
@@ -27806,6 +28549,70 @@ var CodexAppServerClient = class {
|
|
|
27806
28549
|
}
|
|
27807
28550
|
};
|
|
27808
28551
|
}
|
|
28552
|
+
captureTurnRoutings(threadId, capture) {
|
|
28553
|
+
const captures = this.turnRoutingCaptures.get(threadId) ?? /* @__PURE__ */ new Set();
|
|
28554
|
+
captures.add(capture);
|
|
28555
|
+
this.turnRoutingCaptures.set(threadId, captures);
|
|
28556
|
+
let released = false;
|
|
28557
|
+
return () => {
|
|
28558
|
+
if (released) {
|
|
28559
|
+
return;
|
|
28560
|
+
}
|
|
28561
|
+
released = true;
|
|
28562
|
+
captures.delete(capture);
|
|
28563
|
+
if (captures.size === 0) {
|
|
28564
|
+
this.turnRoutingCaptures.delete(threadId);
|
|
28565
|
+
}
|
|
28566
|
+
};
|
|
28567
|
+
}
|
|
28568
|
+
captureThreadStatuses(threadId, capture) {
|
|
28569
|
+
const captures = this.threadStatusCaptures.get(threadId) ?? /* @__PURE__ */ new Set();
|
|
28570
|
+
captures.add(capture);
|
|
28571
|
+
this.threadStatusCaptures.set(threadId, captures);
|
|
28572
|
+
let released = false;
|
|
28573
|
+
return () => {
|
|
28574
|
+
if (released) {
|
|
28575
|
+
return;
|
|
28576
|
+
}
|
|
28577
|
+
released = true;
|
|
28578
|
+
captures.delete(capture);
|
|
28579
|
+
if (captures.size === 0) {
|
|
28580
|
+
this.threadStatusCaptures.delete(threadId);
|
|
28581
|
+
}
|
|
28582
|
+
};
|
|
28583
|
+
}
|
|
28584
|
+
captureThreadGoalUpdates(threadId, capture) {
|
|
28585
|
+
const captures = this.threadGoalUpdateCaptures.get(threadId) ?? /* @__PURE__ */ new Set();
|
|
28586
|
+
captures.add(capture);
|
|
28587
|
+
this.threadGoalUpdateCaptures.set(threadId, captures);
|
|
28588
|
+
let released = false;
|
|
28589
|
+
return () => {
|
|
28590
|
+
if (released) {
|
|
28591
|
+
return;
|
|
28592
|
+
}
|
|
28593
|
+
released = true;
|
|
28594
|
+
captures.delete(capture);
|
|
28595
|
+
if (captures.size === 0) {
|
|
28596
|
+
this.threadGoalUpdateCaptures.delete(threadId);
|
|
28597
|
+
}
|
|
28598
|
+
};
|
|
28599
|
+
}
|
|
28600
|
+
captureThreadGoalClears(threadId, capture) {
|
|
28601
|
+
const captures = this.threadGoalClearedCaptures.get(threadId) ?? /* @__PURE__ */ new Set();
|
|
28602
|
+
captures.add(capture);
|
|
28603
|
+
this.threadGoalClearedCaptures.set(threadId, captures);
|
|
28604
|
+
let released = false;
|
|
28605
|
+
return () => {
|
|
28606
|
+
if (released) {
|
|
28607
|
+
return;
|
|
28608
|
+
}
|
|
28609
|
+
released = true;
|
|
28610
|
+
captures.delete(capture);
|
|
28611
|
+
if (captures.size === 0) {
|
|
28612
|
+
this.threadGoalClearedCaptures.delete(threadId);
|
|
28613
|
+
}
|
|
28614
|
+
};
|
|
28615
|
+
}
|
|
27809
28616
|
resolveMcpServerStartupResolvers() {
|
|
27810
28617
|
const pendingResolvers = [];
|
|
27811
28618
|
for (const resolver of this.mcpServerStartupResolvers) {
|
|
@@ -27868,12 +28675,24 @@ function isMcpServerStatusUpdatedNotification(notification) {
|
|
|
27868
28675
|
function isTurnCompletedNotification(notification) {
|
|
27869
28676
|
return notification.method === "turn/completed";
|
|
27870
28677
|
}
|
|
28678
|
+
function isThreadStatusChangedNotification(notification) {
|
|
28679
|
+
return notification.method === "thread/status/changed";
|
|
28680
|
+
}
|
|
28681
|
+
function isThreadGoalUpdatedNotification(notification) {
|
|
28682
|
+
return notification.method === "thread/goal/updated";
|
|
28683
|
+
}
|
|
28684
|
+
function isThreadGoalClearedNotification(notification) {
|
|
28685
|
+
return notification.method === "thread/goal/cleared";
|
|
28686
|
+
}
|
|
27871
28687
|
function isCompactionCompletedNotification(notification) {
|
|
27872
28688
|
if (notification.method === "thread/compacted") {
|
|
27873
28689
|
return true;
|
|
27874
28690
|
}
|
|
27875
28691
|
return notification.method === "item/completed" && notification.params.item.type === "contextCompaction";
|
|
27876
28692
|
}
|
|
28693
|
+
function goalsMatch(left, right) {
|
|
28694
|
+
return left.threadId === right.threadId && left.objective === right.objective && left.status === right.status && left.tokenBudget === right.tokenBudget && left.updatedAt === right.updatedAt;
|
|
28695
|
+
}
|
|
27877
28696
|
function extractThreadId(notification) {
|
|
27878
28697
|
const params = notification.params;
|
|
27879
28698
|
if (params && typeof params.threadId === "string") {
|
|
@@ -28075,7 +28894,7 @@ function startAcpServer() {
|
|
|
28075
28894
|
codexConnection.process.stderr.addListener("data", (data) => {
|
|
28076
28895
|
stderr = (stderr + data.toString()).slice(-maxStderrTailChars);
|
|
28077
28896
|
});
|
|
28078
|
-
process.stdin.on("close", (
|
|
28897
|
+
process.stdin.on("close", () => {
|
|
28079
28898
|
codexConnection.process.stdin.end();
|
|
28080
28899
|
setTimeout(() => {
|
|
28081
28900
|
if (!codexConnection.process.killed) {
|
|
@@ -28105,5 +28924,5 @@ function startAcpServer() {
|
|
|
28105
28924
|
codexAcpServer = null;
|
|
28106
28925
|
}
|
|
28107
28926
|
});
|
|
28108
|
-
}).onRequest(methods.agent.initialize, (ctx) => getAgent().initialize(ctx.params)).onRequest(methods.agent.session.new, (ctx) => getAgent().newSession(ctx.params)).onRequest(methods.agent.session.load, (ctx) => getAgent().loadSession(ctx.params)).onRequest(methods.agent.session.list, (ctx) => getAgent().listSessions(ctx.params)).onRequest(methods.agent.session.delete, (ctx) => getAgent().deleteSession(ctx.params)).onRequest(methods.agent.session.resume, (ctx) => getAgent().resumeSession(ctx.params)).onRequest(methods.agent.session.close, (ctx) => getAgent().closeSession(ctx.params)).onRequest(methods.agent.session.setMode, (ctx) => getAgent().setSessionMode(ctx.params)).onRequest(methods.agent.session.setConfigOption, (ctx) => getAgent().setSessionConfigOption(ctx.params)).onRequest(methods.agent.authenticate, (ctx) => getAgent().authenticate(ctx.params)).onRequest(methods.agent.logout, (ctx) => getAgent().logout(ctx.params)).onRequest(methods.agent.session.prompt, (ctx) => getAgent().prompt(ctx.params)).onNotification(methods.agent.session.cancel, (ctx) => getAgent().cancel(ctx.params)).onRequest("authentication/status", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/status", ctx.params)).onRequest("authentication/logout", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/logout", ctx.params)).onRequest(LEGACY_SET_SESSION_MODEL_METHOD, legacySetSessionModelParamsParser, (ctx) => getAgent().extMethod(LEGACY_SET_SESSION_MODEL_METHOD, ctx.params)).connect(acpJsonStream);
|
|
28927
|
+
}).onRequest(methods.agent.initialize, (ctx) => getAgent().initialize(ctx.params)).onRequest(methods.agent.session.new, (ctx) => getAgent().newSession(ctx.params)).onRequest(methods.agent.session.load, (ctx) => getAgent().loadSession(ctx.params)).onRequest(methods.agent.session.list, (ctx) => getAgent().listSessions(ctx.params)).onRequest(methods.agent.session.delete, (ctx) => getAgent().deleteSession(ctx.params)).onRequest(methods.agent.session.resume, (ctx) => getAgent().resumeSession(ctx.params)).onRequest(methods.agent.session.close, (ctx) => getAgent().closeSession(ctx.params)).onRequest(methods.agent.session.setMode, (ctx) => getAgent().setSessionMode(ctx.params)).onRequest(methods.agent.session.setConfigOption, (ctx) => getAgent().setSessionConfigOption(ctx.params)).onRequest(methods.agent.authenticate, (ctx) => getAgent().authenticate(ctx.params)).onRequest(methods.agent.logout, (ctx) => getAgent().logout(ctx.params)).onRequest(methods.agent.session.prompt, (ctx) => getAgent().prompt(ctx.params, ctx.signal)).onNotification(methods.agent.session.cancel, (ctx) => getAgent().cancel(ctx.params)).onRequest("authentication/status", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/status", ctx.params)).onRequest("authentication/logout", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/logout", ctx.params)).onRequest(LEGACY_SET_SESSION_MODEL_METHOD, legacySetSessionModelParamsParser, (ctx) => getAgent().extMethod(LEGACY_SET_SESSION_MODEL_METHOD, ctx.params)).connect(acpJsonStream);
|
|
28109
28928
|
}
|