@canonmsg/codex-plugin 0.22.1 → 0.22.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/host.js +52 -7
- package/package.json +2 -2
package/dist/host.js
CHANGED
|
@@ -76,6 +76,7 @@ const MAX_SESSIONS = 12;
|
|
|
76
76
|
const IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
77
77
|
const HEARTBEAT_MS = 30_000;
|
|
78
78
|
const IDLE_CHECK_MS = 60_000;
|
|
79
|
+
const PLAN_REVIEW_TIMEOUT_MS = 10 * 60_000;
|
|
79
80
|
const CODEX_RUNTIME_CAPABILITIES = {
|
|
80
81
|
...DEFAULT_RUNTIME_CAPABILITIES,
|
|
81
82
|
supportsInterrupt: true,
|
|
@@ -1123,6 +1124,19 @@ export async function main() {
|
|
|
1123
1124
|
writeTurn(session);
|
|
1124
1125
|
void runNextTurn(session);
|
|
1125
1126
|
}
|
|
1127
|
+
function enqueueCodexPlanReviewResult(session, result, responseUserId) {
|
|
1128
|
+
if (result.status === 'cancelled' || result.status === 'timeout') {
|
|
1129
|
+
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Plan review ${result.status}`);
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
const feedback = result.feedback?.trim();
|
|
1133
|
+
const prompt = result.status === 'approve'
|
|
1134
|
+
? 'The plan was approved. Implement the approved plan now.'
|
|
1135
|
+
: result.status === 'reject'
|
|
1136
|
+
? `The plan was declined — keep planning and wait for guidance before implementing.${feedback ? `\n\nNotes:\n${feedback}` : ''}`
|
|
1137
|
+
: `Please revise the plan.${feedback ? `\n\nRevision feedback:\n${feedback}` : ''}`;
|
|
1138
|
+
enqueuePrompt(session, prompt, 'queue', false, result.receiptId ?? null, false, [], [], result.status !== 'approve', 'disabled', false, responseUserId);
|
|
1139
|
+
}
|
|
1126
1140
|
function resolveArtifactRoutingMode(participantContext) {
|
|
1127
1141
|
return participantContext.conversationType === 'direct' && participantContext.isOwner
|
|
1128
1142
|
? 'workspace-generated'
|
|
@@ -1331,6 +1345,14 @@ export async function main() {
|
|
|
1331
1345
|
if (isRecord(input.message.metadata)
|
|
1332
1346
|
&& input.message.metadata.type === 'plan_approval_reply'
|
|
1333
1347
|
&& typeof input.message.metadata.decision === 'string') {
|
|
1348
|
+
const planId = readString(input.message.metadata, 'planId');
|
|
1349
|
+
if (planId && runtimeRequests.handleMessage(input.conversationId, {
|
|
1350
|
+
senderId: input.message.senderId,
|
|
1351
|
+
metadata: input.message.metadata,
|
|
1352
|
+
})) {
|
|
1353
|
+
persistInboundRecoveryCursorWhenIdle(input.conversationId, input.message.id);
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1334
1356
|
const session = await getOrCreateSession(input.conversationId);
|
|
1335
1357
|
const feedback = readString(input.message.metadata, 'feedback');
|
|
1336
1358
|
const decision = input.message.metadata.decision;
|
|
@@ -1666,20 +1688,43 @@ export async function main() {
|
|
|
1666
1688
|
requestingUserId: nextTurn.requestingUserId,
|
|
1667
1689
|
ownerId,
|
|
1668
1690
|
});
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1691
|
+
const planId = session.currentTurnId ?? randomUUID();
|
|
1692
|
+
let planCreated = false;
|
|
1693
|
+
let resolvePlanCreated;
|
|
1694
|
+
let rejectPlanCreated;
|
|
1695
|
+
const planCreatedPromise = new Promise((resolve, reject) => {
|
|
1696
|
+
resolvePlanCreated = resolve;
|
|
1697
|
+
rejectPlanCreated = reject;
|
|
1698
|
+
});
|
|
1699
|
+
const planReview = runtimeRequests.request('plan', session.conversationId, {
|
|
1676
1700
|
title: 'Codex Plan',
|
|
1677
1701
|
body: result.finalMessage,
|
|
1678
1702
|
...(responseRouting.responseUserId
|
|
1679
1703
|
? { responseUserId: responseRouting.responseUserId }
|
|
1680
1704
|
: {}),
|
|
1681
1705
|
...(session.currentTurnId ? { turnId: session.currentTurnId } : {}),
|
|
1706
|
+
}, {
|
|
1707
|
+
requestId: planId,
|
|
1708
|
+
expiresAt: Date.now() + PLAN_REVIEW_TIMEOUT_MS,
|
|
1709
|
+
responderPolicy: 'infer',
|
|
1710
|
+
onCreated: () => {
|
|
1711
|
+
planCreated = true;
|
|
1712
|
+
session.turnState = 'waiting_input';
|
|
1713
|
+
writeTurn(session);
|
|
1714
|
+
resolvePlanCreated();
|
|
1715
|
+
},
|
|
1716
|
+
});
|
|
1717
|
+
void planReview.then((planResult) => {
|
|
1718
|
+
resolvePlanCreated();
|
|
1719
|
+
enqueueCodexPlanReviewResult(session, planResult, responseRouting.responseUserId ?? null);
|
|
1720
|
+
}).catch((error) => {
|
|
1721
|
+
if (!planCreated) {
|
|
1722
|
+
rejectPlanCreated(error);
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Plan review failed:`, error instanceof Error ? error.message : error);
|
|
1682
1726
|
});
|
|
1727
|
+
await planCreatedPromise;
|
|
1683
1728
|
await handoffFinalMessage(session.conversationId);
|
|
1684
1729
|
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Sent plan approval card`);
|
|
1685
1730
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/codex-plugin",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.2",
|
|
4
4
|
"description": "Canon host integration for Codex CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@canonmsg/agent-sdk": "^5.1.1",
|
|
33
33
|
"@canonmsg/coding-agent-host": "^0.2.2",
|
|
34
|
-
"@canonmsg/core": "^4.2.
|
|
34
|
+
"@canonmsg/core": "^4.2.3"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=18.0.0"
|