codex-copilot-dx 0.6.7 → 0.6.9
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 +47 -21
- package/package.json +1 -1
- package/src/cli-status.mjs +2 -2
- package/src/config.mjs +18 -0
- package/src/observability.mjs +0 -4
- package/src/pm-studio-asar.mjs +193 -50
- package/src/pm-studio-relay.mjs +40 -30
- package/src/pm-studio-setup.mjs +398 -54
- package/src/pm-studio-status.mjs +67 -7
- package/src/responses-request.mjs +16 -2
- package/src/running-adapter.mjs +3 -1
package/src/pm-studio-status.mjs
CHANGED
|
@@ -16,6 +16,11 @@ import {
|
|
|
16
16
|
pmStudioPatchManifestPath,
|
|
17
17
|
} from "./pm-studio-setup.mjs";
|
|
18
18
|
import { readAdapterStatus } from "./cli-status.mjs";
|
|
19
|
+
import {
|
|
20
|
+
PM_STUDIO_RELAY_MARKER_HEADER,
|
|
21
|
+
PM_STUDIO_RELAY_MARKER_VALUE,
|
|
22
|
+
PM_STUDIO_RELAY_PREFIX,
|
|
23
|
+
} from "./pm-studio-relay.mjs";
|
|
19
24
|
import { checkRunningAdapter } from "./running-adapter.mjs";
|
|
20
25
|
import { status } from "./status.mjs";
|
|
21
26
|
import {
|
|
@@ -27,12 +32,11 @@ import {
|
|
|
27
32
|
|
|
28
33
|
const PM_RELAY_HOST = "127.0.0.1";
|
|
29
34
|
const PM_RELAY_PORT = 2026;
|
|
30
|
-
const
|
|
35
|
+
const PM_RELAY_PROBE_TIMEOUT_MS = 500;
|
|
36
|
+
const PM_RELAY_CAPABILITY = "pm_studio_split_origin_v1";
|
|
31
37
|
const PM_RELAY_ROUTE_NAMES = Object.freeze([
|
|
32
38
|
"pm_models",
|
|
33
39
|
"pm_chat_completions",
|
|
34
|
-
"pm_responses",
|
|
35
|
-
"pm_embeddings",
|
|
36
40
|
]);
|
|
37
41
|
|
|
38
42
|
function selectRecipe(metadata, recipes) {
|
|
@@ -45,6 +49,31 @@ function safeMessage(error) {
|
|
|
45
49
|
return String(error?.message || "inspection failed").replace(/\s+/g, " ").trim();
|
|
46
50
|
}
|
|
47
51
|
|
|
52
|
+
export async function probePmStudioRelay({
|
|
53
|
+
baseUrl,
|
|
54
|
+
fetchImpl = fetch,
|
|
55
|
+
timeoutMs = PM_RELAY_PROBE_TIMEOUT_MS,
|
|
56
|
+
} = {}) {
|
|
57
|
+
const controller = new AbortController();
|
|
58
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
59
|
+
try {
|
|
60
|
+
const response = await fetchImpl(new URL(`${PM_STUDIO_RELAY_PREFIX}/models`, baseUrl).href, {
|
|
61
|
+
method: "GET",
|
|
62
|
+
headers: { Accept: "application/json" },
|
|
63
|
+
redirect: "error",
|
|
64
|
+
signal: controller.signal,
|
|
65
|
+
});
|
|
66
|
+
const result = {
|
|
67
|
+
status: response.status,
|
|
68
|
+
marker: response.headers.get(PM_STUDIO_RELAY_MARKER_HEADER) || "",
|
|
69
|
+
};
|
|
70
|
+
await response.body?.cancel().catch(() => {});
|
|
71
|
+
return result;
|
|
72
|
+
} finally {
|
|
73
|
+
clearTimeout(timer);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
48
77
|
function inspectClaudeProfile(home, readCredentials) {
|
|
49
78
|
try {
|
|
50
79
|
const credentials = readCredentials(AUTH_PROFILE_CLAUDE, { home });
|
|
@@ -73,7 +102,7 @@ function inspectAdapterRuntime(adapter, runtimeStatus) {
|
|
|
73
102
|
issues.push("health and runtime status do not describe the same adapter instance");
|
|
74
103
|
}
|
|
75
104
|
const capabilities = new Set(Array.isArray(data.capabilities) ? data.capabilities : []);
|
|
76
|
-
if (!capabilities.has(PM_RELAY_CAPABILITY)) issues.push("PM Studio relay capability is missing");
|
|
105
|
+
if (!capabilities.has(PM_RELAY_CAPABILITY)) issues.push("PM Studio split-origin relay capability is missing");
|
|
77
106
|
if (data.profiles?.claude?.mode !== "isolated") issues.push("Claude profile mode is not isolated");
|
|
78
107
|
if (data.profiles?.claude?.profile_current !== true) {
|
|
79
108
|
issues.push("running Claude credentials do not match the current isolated profile");
|
|
@@ -93,6 +122,21 @@ function inspectAdapterRuntime(adapter, runtimeStatus) {
|
|
|
93
122
|
};
|
|
94
123
|
}
|
|
95
124
|
|
|
125
|
+
function inspectRelayProbe(runtime, probe) {
|
|
126
|
+
const relayProbe = {
|
|
127
|
+
status: probe?.status,
|
|
128
|
+
marker: String(probe?.marker || ""),
|
|
129
|
+
};
|
|
130
|
+
const issues = [...runtime.issues];
|
|
131
|
+
if (relayProbe.status !== 401) {
|
|
132
|
+
issues.push(`PM Studio relay probe returned HTTP ${relayProbe.status ?? "unknown"}; expected 401`);
|
|
133
|
+
}
|
|
134
|
+
if (relayProbe.marker !== PM_STUDIO_RELAY_MARKER_VALUE) {
|
|
135
|
+
issues.push("PM Studio relay compatibility marker is missing or incompatible");
|
|
136
|
+
}
|
|
137
|
+
return { ...runtime, relayProbe, ok: issues.length === 0, issues };
|
|
138
|
+
}
|
|
139
|
+
|
|
96
140
|
export async function inspectPmStudioStatus({
|
|
97
141
|
appPath = DEFAULT_PM_STUDIO_APP_PATH,
|
|
98
142
|
home = os.homedir(),
|
|
@@ -105,6 +149,7 @@ export async function inspectPmStudioStatus({
|
|
|
105
149
|
readClaudeCredentials = readAuthProfileCredentials,
|
|
106
150
|
checkRunningAdapterFn = checkRunningAdapter,
|
|
107
151
|
readAdapterStatusFn = readAdapterStatus,
|
|
152
|
+
probePmStudioRelayFn = probePmStudioRelay,
|
|
108
153
|
} = {}) {
|
|
109
154
|
const operations = createPmStudioSetupOperations(operationOverrides);
|
|
110
155
|
let app;
|
|
@@ -163,6 +208,18 @@ export async function inspectPmStudioStatus({
|
|
|
163
208
|
} catch (error) {
|
|
164
209
|
runtime = { ok: false, baseUrl: adapter.baseUrl, data: null, issues: [safeMessage(error)] };
|
|
165
210
|
}
|
|
211
|
+
if (runtime.data) {
|
|
212
|
+
try {
|
|
213
|
+
runtime = inspectRelayProbe(runtime, await probePmStudioRelayFn({ baseUrl: adapter.baseUrl }));
|
|
214
|
+
} catch (error) {
|
|
215
|
+
runtime = {
|
|
216
|
+
...runtime,
|
|
217
|
+
ok: false,
|
|
218
|
+
relayProbe: null,
|
|
219
|
+
issues: [...runtime.issues, `PM Studio relay probe failed: ${safeMessage(error)}`],
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
}
|
|
166
223
|
}
|
|
167
224
|
const operational = app.state === "patched"
|
|
168
225
|
&& app.patchRecord?.valid === true
|
|
@@ -182,6 +239,9 @@ function appStatusItem(result, commandName) {
|
|
|
182
239
|
const reason = app.patchRecord?.reason || "installed patch record is missing";
|
|
183
240
|
return { kind: "err", component: "App patch", detail: `${version}; patch record not verified`, message: `PM Studio ${version} matches the patch recipe, but its installed patch record is not verified: ${reason}` };
|
|
184
241
|
}
|
|
242
|
+
if (app.state === "legacy") {
|
|
243
|
+
return { kind: "err", component: "App patch", detail: `${version}; legacy global-origin patch`, message: `PM Studio ${version} has a legacy global-origin patch; run ${commandName} pms setup to migrate` };
|
|
244
|
+
}
|
|
185
245
|
if (app.state === "clean") return { kind: "warn", component: "App patch", detail: `${version}; supported, not patched`, message: `PM Studio ${version} is supported but not patched; run ${commandName} pms setup` };
|
|
186
246
|
if (app.state === "unsupported") return { kind: "err", component: "App patch", detail: `${version}; unsupported version`, message: `PM Studio ${version} has no exact patch recipe; no files will be changed` };
|
|
187
247
|
if (app.state === "drift" && app.patchRecipeMatched) {
|
|
@@ -203,7 +263,7 @@ function pmStudioStatusItems(result, commandName) {
|
|
|
203
263
|
items.push({ kind: "err", component: "Claude profile", detail: "not ready", message: `Isolated Claude profile is not ready${reason}; run ${PM_STUDIO_CLAUDE_AUTH_COMMAND}` });
|
|
204
264
|
}
|
|
205
265
|
if (result.adapter?.ok && result.runtime?.ok) {
|
|
206
|
-
items.push({ kind: "ok", component: "PM relay", detail: `verified at ${result.adapter.baseUrl}`, message: `PM
|
|
266
|
+
items.push({ kind: "ok", component: "PM relay", detail: `verified at ${result.adapter.baseUrl}`, message: `PM model discovery and isolated Claude routing are verified at ${result.adapter.baseUrl}` });
|
|
207
267
|
} else if (result.adapter?.ok) {
|
|
208
268
|
const reason = result.runtime?.issues?.join("; ") || "runtime status is unavailable";
|
|
209
269
|
items.push({ kind: "err", component: "PM relay", detail: "running but routing not ready", message: `The adapter is running at ${result.adapter.baseUrl}, but PM relay routing is not ready: ${reason}; stop it and run ${commandName} start` });
|
|
@@ -213,9 +273,9 @@ function pmStudioStatusItems(result, commandName) {
|
|
|
213
273
|
items.push({ kind: "warn", component: "PM relay", detail: `not running at ${PM_RELAY_HOST}:${PM_RELAY_PORT}`, message: `PM relay is not running at http://${PM_RELAY_HOST}:${PM_RELAY_PORT}; run ${commandName} start` });
|
|
214
274
|
}
|
|
215
275
|
if (result.runtime?.ok) {
|
|
216
|
-
items.push({ kind: "info", component: "Routing", detail: "GPT ->
|
|
276
|
+
items.push({ kind: "info", component: "Routing", detail: "GPT -> native official; models/Claude -> local", message: "Routing: PM GPT uses its native official GitHub Copilot path; model discovery and eligible Claude chat use the local CCDX relay" });
|
|
217
277
|
} else {
|
|
218
|
-
items.push({ kind: "info", component: "Routing", detail: "expected: GPT ->
|
|
278
|
+
items.push({ kind: "info", component: "Routing", detail: "expected: GPT -> native official; models/Claude -> local", message: "Expected routing: PM GPT uses its native official GitHub Copilot path; model discovery and eligible Claude chat use the local CCDX relay" });
|
|
219
279
|
}
|
|
220
280
|
return items;
|
|
221
281
|
}
|
|
@@ -65,9 +65,21 @@ function replayableResponsesOutputItems(output) {
|
|
|
65
65
|
return output.filter((item) => item && typeof item === "object");
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
function isEncryptedContentPart(value) {
|
|
69
|
+
return value && typeof value === "object" && value.type === "encrypted_content";
|
|
70
|
+
}
|
|
71
|
+
|
|
68
72
|
function stripEncryptedReasoningValue(value, state) {
|
|
69
73
|
if (Array.isArray(value)) {
|
|
70
|
-
|
|
74
|
+
const out = [];
|
|
75
|
+
for (const item of value) {
|
|
76
|
+
if (isEncryptedContentPart(item)) {
|
|
77
|
+
state.changed = true;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
out.push(stripEncryptedReasoningValue(item, state));
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
71
83
|
}
|
|
72
84
|
|
|
73
85
|
if (value && typeof value === "object") {
|
|
@@ -87,7 +99,9 @@ function stripEncryptedReasoningValue(value, state) {
|
|
|
87
99
|
|
|
88
100
|
function isEncryptedReasoningInputItem(item) {
|
|
89
101
|
return item && typeof item === "object"
|
|
90
|
-
&& (item.type === "reasoning"
|
|
102
|
+
&& (item.type === "reasoning"
|
|
103
|
+
|| item.type === "encrypted_content"
|
|
104
|
+
|| Object.prototype.hasOwnProperty.call(item, "encrypted_content"));
|
|
91
105
|
}
|
|
92
106
|
|
|
93
107
|
export function sanitizeEncryptedReasoningRequest(reqContext) {
|
package/src/running-adapter.mjs
CHANGED
|
@@ -5,7 +5,9 @@ export const ADAPTER_HEALTH_PATH = "/_ccdx/health";
|
|
|
5
5
|
export const ADAPTER_STATUS_PATH = "/_ccdx/status";
|
|
6
6
|
export const ADAPTER_PROTOCOL_VERSION = 2;
|
|
7
7
|
export const ADAPTER_VERSION = localPackageVersion();
|
|
8
|
-
export const ADAPTER_CAPABILITIES = Object.freeze([
|
|
8
|
+
export const ADAPTER_CAPABILITIES = Object.freeze([
|
|
9
|
+
"pm_studio_split_origin_v1",
|
|
10
|
+
]);
|
|
9
11
|
const ADAPTER_INSTANCE_ID = randomUUID();
|
|
10
12
|
|
|
11
13
|
export function adapterHealthPayload() {
|