@canonmsg/codex-plugin 0.18.5 → 0.18.6

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/adapter.d.ts CHANGED
@@ -8,6 +8,7 @@ export type CodexEvent = {
8
8
  } | {
9
9
  type: 'message';
10
10
  text: string;
11
+ itemId?: string;
11
12
  } | {
12
13
  type: 'plan.updated';
13
14
  text: string;
package/dist/adapter.js CHANGED
@@ -99,7 +99,13 @@ export class CodexConversationAdapter {
99
99
  if (event.item?.type === 'agent_message') {
100
100
  latestMessage = normalizeMessageText(event.item.text);
101
101
  if (latestMessage) {
102
- onEvent({ type: 'message', text: latestMessage });
102
+ onEvent({
103
+ type: 'message',
104
+ text: latestMessage,
105
+ ...(typeof event.item.id === 'string' && event.item.id.trim()
106
+ ? { itemId: event.item.id.trim() }
107
+ : {}),
108
+ });
103
109
  }
104
110
  }
105
111
  else if (event.item?.type === 'command_execution') {
@@ -338,7 +338,7 @@ export class CodexAppServerAdapter {
338
338
  this.messageTextByItem.set(itemId, next);
339
339
  this.currentFinalMessage = next.trim() ? next : this.currentFinalMessage;
340
340
  if (next.trim())
341
- this.currentOnEvent?.({ type: 'message', text: next });
341
+ this.currentOnEvent?.({ type: 'message', text: next, itemId });
342
342
  return;
343
343
  }
344
344
  if (method === 'turn/plan/updated') {
@@ -372,10 +372,15 @@ export class CodexAppServerAdapter {
372
372
  if (method === 'item/completed') {
373
373
  const item = params.item;
374
374
  if (item?.type === 'agentMessage') {
375
+ const itemId = readString(item, 'id');
375
376
  const text = readString(item, 'text');
376
377
  if (text) {
377
378
  this.currentFinalMessage = text;
378
- this.currentOnEvent?.({ type: 'message', text });
379
+ this.currentOnEvent?.({
380
+ type: 'message',
381
+ text,
382
+ ...(itemId ? { itemId } : {}),
383
+ });
379
384
  }
380
385
  }
381
386
  else if (item?.type === 'commandExecution') {
package/dist/host.js CHANGED
@@ -19,7 +19,7 @@ import { startCodexStreamInBackground } from './host-lifecycle.js';
19
19
  import { createCodexControlPoller } from './control-channel.js';
20
20
  import { runCli } from './cli-entry.js';
21
21
  import { collectMissedInboundMessages, STARTUP_RECOVERY_MAX_MESSAGES, STARTUP_RECOVERY_PAGE_SIZE, } from './startup-recovery.js';
22
- import { beginCommandBlock, claimCommandBlock, createCommandBlockTracker, } from './turn-activity.js';
22
+ import { applyTextSegmentBlock, beginCommandBlock, claimCommandBlock, createCommandBlockTracker, } from './turn-activity.js';
23
23
  const HELP = `canon-codex — run a local Codex agent host for Canon
24
24
 
25
25
  USAGE
@@ -675,6 +675,18 @@ export async function main() {
675
675
  blocks: session.turnBlocks,
676
676
  }).catch(() => { });
677
677
  }
678
+ function upsertCodexTextSegment(session, event) {
679
+ const next = applyTextSegmentBlock({
680
+ turnLiveText: session.turnLiveText,
681
+ turnBlocks: session.turnBlocks,
682
+ }, {
683
+ turnId: session.currentTurnId,
684
+ itemId: event.itemId,
685
+ text: event.text,
686
+ });
687
+ session.turnLiveText = next.turnLiveText;
688
+ session.turnBlocks = next.turnBlocks;
689
+ }
678
690
  function upsertTurnBlock(session, block) {
679
691
  const now = Date.now();
680
692
  const index = session.turnBlocks.findIndex((existing) => existing.id === block.id);
@@ -1430,7 +1442,8 @@ export async function main() {
1430
1442
  markTurnProgress(session);
1431
1443
  writeTurn(session);
1432
1444
  stopVisibleWorkSignal(session);
1433
- writeCodexStreaming(session, event.text, 'streaming');
1445
+ upsertCodexTextSegment(session, event);
1446
+ writeCodexStreaming(session, null, 'streaming');
1434
1447
  return;
1435
1448
  }
1436
1449
  if (event.type === 'plan.updated') {
@@ -1,3 +1,4 @@
1
+ import type { TurnOutputBlock } from '@canonmsg/core';
1
2
  interface RunningCommandBlock {
2
3
  command: string;
3
4
  blockId: string;
@@ -7,7 +8,17 @@ export interface CommandBlockTracker {
7
8
  sequence: number;
8
9
  running: RunningCommandBlock[];
9
10
  }
11
+ export interface TextSegmentBlockState {
12
+ turnLiveText: string;
13
+ turnBlocks: TurnOutputBlock[];
14
+ }
10
15
  export declare function createCommandBlockTracker(): CommandBlockTracker;
16
+ export declare function applyTextSegmentBlock(state: TextSegmentBlockState, input: {
17
+ turnId: string | null | undefined;
18
+ itemId?: string;
19
+ text: string;
20
+ now?: number;
21
+ }): TextSegmentBlockState;
11
22
  export declare function beginCommandBlock(tracker: CommandBlockTracker, input: {
12
23
  turnId: string | null | undefined;
13
24
  command: string;
@@ -8,6 +8,49 @@ function normalizeOptionalString(value) {
8
8
  const normalized = value?.trim();
9
9
  return normalized ? normalized : undefined;
10
10
  }
11
+ function textBlockId(turnId, itemId) {
12
+ return `message:${turnId ?? 'turn'}:${normalizeOptionalString(itemId) ?? 'latest'}`;
13
+ }
14
+ function buildLiveText(blocks) {
15
+ return blocks
16
+ .filter((block) => block.kind === 'text' && block.text?.trim())
17
+ .sort((left, right) => {
18
+ if (left.sequence !== right.sequence)
19
+ return left.sequence - right.sequence;
20
+ return left.id.localeCompare(right.id);
21
+ })
22
+ .map((block) => block.text)
23
+ .join('\n\n');
24
+ }
25
+ export function applyTextSegmentBlock(state, input) {
26
+ const id = textBlockId(input.turnId, input.itemId);
27
+ const now = input.now ?? Date.now();
28
+ const index = state.turnBlocks.findIndex((block) => block.id === id);
29
+ const existing = index >= 0 ? state.turnBlocks[index] : null;
30
+ const next = {
31
+ ...(existing ?? {
32
+ sequence: state.turnBlocks.length + 1,
33
+ createdAt: now,
34
+ }),
35
+ id,
36
+ turnId: input.turnId ?? id,
37
+ kind: 'text',
38
+ status: existing?.status ?? 'running',
39
+ text: input.text,
40
+ updatedAt: now,
41
+ };
42
+ const turnBlocks = index >= 0
43
+ ? [
44
+ ...state.turnBlocks.slice(0, index),
45
+ next,
46
+ ...state.turnBlocks.slice(index + 1),
47
+ ]
48
+ : [...state.turnBlocks, next];
49
+ return {
50
+ turnBlocks,
51
+ turnLiveText: buildLiveText(turnBlocks) || state.turnLiveText,
52
+ };
53
+ }
11
54
  function nextCommandBlockId(tracker, turnId, itemId) {
12
55
  const stableTurnId = turnId ?? 'turn';
13
56
  if (itemId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/codex-plugin",
3
- "version": "0.18.5",
3
+ "version": "0.18.6",
4
4
  "description": "Canon host integration for Codex CLI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,9 +29,9 @@
29
29
  "prepack": "npm run build"
30
30
  },
31
31
  "dependencies": {
32
- "@canonmsg/agent-sdk": "^3.2.3",
32
+ "@canonmsg/agent-sdk": "^3.3.1",
33
33
  "@canonmsg/coding-agent-host": "^0.2.2",
34
- "@canonmsg/core": "^2.8.0"
34
+ "@canonmsg/core": "^2.8.1"
35
35
  },
36
36
  "engines": {
37
37
  "node": ">=18.0.0"