codex-copilot-dx 0.9.23 → 0.9.25
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 +20 -20
- package/bin/cli.mjs +51 -19
- package/docs/ARCHITECTURE.md +50 -0
- package/docs/README.md +4 -0
- package/docs/REFERENCE.md +124 -71
- package/package.json +3 -2
- package/src/adapter.mjs +5 -2
- package/src/cli-image.mjs +13 -10
- package/src/cli-options.mjs +13 -4
- package/src/cli-status.mjs +5 -0
- package/src/client-integration.mjs +41 -0
- package/src/codex-config-doctor.mjs +3 -3
- package/src/codex-paths.mjs +10 -0
- package/src/codex-thread-compression.mjs +11 -6
- package/src/config.mjs +10 -6
- package/src/copilot-responses-policy.mjs +4 -2
- package/src/dashboard/index.html +7 -6
- package/src/dashboard/language.js +13 -21
- package/src/dashboard/ui.js +10 -20
- package/src/dashboard-api.mjs +0 -12
- package/src/launcher.mjs +7 -2
- package/src/lock.mjs +29 -0
- package/src/native-prediction-overlay.mjs +92 -0
- package/src/native-prediction-profile.mjs +178 -0
- package/src/native-prediction-state.mjs +29 -0
- package/src/native-prediction-transport.mjs +255 -0
- package/src/native-prediction.mjs +170 -0
- package/src/network-route.mjs +102 -0
- package/src/observability.mjs +2 -0
- package/src/operation-error.mjs +37 -0
- package/src/package-update.mjs +2 -3
- package/src/prediction-retirement.mjs +86 -0
- package/src/proxy-tunnel.mjs +102 -0
- package/src/responses-request.mjs +5 -2
- package/src/suggestion-auto.mjs +3 -103
- package/src/suggestion-mcp.mjs +64 -132
- package/src/user-settings.mjs +17 -4
- package/src/version.mjs +23 -46
- package/src/cli-suggestion.mjs +0 -120
- package/src/suggestion-config.mjs +0 -98
- package/src/suggestion-context.mjs +0 -108
- package/src/suggestion-provider.mjs +0 -41
- package/src/suggestion-ui.html +0 -26
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@ Use Codex App with GitHub Copilot through a local adapter.
|
|
|
5
5
|
CCDX targets Codex App. It discovers Copilot models, adapts the client's model
|
|
6
6
|
catalog, and preserves Responses streaming, tool calls and conversation history.
|
|
7
7
|
Default Auto-review: **GPT-6.1 Sol / low**. Image generation is **off by default**.
|
|
8
|
+
Native predictions are also **off by default**.
|
|
8
9
|
|
|
9
10
|
## Install and run
|
|
10
11
|
|
|
@@ -29,7 +30,7 @@ The dashboard does not poll in the background; refresh when needed.
|
|
|
29
30
|
| Command | Purpose |
|
|
30
31
|
| --- | --- |
|
|
31
32
|
| `ccdx help` | Command help; use `ccdx help <command>` for details |
|
|
32
|
-
| `ccdx start` | Start
|
|
33
|
+
| `ccdx start` | Start or reuse the adapter and open Codex when auto-launch is enabled |
|
|
33
34
|
| `ccdx status` | Runtime, limits and bounded request diagnostics |
|
|
34
35
|
| `ccdx doctor` | Configuration, adapter and read-only App/catalog diagnostics |
|
|
35
36
|
| `ccdx doctor config` | Read-only configuration check |
|
|
@@ -38,14 +39,13 @@ The dashboard does not poll in the background; refresh when needed.
|
|
|
38
39
|
| `ccdx models` | Fresh upstream model list |
|
|
39
40
|
| `ccdx usage` | Recorded tokens and upstream prompt-cache hit rate |
|
|
40
41
|
| `ccdx auto-review-model` | Select model, then reasoning effort; `0` follows client |
|
|
41
|
-
| `ccdx suggestion on` / `ccdx suggestion off` | Enable or disable the optional next-message panel |
|
|
42
|
-
| `ccdx suggestion model` / `ccdx suggestion status` | Choose its model by number, or check settings |
|
|
43
42
|
| `ccdx animation` | Preview and select terminal animation |
|
|
44
43
|
| `ccdx cache --limit 128` | Set the history-cache budget in MiB |
|
|
45
44
|
| `ccdx cache --clean` | Clear the rebuildable image-transform cache |
|
|
46
45
|
| `ccdx limits --decoded 256` | Set the decoded request-body budget; restart to apply |
|
|
47
46
|
| `ccdx enable-image` | Opt in to image generation/editing with your own API |
|
|
48
47
|
| `ccdx image-status` / `ccdx disable-image` | Check or disable optional images |
|
|
48
|
+
| `ccdx prediction on` / `off` / `status` | Opt in to native next-message predictions (macOS) |
|
|
49
49
|
| `ccdx update` | Update the global package |
|
|
50
50
|
|
|
51
51
|
## Compatibility and safety
|
|
@@ -64,20 +64,17 @@ The dashboard does not poll in the background; refresh when needed.
|
|
|
64
64
|
break continuations. Generated images and Codex transcripts are not deleted.
|
|
65
65
|
- Optional image setup/maintenance never blocks the primary service. Disabled
|
|
66
66
|
users get no CCDX image skill or MCP installation.
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
Existing user-managed MCP/profile configuration is preserved. Native prediction
|
|
79
|
-
settings are untouched; account/remote defaults in all future clients cannot be
|
|
80
|
-
reliably detected. Use `ccdx suggestion off` when preferring an official feature.
|
|
67
|
+
- The manual prediction MCP, background hook and dashboard panel are retired.
|
|
68
|
+
Startup removes only unchanged CCDX registrations and disables saved prediction
|
|
69
|
+
settings. The optional image MCP remains unchanged. Modified old registrations
|
|
70
|
+
can use inert compatibility entrypoints; they no longer generate suggestions.
|
|
71
|
+
- Native predictions are a separate, opt-in compatibility feature. Quit Codex,
|
|
72
|
+
run `ccdx prediction on`, then restart CCDX. This adds App-profile certificate
|
|
73
|
+
trust and an App-only route for `chatgpt.com` and `ab.chatgpt.com`; HTTPS on those
|
|
74
|
+
hosts is decrypted locally, but only prediction configuration is changed.
|
|
75
|
+
Other domains and the CCDX model endpoint stay on their existing routes.
|
|
76
|
+
No program files or OS trust are changed. Static HTTP/HTTPS/SOCKS5 proxies and bypass rules are retained.
|
|
77
|
+
Dynamic PAC/WPAD routes are reported as unsupported; see the reference for routing, rollback and client-version limits.
|
|
81
78
|
- CCDX adds experimental local history compression only when installed App
|
|
82
79
|
runtimes support it and report it off. Existing choices are preserved; an
|
|
83
80
|
already-enabled default, unavailable runtime or failed check is skipped.
|
|
@@ -87,11 +84,14 @@ The dashboard does not poll in the background; refresh when needed.
|
|
|
87
84
|
expose it to the public internet. The dashboard is not an authentication wall
|
|
88
85
|
for the API. Diagnostic errors may contain sensitive upstream text.
|
|
89
86
|
|
|
90
|
-
Startup checks GitHub
|
|
87
|
+
Startup checks GitHub's latest-release web redirect, not npm or the anonymous REST quota, and suggests `ccdx update github`.
|
|
88
|
+
Updates install the exact stable tag; dependencies still use npm's configured registry. Lookup errors identify HTTP refusal, timeout, network failure or invalid redirects.
|
|
89
|
+
|
|
90
|
+
The dashboard and CLI separate prediction preference, bridge state and observed config traffic; candidate visibility stays unknown.
|
|
91
|
+
Inference, client integration, optional images and management have separate ownership. See [architecture boundaries](docs/ARCHITECTURE.md).
|
|
91
92
|
|
|
92
93
|
See the [complete command/configuration reference](https://github.com/DaleXiao/codex-copilot-dx/blob/main/docs/REFERENCE.md)
|
|
93
|
-
for authentication recovery, configuration
|
|
94
|
-
logging, image setup and client compatibility details.
|
|
94
|
+
for authentication recovery, configuration safety, limits, logging, images and client compatibility.
|
|
95
95
|
The same reference is included as `docs/REFERENCE.md` in the installed npm package.
|
|
96
96
|
|
|
97
97
|
## Development
|
package/bin/cli.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { ensureAuth, openCodex } from "../src/launcher.mjs";
|
|
4
|
-
import { ensureCodexConfig } from "../src/config.mjs";
|
|
5
4
|
import { startAdapter } from "../src/adapter.mjs";
|
|
6
5
|
import { defaultCopilotClient, refreshVSCodeVersion } from "../src/copilot.mjs";
|
|
7
6
|
import { status } from "../src/status.mjs";
|
|
@@ -22,9 +21,7 @@ import { runAuthCommand } from "../src/cli-auth.mjs";
|
|
|
22
21
|
import { createProfileRuntime } from "../src/profile-runtime.mjs";
|
|
23
22
|
import { createProfileModelRuntime } from "../src/profile-model-runtime.mjs";
|
|
24
23
|
import { createCodexModelCatalog } from "../src/codex-model-catalog.mjs";
|
|
25
|
-
import { readImageProviderConfig } from "../src/image-provider-config.mjs";
|
|
26
24
|
import { setResponseHistoryMaxBytes } from "../src/response-history.mjs";
|
|
27
|
-
import { ensureCodexThreadCompression } from "../src/codex-thread-compression.mjs";
|
|
28
25
|
|
|
29
26
|
const LOCAL_VERSION = localPackageVersion();
|
|
30
27
|
const CLI_NAME = cliCommandName();
|
|
@@ -77,8 +74,24 @@ if (CLI.command === "image") {
|
|
|
77
74
|
}
|
|
78
75
|
if (CLI.command === "suggestion") {
|
|
79
76
|
try {
|
|
80
|
-
const {
|
|
81
|
-
|
|
77
|
+
const { retirePredictionIntegration } = await import("../src/prediction-retirement.mjs");
|
|
78
|
+
const result = retirePredictionIntegration({ dryRun: CLI.action === "status" });
|
|
79
|
+
console.log("The CCDX prediction panel has been retired and cannot be enabled.");
|
|
80
|
+
if (CLI.action === "status" && result.changed) console.log(`Legacy settings remain; run ${CLI_NAME} suggestion off to clean them up.`);
|
|
81
|
+
if (result.preserved) console.warn("Modified prediction settings were preserved.");
|
|
82
|
+
process.exit(0);
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error(status("err", error.message));
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (CLI.command === "prediction") {
|
|
89
|
+
try {
|
|
90
|
+
const { runPredictionCommand } = await import("../src/native-prediction.mjs");
|
|
91
|
+
await runPredictionCommand({ action: CLI.action, runtimeSnapshot: () => {
|
|
92
|
+
const probe = parseAdapterProbeOptions(process.env);
|
|
93
|
+
return readAdapterStatus({ host: probe.adapterHost, port: probe.adapterPort, timeoutMs: probe.existingAdapterTimeoutMs }).then(({ data }) => data);
|
|
94
|
+
} });
|
|
82
95
|
process.exit(0);
|
|
83
96
|
} catch (error) {
|
|
84
97
|
console.error(status("err", error.message));
|
|
@@ -251,6 +264,17 @@ const LOGGING = configureLogging();
|
|
|
251
264
|
let activeServer = null;
|
|
252
265
|
let modelRefreshTimer = null;
|
|
253
266
|
let shuttingDown = false;
|
|
267
|
+
let nativePrediction = null;
|
|
268
|
+
let clientIntegration = null;
|
|
269
|
+
|
|
270
|
+
async function clientIntegrations() {
|
|
271
|
+
if (!clientIntegration) {
|
|
272
|
+
const { createClientIntegration } = await import("../src/client-integration.mjs");
|
|
273
|
+
clientIntegration = createClientIntegration({ port: ADAPTER_PORT, host: ADAPTER_HOST,
|
|
274
|
+
info: (message) => console.log(status("info", message)), warning: (message) => console.warn(status("warn", message)) });
|
|
275
|
+
}
|
|
276
|
+
return clientIntegration;
|
|
277
|
+
}
|
|
254
278
|
|
|
255
279
|
if (LOGGING.filePath) {
|
|
256
280
|
console.log(status("info", `Debug log: ${LOGGING.filePath}`));
|
|
@@ -272,7 +296,18 @@ async function reuseRunningAdapterIfAvailable() {
|
|
|
272
296
|
console.log(status("ok", `Using existing adapter at ${running.baseUrl}`));
|
|
273
297
|
const { compressionSetup } = await configureCodexClient();
|
|
274
298
|
|
|
275
|
-
|
|
299
|
+
let predictionPacUrl = null;
|
|
300
|
+
let predictionApp = null;
|
|
301
|
+
try {
|
|
302
|
+
const { readPredictionSettings } = await import("../src/native-prediction-profile.mjs");
|
|
303
|
+
const preference = readPredictionSettings();
|
|
304
|
+
if (preference.enabled) {
|
|
305
|
+
predictionPacUrl = running.data?.native_prediction_pac || null;
|
|
306
|
+
predictionApp = preference.app?.app;
|
|
307
|
+
if (!predictionPacUrl) console.warn(status("warn", "Restart ccdx to activate the newly enabled prediction bridge"));
|
|
308
|
+
}
|
|
309
|
+
} catch (error) { console.warn(status("warn", error.message)); }
|
|
310
|
+
await openCodex({ predictionPacUrl, predictionApp });
|
|
276
311
|
console.log(`
|
|
277
312
|
${status("ok", "Ready, using the existing ccdx adapter")}
|
|
278
313
|
|
|
@@ -285,17 +320,7 @@ async function reuseRunningAdapterIfAvailable() {
|
|
|
285
320
|
}
|
|
286
321
|
|
|
287
322
|
async function configureCodexClient() {
|
|
288
|
-
|
|
289
|
-
const { imageMcpSkipped } = ensureCodexConfig(ADAPTER_PORT, { host: ADAPTER_HOST, imageProviderEnabled });
|
|
290
|
-
if (imageProviderEnabled && !imageMcpSkipped) {
|
|
291
|
-
try {
|
|
292
|
-
const { syncEnabledImageSkill } = await import("../src/cli-image.mjs");
|
|
293
|
-
syncEnabledImageSkill({ adapterPort: ADAPTER_PORT, adapterHost: ADAPTER_HOST });
|
|
294
|
-
} catch (error) {
|
|
295
|
-
console.warn(status("warn", `Image guidance could not be updated: ${error.message}`));
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
return { compressionSetup: runInBackground(ensureCodexThreadCompression) };
|
|
323
|
+
return (await clientIntegrations()).configure();
|
|
299
324
|
}
|
|
300
325
|
|
|
301
326
|
if (CLI.command === "doctor") {
|
|
@@ -369,13 +394,18 @@ try {
|
|
|
369
394
|
streamHandshakeTimeoutMs: RUNTIME.streamHandshakeTimeoutMs,
|
|
370
395
|
streamIdleTimeoutMs: RUNTIME.streamIdleTimeoutMs,
|
|
371
396
|
terminalAnimationTheme,
|
|
397
|
+
nativePredictionPac: () => nativePrediction?.pacUrl || null,
|
|
398
|
+
clientIntegrationSnapshot: () => clientIntegration?.snapshot() || null,
|
|
372
399
|
});
|
|
373
400
|
|
|
374
401
|
// Point Codex App at the adapter.
|
|
375
402
|
const { compressionSetup } = await configureCodexClient();
|
|
376
403
|
|
|
377
|
-
//
|
|
378
|
-
await
|
|
404
|
+
// Optional native prediction setup must never prevent the core adapter from running.
|
|
405
|
+
nativePrediction = await (await clientIntegrations()).start();
|
|
406
|
+
|
|
407
|
+
// Launch Codex when available. A running App is never forcibly restarted.
|
|
408
|
+
await openCodex({ predictionPacUrl: nativePrediction?.pacUrl, predictionApp: nativePrediction?.app });
|
|
379
409
|
|
|
380
410
|
// Periodically refresh the model list + endpoint cache so a long-running
|
|
381
411
|
// adapter picks up newly released models without a restart.
|
|
@@ -404,6 +434,7 @@ try {
|
|
|
404
434
|
let exitCode = 0;
|
|
405
435
|
try {
|
|
406
436
|
if (modelRefreshTimer) clearInterval(modelRefreshTimer);
|
|
437
|
+
await clientIntegration?.close();
|
|
407
438
|
const result = await closeHttpServer(activeServer, { timeoutMs: RUNTIME.shutdownTimeoutMs });
|
|
408
439
|
if (result.forced) console.warn(status("warn", "Forced remaining adapter connections closed"));
|
|
409
440
|
await flushUsageWrites();
|
|
@@ -420,6 +451,7 @@ try {
|
|
|
420
451
|
await compressionSetup;
|
|
421
452
|
} catch (e) {
|
|
422
453
|
console.error(status("err", e.message));
|
|
454
|
+
await clientIntegration?.close().catch(() => {});
|
|
423
455
|
await closeHttpServer(activeServer, { timeoutMs: RUNTIME.shutdownTimeoutMs }).catch(() => {});
|
|
424
456
|
await flushUsageWrites();
|
|
425
457
|
await LOGGING.cleanup();
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Architecture boundaries
|
|
2
|
+
|
|
3
|
+
CCDX is one local Node service for Codex App. Client integration, image tools and
|
|
4
|
+
the dashboard are optional parts of that service, not a general plugin framework.
|
|
5
|
+
|
|
6
|
+
| Responsibility | Ownership | Boundary |
|
|
7
|
+
| --- | --- | --- |
|
|
8
|
+
| Core inference | `adapter.mjs`, Responses modules, model catalog, history | Copilot requests, streaming and recovery |
|
|
9
|
+
| Client integration | `client-integration.mjs`, Codex config, native prediction | Client setup, optional start/stop, diagnostic snapshots |
|
|
10
|
+
| Optional images | Image provider, CLI setup, image MCP and skill | Opt-in API access and image delivery; failures do not block core startup |
|
|
11
|
+
| Management | CLI, dashboard, observability, package updates | Bounded metadata and explicit user actions |
|
|
12
|
+
| Shared foundations | Codex paths, file locks, atomic files, network routes | No dependency on inference or dashboard rendering |
|
|
13
|
+
|
|
14
|
+
## Composition and lifecycle
|
|
15
|
+
|
|
16
|
+
The CLI composes the service. Client integration owns its `configure`, `start`,
|
|
17
|
+
`snapshot` and `close` operations. It does not forward inference requests or
|
|
18
|
+
render the dashboard. The adapter exposes integration snapshots and keeps
|
|
19
|
+
management/MCP routes separate from the Responses path.
|
|
20
|
+
|
|
21
|
+
Native prediction has a separate loopback transport and an isolated HTTPS agent.
|
|
22
|
+
Only its two selected hosts use the App-specific route. Non-configuration requests
|
|
23
|
+
on those hosts are forwarded unchanged. The bridge does not replace Copilot or
|
|
24
|
+
image-provider networking, modify client program files, or install system trust.
|
|
25
|
+
Static upstream proxy routes and bypass rules are preserved. Dynamic PAC/WPAD
|
|
26
|
+
and CIDR bypass rules are reported as unsupported, not silently discarded.
|
|
27
|
+
|
|
28
|
+
## Configuration ownership
|
|
29
|
+
|
|
30
|
+
`CODEX_HOME` selects Codex configuration. App profile/trust paths have their own
|
|
31
|
+
selection and are not inferred from that directory. CCDX writers use a shared
|
|
32
|
+
per-file lock, reread current contents and preserve unrelated values. Locks do
|
|
33
|
+
not coordinate editors or other applications that ignore them. Read-only status
|
|
34
|
+
and doctor commands do not write configuration.
|
|
35
|
+
|
|
36
|
+
Legacy public module exports remain available. This change adds a concrete
|
|
37
|
+
composition boundary; it does not relocate every file or add speculative APIs.
|
|
38
|
+
|
|
39
|
+
## Evidence and verification
|
|
40
|
+
|
|
41
|
+
Prediction preference, bridge readiness and observed configuration responses are
|
|
42
|
+
different states. None proves that a candidate appeared in the App. The dashboard
|
|
43
|
+
keeps that result unknown. Integration diagnostics retain bounded, redacted
|
|
44
|
+
metadata, not conversation or image contents.
|
|
45
|
+
|
|
46
|
+
Tests cover module dependency direction, default-off behavior, concurrent writers,
|
|
47
|
+
proxy handshakes, TLS validation, streaming, history isolation and release lookup.
|
|
48
|
+
Performance measurements distinguish request preparation from model latency.
|
|
49
|
+
Release reports describe a specific environment, not an SLA or a guarantee of
|
|
50
|
+
compatibility with every future client or corporate network policy.
|
package/docs/README.md
CHANGED
|
@@ -4,6 +4,8 @@ The [root README](../README.md) is the quick start; the [command/configuration
|
|
|
4
4
|
reference](REFERENCE.md) preserves complete current behavior and limits. `ccdx --help` and
|
|
5
5
|
`ccdx <command> --help` describe the installed package's CLI. Code and tests
|
|
6
6
|
resolve any discrepancy; CLI version and running-adapter version can differ.
|
|
7
|
+
The [architecture boundaries](ARCHITECTURE.md) explain module ownership,
|
|
8
|
+
optional integration lifecycle and configuration safety.
|
|
7
9
|
|
|
8
10
|
`ccdx doctor config` performs local, read-only configuration diagnostics and
|
|
9
11
|
previews the current startup writer. It does not claim to resolve the complete
|
|
@@ -15,6 +17,8 @@ These reports record a specific release and test environment. Their version,
|
|
|
15
17
|
test counts, timings, live-provider observations, and limitations remain
|
|
16
18
|
historical facts rather than current guarantees.
|
|
17
19
|
|
|
20
|
+
- [0.9.25: static proxy compatibility, integration boundaries and release diagnostics](RELEASE_0.9.25.md)
|
|
21
|
+
|
|
18
22
|
- [0.9.19: GitHub startup checks and stable-release updates](RELEASE_0.9.19.md)
|
|
19
23
|
- [0.9.21: compatibility-gated local history compression](RELEASE_0.9.21.md)
|
|
20
24
|
- [0.9.20: timing evidence, real-client checks and bounded analytics reuse](RELEASE_0.9.20.md)
|
package/docs/REFERENCE.md
CHANGED
|
@@ -6,78 +6,124 @@ CCDX is a local compatibility adapter for Codex App. It configures Codex to use
|
|
|
6
6
|
|
|
7
7
|
## How it works
|
|
8
8
|
|
|
9
|
-
###
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
### Retired prediction integration
|
|
10
|
+
|
|
11
|
+
The manual prediction MCP, automatic Stop hook and dashboard panel are removed.
|
|
12
|
+
CCDX does not install a prediction skill or replacement predictor. Startup disables
|
|
13
|
+
the old `suggestion.json` preference and removes only unchanged CCDX declarations
|
|
14
|
+
from the active `CODEX_HOME/config.toml` (or `~/.codex/config.toml`).
|
|
15
|
+
`CCDX_SUGGESTION_CONFIG` still identifies the legacy settings path for cleanup.
|
|
16
|
+
For an immediate cleanup without starting the adapter, run `ccdx suggestion off`.
|
|
17
|
+
The old `suggestion on` and `suggestion model` commands cannot re-enable it.
|
|
18
|
+
|
|
19
|
+
Modified, inline and profile-specific declarations are preserved. Cleanup failures
|
|
20
|
+
do not block the core adapter. Saved model preferences and old candidate files are
|
|
21
|
+
not deleted; they are inactive. Native Codex preference settings, hook trust records,
|
|
22
|
+
other hooks and the optional image MCP are untouched. Two inert compatibility
|
|
23
|
+
entrypoints prevent user-modified registrations from invoking a removed module:
|
|
24
|
+
the old Hook exits with an empty result, and the old MCP exposes no tools or panel.
|
|
25
|
+
|
|
26
|
+
### Optional native predictions
|
|
27
|
+
|
|
28
|
+
Native next-message predictions are **off by default** and use no MCP, Hook, skill,
|
|
29
|
+
panel, renderer injection, or client-program modification. This macOS-only
|
|
30
|
+
compatibility feature uses the App's existing composer UI and the conversation's
|
|
31
|
+
selected model through CCDX. Suggestions are not sent automatically. Native
|
|
32
|
+
eligibility rules still apply; availability is not promised for every thread type.
|
|
13
33
|
|
|
14
34
|
```bash
|
|
15
|
-
|
|
16
|
-
ccdx
|
|
17
|
-
|
|
18
|
-
ccdx
|
|
19
|
-
ccdx
|
|
35
|
+
# Fully quit Codex App first.
|
|
36
|
+
ccdx prediction on
|
|
37
|
+
# Restart the running CCDX process, then launch Codex through ccdx.
|
|
38
|
+
ccdx
|
|
39
|
+
ccdx prediction status
|
|
40
|
+
|
|
41
|
+
# To remove the optional setup, fully quit Codex first:
|
|
42
|
+
ccdx prediction off
|
|
20
43
|
```
|
|
21
44
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
45
|
+
Enabling explicitly adds a private certificate trust record to the selected App
|
|
46
|
+
profile and a process-scoped PAC route for `chatgpt.com` and `ab.chatgpt.com` only.
|
|
47
|
+
HTTPS traffic for **all paths on those two hosts** is decrypted and forwarded
|
|
48
|
+
locally; PAC cannot select HTTPS paths before TLS. Only the bootstrap prediction
|
|
49
|
+
flag, prediction configuration, and corresponding Statsig refresh values are
|
|
50
|
+
overlaid. Other paths preserve upstream status, cookies, streaming and WebSocket
|
|
51
|
+
traffic. Upstream TLS verification stays enabled; no OS trust, global proxy, login,
|
|
52
|
+
account identity or account-permission value is rewritten. Credentials are not
|
|
53
|
+
logged or persisted by the bridge. The local private key has owner-only permissions;
|
|
54
|
+
its signing key is discarded after certificate creation.
|
|
55
|
+
|
|
56
|
+
Static proxy settings are composed with the local bridge. For HTTPS targets,
|
|
57
|
+
`https_proxy` takes precedence over `HTTPS_PROXY`, then `all_proxy`/`ALL_PROXY`,
|
|
58
|
+
then the macOS HTTPS proxy or SOCKS proxy. HTTP targets follow their corresponding
|
|
59
|
+
HTTP setting. An HTTP-only environment proxy is not used for HTTPS. HTTP CONNECT,
|
|
60
|
+
TLS to an HTTPS proxy, SOCKS5 (including username/password), `NO_PROXY`/`no_proxy`,
|
|
61
|
+
system exceptions and simple-host exclusions are supported. Proxy credentials
|
|
62
|
+
remain in memory, are never included in PAC responses or diagnostics, and are
|
|
63
|
+
sent only to the proxy. TLS verification remains enabled for both proxy and target.
|
|
64
|
+
Other App domains keep the resolved original route; if a bridge fails, its PAC
|
|
65
|
+
fallback uses that route rather than adding an unrequested direct connection.
|
|
66
|
+
Route selection is a startup snapshot; restart CCDX and Codex after changing it.
|
|
67
|
+
Bypass lists support host/domain patterns and optional ports. Unsupported CIDR
|
|
68
|
+
notation is reported explicitly rather than silently changing the route.
|
|
69
|
+
|
|
70
|
+
Dynamic PAC/WPAD is not executed or overwritten. Setup identifies the exact
|
|
71
|
+
system setting and preserves its rules. A non-default `CODEX_API_BASE_URL` is
|
|
72
|
+
also preserved and reported as a custom-route conflict; setting it to the normal
|
|
73
|
+
`https://chatgpt.com/backend-api` does not cause a conflict. No automatic direct
|
|
74
|
+
fallback after upstream-proxy rejection is added. The default App profile
|
|
75
|
+
is `~/Library/Application Support/Codex`; an explicit
|
|
76
|
+
`CODEX_ELECTRON_USER_DATA_PATH` is respected. Quit the App before trust changes;
|
|
77
|
+
CCDX never kills it. The launcher uses the exact App that passed the compatibility
|
|
78
|
+
check. Updating the App invalidates that check: quit it and run `prediction on`
|
|
79
|
+
again. Unknown client/store/configuration formats are not forcibly rewritten.
|
|
80
|
+
These are checked compatibility boundaries, not a promise for every future App.
|
|
81
|
+
|
|
82
|
+
The bridge changes only its own prediction fields and preserves already-enabled
|
|
83
|
+
official prediction configuration. A missing prediction-config route can receive
|
|
84
|
+
CCDX's own short JSON-suggestion prompt using low reasoning effort. Authentication,
|
|
85
|
+
permission, rate-limit and server errors are returned unchanged. Full and live
|
|
86
|
+
refresh schemas are supported; delta requests ask for complete values to avoid
|
|
87
|
+
merging upstream checksums with locally changed fields. Configuration bodies are
|
|
88
|
+
bounded at 16 MiB; larger or unknown bodies pass through without an overlay.
|
|
89
|
+
No extra inference or bridge exists for users who leave the feature disabled.
|
|
90
|
+
When enabled, prediction requests consume Copilot usage; the setting does not
|
|
91
|
+
provide a separate prediction-model picker.
|
|
92
|
+
|
|
93
|
+
`prediction off` immediately disables new local overlays. Quit/reopen Codex to
|
|
94
|
+
clear its cached predictions and temporary route. If the App is still running,
|
|
95
|
+
trust removal is deferred; quit it and run `prediction off` again. Only the exact
|
|
96
|
+
owned certificate record is removed, never the whole store. Failed activation
|
|
97
|
+
rolls back newly added trust; certificate replacement keeps old trust until the
|
|
98
|
+
new preference is committed. If the bridge stops, new connections can fall back
|
|
99
|
+
to the original route; already-interrupted requests are not replayed. Run `ccdx`
|
|
100
|
+
after quitting Codex to attach a newly started bridge. `CCDX_AUTO_LAUNCH=0` keeps
|
|
101
|
+
automatic launch disabled and does not attach the route to a manually opened App.
|
|
102
|
+
Optional prediction failures never prevent the core adapter or image service from
|
|
103
|
+
starting. `prediction status` reports the saved preference and, when a compatible
|
|
104
|
+
running adapter responds, its bridge state, configuration-response observations
|
|
105
|
+
and bounded TLS/upstream errors. The dashboard uses the same snapshot and manual
|
|
106
|
+
refresh. Configuration traffic is evidence of a request reaching the bridge, not
|
|
107
|
+
proof of a generated/displayed candidate. Candidate visibility remains unknown;
|
|
108
|
+
no prompt matching, UI injection, transcript scanning or extra inference is used
|
|
109
|
+
to invent that status. Prediction settings are stored separately in
|
|
110
|
+
`~/.config/codex-copilot-dx/native-prediction/` (or under `XDG_CONFIG_HOME`).
|
|
111
|
+
|
|
112
|
+
### Configuration ownership
|
|
113
|
+
|
|
114
|
+
Core setup, image setup/guidance, config doctor, optional history compression and
|
|
115
|
+
legacy prediction cleanup resolve the same `CODEX_HOME/config.toml`; absent
|
|
116
|
+
`CODEX_HOME`, they use `~/.codex/config.toml`. An explicit function-level file path
|
|
117
|
+
still takes precedence for embedders. App-profile trust is a separate location
|
|
118
|
+
selected by `CODEX_ELECTRON_USER_DATA_PATH`, not by `CODEX_HOME`.
|
|
119
|
+
|
|
120
|
+
CCDX-owned config mutations share an owner-recorded cross-process lock, reread
|
|
121
|
+
under the lock, and retain existing atomic replacement/rollback checks. User
|
|
122
|
+
settings updates use a separate lock for their shared JSON file; prediction
|
|
123
|
+
on/off uses its own settings lock. Readers take no lock and write no lock file.
|
|
124
|
+
Contention fails with a retry message instead of stealing a live lock. Other
|
|
125
|
+
applications do not participate in these locks, so snapshot conflict checks still
|
|
126
|
+
apply; the locks do not claim a global filesystem transaction.
|
|
81
127
|
|
|
82
128
|
### Core adapter
|
|
83
129
|
|
|
@@ -133,7 +179,7 @@ On a normal launch, CCDX:
|
|
|
133
179
|
1. Prints the installed package version and checks for a newer npm release in the background.
|
|
134
180
|
2. Reuses a compatible running adapter when available; otherwise it reuses a compatible local Copilot credential or starts GitHub Device Flow when authentication is required.
|
|
135
181
|
3. Loads a usable model cache or attempts a live refresh, then starts listening. A cache older than two hours refreshes in the background; a fresh cache can be used immediately. A failed refresh retains the last-known-good list when one is available.
|
|
136
|
-
4. Checks the startup-managed settings in `~/.codex/config.toml
|
|
182
|
+
4. Checks the startup-managed settings in `CODEX_HOME/config.toml` (default `~/.codex/config.toml`), including the local `/v1` endpoint.
|
|
137
183
|
5. Attempts to open Codex App on macOS unless `CCDX_AUTO_LAUNCH` disables it.
|
|
138
184
|
|
|
139
185
|
The `OPENAI_API_KEY=dummy` value used in the Codex shell environment is only a client-side placeholder. It is not a GitHub credential. CCDX exchanges the saved GitHub OAuth credential for short-lived Copilot service tokens internally.
|
|
@@ -148,7 +194,7 @@ If a compatible adapter is already running, a later launch reuses it and checks
|
|
|
148
194
|
|
|
149
195
|
### Codex configuration writes
|
|
150
196
|
|
|
151
|
-
Normal startup and reuse of an existing adapter check `~/.codex/config.toml` once, after startup prerequisites succeed. There is no file watcher or periodic configuration rewrite.
|
|
197
|
+
Normal startup and reuse of an existing adapter check `CODEX_HOME/config.toml` (default `~/.codex/config.toml`) once, after startup prerequisites succeed. There is no file watcher or periodic configuration rewrite. Startup, image setup, config doctor, compression and legacy prediction cleanup share this path. CCDX does not edit project-level Codex files.
|
|
152
198
|
|
|
153
199
|
| Setting | Existing file | New file |
|
|
154
200
|
| --- | --- | --- |
|
|
@@ -310,7 +356,14 @@ ccdx update npm
|
|
|
310
356
|
ccdx update github
|
|
311
357
|
```
|
|
312
358
|
|
|
313
|
-
Normal startup checks the
|
|
359
|
+
Normal startup checks the official GitHub `releases/latest` web endpoint once in
|
|
360
|
+
the background, without accessing the npm registry or REST API. The anonymous
|
|
361
|
+
check requires no PAT or Copilot credentials, has a two-second deadline, validates
|
|
362
|
+
only the redirect header, cancels the response body without reading HTML, and
|
|
363
|
+
silently skips errors. Redirects must use HTTPS, the exact GitHub repository and
|
|
364
|
+
a stable version tag with no credentials, query or fragment. It never follows
|
|
365
|
+
the redirect, retries, polls, installs or restarts. On adapter reuse, Ready is
|
|
366
|
+
displayed before waiting for any remaining check budget.
|
|
314
367
|
|
|
315
368
|
`ccdx update gh` is accepted as shorthand for the GitHub source. The npm source installs `codex-copilot-dx@latest` through the registry already configured for npm, including a company mirror. The GitHub source queries the latest stable published Release (ten-second deadline), validates its version tag, and installs that exact tag from `DaleXiao/codex-copilot-dx`, not `main`. Lookup failure stops before installation, without an npm fallback. It opts in to Git fetching only for that command and does not change npm's persistent `allow-git` setting.
|
|
316
369
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-copilot-dx",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.25",
|
|
4
4
|
"description": "Use Codex App with GitHub Copilot",
|
|
5
5
|
"author": "Dale Xiao",
|
|
6
6
|
"type": "module",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"scripts/benchmark-probes.mjs",
|
|
16
16
|
"scripts/fixtures/",
|
|
17
17
|
"README.md",
|
|
18
|
-
"docs/REFERENCE.md"
|
|
18
|
+
"docs/REFERENCE.md",
|
|
19
|
+
"docs/ARCHITECTURE.md"
|
|
19
20
|
],
|
|
20
21
|
"keywords": [
|
|
21
22
|
"codex",
|
package/src/adapter.mjs
CHANGED
|
@@ -64,7 +64,7 @@ export {
|
|
|
64
64
|
|
|
65
65
|
const ADAPTER_RUNTIME_CONFIG = loadRuntimeConfig();
|
|
66
66
|
const DASHBOARD_PATHS = new Set(["/", "/ui.css", "/theme.js", "/language.js", "/ui.js"]);
|
|
67
|
-
const DASHBOARD_API_PATHS = new Set(["/_ccdx/ui/animation", "/_ccdx/ui/models/live", "/_ccdx/ui/usage", "/_ccdx/ui/auth"
|
|
67
|
+
const DASHBOARD_API_PATHS = new Set(["/_ccdx/ui/animation", "/_ccdx/ui/models/live", "/_ccdx/ui/usage", "/_ccdx/ui/auth"]);
|
|
68
68
|
|
|
69
69
|
export function requestPath(reqUrl) {
|
|
70
70
|
return new URL(reqUrl || "/", "http://localhost").pathname;
|
|
@@ -236,13 +236,16 @@ export function createAdapterHandler(options = {}) {
|
|
|
236
236
|
codexClient,
|
|
237
237
|
codexModelRegistry,
|
|
238
238
|
codexModelCatalog,
|
|
239
|
+
clientIntegrations: options.clientIntegrationSnapshot?.(),
|
|
239
240
|
})));
|
|
240
241
|
return;
|
|
241
242
|
}
|
|
242
243
|
|
|
243
244
|
if (req.method === "GET" && pathname === ADAPTER_HEALTH_PATH) {
|
|
244
245
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
245
|
-
|
|
246
|
+
const predictionPac = isLoopbackAddress(req.socket?.remoteAddress) && isLoopbackHostHeader(req.headers?.host)
|
|
247
|
+
? options.nativePredictionPac?.() : null;
|
|
248
|
+
res.end(JSON.stringify({ ...adapterHealthPayload(), ...(predictionPac ? { native_prediction_pac: predictionPac } : {}) }));
|
|
246
249
|
return;
|
|
247
250
|
}
|
|
248
251
|
|