@canonmsg/codex-plugin 0.6.1 → 0.6.2

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.
@@ -0,0 +1,2 @@
1
+ export declare function isDirectExecution(moduleUrl: string): boolean;
2
+ export declare function runCli(moduleUrl: string, main: () => void | Promise<void>, onError: (error: unknown) => void): void;
@@ -0,0 +1,16 @@
1
+ import { resolve } from 'node:path';
2
+ import { pathToFileURL } from 'node:url';
3
+ export function isDirectExecution(moduleUrl) {
4
+ const entry = process.argv[1];
5
+ if (!entry)
6
+ return false;
7
+ return pathToFileURL(resolve(entry)).href === moduleUrl;
8
+ }
9
+ export function runCli(moduleUrl, main, onError) {
10
+ if (!isDirectExecution(moduleUrl)) {
11
+ return;
12
+ }
13
+ Promise.resolve()
14
+ .then(() => main())
15
+ .catch(onError);
16
+ }
package/dist/host.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ export declare function main(): Promise<void>;
package/dist/host.js CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import { setDefaultResultOrder } from 'node:dns';
3
- setDefaultResultOrder('ipv4first');
4
3
  import { randomUUID } from 'node:crypto';
5
4
  import { parseArgs } from 'node:util';
6
5
  import { getCodexImagePath, materializeMessageMedia, } from '@canonmsg/agent-sdk';
@@ -10,6 +9,7 @@ import { buildInboundContextLines, decideAutoReply, } from './inbound-policy.js'
10
9
  import { CodexConversationAdapter, } from './adapter.js';
11
10
  import { clearStoredThreadId, loadStoredThreadId, saveStoredThreadId, } from './session-store.js';
12
11
  import { deriveCodexPermissionEnvelope, mapCanonPermissionToCodex, } from './permission-mode.js';
12
+ import { runCli } from './cli-entry.js';
13
13
  const MAX_SESSIONS = 12;
14
14
  const IDLE_TIMEOUT_MS = 30 * 60 * 1000;
15
15
  const HEARTBEAT_MS = 30_000;
