@agentclientprotocol/codex-acp 1.0.1 → 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/dist/index.js +471 -32
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -22544,15 +22544,24 @@ ${event.details}` : "";
|
|
|
22544
22544
|
};
|
|
22545
22545
|
}
|
|
22546
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;
|
|
22547
22552
|
const status = this.formatThreadGoalStatus(event.goal.status);
|
|
22548
|
-
const objective =
|
|
22553
|
+
const objective = goalSnapshot.objective;
|
|
22549
22554
|
const text = objective.includes("\n") ? `Goal updated (${status}):
|
|
22550
22555
|
${objective}` : `Goal updated (${status}): ${objective}`;
|
|
22551
22556
|
return {
|
|
22552
22557
|
sessionUpdate: "agent_message_chunk",
|
|
22553
22558
|
content: {
|
|
22554
22559
|
type: "text",
|
|
22555
|
-
text
|
|
22560
|
+
text: `
|
|
22561
|
+
|
|
22562
|
+
${text}
|
|
22563
|
+
|
|
22564
|
+
`
|
|
22556
22565
|
}
|
|
22557
22566
|
};
|
|
22558
22567
|
}
|
|
@@ -22573,14 +22582,28 @@ ${objective}` : `Goal updated (${status}): ${objective}`;
|
|
|
22573
22582
|
}
|
|
22574
22583
|
}
|
|
22575
22584
|
createThreadGoalClearedEvent(_event) {
|
|
22585
|
+
if (this.sessionState.currentGoal === null) {
|
|
22586
|
+
return null;
|
|
22587
|
+
}
|
|
22588
|
+
this.sessionState.currentGoal = null;
|
|
22576
22589
|
return {
|
|
22577
22590
|
sessionUpdate: "agent_message_chunk",
|
|
22578
22591
|
content: {
|
|
22579
22592
|
type: "text",
|
|
22580
|
-
text: "
|
|
22593
|
+
text: "\n\nGoal cleared.\n\n"
|
|
22581
22594
|
}
|
|
22582
22595
|
};
|
|
22583
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
|
+
}
|
|
22584
22607
|
createReasoningDeltaEvent(event) {
|
|
22585
22608
|
this.seenReasoningDeltaItemIds.add(event.itemId);
|
|
22586
22609
|
return this.createAgentThoughtEvent(event.delta);
|
|
@@ -24259,7 +24282,7 @@ var package_default = {
|
|
|
24259
24282
|
publishConfig: {
|
|
24260
24283
|
access: "public"
|
|
24261
24284
|
},
|
|
24262
|
-
version: "1.0.
|
|
24285
|
+
version: "1.0.2",
|
|
24263
24286
|
description: "",
|
|
24264
24287
|
main: "dist/index.js",
|
|
24265
24288
|
bin: {
|
|
@@ -24318,7 +24341,7 @@ var package_default = {
|
|
|
24318
24341
|
},
|
|
24319
24342
|
dependencies: {
|
|
24320
24343
|
"@agentclientprotocol/sdk": "^1.0.0",
|
|
24321
|
-
"@openai/codex": "^0.142.
|
|
24344
|
+
"@openai/codex": "^0.142.4",
|
|
24322
24345
|
diff: "^8.0.3",
|
|
24323
24346
|
open: "^11.0.0",
|
|
24324
24347
|
"vscode-jsonrpc": "^8.2.1",
|
|
@@ -24573,6 +24596,28 @@ var CodexAcpClient = class {
|
|
|
24573
24596
|
async runCompact(sessionId) {
|
|
24574
24597
|
await this.codexClient.runCompact({ threadId: sessionId });
|
|
24575
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
|
+
}
|
|
24576
24621
|
async awaitMcpServerStartup(serverNames, afterVersion) {
|
|
24577
24622
|
return await this.codexClient.awaitMcpServerStartup(serverNames, afterVersion);
|
|
24578
24623
|
}
|
|
@@ -25088,22 +25133,27 @@ var CodexCommands = class {
|
|
|
25088
25133
|
this.runWithProcessCheck = runWithProcessCheck;
|
|
25089
25134
|
this.onLogout = onLogout;
|
|
25090
25135
|
}
|
|
25091
|
-
async publish(
|
|
25136
|
+
async publish(sessionState) {
|
|
25092
25137
|
try {
|
|
25093
|
-
const skillsResponse = await this.runWithProcessCheck(() => this.codexAcpClient.listSkills());
|
|
25138
|
+
const skillsResponse = await this.runWithProcessCheck(() => this.codexAcpClient.listSkills(this.createSkillsListParams(sessionState)));
|
|
25094
25139
|
const availableCommands = this.buildAvailableCommands(skillsResponse?.data ?? []);
|
|
25095
25140
|
if (availableCommands.length === 0) {
|
|
25096
25141
|
return;
|
|
25097
25142
|
}
|
|
25098
|
-
const session = new ACPSessionConnection(this.connection, sessionId);
|
|
25143
|
+
const session = new ACPSessionConnection(this.connection, sessionState.sessionId);
|
|
25099
25144
|
await session.update({
|
|
25100
25145
|
sessionUpdate: "available_commands_update",
|
|
25101
25146
|
availableCommands
|
|
25102
25147
|
});
|
|
25103
25148
|
} catch (err) {
|
|
25104
|
-
logger.error(`Failed to publish available commands for session ${sessionId}`, err);
|
|
25149
|
+
logger.error(`Failed to publish available commands for session ${sessionState.sessionId}`, err);
|
|
25105
25150
|
}
|
|
25106
25151
|
}
|
|
25152
|
+
createSkillsListParams(sessionState) {
|
|
25153
|
+
return {
|
|
25154
|
+
cwds: [sessionState.cwd, ...sessionState.additionalDirectories]
|
|
25155
|
+
};
|
|
25156
|
+
}
|
|
25107
25157
|
buildAvailableCommands(skillsEntries) {
|
|
25108
25158
|
const commands = /* @__PURE__ */ new Map();
|
|
25109
25159
|
for (const builtin of this.getBuiltinCommands()) {
|
|
@@ -25163,6 +25213,11 @@ var CodexCommands = class {
|
|
|
25163
25213
|
description: "Summarize conversation to avoid hitting the context limit.",
|
|
25164
25214
|
input: null
|
|
25165
25215
|
},
|
|
25216
|
+
{
|
|
25217
|
+
name: "goal",
|
|
25218
|
+
description: "Set, pause, resume, or clear a task goal.",
|
|
25219
|
+
input: { hint: "[<objective>|clear|pause|resume]" }
|
|
25220
|
+
},
|
|
25166
25221
|
{
|
|
25167
25222
|
name: "logout",
|
|
25168
25223
|
description: "Sign out of Codex. This option is available when you are logged in via ChatGPT.",
|
|
@@ -25195,6 +25250,9 @@ var CodexCommands = class {
|
|
|
25195
25250
|
await this.runWithProcessCheck(() => this.codexAcpClient.runCompact(sessionId));
|
|
25196
25251
|
return { handled: true };
|
|
25197
25252
|
}
|
|
25253
|
+
case "goal": {
|
|
25254
|
+
return await this.runGoalCommand(sessionState, command.rest, options);
|
|
25255
|
+
}
|
|
25198
25256
|
case "review": {
|
|
25199
25257
|
const target = this.buildReviewTarget(command.rest);
|
|
25200
25258
|
const turnCompleted = await this.runReviewCommand(sessionState, target, options);
|
|
@@ -25243,7 +25301,7 @@ var CodexCommands = class {
|
|
|
25243
25301
|
return { handled: true };
|
|
25244
25302
|
}
|
|
25245
25303
|
case "skills": {
|
|
25246
|
-
const response = await this.runWithProcessCheck(() => this.codexAcpClient.listSkills());
|
|
25304
|
+
const response = await this.runWithProcessCheck(() => this.codexAcpClient.listSkills(this.createSkillsListParams(sessionState)));
|
|
25247
25305
|
const skills = (response?.data ?? []).flatMap((entry) => entry.skills);
|
|
25248
25306
|
const lines = skills.map((skill) => {
|
|
25249
25307
|
const description = skill.shortDescription ?? skill.description ?? "";
|
|
@@ -25280,18 +25338,74 @@ var CodexCommands = class {
|
|
|
25280
25338
|
}
|
|
25281
25339
|
}
|
|
25282
25340
|
async runReviewCommand(sessionState, target, options) {
|
|
25341
|
+
options.onTurnStartPending?.();
|
|
25283
25342
|
return await this.runWithProcessCheck(() => this.codexAcpClient.runReview(
|
|
25284
25343
|
sessionState.sessionId,
|
|
25285
25344
|
target,
|
|
25286
25345
|
(turnId, threadId) => {
|
|
25287
|
-
|
|
25288
|
-
options.onTurnStarted(turnId, threadId);
|
|
25289
|
-
} else {
|
|
25290
|
-
sessionState.currentTurnId = turnId;
|
|
25291
|
-
}
|
|
25346
|
+
this.handleCommandTurnStarted(sessionState, options, turnId, threadId);
|
|
25292
25347
|
}
|
|
25293
25348
|
));
|
|
25294
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
|
+
}
|
|
25295
25409
|
buildReviewTarget(instructions) {
|
|
25296
25410
|
if (instructions.length === 0) {
|
|
25297
25411
|
return { type: "uncommittedChanges" };
|
|
@@ -26734,7 +26848,7 @@ You have been logged out. Please try again.`);
|
|
|
26734
26848
|
});
|
|
26735
26849
|
this.publishMcpStartupStatusAsync(sessionId);
|
|
26736
26850
|
}
|
|
26737
|
-
this.publishAvailableCommandsAsync(
|
|
26851
|
+
this.publishAvailableCommandsAsync(sessionState);
|
|
26738
26852
|
const sessionModelState = this.createModelState(models, currentModelId);
|
|
26739
26853
|
const sessionModeState = sessionState.agentMode.toSessionModeState();
|
|
26740
26854
|
return [sessionId, sessionModelState, sessionModeState];
|
|
@@ -27042,7 +27156,9 @@ You have been logged out. Please try again.`);
|
|
|
27042
27156
|
createReasoningEffortConfigOption(sessionState.supportedReasoningEfforts, currentModelId.effort)
|
|
27043
27157
|
);
|
|
27044
27158
|
}
|
|
27045
|
-
|
|
27159
|
+
if (sessionState.currentModelSupportsFast) {
|
|
27160
|
+
configOptions.push(createFastModeConfigOption(sessionState.fastModeEnabled));
|
|
27161
|
+
}
|
|
27046
27162
|
return configOptions;
|
|
27047
27163
|
}
|
|
27048
27164
|
createSessionConfigOptionsResponse(sessionState) {
|
|
@@ -27056,8 +27172,8 @@ You have been logged out. Please try again.`);
|
|
|
27056
27172
|
isSessionConfigEnabled() {
|
|
27057
27173
|
return !isJetBrains2026_1Client(this.clientInfo);
|
|
27058
27174
|
}
|
|
27059
|
-
publishAvailableCommandsAsync(
|
|
27060
|
-
void this.availableCommands.publish(
|
|
27175
|
+
publishAvailableCommandsAsync(sessionState) {
|
|
27176
|
+
void this.availableCommands.publish(sessionState);
|
|
27061
27177
|
}
|
|
27062
27178
|
findCurrentModel(models, currentModelId) {
|
|
27063
27179
|
const modelId = ModelId.fromString(currentModelId);
|
|
@@ -27148,7 +27264,7 @@ You have been logged out. Please try again.`);
|
|
|
27148
27264
|
});
|
|
27149
27265
|
this.publishMcpStartupStatusAsync(sessionId);
|
|
27150
27266
|
}
|
|
27151
|
-
await this.availableCommands.publish(
|
|
27267
|
+
await this.availableCommands.publish(sessionState);
|
|
27152
27268
|
const sessionModelState = this.createModelState(models, currentModelId);
|
|
27153
27269
|
const sessionModeState = sessionState.agentMode.toSessionModeState();
|
|
27154
27270
|
return {
|
|
@@ -27563,6 +27679,13 @@ ${item.text}`
|
|
|
27563
27679
|
sessionState.lastTokenUsage = null;
|
|
27564
27680
|
const activePrompt = this.trackActivePrompt(params.sessionId);
|
|
27565
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
|
+
};
|
|
27566
27689
|
const disposePromptRequestCancellation = this.observePromptRequestCancellation(signal, sessionState, activePrompt);
|
|
27567
27690
|
try {
|
|
27568
27691
|
const eventHandler = new CodexEventHandler(this.connection, sessionState);
|
|
@@ -27581,6 +27704,9 @@ ${item.text}`
|
|
|
27581
27704
|
return this.cancelledPromptResponse(sessionState);
|
|
27582
27705
|
}
|
|
27583
27706
|
const commandPromise = this.availableCommands.tryHandleCommand(params.prompt, sessionState, {
|
|
27707
|
+
onTurnStartPending: () => {
|
|
27708
|
+
ensurePendingTurnStart();
|
|
27709
|
+
},
|
|
27584
27710
|
onTurnStarted: (turnId, threadId) => {
|
|
27585
27711
|
const turn = { threadId, turnId };
|
|
27586
27712
|
activePrompt.currentTurn = turn;
|
|
@@ -27589,6 +27715,7 @@ ${item.text}`
|
|
|
27589
27715
|
return;
|
|
27590
27716
|
}
|
|
27591
27717
|
sessionState.currentTurnId = turnId;
|
|
27718
|
+
pendingTurnStart?.resolve(turnId);
|
|
27592
27719
|
}
|
|
27593
27720
|
});
|
|
27594
27721
|
void commandPromise.catch((err) => {
|
|
@@ -27641,8 +27768,7 @@ ${item.text}`
|
|
|
27641
27768
|
sessionState.fastModeEnabled,
|
|
27642
27769
|
sessionState.currentModelSupportsFast
|
|
27643
27770
|
);
|
|
27644
|
-
|
|
27645
|
-
this.pendingTurnStarts.set(params.sessionId, pendingTurnStart);
|
|
27771
|
+
ensurePendingTurnStart();
|
|
27646
27772
|
const sendPromptPromise = this.runWithProcessCheck(
|
|
27647
27773
|
() => this.codexAcpClient.sendPrompt(
|
|
27648
27774
|
params,
|
|
@@ -27699,10 +27825,11 @@ ${item.text}`
|
|
|
27699
27825
|
logger.log("Prompt completed", { sessionId: params.sessionId });
|
|
27700
27826
|
disposePromptRequestCancellation();
|
|
27701
27827
|
sessionState.currentTurnId = null;
|
|
27702
|
-
|
|
27828
|
+
const registeredPendingTurnStart = this.pendingTurnStarts.get(params.sessionId);
|
|
27829
|
+
if (registeredPendingTurnStart !== void 0) {
|
|
27703
27830
|
this.pendingTurnStarts.delete(params.sessionId);
|
|
27831
|
+
registeredPendingTurnStart.resolve(null);
|
|
27704
27832
|
}
|
|
27705
|
-
pendingTurnStart?.resolve(null);
|
|
27706
27833
|
activePrompt.complete();
|
|
27707
27834
|
}
|
|
27708
27835
|
}
|
|
@@ -27834,6 +27961,7 @@ var CommandExecutionApprovalRequest = new import_node2.RequestType("item/command
|
|
|
27834
27961
|
var FileChangeApprovalRequest = new import_node2.RequestType("item/fileChange/requestApproval");
|
|
27835
27962
|
var PermissionsApprovalRequest = new import_node2.RequestType("item/permissions/requestApproval");
|
|
27836
27963
|
var McpServerElicitationRequest = new import_node2.RequestType("mcpServer/elicitation/request");
|
|
27964
|
+
var GOAL_RUNTIME_EFFECTS_GRACE_MS = 1e3;
|
|
27837
27965
|
var CodexAppServerClient = class {
|
|
27838
27966
|
connection;
|
|
27839
27967
|
approvalHandlers = /* @__PURE__ */ new Map();
|
|
@@ -27844,6 +27972,10 @@ var CodexAppServerClient = class {
|
|
|
27844
27972
|
pendingTurnCompletionResolvers = /* @__PURE__ */ new Map();
|
|
27845
27973
|
pendingCompactionCompletionResolvers = /* @__PURE__ */ new Map();
|
|
27846
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();
|
|
27847
27979
|
staleTurnIds = /* @__PURE__ */ new Map();
|
|
27848
27980
|
constructor(connection) {
|
|
27849
27981
|
this.connection = connection;
|
|
@@ -27864,15 +27996,21 @@ var CodexAppServerClient = class {
|
|
|
27864
27996
|
if (isCompactionCompletedNotification(serverNotification)) {
|
|
27865
27997
|
this.recordCompactionCompleted(serverNotification);
|
|
27866
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
|
+
}
|
|
27867
28008
|
const routing = extractTurnRouting(serverNotification);
|
|
27868
|
-
|
|
27869
|
-
|
|
27870
|
-
|
|
27871
|
-
|
|
27872
|
-
|
|
27873
|
-
for (const callback of this.codexEventHandlers) {
|
|
27874
|
-
callback({ eventType: "notification", ...serverNotification });
|
|
27875
|
-
}
|
|
28009
|
+
if (this.handleStaleTurnNotification(serverNotification, routing)) {
|
|
28010
|
+
return;
|
|
28011
|
+
}
|
|
28012
|
+
this.recordTurnRouting(routing);
|
|
28013
|
+
if (this.handleStaleTurnNotification(serverNotification, routing)) {
|
|
27876
28014
|
return;
|
|
27877
28015
|
}
|
|
27878
28016
|
this.notify(serverNotification);
|
|
@@ -27974,6 +28112,174 @@ var CodexAppServerClient = class {
|
|
|
27974
28112
|
releaseCapture();
|
|
27975
28113
|
}
|
|
27976
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
|
+
}
|
|
27977
28283
|
async runCompact(params) {
|
|
27978
28284
|
const compactionCompleted = this.awaitCompactionCompleted(params.threadId);
|
|
27979
28285
|
await this.threadCompactStart(params);
|
|
@@ -28014,6 +28320,12 @@ var CodexAppServerClient = class {
|
|
|
28014
28320
|
async threadCompactStart(params) {
|
|
28015
28321
|
return await this.sendRequest({ method: "thread/compact/start", params });
|
|
28016
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
|
+
}
|
|
28017
28329
|
async listMcpServerStatus(params) {
|
|
28018
28330
|
return await this.sendRequest({ method: "mcpServerStatus/list", params });
|
|
28019
28331
|
}
|
|
@@ -28145,6 +28457,57 @@ var CodexAppServerClient = class {
|
|
|
28145
28457
|
resolve(event);
|
|
28146
28458
|
}
|
|
28147
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
|
+
}
|
|
28148
28511
|
isStaleTurn(threadId, turnId) {
|
|
28149
28512
|
if (threadId === null || turnId === null) {
|
|
28150
28513
|
return false;
|
|
@@ -28186,6 +28549,70 @@ var CodexAppServerClient = class {
|
|
|
28186
28549
|
}
|
|
28187
28550
|
};
|
|
28188
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
|
+
}
|
|
28189
28616
|
resolveMcpServerStartupResolvers() {
|
|
28190
28617
|
const pendingResolvers = [];
|
|
28191
28618
|
for (const resolver of this.mcpServerStartupResolvers) {
|
|
@@ -28248,12 +28675,24 @@ function isMcpServerStatusUpdatedNotification(notification) {
|
|
|
28248
28675
|
function isTurnCompletedNotification(notification) {
|
|
28249
28676
|
return notification.method === "turn/completed";
|
|
28250
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
|
+
}
|
|
28251
28687
|
function isCompactionCompletedNotification(notification) {
|
|
28252
28688
|
if (notification.method === "thread/compacted") {
|
|
28253
28689
|
return true;
|
|
28254
28690
|
}
|
|
28255
28691
|
return notification.method === "item/completed" && notification.params.item.type === "contextCompaction";
|
|
28256
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
|
+
}
|
|
28257
28696
|
function extractThreadId(notification) {
|
|
28258
28697
|
const params = notification.params;
|
|
28259
28698
|
if (params && typeof params.threadId === "string") {
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.2",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"bin": {
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@agentclientprotocol/sdk": "^1.0.0",
|
|
65
|
-
"@openai/codex": "^0.142.
|
|
65
|
+
"@openai/codex": "^0.142.4",
|
|
66
66
|
"diff": "^8.0.3",
|
|
67
67
|
"open": "^11.0.0",
|
|
68
68
|
"vscode-jsonrpc": "^8.2.1",
|