@canonmsg/codex-plugin 0.13.2 → 0.13.3
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 +3 -1
- package/dist/adapter.d.ts +2 -0
- package/dist/adapter.js +6 -0
- package/dist/app-server-adapter.js +31 -6
- package/dist/host.js +42 -8
- package/dist/turn-activity.d.ts +21 -0
- package/dist/turn-activity.js +47 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -80,11 +80,13 @@ Worktree mode is project isolation, not an operating-system sandbox. The Codex C
|
|
|
80
80
|
Useful flags:
|
|
81
81
|
|
|
82
82
|
```bash
|
|
83
|
-
canon-codex --cwd /path/to/project --model gpt-5.
|
|
83
|
+
canon-codex --cwd /path/to/project --model gpt-5.5 --full-auto
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
Codex also supports `--add-dir /extra/path` for additional writable directories passed through to `codex exec`. Canon does not yet render those extra directories as workspace choices.
|
|
87
87
|
|
|
88
|
+
`gpt-5.5` requires a recent local Codex CLI. Older CLIs fail early with an upgrade message; upgrade Codex or choose a model supported by your installed CLI.
|
|
89
|
+
|
|
88
90
|
Recent Codex CLI releases no longer accept `--ask-for-approval` with `codex exec`. If you previously launched Canon with `--sandbox workspace-write --ask-for-approval never`, switch to `--full-auto`.
|
|
89
91
|
|
|
90
92
|
Do not start Canon with `--sandbox danger-full-access` as an unlabeled default. Use `--dangerously-bypass-approvals-and-sandbox` only when you intentionally want Canon to advertise the owner-only Bypass policy.
|
package/dist/adapter.d.ts
CHANGED
|
@@ -17,11 +17,13 @@ export type CodexEvent = {
|
|
|
17
17
|
} | {
|
|
18
18
|
type: 'command.started';
|
|
19
19
|
command: string;
|
|
20
|
+
itemId?: string;
|
|
20
21
|
} | {
|
|
21
22
|
type: 'command.completed';
|
|
22
23
|
command: string;
|
|
23
24
|
output: string;
|
|
24
25
|
exitCode: number | null;
|
|
26
|
+
itemId?: string;
|
|
25
27
|
} | {
|
|
26
28
|
type: 'turn.completed';
|
|
27
29
|
usage?: {
|
package/dist/adapter.js
CHANGED
|
@@ -83,6 +83,9 @@ export class CodexConversationAdapter {
|
|
|
83
83
|
onEvent({
|
|
84
84
|
type: 'command.started',
|
|
85
85
|
command: String(event.item.command ?? ''),
|
|
86
|
+
...(typeof event.item.id === 'string' && event.item.id.trim()
|
|
87
|
+
? { itemId: event.item.id.trim() }
|
|
88
|
+
: {}),
|
|
86
89
|
});
|
|
87
90
|
}
|
|
88
91
|
break;
|
|
@@ -99,6 +102,9 @@ export class CodexConversationAdapter {
|
|
|
99
102
|
command: String(event.item.command ?? ''),
|
|
100
103
|
output: String(event.item.aggregated_output ?? ''),
|
|
101
104
|
exitCode: typeof event.item.exit_code === 'number' ? event.item.exit_code : null,
|
|
105
|
+
...(typeof event.item.id === 'string' && event.item.id.trim()
|
|
106
|
+
? { itemId: event.item.id.trim() }
|
|
107
|
+
: {}),
|
|
102
108
|
});
|
|
103
109
|
}
|
|
104
110
|
break;
|
|
@@ -311,10 +311,10 @@ export class CodexAppServerAdapter {
|
|
|
311
311
|
}
|
|
312
312
|
if (method === 'item/agentMessage/delta') {
|
|
313
313
|
const itemId = readString(params, 'itemId') ?? 'agent-message';
|
|
314
|
-
const delta =
|
|
314
|
+
const delta = readRawString(params, 'delta') ?? '';
|
|
315
315
|
const next = `${this.messageTextByItem.get(itemId) ?? ''}${delta}`;
|
|
316
316
|
this.messageTextByItem.set(itemId, next);
|
|
317
|
-
this.currentFinalMessage = next.trim()
|
|
317
|
+
this.currentFinalMessage = next.trim() ? next : this.currentFinalMessage;
|
|
318
318
|
if (next.trim())
|
|
319
319
|
this.currentOnEvent?.({ type: 'message', text: next });
|
|
320
320
|
return;
|
|
@@ -327,9 +327,9 @@ export class CodexAppServerAdapter {
|
|
|
327
327
|
return;
|
|
328
328
|
}
|
|
329
329
|
if (method === 'item/plan/delta') {
|
|
330
|
-
const delta =
|
|
330
|
+
const delta = readRawString(params, 'delta') ?? '';
|
|
331
331
|
this.planText = `${this.planText}${delta}`;
|
|
332
|
-
this.currentFinalMessage = this.planText.trim()
|
|
332
|
+
this.currentFinalMessage = this.planText.trim() ? this.planText : this.currentFinalMessage;
|
|
333
333
|
if (this.planText.trim())
|
|
334
334
|
this.currentOnEvent?.({ type: 'plan.updated', text: this.planText });
|
|
335
335
|
return;
|
|
@@ -337,8 +337,14 @@ export class CodexAppServerAdapter {
|
|
|
337
337
|
if (method === 'item/started') {
|
|
338
338
|
const item = params.item;
|
|
339
339
|
const summary = summarizeItem(item);
|
|
340
|
-
if (summary)
|
|
341
|
-
|
|
340
|
+
if (summary) {
|
|
341
|
+
const itemId = readString(item, 'id');
|
|
342
|
+
this.currentOnEvent?.({
|
|
343
|
+
type: 'command.started',
|
|
344
|
+
command: summary,
|
|
345
|
+
...(itemId ? { itemId } : {}),
|
|
346
|
+
});
|
|
347
|
+
}
|
|
342
348
|
return;
|
|
343
349
|
}
|
|
344
350
|
if (method === 'item/completed') {
|
|
@@ -351,13 +357,28 @@ export class CodexAppServerAdapter {
|
|
|
351
357
|
}
|
|
352
358
|
}
|
|
353
359
|
else if (item?.type === 'commandExecution') {
|
|
360
|
+
const itemId = readString(item, 'id');
|
|
354
361
|
this.currentOnEvent?.({
|
|
355
362
|
type: 'command.completed',
|
|
356
363
|
command: readString(item, 'command') ?? 'Command',
|
|
357
364
|
output: readString(item, 'aggregatedOutput') ?? '',
|
|
358
365
|
exitCode: typeof item.exitCode === 'number' ? item.exitCode : null,
|
|
366
|
+
...(itemId ? { itemId } : {}),
|
|
359
367
|
});
|
|
360
368
|
}
|
|
369
|
+
else {
|
|
370
|
+
const summary = summarizeItem(item);
|
|
371
|
+
if (summary) {
|
|
372
|
+
const itemId = readString(item, 'id');
|
|
373
|
+
this.currentOnEvent?.({
|
|
374
|
+
type: 'command.completed',
|
|
375
|
+
command: summary,
|
|
376
|
+
output: '',
|
|
377
|
+
exitCode: null,
|
|
378
|
+
...(itemId ? { itemId } : {}),
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
}
|
|
361
382
|
return;
|
|
362
383
|
}
|
|
363
384
|
if (method === 'turn/completed') {
|
|
@@ -432,6 +453,10 @@ function readString(record, key) {
|
|
|
432
453
|
const value = record?.[key];
|
|
433
454
|
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
434
455
|
}
|
|
456
|
+
function readRawString(record, key) {
|
|
457
|
+
const value = record?.[key];
|
|
458
|
+
return typeof value === 'string' ? value : undefined;
|
|
459
|
+
}
|
|
435
460
|
function stringifyPreview(value) {
|
|
436
461
|
if (typeof value === 'string')
|
|
437
462
|
return value;
|
package/dist/host.js
CHANGED
|
@@ -5,7 +5,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
5
5
|
import { dirname } from 'node:path';
|
|
6
6
|
import { parseArgs } from 'node:util';
|
|
7
7
|
import { getCodexImagePath, materializeMessageMedia, materializeReplyContextMedia, } from '@canonmsg/agent-sdk';
|
|
8
|
-
import { RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildPlanApprovalRequest, buildCanonHostPrompt, buildConfiguredWorkspaceOptionsWithRoots, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, buildRuntimePresentationPolicy, DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, createConversationMetadataLoader, createRuntimeStatePublisher, createTypingStatusPublisher, 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, parseRuntimeCardV1, prepareConversationEnvironment, loadHostSessionConfig, releaseConversationEnvironment, resolveCanonAgent, rtdbRead, rtdbWrite, sendMessageWithRetry, shouldTriggerAgentTurn, saveRuntimeSessionState, buildBoundedTurnTrail, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, resolveHostWorkspaceCwd, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
8
|
+
import { RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, buildPlanApprovalRequest, buildCanonHostPrompt, buildCanonTurnEnvelopeV1, buildConfiguredWorkspaceOptionsWithRoots, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, buildRuntimePresentationPolicy, DEFAULT_FIRST_PARTY_RUNTIME_PRESENTATION, createConversationMetadataLoader, createRuntimeStatePublisher, createTypingStatusPublisher, 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, parseRuntimeCardV1, prepareConversationEnvironment, loadHostSessionConfig, releaseConversationEnvironment, resolveCanonAgent, rtdbRead, rtdbWrite, CanonApiError, sendMessageWithRetry, sendMessageWithRetryChunked, shouldTriggerAgentTurn, saveRuntimeSessionState, buildBoundedTurnTrail, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, renderCanonTurnEnvelopePrompt, resolveCanonHostPromptMode, resolveHostWorkspaceCwd, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
9
9
|
import { buildInboundContextLines, decideAutoReply, } from './inbound-policy.js';
|
|
10
10
|
import { CodexConversationAdapter, } from './adapter.js';
|
|
11
11
|
import { CodexAppServerAdapter } from './app-server-adapter.js';
|
|
@@ -16,6 +16,7 @@ import { detectCodexCliVersion } from './codex-cli-version.js';
|
|
|
16
16
|
import { buildCodexModelGuardMessage, formatCodexTurnFailure, isRecoverableCodexThreadError, } from './error-format.js';
|
|
17
17
|
import { startCodexStreamInBackground } from './host-lifecycle.js';
|
|
18
18
|
import { runCli } from './cli-entry.js';
|
|
19
|
+
import { beginCommandBlock, claimCommandBlock, createCommandBlockTracker, } from './turn-activity.js';
|
|
19
20
|
const HELP = `canon-codex — run a local Codex agent host for Canon
|
|
20
21
|
|
|
21
22
|
USAGE
|
|
@@ -49,6 +50,7 @@ Keep this terminal open while you want Canon to reach the agent. Closing it,
|
|
|
49
50
|
logging out, rebooting, or sleeping long enough to stop the process takes the
|
|
50
51
|
local agent offline until you revive it. Docs:
|
|
51
52
|
https://canonmail.com/agents/integrations`;
|
|
53
|
+
const HOST_PROMPT_MODE = resolveCanonHostPromptMode(process.env.CANON_HOST_PROMPT_MODE);
|
|
52
54
|
const MAX_SESSIONS = 12;
|
|
53
55
|
const IDLE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
54
56
|
const HEARTBEAT_MS = 30_000;
|
|
@@ -227,6 +229,20 @@ function resolveCodexEffectiveRuntimePolicy(input) {
|
|
|
227
229
|
};
|
|
228
230
|
}
|
|
229
231
|
function buildCanonPrompt(input) {
|
|
232
|
+
if (HOST_PROMPT_MODE === 'envelope') {
|
|
233
|
+
return renderCanonTurnEnvelopePrompt(buildCanonTurnEnvelopeV1({
|
|
234
|
+
content: input.content,
|
|
235
|
+
conversationId: input.conversationId,
|
|
236
|
+
participantContext: input.participantContext,
|
|
237
|
+
behavior: input.behavior,
|
|
238
|
+
selfContexts: input.selfContexts,
|
|
239
|
+
activeSelfContextId: input.activeSelfContextId,
|
|
240
|
+
provenance: input.provenance,
|
|
241
|
+
replyContext: input.replyContext,
|
|
242
|
+
message: input.message,
|
|
243
|
+
hydratedFromPage: input.hydratedFromPage,
|
|
244
|
+
}));
|
|
245
|
+
}
|
|
230
246
|
return buildCanonHostPrompt({
|
|
231
247
|
hostLabel: 'Codex',
|
|
232
248
|
buildInboundContextLines,
|
|
@@ -844,6 +860,7 @@ export async function main() {
|
|
|
844
860
|
closed: false,
|
|
845
861
|
turnLiveText: '',
|
|
846
862
|
turnBlocks: [],
|
|
863
|
+
turnCommandBlocks: createCommandBlockTracker(),
|
|
847
864
|
};
|
|
848
865
|
sessions.set(conversationId, session);
|
|
849
866
|
await Promise.all([
|
|
@@ -1214,7 +1231,7 @@ export async function main() {
|
|
|
1214
1231
|
const userMessage = error instanceof ExecutionEnvironmentError ? error.userMessage : message;
|
|
1215
1232
|
console.error(`[canon-codex] [${input.conversationId.slice(0, 8)}] Failed to create session: ${message}`);
|
|
1216
1233
|
await markQueuedMessageAccepted(input.conversationId, input.message.id, shouldMarkAccepted);
|
|
1217
|
-
await
|
|
1234
|
+
await sendMessageWithRetryChunked(client, input.conversationId, `I couldn't start a coding session for this workspace: ${userMessage}`, {
|
|
1218
1235
|
messageId: `codex-start-failed-${input.message.id}`,
|
|
1219
1236
|
...(activeSelfContextId ? { selfContextId: activeSelfContextId } : {}),
|
|
1220
1237
|
metadata: {
|
|
@@ -1231,7 +1248,11 @@ export async function main() {
|
|
|
1231
1248
|
participantContext,
|
|
1232
1249
|
behavior,
|
|
1233
1250
|
selfContexts,
|
|
1251
|
+
activeSelfContextId,
|
|
1252
|
+
provenance: hydrated.provenance,
|
|
1234
1253
|
replyContext,
|
|
1254
|
+
message: input.message,
|
|
1255
|
+
hydratedFromPage: hydrated.hydratedFromPage,
|
|
1235
1256
|
});
|
|
1236
1257
|
if (session.running && deliveryIntent === 'interrupt') {
|
|
1237
1258
|
enqueuePrompt(session, prompt, deliveryIntent, true, input.message.id, shouldMarkAccepted, imagePaths, mediaAddDirs, planCommand.planMode);
|
|
@@ -1255,6 +1276,7 @@ export async function main() {
|
|
|
1255
1276
|
session.currentTurnId = randomUUID();
|
|
1256
1277
|
session.turnLiveText = '';
|
|
1257
1278
|
session.turnBlocks = [];
|
|
1279
|
+
session.turnCommandBlocks = createCommandBlockTracker();
|
|
1258
1280
|
session.currentTurnOpenedAt = Date.now();
|
|
1259
1281
|
session.currentTurnUpdatedAt = session.currentTurnOpenedAt;
|
|
1260
1282
|
session.lastAcceptedIntent = nextTurn.intent;
|
|
@@ -1318,8 +1340,13 @@ export async function main() {
|
|
|
1318
1340
|
markTurnProgress(session);
|
|
1319
1341
|
writeTurn(session);
|
|
1320
1342
|
startVisibleWorkSignal(session);
|
|
1343
|
+
const blockId = beginCommandBlock(session.turnCommandBlocks, {
|
|
1344
|
+
turnId: session.currentTurnId,
|
|
1345
|
+
command: event.command,
|
|
1346
|
+
itemId: event.itemId,
|
|
1347
|
+
});
|
|
1321
1348
|
upsertTurnBlock(session, {
|
|
1322
|
-
id:
|
|
1349
|
+
id: blockId,
|
|
1323
1350
|
kind: 'tool',
|
|
1324
1351
|
status: 'running',
|
|
1325
1352
|
title: summarizeCommand(event.command),
|
|
@@ -1329,7 +1356,12 @@ export async function main() {
|
|
|
1329
1356
|
return;
|
|
1330
1357
|
}
|
|
1331
1358
|
if (event.type === 'command.completed') {
|
|
1332
|
-
|
|
1359
|
+
const blockId = claimCommandBlock(session.turnCommandBlocks, {
|
|
1360
|
+
turnId: session.currentTurnId,
|
|
1361
|
+
command: event.command,
|
|
1362
|
+
itemId: event.itemId,
|
|
1363
|
+
});
|
|
1364
|
+
completeTurnBlock(session, blockId, 'Command completed');
|
|
1333
1365
|
if (session.turnState === 'tool') {
|
|
1334
1366
|
session.turnState = 'thinking';
|
|
1335
1367
|
markTurnProgress(session);
|
|
@@ -1390,7 +1422,7 @@ export async function main() {
|
|
|
1390
1422
|
clearStoredThread();
|
|
1391
1423
|
}
|
|
1392
1424
|
const turnTrail = buildFinalTurnTrail(session);
|
|
1393
|
-
await
|
|
1425
|
+
await sendMessageWithRetryChunked(client, session.conversationId, result.finalMessage, {
|
|
1394
1426
|
messageId: buildCodexMessageId(session, 'final'),
|
|
1395
1427
|
...(session.activeSelfContextId
|
|
1396
1428
|
? { selfContextId: session.activeSelfContextId }
|
|
@@ -1413,7 +1445,7 @@ export async function main() {
|
|
|
1413
1445
|
console.error(`[canon-codex] [${session.conversationId.slice(0, 8)}] Turn exited ${result.exitCode}: ${result.errorText}`);
|
|
1414
1446
|
}
|
|
1415
1447
|
const turnTrail = buildFinalTurnTrail(session);
|
|
1416
|
-
await
|
|
1448
|
+
await sendMessageWithRetryChunked(client, session.conversationId, userVisibleError, {
|
|
1417
1449
|
messageId: buildCodexMessageId(session, 'error'),
|
|
1418
1450
|
...(session.activeSelfContextId
|
|
1419
1451
|
? { selfContextId: session.activeSelfContextId }
|
|
@@ -1442,10 +1474,12 @@ export async function main() {
|
|
|
1442
1474
|
catch (error) {
|
|
1443
1475
|
const message = error instanceof ExecutionEnvironmentError
|
|
1444
1476
|
? error.userMessage
|
|
1445
|
-
:
|
|
1477
|
+
: error instanceof CanonApiError
|
|
1478
|
+
? `The Codex host completed the turn, but Canon could not deliver the reply: ${error.message}`
|
|
1479
|
+
: `The Codex host failed during the turn: ${error instanceof Error ? error.message : String(error)}`;
|
|
1446
1480
|
session.state.lastError = message;
|
|
1447
1481
|
writeState(session);
|
|
1448
|
-
await
|
|
1482
|
+
await sendMessageWithRetryChunked(client, session.conversationId, message, {
|
|
1449
1483
|
messageId: buildCodexMessageId(session, 'failure'),
|
|
1450
1484
|
...(session.activeSelfContextId
|
|
1451
1485
|
? { selfContextId: session.activeSelfContextId }
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
interface RunningCommandBlock {
|
|
2
|
+
command: string;
|
|
3
|
+
blockId: string;
|
|
4
|
+
itemId?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CommandBlockTracker {
|
|
7
|
+
sequence: number;
|
|
8
|
+
running: RunningCommandBlock[];
|
|
9
|
+
}
|
|
10
|
+
export declare function createCommandBlockTracker(): CommandBlockTracker;
|
|
11
|
+
export declare function beginCommandBlock(tracker: CommandBlockTracker, input: {
|
|
12
|
+
turnId: string | null | undefined;
|
|
13
|
+
command: string;
|
|
14
|
+
itemId?: string;
|
|
15
|
+
}): string;
|
|
16
|
+
export declare function claimCommandBlock(tracker: CommandBlockTracker, input: {
|
|
17
|
+
turnId: string | null | undefined;
|
|
18
|
+
command: string;
|
|
19
|
+
itemId?: string;
|
|
20
|
+
}): string;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function createCommandBlockTracker() {
|
|
2
|
+
return {
|
|
3
|
+
sequence: 0,
|
|
4
|
+
running: [],
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
function normalizeOptionalString(value) {
|
|
8
|
+
const normalized = value?.trim();
|
|
9
|
+
return normalized ? normalized : undefined;
|
|
10
|
+
}
|
|
11
|
+
function nextCommandBlockId(tracker, turnId, itemId) {
|
|
12
|
+
const stableTurnId = turnId ?? 'turn';
|
|
13
|
+
if (itemId)
|
|
14
|
+
return `command:${stableTurnId}:${itemId}`;
|
|
15
|
+
tracker.sequence += 1;
|
|
16
|
+
return `command:${stableTurnId}:${tracker.sequence}`;
|
|
17
|
+
}
|
|
18
|
+
export function beginCommandBlock(tracker, input) {
|
|
19
|
+
const itemId = normalizeOptionalString(input.itemId);
|
|
20
|
+
if (itemId) {
|
|
21
|
+
const existing = tracker.running.find((block) => block.itemId === itemId);
|
|
22
|
+
if (existing)
|
|
23
|
+
return existing.blockId;
|
|
24
|
+
}
|
|
25
|
+
const blockId = nextCommandBlockId(tracker, input.turnId, itemId);
|
|
26
|
+
tracker.running.push({
|
|
27
|
+
command: input.command.trim(),
|
|
28
|
+
blockId,
|
|
29
|
+
...(itemId ? { itemId } : {}),
|
|
30
|
+
});
|
|
31
|
+
return blockId;
|
|
32
|
+
}
|
|
33
|
+
export function claimCommandBlock(tracker, input) {
|
|
34
|
+
const itemId = normalizeOptionalString(input.itemId);
|
|
35
|
+
const command = input.command.trim();
|
|
36
|
+
const matchingIndex = itemId
|
|
37
|
+
? tracker.running.findIndex((block) => block.itemId === itemId)
|
|
38
|
+
: tracker.running.findIndex((block) => !block.itemId && block.command === command);
|
|
39
|
+
const fallbackIndex = matchingIndex >= 0
|
|
40
|
+
? matchingIndex
|
|
41
|
+
: tracker.running.findIndex((block) => !block.itemId);
|
|
42
|
+
if (fallbackIndex >= 0) {
|
|
43
|
+
const [block] = tracker.running.splice(fallbackIndex, 1);
|
|
44
|
+
return block.blockId;
|
|
45
|
+
}
|
|
46
|
+
return nextCommandBlockId(tracker, input.turnId, itemId);
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/codex-plugin",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.3",
|
|
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": "^2.
|
|
33
|
-
"@canonmsg/core": "^1.
|
|
32
|
+
"@canonmsg/agent-sdk": "^2.4.0",
|
|
33
|
+
"@canonmsg/core": "^1.7.0"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=18.0.0"
|