@canonmsg/codex-plugin 0.9.8 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/host.js +43 -23
- package/dist/session-store.js +15 -0
- package/package.json +3 -3
package/dist/host.js
CHANGED
|
@@ -4,7 +4,7 @@ import { randomUUID } from 'node:crypto';
|
|
|
4
4
|
import { dirname } from 'node:path';
|
|
5
5
|
import { parseArgs } from 'node:util';
|
|
6
6
|
import { getCodexImagePath, materializeMessageMedia, } from '@canonmsg/agent-sdk';
|
|
7
|
-
import { buildCanonHostPrompt, buildConfiguredWorkspaceOptionsWithRoots, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, createConversationMetadataLoader, createRuntimeStatePublisher, EXECUTION_ENVIRONMENT_MODES, ExecutionEnvironmentError, CanonClient, CanonStream, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, getActiveProfileLock, initRTDBAuth, buildLocalRuntimeId, heartbeatLocalRuntimeEntry, loadRuntimeSessionState, markLocalRuntimeStopped, normalizeTurnMetadata, normalizeTurnState, prepareConversationEnvironment, loadHostSessionConfig, releaseConversationEnvironment, resolveCanonAgent, rtdbRead, rtdbWrite, shouldTriggerAgentTurn, saveRuntimeSessionState, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, resolveHostWorkspaceCwd, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
7
|
+
import { RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildCanonHostPrompt, buildConfiguredWorkspaceOptionsWithRoots, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, createConversationMetadataLoader, createRuntimeStatePublisher, EXECUTION_ENVIRONMENT_MODES, ExecutionEnvironmentError, CanonClient, CanonStream, DEFAULT_PARTICIPATION_HISTORY_FETCH_LIMIT, DEFAULT_RUNTIME_CAPABILITIES, FINAL_MESSAGE_HANDOFF_MS, getActiveProfileLock, initRTDBAuth, buildLocalRuntimeId, heartbeatLocalRuntimeEntry, loadRuntimeSessionState, markLocalRuntimeStopped, normalizeTurnMetadata, normalizeTurnState, prepareConversationEnvironment, loadHostSessionConfig, releaseConversationEnvironment, resolveCanonAgent, rtdbRead, rtdbWrite, shouldTriggerAgentTurn, saveRuntimeSessionState, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, resolveHostWorkspaceCwd, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
8
8
|
import { buildInboundContextLines, decideAutoReply, } from './inbound-policy.js';
|
|
9
9
|
import { CodexConversationAdapter, } from './adapter.js';
|
|
10
10
|
import { clearStoredThreadId, buildCodexThreadPolicyFingerprint, loadStoredThreadId, saveStoredThreadId, } from './session-store.js';
|
|
@@ -65,26 +65,9 @@ function buildCodexRuntimeDescriptor(input) {
|
|
|
65
65
|
defaultPermissionMode: input.defaultPermissionMode,
|
|
66
66
|
streamingTextMode: 'snapshot',
|
|
67
67
|
actions: [
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
description: 'Interrupt the current Codex exec turn.',
|
|
72
|
-
aliases: ['stop'],
|
|
73
|
-
category: 'turn',
|
|
74
|
-
placements: ['composer_slash', 'command_palette'],
|
|
75
|
-
availability: ['busy'],
|
|
76
|
-
dispatch: { kind: 'signal', signal: 'interrupt' },
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
id: 'stop-and-clear-queue',
|
|
80
|
-
label: 'Stop & clear queue',
|
|
81
|
-
description: 'Interrupt the current Codex exec turn and drop queued Canon messages.',
|
|
82
|
-
aliases: ['stop-clear', 'clear-queue'],
|
|
83
|
-
category: 'turn',
|
|
84
|
-
placements: ['composer_slash', 'command_palette', 'session_strip'],
|
|
85
|
-
availability: ['busy_with_queue'],
|
|
86
|
-
dispatch: { kind: 'signal', signal: 'stop_and_drop' },
|
|
87
|
-
},
|
|
68
|
+
RUNTIME_STOP_ACTION,
|
|
69
|
+
RUNTIME_STOP_AND_DROP_ACTION,
|
|
70
|
+
RUNTIME_NEW_SESSION_ACTION,
|
|
88
71
|
],
|
|
89
72
|
});
|
|
90
73
|
if (input.models.length > 0) {
|
|
@@ -452,6 +435,32 @@ export async function main() {
|
|
|
452
435
|
client.setTyping(conversationId, false).catch(() => { });
|
|
453
436
|
sessions.delete(conversationId);
|
|
454
437
|
}
|
|
438
|
+
async function resetRuntimeSession(session) {
|
|
439
|
+
const conversationId = session.conversationId;
|
|
440
|
+
session.resetRequested = true;
|
|
441
|
+
const droppedPrompts = session.queue.splice(0);
|
|
442
|
+
await markQueuedPromptsRejected(conversationId, droppedPrompts);
|
|
443
|
+
clearStoredThreadId(runtimeId, agentId, conversationId, session.environment.baseCwd, session.environment.mode);
|
|
444
|
+
session.adapter.clearThreadId();
|
|
445
|
+
session.activeSelfContextId = null;
|
|
446
|
+
session.state.lastError = undefined;
|
|
447
|
+
if (session.running) {
|
|
448
|
+
await session.adapter.interrupt();
|
|
449
|
+
session.turnState = 'interrupted';
|
|
450
|
+
}
|
|
451
|
+
else {
|
|
452
|
+
session.turnState = 'idle';
|
|
453
|
+
session.currentTurnId = null;
|
|
454
|
+
session.currentTurnOpenedAt = null;
|
|
455
|
+
session.lastAcceptedIntent = null;
|
|
456
|
+
session.resetRequested = false;
|
|
457
|
+
}
|
|
458
|
+
stopVisibleWorkSignal(session);
|
|
459
|
+
clearStreaming(conversationId);
|
|
460
|
+
client.setTyping(conversationId, false).catch(() => { });
|
|
461
|
+
writeState(session);
|
|
462
|
+
writeTurn(session);
|
|
463
|
+
}
|
|
455
464
|
function evictOldestIdle() {
|
|
456
465
|
let oldest = null;
|
|
457
466
|
for (const session of sessions.values()) {
|
|
@@ -531,6 +540,7 @@ export async function main() {
|
|
|
531
540
|
currentTurnOpenedAt: null,
|
|
532
541
|
activeSelfContextId: null,
|
|
533
542
|
lastAcceptedIntent: null,
|
|
543
|
+
resetRequested: false,
|
|
534
544
|
lastActivity: Date.now(),
|
|
535
545
|
typingKeepaliveTimer: null,
|
|
536
546
|
closed: false,
|
|
@@ -680,6 +690,9 @@ export async function main() {
|
|
|
680
690
|
const handleCodexEvent = (event) => {
|
|
681
691
|
session.lastActivity = Date.now();
|
|
682
692
|
if (event.type === 'thread.started') {
|
|
693
|
+
if (session.resetRequested) {
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
683
696
|
saveStoredThreadId(runtimeId, agentId, session.conversationId, session.environment.baseCwd, event.threadId, session.environment.mode, session.policyFingerprint);
|
|
684
697
|
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Thread ${event.threadId}`);
|
|
685
698
|
return;
|
|
@@ -727,7 +740,7 @@ export async function main() {
|
|
|
727
740
|
clearStoredThread();
|
|
728
741
|
result = await runTurnOnce();
|
|
729
742
|
}
|
|
730
|
-
if (result.threadId) {
|
|
743
|
+
if (result.threadId && !session.resetRequested) {
|
|
731
744
|
saveStoredThreadId(runtimeId, agentId, session.conversationId, session.environment.baseCwd, result.threadId, session.environment.mode, session.policyFingerprint);
|
|
732
745
|
}
|
|
733
746
|
if (!result.interrupted && result.finalMessage) {
|
|
@@ -811,6 +824,7 @@ export async function main() {
|
|
|
811
824
|
session.currentTurnId = null;
|
|
812
825
|
session.currentTurnOpenedAt = null;
|
|
813
826
|
session.lastAcceptedIntent = null;
|
|
827
|
+
session.resetRequested = false;
|
|
814
828
|
session.lastActivity = Date.now();
|
|
815
829
|
writeState(session);
|
|
816
830
|
writeTurn(session);
|
|
@@ -1153,7 +1167,7 @@ export async function main() {
|
|
|
1153
1167
|
continue;
|
|
1154
1168
|
const signal = raw;
|
|
1155
1169
|
const timestamp = signal.updatedAt ?? 0;
|
|
1156
|
-
if ((signal.type !== 'interrupt' && signal.type !== 'stop_and_drop')
|
|
1170
|
+
if ((signal.type !== 'interrupt' && signal.type !== 'stop_and_drop' && signal.type !== 'new_session')
|
|
1157
1171
|
|| timestamp <= (lastSeenSignal.get(conversationId) ?? 0)) {
|
|
1158
1172
|
continue;
|
|
1159
1173
|
}
|
|
@@ -1161,6 +1175,12 @@ export async function main() {
|
|
|
1161
1175
|
const session = sessions.get(conversationId);
|
|
1162
1176
|
if (!session || session.closed)
|
|
1163
1177
|
continue;
|
|
1178
|
+
if (signal.type === 'new_session') {
|
|
1179
|
+
console.error(`[canon-codex] [${conversationId.slice(0, 8)}] new_session signal`);
|
|
1180
|
+
await resetRuntimeSession(session);
|
|
1181
|
+
await rtdbWrite(`/control/${conversationId}/${agentId}/signal`, null).catch(() => { });
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1164
1184
|
if (!session.running && (signal.type !== 'stop_and_drop' || session.queue.length === 0)) {
|
|
1165
1185
|
await rtdbWrite(`/control/${conversationId}/${agentId}/signal`, null).catch(() => { });
|
|
1166
1186
|
continue;
|
package/dist/session-store.js
CHANGED
|
@@ -84,11 +84,26 @@ export function saveStoredThreadId(runtimeId, agentId, conversationId, baseCwd,
|
|
|
84
84
|
}
|
|
85
85
|
export function clearStoredThreadId(runtimeId, agentId, conversationId, baseCwd, executionMode) {
|
|
86
86
|
if (runtimeId) {
|
|
87
|
+
const existing = baseCwd
|
|
88
|
+
? loadRuntimeSessionState(runtimeId, {
|
|
89
|
+
conversationId,
|
|
90
|
+
baseCwd,
|
|
91
|
+
executionMode,
|
|
92
|
+
})
|
|
93
|
+
: null;
|
|
87
94
|
clearRuntimeSessionState(runtimeId, {
|
|
88
95
|
conversationId,
|
|
89
96
|
baseCwd,
|
|
90
97
|
executionMode,
|
|
91
98
|
});
|
|
99
|
+
if (existing?.lastInboundMessageId && baseCwd) {
|
|
100
|
+
saveRuntimeSessionState(runtimeId, {
|
|
101
|
+
conversationId,
|
|
102
|
+
baseCwd,
|
|
103
|
+
...(executionMode ? { executionMode } : {}),
|
|
104
|
+
lastInboundMessageId: existing.lastInboundMessageId,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
92
107
|
return;
|
|
93
108
|
}
|
|
94
109
|
const store = loadStore();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/codex-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Canon host integration for Codex CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"prepack": "npm run build"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@canonmsg/agent-sdk": "^1.
|
|
33
|
-
"@canonmsg/core": "^0.
|
|
32
|
+
"@canonmsg/agent-sdk": "^1.2.0",
|
|
33
|
+
"@canonmsg/core": "^0.16.0"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=18.0.0"
|