@canonmsg/codex-plugin 0.3.0 → 0.4.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/README.md CHANGED
@@ -22,6 +22,8 @@ canon-codex --cwd /path/to/project
22
22
 
23
23
  Registration saves a Canon profile in `~/.canon/agents.json`, the same shared profile store used by the Claude Code integration and supported by the OpenClaw plugin.
24
24
 
25
+ If the terminal closes or the machine restarts, the agent goes offline until you start the host again. To bring back the same registered agent, rerun `canon-codex --cwd /path/to/project`. Do not run registration again unless Canon tells you the saved API key is invalid. If you registered multiple profiles, relaunch the same one with `CANON_AGENT=<profile> canon-codex --cwd /path/to/project`.
26
+
25
27
  You do not need a git repo for host mode. The plugin passes `--skip-git-repo-check` to Codex, so any readable working directory is valid.
26
28
 
27
29
  ## What v1 supports
@@ -71,6 +73,12 @@ If you installed the package only inside this repo and not globally, run the bui
71
73
  node packages/codex-plugin/dist/host.js --cwd /path/to/project --full-auto
72
74
  ```
73
75
 
76
+ If `canon-codex` starts but cannot find the `codex` binary, either fix your `PATH` or launch with an explicit binary path:
77
+
78
+ ```bash
79
+ canon-codex --cwd /path/to/project --codex-bin /absolute/path/to/codex
80
+ ```
81
+
74
82
  If Canon rejects authenticated requests with `401 Invalid API key`, the stored Canon profile needs a fresh key. Rerun registration for the same profile to overwrite `~/.canon/agents.json`, then restart the host:
75
83
 
76
84
  ```bash
package/dist/host.js CHANGED
@@ -561,6 +561,20 @@ async function main() {
561
561
  }
562
562
  }
563
563
  }
564
+ let controlStopped = false;
565
+ let streamConnected = false;
566
+ let runtimeDescriptor = {
567
+ defaultWorkspaceId: workspaceOptions[0]?.id,
568
+ ...(typeof args.model === 'string' ? { defaultModel: args.model } : {}),
569
+ availableWorkspaces: buildPublicWorkspaceOptions(workspaceOptions),
570
+ };
571
+ const publishRuntimeHeartbeat = async () => {
572
+ if (!streamConnected)
573
+ return;
574
+ await publishAgentRuntime(agentId, runtimeDescriptor).catch((error) => {
575
+ console.error('[canon-codex] Failed to publish agent runtime:', error);
576
+ });
577
+ };
564
578
  const stream = new CanonStream({
565
579
  apiKey,
566
580
  agentId,
@@ -577,20 +591,31 @@ async function main() {
577
591
  behavior: payload.behavior,
578
592
  });
579
593
  },
580
- onConnected: () => console.error('[canon-codex] SSE connected'),
581
- onDisconnected: () => console.error('[canon-codex] SSE disconnected'),
594
+ onConnected: () => {
595
+ streamConnected = true;
596
+ void publishRuntimeHeartbeat();
597
+ console.error('[canon-codex] SSE connected');
598
+ },
599
+ onDisconnected: () => {
600
+ streamConnected = false;
601
+ rtdbWrite(`/agent-runtime/${agentId}`, null).catch(() => { });
602
+ console.error('[canon-codex] SSE disconnected');
603
+ },
582
604
  onError: (error) => console.error(`[canon-codex] SSE error: ${error.message}`),
583
605
  },
584
606
  });
585
607
  try {
586
- await publishAgentRuntime(agentId, {
608
+ runtimeDescriptor = {
587
609
  defaultWorkspaceId: workspaceOptions[0]?.id,
588
610
  ...(typeof args.model === 'string' ? { defaultModel: args.model } : {}),
589
611
  availableWorkspaces: buildPublicWorkspaceOptions(workspaceOptions),
590
- });
612
+ };
591
613
  }
592
- catch (error) {
593
- console.error('[canon-codex] Failed to publish agent runtime:', error);
614
+ catch {
615
+ runtimeDescriptor = {
616
+ defaultWorkspaceId: workspaceOptions[0]?.id,
617
+ availableWorkspaces: buildPublicWorkspaceOptions(workspaceOptions),
618
+ };
594
619
  }
595
620
  try {
596
621
  const conversations = await client.getConversations();
@@ -634,7 +659,6 @@ async function main() {
634
659
  await stream.start().catch((error) => {
635
660
  console.error('[canon-codex] SSE start error:', error instanceof Error ? error.message : error);
636
661
  });
637
- let controlStopped = false;
638
662
  const lastSeenControl = new Map();
639
663
  const lastSeenSignal = new Map();
640
664
  const pollControl = async () => {
@@ -700,6 +724,7 @@ async function main() {
700
724
  writeState(session);
701
725
  writeTurn(session);
702
726
  }
727
+ void publishRuntimeHeartbeat();
703
728
  }, HEARTBEAT_MS);
704
729
  const idleCheck = setInterval(() => {
705
730
  const now = Date.now();
@@ -719,6 +744,7 @@ async function main() {
719
744
  clearInterval(heartbeat);
720
745
  clearInterval(idleCheck);
721
746
  stream.stop();
747
+ await rtdbWrite(`/agent-runtime/${agentId}`, null).catch(() => { });
722
748
  for (const session of [...sessions.values()]) {
723
749
  await session.adapter.interrupt().catch(() => { });
724
750
  closeSession(session.conversationId);
package/dist/register.js CHANGED
@@ -23,6 +23,14 @@ if (!values.name || !values.description || !values.phone) {
23
23
  process.exit(1);
24
24
  }
25
25
  const profileName = values.profile || values.name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
26
+ let existingAgentId;
27
+ try {
28
+ const profiles = JSON.parse(readFileSync(AGENTS_PATH, 'utf-8'));
29
+ existingAgentId = profiles[profileName]?.agentId;
30
+ }
31
+ catch {
32
+ // No existing profile state.
33
+ }
26
34
  console.log(`Registering Codex agent "${values.name}" (profile: ${profileName})...`);
27
35
  const result = await registerAndWaitForApproval({
28
36
  name: values.name,
@@ -31,6 +39,7 @@ const result = await registerAndWaitForApproval({
31
39
  developerInfo: 'Codex host plugin',
32
40
  clientType: 'codex',
33
41
  baseUrl: values['base-url'],
42
+ requestedAgentId: existingAgentId,
34
43
  }, {
35
44
  onSubmitted: (requestId) => {
36
45
  console.log(`Registration submitted (request ID: ${requestId}).`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonmsg/codex-plugin",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Canon host integration for Codex CLI",
5
5
  "type": "module",
6
6
  "main": "dist/host.js",
@@ -22,7 +22,7 @@
22
22
  "prepack": "npm run build"
23
23
  },
24
24
  "dependencies": {
25
- "@canonmsg/core": "^0.4.0"
25
+ "@canonmsg/core": "^0.5.0"
26
26
  },
27
27
  "engines": {
28
28
  "node": ">=18.0.0"