@canonmsg/codex-plugin 0.22.4 → 0.23.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 +11 -3
- package/dist/host.js +13 -4
- package/dist/register.js +34 -15
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -13,6 +13,9 @@ npm install -g @canonmsg/codex-plugin
|
|
|
13
13
|
# Make sure Codex itself is logged in the way you want Canon to use
|
|
14
14
|
codex login status
|
|
15
15
|
|
|
16
|
+
# Select the Canon trust domain supplied for your account
|
|
17
|
+
export CANON_ENVIRONMENT_ID=canon-legacy-v1
|
|
18
|
+
|
|
16
19
|
# Register (approve in Canon when prompted)
|
|
17
20
|
canon-codex-register --name "My Codex" --description "My local coding agent" --phone "+15551234567"
|
|
18
21
|
|
|
@@ -20,7 +23,12 @@ canon-codex-register --name "My Codex" --description "My local coding agent" --p
|
|
|
20
23
|
canon-codex --cwd /path/to/project
|
|
21
24
|
```
|
|
22
25
|
|
|
23
|
-
Registration
|
|
26
|
+
Registration verifies the selected Canon API and stream before sending the
|
|
27
|
+
request, then saves the environment ID and complete endpoint snapshot with the
|
|
28
|
+
credential in `~/.canon/agents.json`. The same environment-bound profile store
|
|
29
|
+
is used by the Claude Code integration and supported by the OpenClaw plugin.
|
|
30
|
+
An older profile without this binding must be reconnected or migrated before a
|
|
31
|
+
new host will start it.
|
|
24
32
|
|
|
25
33
|
`canon-codex` is the local agent process. Keep that terminal open while you want Canon to reach the agent. Closing it, logging out, rebooting, or sleeping long enough to stop the process takes the local agent offline until you revive it.
|
|
26
34
|
|
|
@@ -120,7 +128,7 @@ canon-codex --cwd /path/to/project --codex-bin /absolute/path/to/codex
|
|
|
120
128
|
If Canon rejects authenticated requests with `401 Invalid API key`, the stored Canon profile needs a fresh key. Reconnect the same profile to overwrite `~/.canon/agents.json`, then restart or revive the host:
|
|
121
129
|
|
|
122
130
|
```bash
|
|
123
|
-
canon-codex-register --name "My Codex" --description "My local coding agent" --phone "+15551234567" --profile my-codex
|
|
131
|
+
canon-codex-register --environment canon-legacy-v1 --name "My Codex" --description "My local coding agent" --phone "+15551234567" --profile my-codex
|
|
124
132
|
```
|
|
125
133
|
|
|
126
134
|
If Codex reports API-key quota errors while another local tool on the same machine uses OpenAI API keys, check Codex's own stored login state:
|
|
@@ -142,7 +150,7 @@ Restart `canon-codex` after changing the Codex login state.
|
|
|
142
150
|
## Multiple agents
|
|
143
151
|
|
|
144
152
|
```bash
|
|
145
|
-
canon-codex-register --name "Frontend" --description "React work" --phone "+1..." --profile frontend
|
|
153
|
+
canon-codex-register --environment canon-legacy-v1 --name "Frontend" --description "React work" --phone "+1..." --profile frontend
|
|
146
154
|
CANON_AGENT=frontend canon-codex --cwd ~/projects/frontend
|
|
147
155
|
```
|
|
148
156
|
|
package/dist/host.js
CHANGED
|
@@ -6,7 +6,7 @@ import { dirname } from 'node:path';
|
|
|
6
6
|
import { parseArgs } from 'node:util';
|
|
7
7
|
import { getCodexImagePath, materializeMessageMedia, materializeReplyContextMedia, sendMediaFileMessage, } from '@canonmsg/agent-sdk';
|
|
8
8
|
import { captureTurnArtifactSnapshot, collectTurnArtifacts, } from '@canonmsg/coding-agent-host';
|
|
9
|
-
import { RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, resolveQuestionAllowOther, buildCanonTurnContextV2, buildConfiguredWorkspaceOptionsWithRoots, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, buildRuntimePresentationPolicy, buildCanonInboundFrameV1, 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, markLocalRuntimeStopped, normalizeTurnMetadata, parseRuntimeCardV1, RuntimeRequestManager, prepareConversationEnvironment, loadHostSessionConfig, releaseConversationEnvironment, resolveCanonAgent, CanonApiError, loadRuntimeSessionState, sendMessageWithRetry, sendMessageWithRetryChunked, saveRuntimeSessionState, buildBoundedTurnTrail, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, renderCodingHostInboundPrompt, resolveHostWorkspaceCwd, shouldTriggerAgentTurn, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
9
|
+
import { RUNTIME_NEW_SESSION_ACTION, RUNTIME_STOP_ACTION, RUNTIME_STOP_AND_DROP_ACTION, buildRuntimeCardOutcome, resolveQuestionAllowOther, buildCanonTurnContextV2, buildConfiguredWorkspaceOptionsWithRoots, buildFirstPartyCodingRuntimeDescriptor, buildHydratedInboundContext, diffCanonMemberIds, buildPublicWorkspaceRoots, buildPublicWorkspaceOptions, buildRuntimePresentationPolicy, buildCanonInboundFrameV1, 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, markLocalRuntimeStopped, normalizeTurnMetadata, parseRuntimeCardV1, RuntimeRequestManager, prepareConversationEnvironment, loadHostSessionConfig, releaseConversationEnvironment, resolveCanonAgent, verifyResolvedAgentEnvironment, CanonApiError, loadRuntimeSessionState, sendMessageWithRetry, sendMessageWithRetryChunked, saveRuntimeSessionState, buildBoundedTurnTrail, publishHostAgentRuntime, publishHostSessionSnapshots, renderCanonHostInboundContent, renderCodingHostInboundPrompt, resolveHostWorkspaceCwd, shouldTriggerAgentTurn, upsertLocalRuntimeEntry, } from '@canonmsg/core';
|
|
10
10
|
import { decideAutoReply, } from './inbound-policy.js';
|
|
11
11
|
import { CodexConversationAdapter, } from './adapter.js';
|
|
12
12
|
import { CodexAppServerAdapter, } from './app-server-adapter.js';
|
|
@@ -45,7 +45,7 @@ COMMON FLAGS
|
|
|
45
45
|
|
|
46
46
|
AUTH
|
|
47
47
|
CANON_AGENT=<profile> canon-codex --cwd /path/to/project
|
|
48
|
-
CANON_API_KEY=agk_live_... canon-codex --cwd /path/to/project
|
|
48
|
+
CANON_ENVIRONMENT_ID=<id> CANON_API_KEY=agk_live_... canon-codex --cwd /path/to/project
|
|
49
49
|
|
|
50
50
|
EXAMPLES
|
|
51
51
|
canon-codex --cwd ~/dev/canon
|
|
@@ -487,10 +487,18 @@ export async function main() {
|
|
|
487
487
|
console.error(`[canon-codex] Could not detect Codex CLI version for ${codexBin}: ${codexCliStatus.error ?? 'unknown result'}`);
|
|
488
488
|
}
|
|
489
489
|
console.error(`[canon-codex] Codex transport: ${useAppServer ? 'app-server' : 'exec --json'}`);
|
|
490
|
-
const
|
|
490
|
+
const resolvedAgent = resolveCanonAgent({ logPrefix: '[canon-codex]', expectedClientType: 'codex' });
|
|
491
|
+
const { apiKey, agentId: profileAgentId, agentName: profileAgentName, profile, baseUrl, streamUrl, rtdbUrl, firebaseApiKey, lockHandle, } = resolvedAgent;
|
|
491
492
|
console.error(`[canon-codex] Starting${profile ? ` (profile: ${profile})` : ''} in ${workingDir}`);
|
|
493
|
+
try {
|
|
494
|
+
await verifyResolvedAgentEnvironment(resolvedAgent);
|
|
495
|
+
}
|
|
496
|
+
catch (error) {
|
|
497
|
+
lockHandle?.release();
|
|
498
|
+
throw error;
|
|
499
|
+
}
|
|
492
500
|
const client = new CanonClient(apiKey, baseUrl);
|
|
493
|
-
const rtdb = initRTDBAuth(client);
|
|
501
|
+
const rtdb = initRTDBAuth(client, { rtdbUrl, firebaseApiKey });
|
|
494
502
|
const typingSignals = createTypingStatusPublisher({
|
|
495
503
|
setTyping: (conversationId, typing, status) => status
|
|
496
504
|
? client.setTyping(conversationId, typing, status)
|
|
@@ -2202,6 +2210,7 @@ export async function main() {
|
|
|
2202
2210
|
const stream = new CanonStream({
|
|
2203
2211
|
apiKey,
|
|
2204
2212
|
agentId,
|
|
2213
|
+
streamUrl,
|
|
2205
2214
|
handler: {
|
|
2206
2215
|
onMessage: (payload) => {
|
|
2207
2216
|
const message = payload.message;
|
package/dist/register.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { setDefaultResultOrder } from 'node:dns';
|
|
3
|
-
import { readFileSync } from 'node:fs';
|
|
4
3
|
import { parseArgs } from 'node:util';
|
|
5
|
-
import { ackRegistrationApproval, clearPendingRegistration, getOrCreatePendingRegistration, registerAndWaitForApproval, updatePendingRegistration, upsertAgentProfile,
|
|
4
|
+
import { ackRegistrationApproval, clearPendingRegistration, getOrCreatePendingRegistration, registerAndWaitForApproval, resolveCanonRuntimeConnection, loadProfiles, updatePendingRegistration, upsertAgentProfile, verifyCanonRuntimeConnection, } from '@canonmsg/core';
|
|
6
5
|
import { runCli } from './cli-entry.js';
|
|
7
6
|
const HELP = `canon-codex-register — register or reconnect a Codex agent in Canon
|
|
8
7
|
|
|
@@ -16,13 +15,17 @@ REQUIRED
|
|
|
16
15
|
|
|
17
16
|
FLAGS
|
|
18
17
|
--profile <name> Local profile name in ~/.canon/agents.json
|
|
18
|
+
--environment <id> Canon environment ID (or CANON_ENVIRONMENT_ID)
|
|
19
19
|
--base-url <url> Canon API base URL override
|
|
20
|
+
--stream-url <url> Canon stream URL override
|
|
21
|
+
--rtdb-url <url> Canon RTDB URL override
|
|
22
|
+
--firebase-api-key <key> Firebase web API key override (public config)
|
|
20
23
|
--help, -h Show this help
|
|
21
24
|
--version, -V Show package version
|
|
22
25
|
|
|
23
26
|
EXAMPLES
|
|
24
|
-
canon-codex-register --name "My Codex" --description "Local coding agent" --phone "+15551234567"
|
|
25
|
-
canon-codex-register --name "Frontend" --description "React work" --phone "+15551234567" --profile frontend
|
|
27
|
+
canon-codex-register --environment canon-legacy-v1 --name "My Codex" --description "Local coding agent" --phone "+15551234567"
|
|
28
|
+
canon-codex-register --environment canon-legacy-v1 --name "Frontend" --description "React work" --phone "+15551234567" --profile frontend
|
|
26
29
|
|
|
27
30
|
After approval, start it with CANON_AGENT=<profile> canon-codex --cwd /path/to/project.`;
|
|
28
31
|
export async function main() {
|
|
@@ -33,7 +36,11 @@ export async function main() {
|
|
|
33
36
|
description: { type: 'string' },
|
|
34
37
|
phone: { type: 'string' },
|
|
35
38
|
profile: { type: 'string' },
|
|
39
|
+
environment: { type: 'string' },
|
|
36
40
|
'base-url': { type: 'string' },
|
|
41
|
+
'stream-url': { type: 'string' },
|
|
42
|
+
'rtdb-url': { type: 'string' },
|
|
43
|
+
'firebase-api-key': { type: 'string' },
|
|
37
44
|
},
|
|
38
45
|
strict: true,
|
|
39
46
|
});
|
|
@@ -42,23 +49,31 @@ export async function main() {
|
|
|
42
49
|
process.exit(1);
|
|
43
50
|
}
|
|
44
51
|
const profileName = values.profile || values.name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
existingAgentId = profiles[profileName]?.agentId;
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
// No existing profile state.
|
|
52
|
+
const environmentId = values.environment || process.env.CANON_ENVIRONMENT_ID;
|
|
53
|
+
if (!environmentId) {
|
|
54
|
+
throw new Error('--environment or CANON_ENVIRONMENT_ID is required');
|
|
52
55
|
}
|
|
56
|
+
const connection = resolveCanonRuntimeConnection({
|
|
57
|
+
environmentId,
|
|
58
|
+
apiBaseUrl: values['base-url'],
|
|
59
|
+
streamUrl: values['stream-url'],
|
|
60
|
+
rtdbUrl: values['rtdb-url'],
|
|
61
|
+
firebaseWebApiKey: values['firebase-api-key'],
|
|
62
|
+
});
|
|
63
|
+
await verifyCanonRuntimeConnection(connection);
|
|
64
|
+
const existingProfile = loadProfiles()[profileName];
|
|
65
|
+
const existingAgentId = existingProfile?.environmentId === connection.environmentId
|
|
66
|
+
? existingProfile.agentId
|
|
67
|
+
: undefined;
|
|
53
68
|
console.log(`Registering Codex agent "${values.name}" (profile: ${profileName})...`);
|
|
54
|
-
const pending = getOrCreatePendingRegistration(profileName, 'codex');
|
|
69
|
+
const pending = getOrCreatePendingRegistration(profileName, 'codex', connection);
|
|
55
70
|
const result = await registerAndWaitForApproval({
|
|
56
71
|
name: values.name,
|
|
57
72
|
description: values.description,
|
|
58
73
|
ownerPhone: values.phone,
|
|
59
74
|
developerInfo: 'Codex host plugin',
|
|
60
75
|
clientType: 'codex',
|
|
61
|
-
baseUrl:
|
|
76
|
+
baseUrl: connection.apiBaseUrl,
|
|
62
77
|
requestedAgentId: existingAgentId,
|
|
63
78
|
localRegistrationId: pending.localRegistrationId,
|
|
64
79
|
}, {
|
|
@@ -87,11 +102,15 @@ export async function main() {
|
|
|
87
102
|
agentId: result.agentId,
|
|
88
103
|
agentName: result.agentName,
|
|
89
104
|
registeredAt: new Date().toISOString(),
|
|
105
|
+
environmentId: connection.environmentId,
|
|
106
|
+
baseUrl: connection.apiBaseUrl,
|
|
107
|
+
streamUrl: connection.streamUrl,
|
|
108
|
+
rtdbUrl: connection.rtdbUrl,
|
|
109
|
+
firebaseApiKey: connection.firebaseWebApiKey,
|
|
90
110
|
clientType: 'codex',
|
|
91
|
-
...(typeof values['base-url'] === 'string' ? { baseUrl: values['base-url'] } : {}),
|
|
92
111
|
});
|
|
93
112
|
if (result.requestId) {
|
|
94
|
-
await ackRegistrationApproval(
|
|
113
|
+
await ackRegistrationApproval(connection.apiBaseUrl, result.requestId, result.pollToken);
|
|
95
114
|
}
|
|
96
115
|
clearPendingRegistration(profileName);
|
|
97
116
|
console.log(`Approved! Agent: ${result.agentName} (${result.agentId})`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonmsg/codex-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
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": "^
|
|
32
|
+
"@canonmsg/agent-sdk": "^6.0.0",
|
|
33
33
|
"@canonmsg/coding-agent-host": "^0.2.2",
|
|
34
|
-
"@canonmsg/core": "^
|
|
34
|
+
"@canonmsg/core": "^6.0.0"
|
|
35
35
|
},
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=18.0.0"
|