codex-copilot-dx 0.6.12 → 0.6.13
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 +26 -36
- package/package.json +1 -1
- package/src/doctor.mjs +2 -2
- package/src/pm-studio-asar.mjs +136 -22
- package/src/pm-studio-setup.mjs +103 -301
- package/src/pm-studio-status.mjs +15 -22
- package/src/pm-studio-provenance.mjs +0 -701
package/README.md
CHANGED
|
@@ -118,15 +118,15 @@ discovery tries the compatible local CCDX merge first, and only exact enabled
|
|
|
118
118
|
Anthropic model IDs use the isolated CCDX Claude profile. Neither credential is
|
|
119
119
|
copied into the other application.
|
|
120
120
|
|
|
121
|
-
CCDX
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
ambiguous module, changed request transport, unsupported
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
121
|
+
CCDX treats the local PM Studio App selected for setup as the source of truth.
|
|
122
|
+
Its version and build label backup and recovery records; neither they nor the
|
|
123
|
+
installation source or original signature are compatibility admission gates.
|
|
124
|
+
Setup derives a source-bound recipe whenever the local ASAR integrity metadata
|
|
125
|
+
and exactly one compatible Copilot configuration module can be verified. A
|
|
126
|
+
missing or ambiguous module, changed request transport, or unsupported
|
|
127
|
+
integrity policy is rejected without modifying the App. Authorize the isolated
|
|
128
|
+
Claude profile first, quit PM Studio and its updater, then run the one-time
|
|
129
|
+
setup command:
|
|
130
130
|
|
|
131
131
|
```bash
|
|
132
132
|
ccdx auth login claude --reauth --github-login <personal-github-login>
|
|
@@ -142,29 +142,20 @@ ccdx pms status
|
|
|
142
142
|
|
|
143
143
|
`ccdx pm-studio status` and `ccdx pm-studio setup` are equivalent long-form aliases.
|
|
144
144
|
|
|
145
|
-
`ccdx pms setup` performs preflight,
|
|
146
|
-
integrity, signing, and replacement work. It
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
(apart from strictly scoped locale pruning) before any backup or staging write.
|
|
154
|
-
Network, hash, tree, structure, partial-patch, running-process, space, and every
|
|
155
|
-
other pre-replacement failure leave the installed App unchanged. If final
|
|
145
|
+
`ccdx pms setup` performs local preflight, structural verification, backup,
|
|
146
|
+
staging, integrity, signing, and replacement work. It does not access a PM
|
|
147
|
+
Studio repository, release asset, PAT, or source-signing service. It never
|
|
148
|
+
starts Device Flow, the adapter, Codex, or PM Studio, and it does not modify PM
|
|
149
|
+
profiles, cached model lists, or saved PM tokens. Local fingerprints bind the
|
|
150
|
+
recipe, backup, staged App, and installed App without deciding whether the
|
|
151
|
+
original package is trusted. Structure, partial-patch, running-process, space,
|
|
152
|
+
and every other pre-replacement failure leave the installed App unchanged. If final
|
|
156
153
|
read-only verification after an atomic replacement detects exceptional
|
|
157
154
|
filesystem drift, setup does not attempt a second automatic write: it preserves
|
|
158
155
|
the verified backup, retains any diagnostic stage still present, and prints
|
|
159
156
|
recovery paths. Repeating setup reuses the version/source-bound verified backup
|
|
160
|
-
and is idempotent
|
|
161
|
-
|
|
162
|
-
Some official PM Studio artifacts can fail macOS's vendor-signature verifier
|
|
163
|
-
even though their signing metadata remains readable. CCDX does not generally
|
|
164
|
-
ignore that failure: exact built-in recipes require their frozen official
|
|
165
|
-
fingerprint, while compatible unknown versions require the verified official
|
|
166
|
-
GitHub asset and tree comparison described above. The staged and installed
|
|
167
|
-
CCDX patch must still pass strict ad-hoc signature verification and match the
|
|
157
|
+
and is idempotent. The staged and installed CCDX patch must still pass strict
|
|
158
|
+
ad-hoc signature verification, use the App's bundle identifier, and match the
|
|
168
159
|
complete patched-tree record in the backup manifest.
|
|
169
160
|
|
|
170
161
|
The patch uses split origins, not an App-wide proxy. GPT and other non-Claude
|
|
@@ -183,9 +174,9 @@ CCDX uses the PM bearer only to fetch or validate official model access; it is
|
|
|
183
174
|
never used as the credential for the isolated Claude upstream request. Keep
|
|
184
175
|
port 2026 local to the machine.
|
|
185
176
|
|
|
186
|
-
Patching
|
|
177
|
+
Patching applies an ad-hoc signature to the staged App. PM Studio's
|
|
187
178
|
updater is not disabled; an official update may overwrite the patch or may
|
|
188
|
-
require reinstalling
|
|
179
|
+
require reinstalling PM Studio. Setup prints the verified backup and
|
|
189
180
|
manifest paths plus the version-matched restore procedure. Never restore a
|
|
190
181
|
backup over a different PM Studio version or build.
|
|
191
182
|
|
|
@@ -202,7 +193,7 @@ BACKUP_APP="<verified-backup-path-from-ccdx-pms-setup>"
|
|
|
202
193
|
```
|
|
203
194
|
|
|
204
195
|
Only when all four values match each other and the version/build recorded in the
|
|
205
|
-
source-bound manifest, move the patched App aside, restore the complete
|
|
196
|
+
source-bound manifest, move the patched App aside, restore the complete local
|
|
206
197
|
bundle, and verify it before launch:
|
|
207
198
|
|
|
208
199
|
```bash
|
|
@@ -214,12 +205,11 @@ mv "/Applications/PM Studio.app" "$PATCHED_APP"
|
|
|
214
205
|
ccdx pms status
|
|
215
206
|
```
|
|
216
207
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
or both verification paths fail,
|
|
208
|
+
The App-patch row from `ccdx pms status` must classify the restored bundle as
|
|
209
|
+
the recorded clean local content rather than integrity drift. If the version
|
|
210
|
+
check, copy, or either verification path fails,
|
|
221
211
|
do not launch the restored App. Keep the moved patched bundle at `$PATCHED_APP`
|
|
222
|
-
and reinstall
|
|
212
|
+
and reinstall PM Studio instead of applying a version-mismatched
|
|
223
213
|
backup. CCDX never runs these restore commands or `sudo` automatically.
|
|
224
214
|
|
|
225
215
|
To change the model used by Codex Auto-review, run:
|
package/package.json
CHANGED
package/src/doctor.mjs
CHANGED
|
@@ -599,11 +599,11 @@ export async function collectDoctorChecks({
|
|
|
599
599
|
} else if (pm.app.state === "clean") {
|
|
600
600
|
checks.push({
|
|
601
601
|
kind: "warn",
|
|
602
|
-
message: `PM Studio ${version}
|
|
602
|
+
message: `PM Studio ${version} has a compatible local patch structure but is not patched`,
|
|
603
603
|
fix: "ccdx pms setup",
|
|
604
604
|
});
|
|
605
605
|
} else if (pm.app.state === "unsupported") {
|
|
606
|
-
checks.push({ kind: "warn", message: `PM Studio ${version}
|
|
606
|
+
checks.push({ kind: "warn", message: `PM Studio ${version} does not expose one uniquely compatible patch structure; no files will be changed` });
|
|
607
607
|
} else if (pm.app.state === "drift" || pm.app.state === "error") {
|
|
608
608
|
checks.push({ kind: "err", message: `PM Studio integrity check failed: ${pm.app.issues.join("; ")}` });
|
|
609
609
|
}
|
package/src/pm-studio-asar.mjs
CHANGED
|
@@ -8,17 +8,42 @@ export const ELECTRON_ASAR_INTEGRITY_SENTINEL = "AGbevlPCksUGKNL8TSn7wGmJEuJsXb2
|
|
|
8
8
|
const PM_STUDIO_COPILOT_CONFIG_MODULE_LENGTH = 2_121;
|
|
9
9
|
const PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE_SHA256 = "3da6245d676015ab6cd26e4d6a0d2f54894a687c370aa419c5ad170533d086aa";
|
|
10
10
|
const PM_STUDIO_COPILOT_CONFIG_MODULE_ANCHOR = "47024(I,e,t){";
|
|
11
|
+
const PM_STUDIO_COPILOT_CONFIG_MODULE_SENTINEL = `API_ENDPOINT:"${PM_STUDIO_ORIGIN}"`;
|
|
11
12
|
const PM_STUDIO_COPILOT_CONFIG_MODULE_PATH = "dist/main/main.js";
|
|
12
13
|
const PM_STUDIO_COMPATIBILITY_ID = "exact-copilot-config-module-v1";
|
|
13
14
|
const PM_STUDIO_COMPATIBLE_TARGET_MAX_BYTES = 128 * 1024 * 1024;
|
|
14
15
|
const PM_STUDIO_COMPATIBLE_BLOCK_MAX_COUNT = 16_384;
|
|
16
|
+
const PM_STUDIO_COMPATIBLE_MODULE_PREFIX_MAX_BYTES = 512;
|
|
17
|
+
const PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE = '47024(I,e,t){"use strict";t.d(e,{qn:()=>l});const l={CLIENT_ID:"Iv1.b507a08c87ecfe98",CLIENT_SECRET:void 0,API_ENDPOINT:"https://api.githubcopilot.com",DEVICE_CODE_URL:"https://github.com/login/device/code",ACCESS_TOKEN_URL:"https://github.com/login/oauth/access_token",COPILOT_TOKEN_URL:"https://api.github.com/copilot_internal/v2/token",USER_AGENT:"GitHubCopilotChat/0.26.7",EDITOR_VERSION:"vscode/1.99.3",EDITOR_PLUGIN_VERSION:"copilot-chat/0.26.7",INTEGRATION_ID:"vscode-chat",STANDARD_HEADERS:{Accept:"application/json","Content-Type":"application/json","User-Agent":"GitHubCopilotChat/0.26.7","Editor-Version":"vscode/1.99.3","Editor-Plugin-Version":"copilot-chat/0.26.7","Copilot-Integration-Id":"vscode-chat","X-Request-Id":()=>`req_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}};class c{constructor(){this.config={...l}}static getInstance(){return c.instance||(c.instance=new c),c.instance}getConfig(){return{...this.config}}updateConfig(I){this.config={...this.config,...I}}resetConfig(){this.config={...l}}validateConfig(){return function(){const I=[];return l.CLIENT_ID||I.push("GitHub Copilot Client ID is required"),l.API_ENDPOINT||I.push("GitHub Copilot API endpoint is required"),{valid:0===I.length,errors:I}}()}getStandardHeaders(I){return function(I){const e={Accept:l.STANDARD_HEADERS.Accept,"Content-Type":l.STANDARD_HEADERS["Content-Type"],"User-Agent":l.STANDARD_HEADERS["User-Agent"],"Editor-Version":l.STANDARD_HEADERS["Editor-Version"],"Editor-Plugin-Version":l.STANDARD_HEADERS["Editor-Plugin-Version"],"Copilot-Integration-Id":l.STANDARD_HEADERS["Copilot-Integration-Id"],"X-Request-Id":"function"==typeof l.STANDARD_HEADERS["X-Request-Id"]?l.STANDARD_HEADERS["X-Request-Id"]():l.STANDARD_HEADERS["X-Request-Id"]};return I&&(e.Authorization=`Bearer ${I}`),e}(I)}getCopilotTokenHeaders(I){return function(I){return{Authorization:`Bearer ${I}`,Accept:"application/json","User-Agent":l.USER_AGENT,"Editor-Version":l.EDITOR_VERSION,"Editor-Plugin-Version":l.EDITOR_PLUGIN_VERSION}}(I)}getDeviceCodeHeaders(){return{Accept:"application/json","User-Agent":l.USER_AGENT}}}c.getInstance()}';
|
|
18
|
+
|
|
19
|
+
function copilotConfigAlphaTemplate() {
|
|
20
|
+
// This is a reviewed byte template, not a generic JavaScript normalizer:
|
|
21
|
+
// only the five minifier bindings vary; every other byte remains exact.
|
|
22
|
+
const parts = [];
|
|
23
|
+
const moduleIdEnd = PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE.indexOf("(");
|
|
24
|
+
const pattern = /(?<![$\w])(?:I|e|t|l|c)(?![$\w])/g;
|
|
25
|
+
pattern.lastIndex = moduleIdEnd;
|
|
26
|
+
let offset = moduleIdEnd;
|
|
27
|
+
for (let match = pattern.exec(PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE); match; match = pattern.exec(PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE)) {
|
|
28
|
+
parts.push(PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE.slice(offset, match.index));
|
|
29
|
+
parts.push(Object.freeze({ identifier: match[0] }));
|
|
30
|
+
offset = match.index + match[0].length;
|
|
31
|
+
}
|
|
32
|
+
parts.push(PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE.slice(offset));
|
|
33
|
+
return Object.freeze(parts);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const PM_STUDIO_COPILOT_CONFIG_ALPHA_TEMPLATE = copilotConfigAlphaTemplate();
|
|
15
37
|
|
|
16
|
-
function splitOriginConfigModule(
|
|
17
|
-
|
|
18
|
-
|
|
38
|
+
function splitOriginConfigModule(
|
|
39
|
+
moduleId = "47024",
|
|
40
|
+
windowLength = PM_STUDIO_COPILOT_CONFIG_MODULE_LENGTH,
|
|
41
|
+
) {
|
|
42
|
+
const source = `${moduleId}(I,e,t){"use strict";t.d(e,{qn:()=>l});const l={CLIENT_ID:"Iv1.b507a08c87ecfe98",CLIENT_SECRET:void 0,API_ENDPOINT:"${PM_STUDIO_ORIGIN}",DEVICE_CODE_URL:"https://github.com/login/device/code",ACCESS_TOKEN_URL:"https://github.com/login/oauth/access_token",COPILOT_TOKEN_URL:"https://api.github.com/copilot_internal/v2/token",USER_AGENT:"GitHubCopilotChat/0.26.7",EDITOR_VERSION:"vscode/1.99.3",EDITOR_PLUGIN_VERSION:"copilot-chat/0.26.7",INTEGRATION_ID:"vscode-chat",STANDARD_HEADERS:{Accept:"application/json","Content-Type":"application/json","User-Agent":"GitHubCopilotChat/0.26.7","Editor-Version":"vscode/1.99.3","Editor-Plugin-Version":"copilot-chat/0.26.7","Copilot-Integration-Id":"vscode-chat","X-Request-Id":()=>\`req_\${Date.now()}_\${Math.random().toString(36).substr(2,9)}\`}};const c=fetch.bind(globalThis),n="${CCDX_PM_STUDIO_ORIGIN}",a="${PM_STUDIO_SPLIT_ORIGIN_MARKER}",h="X-CCDX-PM-Relay",d=new Set,m=I=>I.headers.get(h)===a,q=I=>AbortSignal.any([I,AbortSignal.timeout(750)].filter(Boolean)),f=(I,e=400)=>Response.json({error:{code:I}},{status:e,headers:{[h]:a}});globalThis.fetch=async(I,e)=>{const t=I.url||I+"";if(t===\`\${l.API_ENDPOINT}/models\`){try{const t=await c(\`\${n}/models\`,e);if(t.ok&&m(t))try{let I=await t.clone().json(),e=I.data||I;if(Array.isArray(e)){d.clear();for(const I of e)/anthropic/i.test(I.vendor||I.owned_by)&&d.add(I.id);return t}}catch{}t.body?.cancel?.()?.catch?.(()=>{})}catch(I){if(e?.signal?.aborted)throw e.signal.reason||I}return c(I,e)}const s=t.startsWith(l.API_ENDPOINT)?t.slice(l.API_ENDPOINT.length):"";if("POST"===e?.method&&["/chat/completions","/responses","/embeddings"].includes(s)){let t="";try{t=(JSON.parse(e.body).model||"").trim()}catch{}if(d.has(t)||/^claude-/i.test(t)){if("/chat/completions"!==s)return f("model_not_supported");try{const I=await c(\`\${n}/models\`,{signal:q(e?.signal)}),t=401===I.status&&m(I);await I.text();if(!t)throw 0;const l=await c(\`\${n}\${s}\`,e);if(!m(l)){await l.body?.cancel?.();throw 0}return l}catch(I){if(e?.signal?.aborted)throw e.signal.reason||I;return f("relay_incompatible",503)}}}return c(I,e)}}`;
|
|
43
|
+
if (source.length > windowLength) {
|
|
19
44
|
throw new Error("PM Studio split-origin module exceeds its exact source window");
|
|
20
45
|
}
|
|
21
|
-
return `${source.slice(0, -1)}${" ".repeat(
|
|
46
|
+
return `${source.slice(0, -1)}${" ".repeat(windowLength - source.length)}}`;
|
|
22
47
|
}
|
|
23
48
|
|
|
24
49
|
export const PM_STUDIO_SPLIT_ORIGIN_CONFIG_MODULE = splitOriginConfigModule();
|
|
@@ -320,6 +345,93 @@ function occurrencePositions(haystack, needle) {
|
|
|
320
345
|
return positions;
|
|
321
346
|
}
|
|
322
347
|
|
|
348
|
+
function asciiDigit(byte) {
|
|
349
|
+
return byte >= 48 && byte <= 57;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function asciiIdentifierStart(byte) {
|
|
353
|
+
return byte === 36
|
|
354
|
+
|| byte === 95
|
|
355
|
+
|| (byte >= 65 && byte <= 90)
|
|
356
|
+
|| (byte >= 97 && byte <= 122);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function matchCopilotConfigAlphaTemplate(source, offset) {
|
|
360
|
+
let moduleIdEnd = offset;
|
|
361
|
+
while (moduleIdEnd < source.length && asciiDigit(source[moduleIdEnd])) moduleIdEnd += 1;
|
|
362
|
+
const moduleIdLength = moduleIdEnd - offset;
|
|
363
|
+
if (moduleIdLength === 0
|
|
364
|
+
|| moduleIdLength > 10
|
|
365
|
+
|| (moduleIdLength > 1 && source[offset] === 48)) return null;
|
|
366
|
+
const moduleId = source.subarray(offset, moduleIdEnd).toString("ascii");
|
|
367
|
+
if (!Number.isSafeInteger(Number(moduleId))) return null;
|
|
368
|
+
|
|
369
|
+
let cursor = moduleIdEnd;
|
|
370
|
+
const identifiers = new Map();
|
|
371
|
+
const reverseIdentifiers = new Map();
|
|
372
|
+
for (const part of PM_STUDIO_COPILOT_CONFIG_ALPHA_TEMPLATE) {
|
|
373
|
+
if (typeof part === "string") {
|
|
374
|
+
const literal = Buffer.from(part);
|
|
375
|
+
if (cursor + literal.length > source.length
|
|
376
|
+
|| !source.subarray(cursor, cursor + literal.length).equals(literal)) return null;
|
|
377
|
+
cursor += literal.length;
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
if (!asciiIdentifierStart(source[cursor])
|
|
382
|
+
|| asciiIdentifierStart(source[cursor + 1])
|
|
383
|
+
|| asciiDigit(source[cursor + 1])) return null;
|
|
384
|
+
const candidate = String.fromCharCode(source[cursor]);
|
|
385
|
+
// The audited module uses single-byte minifier names. Keeping that bound
|
|
386
|
+
// rejects capture-prone "semantic" guesses while allowing permutations.
|
|
387
|
+
const mapped = identifiers.get(part.identifier);
|
|
388
|
+
const reverse = reverseIdentifiers.get(candidate);
|
|
389
|
+
if ((mapped && mapped !== candidate) || (reverse && reverse !== part.identifier)) return null;
|
|
390
|
+
identifiers.set(part.identifier, candidate);
|
|
391
|
+
reverseIdentifiers.set(candidate, part.identifier);
|
|
392
|
+
cursor += 1;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (cursor < source.length && source[cursor] !== 44 && source[cursor] !== 125) return null;
|
|
396
|
+
return {
|
|
397
|
+
offset,
|
|
398
|
+
end: cursor,
|
|
399
|
+
length: cursor - offset,
|
|
400
|
+
moduleId,
|
|
401
|
+
anchor: `${moduleId}(`,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
function locateCompatibleCopilotConfigModule(source) {
|
|
406
|
+
const sentinel = Buffer.from(PM_STUDIO_COPILOT_CONFIG_MODULE_SENTINEL);
|
|
407
|
+
const matches = new Map();
|
|
408
|
+
let sentinelCount = 0;
|
|
409
|
+
let searchOffset = 0;
|
|
410
|
+
while (searchOffset <= source.length - sentinel.length) {
|
|
411
|
+
const sentinelOffset = source.indexOf(sentinel, searchOffset);
|
|
412
|
+
if (sentinelOffset < 0) break;
|
|
413
|
+
sentinelCount += 1;
|
|
414
|
+
searchOffset = sentinelOffset + sentinel.length;
|
|
415
|
+
|
|
416
|
+
const lowerBound = Math.max(0, sentinelOffset - PM_STUDIO_COMPATIBLE_MODULE_PREFIX_MAX_BYTES);
|
|
417
|
+
for (let offset = lowerBound; offset <= sentinelOffset; offset += 1) {
|
|
418
|
+
if (!asciiDigit(source[offset]) || (offset > 0 && asciiDigit(source[offset - 1]))) continue;
|
|
419
|
+
if (offset > 0 && source[offset - 1] !== 44 && source[offset - 1] !== 123) continue;
|
|
420
|
+
const match = matchCopilotConfigAlphaTemplate(source, offset);
|
|
421
|
+
if (match && sentinelOffset >= match.offset && sentinelOffset < match.end) {
|
|
422
|
+
matches.set(match.offset, match);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
if (sentinelCount === 0) {
|
|
427
|
+
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} has no compatible Copilot configuration sentinel`);
|
|
428
|
+
}
|
|
429
|
+
if (matches.size !== 1) {
|
|
430
|
+
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} has ${matches.size} alpha-compatible Copilot configuration modules, expected exactly one`);
|
|
431
|
+
}
|
|
432
|
+
return matches.values().next().value;
|
|
433
|
+
}
|
|
434
|
+
|
|
323
435
|
export function blockSha256(buffer, blockSize) {
|
|
324
436
|
const size = integer(blockSize, "block size");
|
|
325
437
|
if (size === 0) throw new Error("Invalid ASAR block size: 0");
|
|
@@ -385,22 +497,24 @@ export function createCompatiblePmStudioRecipe(value, options = {}) {
|
|
|
385
497
|
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} integrity metadata does not match its bytes`);
|
|
386
498
|
}
|
|
387
499
|
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
);
|
|
392
|
-
|
|
393
|
-
|
|
500
|
+
const compatibleModule = locateCompatibleCopilotConfigModule(sourceTarget);
|
|
501
|
+
const editOffset = compatibleModule.offset;
|
|
502
|
+
const editEnd = compatibleModule.end;
|
|
503
|
+
const sourceEdit = sourceTarget.subarray(editOffset, editEnd);
|
|
504
|
+
const anchorPositions = occurrencePositions(sourceTarget, Buffer.from(compatibleModule.anchor));
|
|
505
|
+
if (anchorPositions.length !== 1 || anchorPositions[0] !== editOffset) {
|
|
506
|
+
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} compatible module header is not unique`);
|
|
507
|
+
}
|
|
508
|
+
let replacementSource;
|
|
509
|
+
try {
|
|
510
|
+
replacementSource = splitOriginConfigModule(compatibleModule.moduleId, compatibleModule.length);
|
|
511
|
+
} catch (error) {
|
|
512
|
+
throw incompatibleAsar(error.message);
|
|
394
513
|
}
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|| sha256Hex(sourceTarget.subarray(editOffset, editEnd))
|
|
399
|
-
!== PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE_SHA256) {
|
|
400
|
-
throw incompatibleAsar("PM Studio Copilot configuration module is not the exact compatible source window");
|
|
514
|
+
const replacement = Buffer.from(replacementSource);
|
|
515
|
+
if (replacement.length !== compatibleModule.length) {
|
|
516
|
+
throw incompatibleAsar("PM Studio split-origin replacement does not preserve the compatible module size");
|
|
401
517
|
}
|
|
402
|
-
|
|
403
|
-
const replacement = Buffer.from(PM_STUDIO_SPLIT_ORIGIN_CONFIG_MODULE);
|
|
404
518
|
const patchedTarget = Buffer.from(sourceTarget);
|
|
405
519
|
replacement.copy(patchedTarget, editOffset);
|
|
406
520
|
const patchedTargetSha256 = sha256Hex(patchedTarget);
|
|
@@ -436,12 +550,12 @@ export function createCompatiblePmStudioRecipe(value, options = {}) {
|
|
|
436
550
|
const edit = Object.freeze({
|
|
437
551
|
offset: editOffset,
|
|
438
552
|
absoluteOffset: absoluteOffset + editOffset,
|
|
439
|
-
length:
|
|
440
|
-
anchor:
|
|
553
|
+
length: compatibleModule.length,
|
|
554
|
+
anchor: compatibleModule.anchor,
|
|
441
555
|
anchorCount: 1,
|
|
442
|
-
sourceSha256:
|
|
556
|
+
sourceSha256: sha256Hex(sourceEdit),
|
|
443
557
|
patchedSha256: sha256Hex(replacement),
|
|
444
|
-
replacement:
|
|
558
|
+
replacement: replacementSource,
|
|
445
559
|
});
|
|
446
560
|
const target = Object.freeze({
|
|
447
561
|
path: PM_STUDIO_COPILOT_CONFIG_MODULE_PATH,
|