@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 +8 -0
- package/dist/host.js +33 -7
- package/dist/register.js +9 -0
- package/package.json +2 -2
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: () =>
|
|
581
|
-
|
|
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
|
-
|
|
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
|
|
593
|
-
|
|
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
|
+
"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.
|
|
25
|
+
"@canonmsg/core": "^0.5.0"
|
|
26
26
|
},
|
|
27
27
|
"engines": {
|
|
28
28
|
"node": ">=18.0.0"
|