@@ -92,7 +92,8 @@ function formatTurnFailure(errorText) {
92
92
  function sleep(ms) {
93
93
  return new Promise((resolve) => setTimeout(resolve, ms));
94
94
  }
95
- async function main() {
95
+ export async function main() {
96
+ setDefaultResultOrder('ipv4first');
96
97
  const { values: args } = parseArgs({
97
98
  options: {
98
99
  cwd: { type: 'string' },
@@ -765,7 +766,7 @@ async function main() {
765
766
  console.error('[canon-codex] Ready — sessions created on demand');
766
767
  await new Promise(() => { });
767
768
  }
768
- main().catch((error) => {
769
+ runCli(import.meta.url, main, (error) => {
769
770
  console.error('[canon-codex] Fatal error:', error);
770
771
  const activeProfile = getActiveProfile();
771
772
  if (activeProfile)
@@ -0,0 +1,3 @@
1
+ export { main as hostMain } from './host.js';
2
+ export { main as registerMain } from './register.js';
3
+ export { main as setupMain } from './setup.js';
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { main as hostMain } from './host.js';
2
+ export { main as registerMain } from './register.js';
3
+ export { main as setupMain } from './setup.js';
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ export declare function main(): Promise<void>;
package/dist/register.js CHANGED
@@ -1,83 +1,90 @@
1
1
  #!/usr/bin/env node
2
2
  import { setDefaultResultOrder } from 'node:dns';
3
- setDefaultResultOrder('ipv4first');
4
3
  import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
5
4
  import { homedir } from 'node:os';
6
5
  import { join } from 'node:path';
7
6
  import { parseArgs } from 'node:util';
8
7
  import { registerAndWaitForApproval } from '@canonmsg/core';
8
+ import { runCli } from './cli-entry.js';
9
9
  const CANON_DIR = join(homedir(), '.canon');
10
10
  const AGENTS_PATH = join(CANON_DIR, 'agents.json');
11
- const { values } = parseArgs({
12
- options: {
13
- name: { type: 'string' },
14
- description: { type: 'string' },
15
- phone: { type: 'string' },
16
- profile: { type: 'string' },
17
- 'base-url': { type: 'string' },
18
- },
19
- strict: true,
20
- });
21
- if (!values.name || !values.description || !values.phone) {
22
- console.error('Usage: canon-codex-register --name "Agent Name" --description "Description" --phone "+15551234567" [--profile "my-agent"]');
23
- process.exit(1);
24
- }
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
- }
34
- console.log(`Registering Codex agent "${values.name}" (profile: ${profileName})...`);
35
- const result = await registerAndWaitForApproval({
36
- name: values.name,
37
- description: values.description,
38
- ownerPhone: values.phone,
39
- developerInfo: 'Codex host plugin',
40
- clientType: 'codex',
41
- baseUrl: values['base-url'],
42
- requestedAgentId: existingAgentId,
43
- }, {
44
- onSubmitted: (requestId) => {
45
- console.log(`Registration submitted (request ID: ${requestId}).`);
46
- console.log('Waiting for approval in Canon app...');
47
- },
48
- onPollUpdate: () => {
49
- process.stdout.write('.');
50
- },
51
- });
52
- console.log('');
53
- switch (result.status) {
54
- case 'approved': {
55
- mkdirSync(CANON_DIR, { recursive: true });
56
- let profiles = {};
57
- try {
58
- profiles = JSON.parse(readFileSync(AGENTS_PATH, 'utf-8'));
59
- }
60
- catch {
61
- // File does not exist yet.
11
+ export async function main() {
12
+ setDefaultResultOrder('ipv4first');
13
+ const { values } = parseArgs({
14
+ options: {
15
+ name: { type: 'string' },
16
+ description: { type: 'string' },
17
+ phone: { type: 'string' },
18
+ profile: { type: 'string' },
19
+ 'base-url': { type: 'string' },
20
+ },
21
+ strict: true,
22
+ });
23
+ if (!values.name || !values.description || !values.phone) {
24
+ console.error('Usage: canon-codex-register --name "Agent Name" --description "Description" --phone "+15551234567" [--profile "my-agent"]');
25
+ process.exit(1);
26
+ }
27
+ const profileName = values.profile || values.name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
28
+ let existingAgentId;
29
+ try {
30
+ const profiles = JSON.parse(readFileSync(AGENTS_PATH, 'utf-8'));
31
+ existingAgentId = profiles[profileName]?.agentId;
32
+ }
33
+ catch {
34
+ // No existing profile state.
35
+ }
36
+ console.log(`Registering Codex agent "${values.name}" (profile: ${profileName})...`);
37
+ const result = await registerAndWaitForApproval({
38
+ name: values.name,
39
+ description: values.description,
40
+ ownerPhone: values.phone,
41
+ developerInfo: 'Codex host plugin',
42
+ clientType: 'codex',
43
+ baseUrl: values['base-url'],
44
+ requestedAgentId: existingAgentId,
45
+ }, {
46
+ onSubmitted: (requestId) => {
47
+ console.log(`Registration submitted (request ID: ${requestId}).`);
48
+ console.log('Waiting for approval in Canon app...');
49
+ },
50
+ onPollUpdate: () => {
51
+ process.stdout.write('.');
52
+ },
53
+ });
54
+ console.log('');
55
+ switch (result.status) {
56
+ case 'approved': {
57
+ mkdirSync(CANON_DIR, { recursive: true });
58
+ let profiles = {};
59
+ try {
60
+ profiles = JSON.parse(readFileSync(AGENTS_PATH, 'utf-8'));
61
+ }
62
+ catch {
63
+ // File does not exist yet.
64
+ }
65
+ profiles[profileName] = {
66
+ apiKey: result.apiKey,
67
+ agentId: result.agentId,
68
+ agentName: result.agentName,
69
+ registeredAt: new Date().toISOString(),
70
+ };
71
+ writeFileSync(AGENTS_PATH, JSON.stringify(profiles, null, 2));
72
+ console.log(`Approved! Agent: ${result.agentName} (${result.agentId})`);
73
+ console.log(`Saved as profile "${profileName}" in ~/.canon/agents.json`);
74
+ console.log('Start it with: canon-codex --cwd /path/to/project');
75
+ break;
62
76
  }
63
- profiles[profileName] = {
64
- apiKey: result.apiKey,
65
- agentId: result.agentId,
66
- agentName: result.agentName,
67
- registeredAt: new Date().toISOString(),
68
- };
69
- writeFileSync(AGENTS_PATH, JSON.stringify(profiles, null, 2));
70
- console.log(`Approved! Agent: ${result.agentName} (${result.agentId})`);
71
- console.log(`Saved as profile "${profileName}" in ~/.canon/agents.json`);
72
- console.log('Start it with: canon-codex --cwd /path/to/project');
73
- break;
77
+ case 'rejected':
78
+ console.log('Registration was rejected.');
79
+ process.exit(1);
80
+ break;
81
+ case 'timeout':
82
+ console.log('Registration timed out (5 minutes). Try again later.');
83
+ process.exit(1);
84
+ break;
74
85
  }
75
- case 'rejected':
76
- console.log('Registration was rejected.');
77
- process.exit(1);
78
- break;
79
- case 'timeout':
80
- console.log('Registration timed out (5 minutes). Try again later.');
81
- process.exit(1);
82
- break;
83
86
  }
87
+ runCli(import.meta.url, main, (error) => {
88
+ console.error('[canon-codex-register] Fatal error:', error);
89
+ process.exit(1);
90
+ });
package/dist/setup.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export {};
2
+ export declare function main(): void;
package/dist/setup.js CHANGED
@@ -1,32 +1,39 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawnSync } from 'node:child_process';
3
- console.log('Canon Codex Plugin Setup');
4
- console.log('========================\n');
5
- const version = spawnSync('codex', ['--version'], { encoding: 'utf-8' });
6
- if (version.status === 0) {
7
- console.log(`Detected Codex CLI: ${version.stdout.trim()}\n`);
3
+ import { runCli } from './cli-entry.js';
4
+ export function main() {
5
+ console.log('Canon Codex Plugin Setup');
6
+ console.log('========================\n');
7
+ const version = spawnSync('codex', ['--version'], { encoding: 'utf-8' });
8
+ if (version.status === 0) {
9
+ console.log(`Detected Codex CLI: ${version.stdout.trim()}\n`);
10
+ }
11
+ else {
12
+ console.log('Codex CLI was not detected on PATH.');
13
+ console.log('Install Codex first, then rerun this setup.\n');
14
+ }
15
+ console.log('Next steps:');
16
+ console.log(' 0. Confirm Codex is logged in the way you want Canon to use');
17
+ console.log(' codex login status');
18
+ console.log('');
19
+ console.log(' 1. Register your agent');
20
+ console.log(' canon-codex-register --name "My Codex" --description "My local coding agent" --phone "+15551234567"');
21
+ console.log('');
22
+ console.log(' 2. Start the host in a project directory and keep it running');
23
+ console.log(' canon-codex --cwd /path/to/project');
24
+ console.log('');
25
+ console.log(' A git repo is not required; any readable directory works.');
26
+ console.log('');
27
+ console.log('Optional flags:');
28
+ console.log(' --model gpt-5.4');
29
+ console.log(' --sandbox workspace-write');
30
+ console.log(' --full-auto');
31
+ console.log('');
32
+ console.log('Note: recent Codex CLI versions use --full-auto for non-interactive write access.');
33
+ console.log('Note: Canon uses the local Codex login state by default (for example ChatGPT/device auth or API-key auth).');
34
+ console.log('Note: If Canon starts returning "Invalid API key", rerun canon-codex-register to replace the saved profile and then restart the host.');
8
35
  }
9
- else {
10
- console.log('Codex CLI was not detected on PATH.');
11
- console.log('Install Codex first, then rerun this setup.\n');
12
- }
13
- console.log('Next steps:');
14
- console.log(' 0. Confirm Codex is logged in the way you want Canon to use');
15
- console.log(' codex login status');
16
- console.log('');
17
- console.log(' 1. Register your agent');
18
- console.log(' canon-codex-register --name "My Codex" --description "My local coding agent" --phone "+15551234567"');
19
- console.log('');
20
- console.log(' 2. Start the host in a project directory and keep it running');
21
- console.log(' canon-codex --cwd /path/to/project');
22
- console.log('');
23
- console.log(' A git repo is not required; any readable directory works.');
24
- console.log('');
25
- console.log('Optional flags:');
26
- console.log(' --model gpt-5.4');
27
- console.log(' --sandbox workspace-write');
28
- console.log(' --full-auto');
29
- console.log('');
30
- console.log('Note: recent Codex CLI versions use --full-auto for non-interactive write access.');
31
- console.log('Note: Canon uses the local Codex login state by default (for example ChatGPT/device auth or API-key auth).');
32
- console.log('Note: If Canon starts returning "Invalid API key", rerun canon-codex-register to replace the saved profile and then restart the host.');
36
+ runCli(import.meta.url, main, (error) => {
37
+ console.error('[canon-codex-setup] Fatal error:', error);
38
+ process.exit(1);
39
+ });
package/package.json CHANGED
@@ -1,10 +1,16 @@
1
1
  {
2
2
  "name": "@canonmsg/codex-plugin",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Canon host integration for Codex CLI",
5
5
  "type": "module",
6
- "main": "dist/host.js",
7
- "types": "dist/host.d.ts",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
8
14
  "bin": {
9
15
  "canon-codex": "dist/host.js",
10
16
  "canon-codex-register": "dist/register.js",