customer-map-codex-bridge 0.5.1 → 0.5.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.
- package/README.md +52 -52
- package/codex-process.mjs +43 -0
- package/index.mjs +643 -645
- package/mail-action.mjs +363 -363
- package/package.json +22 -21
package/README.md
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
# Customer Map Codex Bridge
|
|
2
|
-
|
|
3
|
-
This local helper connects a user's already-authenticated Codex installation to Customer Map without sending Codex credentials or API keys to Customer Map.
|
|
4
|
-
|
|
5
|
-
## Requirements
|
|
6
|
-
|
|
7
|
-
- Codex CLI installed and already signed in locally (`codex login`).
|
|
8
|
-
- Optional Gmail actions require `gog` v0.11.0+ with the intended Gmail account already authorized locally.
|
|
9
|
-
- Node.js 18+.
|
|
10
|
-
- The Customer Map Agent settings panel must provide a one-time `CMAP-CODEX-*` code.
|
|
11
|
-
|
|
12
|
-
The settings panel reports **Connected** only after both the local Codex app-server and the Customer Map relay WebSocket are online. A claimed code by itself is only a pending binding.
|
|
13
|
-
|
|
14
|
-
## Run
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npx -y customer-map-codex-bridge@0.5.
|
|
18
|
-
--site https://your-customer-map.example \
|
|
19
|
-
--code CMAP-CODEX-XXXXXXXXXXXX
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Starting a newly authorized Bridge automatically replaces the older Bridge for the same Customer Map account. Clicking **Remove connection** in Customer Map disconnects the running Bridge, so users do not need to find or kill local processes.
|
|
23
|
-
|
|
24
|
-
The Bridge automatically reconnects to the Relay after temporary network or Relay interruptions, using exponential backoff from 1 second up to 30 seconds. It keeps the local Codex process and bridge token in memory during retries. A removed connection, an expired token, or a Bridge replaced by a newer Bridge exits instead of retrying.
|
|
25
|
-
|
|
26
|
-
The bridge initializes Codex App Server with native live web search enabled, then explicitly applies a read-only sandbox with no approval prompts and command network access disabled to every new thread and every turn. This lets the assistants search and read public pages without granting model-generated shell commands arbitrary network or file-write access. Credentials stay on the local machine, and thread IDs are stored under `~/.customer-map-codex/state.json` and resumed after Bridge restarts. Task Assistant, Workbench Assistant, and Sales Assistant use separate thread scopes.
|
|
27
|
-
|
|
28
|
-
When the user explicitly chooses **Save Gmail draft** or **Send email** in Customer Map, the bridge bypasses the Codex turn and executes only a validated, fixed `gog gmail drafts create` or `gog gmail send` argument list. It verifies the content hash and requires a real Gmail message/draft ID before reporting success. Chat cannot turn this into an arbitrary shell or network action.
|
|
29
|
-
|
|
30
|
-
If the protocol handler cannot find `codex`, pass its absolute path explicitly:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npx -y customer-map-codex-bridge@0.5.
|
|
34
|
-
--site https://your-customer-map.example \
|
|
35
|
-
--code CMAP-CODEX-XXXXXXXXXXXX \
|
|
36
|
-
--codex /absolute/path/to/codex
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
If `gog` is outside the standard Homebrew/system paths, pass it explicitly:
|
|
40
|
-
|
|
41
|
-
```bash
|
|
42
|
-
npx -y customer-map-codex-bridge@0.5.
|
|
43
|
-
--site https://your-customer-map.example \
|
|
44
|
-
--code CMAP-CODEX-XXXXXXXXXXXX \
|
|
45
|
-
--gog /absolute/path/to/gog
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
The website can then open:
|
|
49
|
-
|
|
50
|
-
```text
|
|
51
|
-
customer-map-codex://connect?site=https%3A%2F%2Fyour-customer-map.example&code=CMAP-CODEX-XXXXXXXXXXXX
|
|
52
|
-
```
|
|
1
|
+
# Customer Map Codex Bridge
|
|
2
|
+
|
|
3
|
+
This local helper connects a user's already-authenticated Codex installation to Customer Map without sending Codex credentials or API keys to Customer Map.
|
|
4
|
+
|
|
5
|
+
## Requirements
|
|
6
|
+
|
|
7
|
+
- Codex CLI installed and already signed in locally (`codex login`).
|
|
8
|
+
- Optional Gmail actions require `gog` v0.11.0+ with the intended Gmail account already authorized locally.
|
|
9
|
+
- Node.js 18+.
|
|
10
|
+
- The Customer Map Agent settings panel must provide a one-time `CMAP-CODEX-*` code.
|
|
11
|
+
|
|
12
|
+
The settings panel reports **Connected** only after both the local Codex app-server and the Customer Map relay WebSocket are online. A claimed code by itself is only a pending binding.
|
|
13
|
+
|
|
14
|
+
## Run
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npx -y customer-map-codex-bridge@0.5.2 \
|
|
18
|
+
--site https://your-customer-map.example \
|
|
19
|
+
--code CMAP-CODEX-XXXXXXXXXXXX
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Starting a newly authorized Bridge automatically replaces the older Bridge for the same Customer Map account. Clicking **Remove connection** in Customer Map disconnects the running Bridge, so users do not need to find or kill local processes.
|
|
23
|
+
|
|
24
|
+
The Bridge automatically reconnects to the Relay after temporary network or Relay interruptions, using exponential backoff from 1 second up to 30 seconds. It keeps the local Codex process and bridge token in memory during retries. A removed connection, an expired token, or a Bridge replaced by a newer Bridge exits instead of retrying.
|
|
25
|
+
|
|
26
|
+
The bridge initializes Codex App Server with native live web search enabled, then explicitly applies a read-only sandbox with no approval prompts and command network access disabled to every new thread and every turn. This lets the assistants search and read public pages without granting model-generated shell commands arbitrary network or file-write access. Credentials stay on the local machine, and thread IDs are stored under `~/.customer-map-codex/state.json` and resumed after Bridge restarts. Task Assistant, Workbench Assistant, and Sales Assistant use separate thread scopes.
|
|
27
|
+
|
|
28
|
+
When the user explicitly chooses **Save Gmail draft** or **Send email** in Customer Map, the bridge bypasses the Codex turn and executes only a validated, fixed `gog gmail drafts create` or `gog gmail send` argument list. It verifies the content hash and requires a real Gmail message/draft ID before reporting success. Chat cannot turn this into an arbitrary shell or network action.
|
|
29
|
+
|
|
30
|
+
If the protocol handler cannot find `codex`, pass its absolute path explicitly:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx -y customer-map-codex-bridge@0.5.2 \
|
|
34
|
+
--site https://your-customer-map.example \
|
|
35
|
+
--code CMAP-CODEX-XXXXXXXXXXXX \
|
|
36
|
+
--codex /absolute/path/to/codex
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
If `gog` is outside the standard Homebrew/system paths, pass it explicitly:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx -y customer-map-codex-bridge@0.5.2 \
|
|
43
|
+
--site https://your-customer-map.example \
|
|
44
|
+
--code CMAP-CODEX-XXXXXXXXXXXX \
|
|
45
|
+
--gog /absolute/path/to/gog
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The website can then open:
|
|
49
|
+
|
|
50
|
+
```text
|
|
51
|
+
customer-map-codex://connect?site=https%3A%2F%2Fyour-customer-map.example&code=CMAP-CODEX-XXXXXXXXXXXX
|
|
52
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { delimiter, dirname } from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
|
|
5
|
+
export const CODEX_APP_SERVER_ARGS = [
|
|
6
|
+
'app-server',
|
|
7
|
+
'--listen',
|
|
8
|
+
'stdio://',
|
|
9
|
+
'-c',
|
|
10
|
+
'web_search="live"',
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
export function startCodexAppServer(cwd, command) {
|
|
14
|
+
const pathValue = [dirname(process.execPath), dirname(command), process.env.PATH || '']
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.join(delimiter);
|
|
17
|
+
const options = {
|
|
18
|
+
cwd,
|
|
19
|
+
stdio: ['pipe', 'pipe', 'inherit'],
|
|
20
|
+
windowsHide: true,
|
|
21
|
+
env: { ...process.env, PATH: pathValue },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if (process.platform !== 'win32') return spawn(command, CODEX_APP_SERVER_ARGS, options);
|
|
25
|
+
|
|
26
|
+
const commandShell = process.env.ComSpec || process.env.COMSPEC || 'C:\\Windows\\System32\\cmd.exe';
|
|
27
|
+
// cmd.exe needs one outer pair of quotes around the complete /c command.
|
|
28
|
+
// windowsVerbatimArguments keeps Node from escaping those quotes.
|
|
29
|
+
const commandLine = buildWindowsCodexCommandLine(command, CODEX_APP_SERVER_ARGS);
|
|
30
|
+
return spawn(commandShell, ['/d', '/s', '/c', commandLine], {
|
|
31
|
+
...options,
|
|
32
|
+
windowsVerbatimArguments: true,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function buildWindowsCodexCommandLine(command, args = CODEX_APP_SERVER_ARGS) {
|
|
37
|
+
return '"' + [command, ...args].map(quoteWindowsArg).join(' ') + '"';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function quoteWindowsArg(value) {
|
|
41
|
+
// Within a cmd.exe command, embedded quotes are escaped by doubling them.
|
|
42
|
+
return '"' + String(value).replaceAll('"', '""') + '"';
|
|
43
|
+
}
|