codex-copilot-dx 0.6.11 → 0.6.12
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 +44 -33
- package/package.json +1 -1
- package/src/cli-options.mjs +2 -2
- package/src/doctor.mjs +1 -1
- package/src/pm-studio-asar.mjs +156 -0
- package/src/pm-studio-provenance.mjs +701 -0
- package/src/pm-studio-setup-lock.mjs +336 -0
- package/src/pm-studio-setup.mjs +456 -5
- package/src/pm-studio-status.mjs +25 -3
package/README.md
CHANGED
|
@@ -118,11 +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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
CCDX keeps exact built-in recipes for PM Studio 2.9.7 and 2.9.10, and can also
|
|
122
|
+
derive a source-bound recipe for a newer macOS build when its signed App layout,
|
|
123
|
+
ASAR integrity metadata, and one exact Copilot configuration module remain
|
|
124
|
+
structurally compatible. This is best-effort semantic compatibility, not a
|
|
125
|
+
promise that every future PM Studio architecture can be patched. A missing or
|
|
126
|
+
ambiguous module, changed request transport, unsupported integrity policy, or
|
|
127
|
+
unverifiable source is rejected without modifying the App. Authorize the
|
|
128
|
+
isolated Claude profile first, quit PM Studio and its updater, then run the
|
|
129
|
+
one-time setup command:
|
|
126
130
|
|
|
127
131
|
```bash
|
|
128
132
|
ccdx auth login claude --reauth --github-login <personal-github-login>
|
|
@@ -138,24 +142,30 @@ ccdx pms status
|
|
|
138
142
|
|
|
139
143
|
`ccdx pm-studio status` and `ccdx pm-studio setup` are equivalent long-form aliases.
|
|
140
144
|
|
|
141
|
-
`ccdx pms setup` performs
|
|
142
|
-
signing, and replacement work. It never starts Device Flow, the
|
|
143
|
-
Codex, or PM Studio, and it does not modify PM profiles, cached model
|
|
144
|
-
saved PM tokens.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
145
|
+
`ccdx pms setup` performs preflight, source verification, backup, staging,
|
|
146
|
+
integrity, signing, and replacement work. It never starts Device Flow, the
|
|
147
|
+
adapter, Codex, or PM Studio, and it does not modify PM profiles, cached model
|
|
148
|
+
lists, or saved PM tokens. A structurally compatible unknown version with an
|
|
149
|
+
intact vendor signature is verified locally. If the upstream release has the
|
|
150
|
+
known invalid-signature shape, setup downloads only the exact stable asset from
|
|
151
|
+
the fixed official GitHub repository, enforces its API-provided SHA-256 and
|
|
152
|
+
size, extracts it privately, and requires the installed App to match that tree
|
|
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
|
|
156
|
+
read-only verification after an atomic replacement detects exceptional
|
|
157
|
+
filesystem drift, setup does not attempt a second automatic write: it preserves
|
|
158
|
+
the verified backup, retains any diagnostic stage still present, and prints
|
|
159
|
+
recovery paths. Repeating setup reuses the version/source-bound verified backup
|
|
160
|
+
and is idempotent; status and repeated setup do not redownload the release.
|
|
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
|
|
168
|
+
complete patched-tree record in the backup manifest.
|
|
159
169
|
|
|
160
170
|
The patch uses split origins, not an App-wide proxy. GPT and other non-Claude
|
|
161
171
|
inference requests remain on PM Studio's native official GitHub Copilot origin;
|
|
@@ -181,8 +191,7 @@ backup over a different PM Studio version or build.
|
|
|
181
191
|
|
|
182
192
|
To restore, first quit PM Studio and its updater. Use the exact verified backup
|
|
183
193
|
path printed by setup as `BACKUP_APP`, then confirm that both the installed App
|
|
184
|
-
and backup still report the same version/build printed by setup
|
|
185
|
-
or `2.9.10/2.9.10`):
|
|
194
|
+
and backup still report the same version/build printed by setup:
|
|
186
195
|
|
|
187
196
|
```bash
|
|
188
197
|
BACKUP_APP="<verified-backup-path-from-ccdx-pms-setup>"
|
|
@@ -192,8 +201,9 @@ BACKUP_APP="<verified-backup-path-from-ccdx-pms-setup>"
|
|
|
192
201
|
/usr/bin/plutil -extract CFBundleVersion raw -o - "$BACKUP_APP/Contents/Info.plist"
|
|
193
202
|
```
|
|
194
203
|
|
|
195
|
-
Only when all four values match
|
|
196
|
-
|
|
204
|
+
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 vendor
|
|
206
|
+
bundle, and verify it before launch:
|
|
197
207
|
|
|
198
208
|
```bash
|
|
199
209
|
RECOVERY_DIR="$(/usr/bin/mktemp -d '/Applications/CCDX-PM-Studio-recovery.XXXXXX')"
|
|
@@ -204,10 +214,10 @@ mv "/Applications/PM Studio.app" "$PATCHED_APP"
|
|
|
204
214
|
ccdx pms status
|
|
205
215
|
```
|
|
206
216
|
|
|
207
|
-
For
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
217
|
+
For an official artifact with the documented upstream signature failure, the
|
|
218
|
+
App-patch row from `ccdx pms status` must still classify the restored bundle as
|
|
219
|
+
verified clean content rather than integrity drift. If the version check, copy,
|
|
220
|
+
or both verification paths fail,
|
|
211
221
|
do not launch the restored App. Keep the moved patched bundle at `$PATCHED_APP`
|
|
212
222
|
and reinstall the official PM Studio instead of applying a version-mismatched
|
|
213
223
|
backup. CCDX never runs these restore commands or `sudo` automatically.
|
|
@@ -280,8 +290,9 @@ The command exits with status `1` when it finds an invalid configuration and `0`
|
|
|
280
290
|
The doctor checks the GitHub token, Codex config, Claude Code settings, Claude
|
|
281
291
|
App gateway profile, adapter availability, and an installed PM Studio bundle.
|
|
282
292
|
It ends with passed/warning/error totals and deduplicated next-step commands.
|
|
283
|
-
An absent PM Studio installation is ignored;
|
|
284
|
-
without modification, while integrity
|
|
293
|
+
An absent PM Studio installation is ignored; versions whose compatibility
|
|
294
|
+
cannot be safely verified are reported without modification, while integrity
|
|
295
|
+
drift remains an error.
|
|
285
296
|
|
|
286
297
|
For a read-only live check of the saved GitHub token, Copilot entitlement, and models endpoint, run:
|
|
287
298
|
|
package/package.json
CHANGED
package/src/cli-options.mjs
CHANGED
|
@@ -292,8 +292,8 @@ function topicHelp(name, topic) {
|
|
|
292
292
|
doctor: `Usage:\n ${name} doctor [--online] [--compat] [--profile codex|claude|all]\n\nChecks local credentials, client configuration, PM Studio state, and the adapter. --online validates account entitlement; --compat sends minimal inference requests and consumes a small amount of Copilot usage.`,
|
|
293
293
|
status: `Usage:\n ${name} status\n\nShows bounded runtime, routing, performance, cache, queue, and PM relay metrics from a running adapter.`,
|
|
294
294
|
models: `Usage:\n ${name} models [--profile codex|claude] [--format table|plain]\n\nPerforms a fresh, read-only Copilot model-directory lookup for one saved profile. Interactive terminals use a table by default.`,
|
|
295
|
-
pms: `Usage:\n ${name} pms status [--format table|plain]\n ${name} pms setup\n ${name} pm-studio status [--format table|plain]\n ${name} pm-studio setup\n\nInspects or installs the
|
|
296
|
-
"pms setup": `Usage:\n ${name} pms setup\n\nBacks up, patches, verifies, and ad-hoc signs an
|
|
295
|
+
pms: `Usage:\n ${name} pms status [--format table|plain]\n ${name} pms setup\n ${name} pm-studio status [--format table|plain]\n ${name} pm-studio setup\n\nInspects or installs the fail-closed PM Studio split-origin patch. setup modifies the installed app only after exact or semantic compatibility and source checks pass.`,
|
|
296
|
+
"pms setup": `Usage:\n ${name} pms setup\n\nBacks up, patches, verifies, and ad-hoc signs an exact or structurally compatible PM Studio bundle. Unverifiable versions and drift are never modified.`,
|
|
297
297
|
"pms status": `Usage:\n ${name} pms status [--format table|plain]\n\nRead-only inspection of the installed PM Studio version, patch integrity, Claude profile, and relay availability. Interactive terminals use a table by default.`,
|
|
298
298
|
usage: `Usage:\n ${name} usage [--format table|plain]\n\nSummarizes local token usage metadata without reading prompt or completion content. Interactive terminals use a table by default.`,
|
|
299
299
|
"auto-review-model": `Usage:\n ${name} auto-review-model\n\nInteractively selects an enabled Responses model for Codex Auto-review.`,
|
package/src/doctor.mjs
CHANGED
|
@@ -603,7 +603,7 @@ export async function collectDoctorChecks({
|
|
|
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} compatibility cannot be safely verified; 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
|
@@ -7,6 +7,11 @@ export const ELECTRON_ASAR_INTEGRITY_SENTINEL = "AGbevlPCksUGKNL8TSn7wGmJEuJsXb2
|
|
|
7
7
|
|
|
8
8
|
const PM_STUDIO_COPILOT_CONFIG_MODULE_LENGTH = 2_121;
|
|
9
9
|
const PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE_SHA256 = "3da6245d676015ab6cd26e4d6a0d2f54894a687c370aa419c5ad170533d086aa";
|
|
10
|
+
const PM_STUDIO_COPILOT_CONFIG_MODULE_ANCHOR = "47024(I,e,t){";
|
|
11
|
+
const PM_STUDIO_COPILOT_CONFIG_MODULE_PATH = "dist/main/main.js";
|
|
12
|
+
const PM_STUDIO_COMPATIBILITY_ID = "exact-copilot-config-module-v1";
|
|
13
|
+
const PM_STUDIO_COMPATIBLE_TARGET_MAX_BYTES = 128 * 1024 * 1024;
|
|
14
|
+
const PM_STUDIO_COMPATIBLE_BLOCK_MAX_COUNT = 16_384;
|
|
10
15
|
|
|
11
16
|
function splitOriginConfigModule() {
|
|
12
17
|
const source = `47024(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)}}`;
|
|
@@ -326,6 +331,157 @@ export function blockSha256(buffer, blockSize) {
|
|
|
326
331
|
return hashes;
|
|
327
332
|
}
|
|
328
333
|
|
|
334
|
+
function incompatibleAsar(message) {
|
|
335
|
+
const error = new Error(message);
|
|
336
|
+
error.code = "PM_STUDIO_ASAR_INCOMPATIBLE";
|
|
337
|
+
return error;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function requiredRecipeString(value, name) {
|
|
341
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
342
|
+
throw incompatibleAsar(`PM Studio compatible recipe has no ${name}`);
|
|
343
|
+
}
|
|
344
|
+
return value;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function createCompatiblePmStudioRecipe(value, options = {}) {
|
|
348
|
+
const parsed = parseAsarBuffer(value);
|
|
349
|
+
const entry = findAsarEntry(parsed.header, PM_STUDIO_COPILOT_CONFIG_MODULE_PATH);
|
|
350
|
+
if (!entry) throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} is missing`);
|
|
351
|
+
|
|
352
|
+
let targetOffset;
|
|
353
|
+
let targetSize;
|
|
354
|
+
let blockSize;
|
|
355
|
+
try {
|
|
356
|
+
targetOffset = entryOffset(entry.offset, `${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} offset`);
|
|
357
|
+
targetSize = entrySize(entry.size, `${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} size`);
|
|
358
|
+
blockSize = integer(entry.integrity?.blockSize,
|
|
359
|
+
`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} block size`);
|
|
360
|
+
} catch (error) {
|
|
361
|
+
throw incompatibleAsar(error.message);
|
|
362
|
+
}
|
|
363
|
+
const absoluteOffset = parsed.dataOffset + targetOffset;
|
|
364
|
+
if (entry.unpacked || entry.link || absoluteOffset + targetSize > parsed.buffer.length) {
|
|
365
|
+
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} is not one packed regular ASAR entry`);
|
|
366
|
+
}
|
|
367
|
+
if (blockSize === 0
|
|
368
|
+
|| entry.integrity?.algorithm !== "SHA256"
|
|
369
|
+
|| !sameArray(Object.keys(entry.integrity || {}).sort(), ["algorithm", "blockSize", "blocks", "hash"])) {
|
|
370
|
+
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} has unsupported integrity metadata`);
|
|
371
|
+
}
|
|
372
|
+
const expectedBlockCount = Math.ceil(targetSize / blockSize);
|
|
373
|
+
if (targetSize > PM_STUDIO_COMPATIBLE_TARGET_MAX_BYTES
|
|
374
|
+
|| blockSize < 16
|
|
375
|
+
|| expectedBlockCount > PM_STUDIO_COMPATIBLE_BLOCK_MAX_COUNT
|
|
376
|
+
|| entry.integrity.blocks.length !== expectedBlockCount) {
|
|
377
|
+
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} has unsafe integrity block geometry`);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const sourceTarget = parsed.buffer.subarray(absoluteOffset, absoluteOffset + targetSize);
|
|
381
|
+
const sourceTargetSha256 = sha256Hex(sourceTarget);
|
|
382
|
+
const sourceBlocks = blockSha256(sourceTarget, blockSize);
|
|
383
|
+
if (entry.integrity.hash !== sourceTargetSha256
|
|
384
|
+
|| !sameArray(entry.integrity.blocks, sourceBlocks)) {
|
|
385
|
+
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} integrity metadata does not match its bytes`);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
const anchorPositions = occurrencePositions(
|
|
389
|
+
sourceTarget,
|
|
390
|
+
Buffer.from(PM_STUDIO_COPILOT_CONFIG_MODULE_ANCHOR),
|
|
391
|
+
);
|
|
392
|
+
if (anchorPositions.length !== 1) {
|
|
393
|
+
throw incompatibleAsar(`${PM_STUDIO_COPILOT_CONFIG_MODULE_PATH} has ${anchorPositions.length} compatible module anchors, expected exactly one`);
|
|
394
|
+
}
|
|
395
|
+
const editOffset = anchorPositions[0];
|
|
396
|
+
const editEnd = editOffset + PM_STUDIO_COPILOT_CONFIG_MODULE_LENGTH;
|
|
397
|
+
if (editEnd > sourceTarget.length
|
|
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");
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const replacement = Buffer.from(PM_STUDIO_SPLIT_ORIGIN_CONFIG_MODULE);
|
|
404
|
+
const patchedTarget = Buffer.from(sourceTarget);
|
|
405
|
+
replacement.copy(patchedTarget, editOffset);
|
|
406
|
+
const patchedTargetSha256 = sha256Hex(patchedTarget);
|
|
407
|
+
const patchedBlocks = blockSha256(patchedTarget, blockSize);
|
|
408
|
+
const patchedAsar = Buffer.from(parsed.buffer);
|
|
409
|
+
replacement.copy(patchedAsar, absoluteOffset + editOffset);
|
|
410
|
+
const patchedParsed = parseAsarBuffer(patchedAsar);
|
|
411
|
+
const patchedEntry = findAsarEntry(patchedParsed.header, PM_STUDIO_COPILOT_CONFIG_MODULE_PATH);
|
|
412
|
+
patchedEntry.integrity = {
|
|
413
|
+
...patchedEntry.integrity,
|
|
414
|
+
algorithm: "SHA256",
|
|
415
|
+
hash: patchedTargetSha256,
|
|
416
|
+
blockSize,
|
|
417
|
+
blocks: [...patchedBlocks],
|
|
418
|
+
};
|
|
419
|
+
const patchedHeaderBytes = Buffer.from(JSON.stringify(patchedParsed.header));
|
|
420
|
+
if (patchedHeaderBytes.length !== patchedParsed.headerLength) {
|
|
421
|
+
throw incompatibleAsar(`Compatible ASAR header changed size (${patchedParsed.headerLength} -> ${patchedHeaderBytes.length})`);
|
|
422
|
+
}
|
|
423
|
+
patchedHeaderBytes.copy(patchedAsar, patchedParsed.headerStart);
|
|
424
|
+
|
|
425
|
+
const version = requiredRecipeString(String(options.version || ""), "version");
|
|
426
|
+
const build = requiredRecipeString(String(options.build || ""), "build");
|
|
427
|
+
const bundleIdentifier = requiredRecipeString(options.bundleIdentifier, "bundle identifier");
|
|
428
|
+
const sourceAsarSha256 = sha256Hex(parsed.buffer);
|
|
429
|
+
const identity = sha256Hex(`${PM_STUDIO_COMPATIBILITY_ID}\0${bundleIdentifier}\0${version}\0${build}\0${sourceAsarSha256}`).slice(0, 24);
|
|
430
|
+
const sourceBundleContent = options.sourceBundleContent
|
|
431
|
+
? Object.freeze({
|
|
432
|
+
...options.sourceBundleContent,
|
|
433
|
+
ignoredXattrs: Object.freeze([...(options.sourceBundleContent.ignoredXattrs || [])]),
|
|
434
|
+
})
|
|
435
|
+
: undefined;
|
|
436
|
+
const edit = Object.freeze({
|
|
437
|
+
offset: editOffset,
|
|
438
|
+
absoluteOffset: absoluteOffset + editOffset,
|
|
439
|
+
length: PM_STUDIO_COPILOT_CONFIG_MODULE_LENGTH,
|
|
440
|
+
anchor: PM_STUDIO_COPILOT_CONFIG_MODULE_ANCHOR,
|
|
441
|
+
anchorCount: 1,
|
|
442
|
+
sourceSha256: PM_STUDIO_COPILOT_CONFIG_MODULE_SOURCE_SHA256,
|
|
443
|
+
patchedSha256: sha256Hex(replacement),
|
|
444
|
+
replacement: PM_STUDIO_SPLIT_ORIGIN_CONFIG_MODULE,
|
|
445
|
+
});
|
|
446
|
+
const target = Object.freeze({
|
|
447
|
+
path: PM_STUDIO_COPILOT_CONFIG_MODULE_PATH,
|
|
448
|
+
offset: targetOffset,
|
|
449
|
+
size: targetSize,
|
|
450
|
+
blockSize,
|
|
451
|
+
sourceSha256: sourceTargetSha256,
|
|
452
|
+
patchedSha256: patchedTargetSha256,
|
|
453
|
+
sourceBlocks: Object.freeze([...sourceBlocks]),
|
|
454
|
+
patchedBlocks: Object.freeze([...patchedBlocks]),
|
|
455
|
+
edit,
|
|
456
|
+
});
|
|
457
|
+
return Object.freeze({
|
|
458
|
+
id: `pm-studio-compatible-${identity}`,
|
|
459
|
+
compatibility: PM_STUDIO_COMPATIBILITY_ID,
|
|
460
|
+
version,
|
|
461
|
+
build,
|
|
462
|
+
bundleIdentifier,
|
|
463
|
+
sourceTeamIdentifier: requiredRecipeString(options.sourceTeamIdentifier, "source TeamIdentifier"),
|
|
464
|
+
executable: requiredRecipeString(options.executable, "executable"),
|
|
465
|
+
sourceExecutableSha256: requiredRecipeString(options.sourceExecutableSha256, "source executable SHA-256"),
|
|
466
|
+
electronFrameworkPath: requiredRecipeString(options.electronFrameworkPath, "Electron Framework path"),
|
|
467
|
+
sourceElectronFrameworkSha256: requiredRecipeString(
|
|
468
|
+
options.sourceElectronFrameworkSha256,
|
|
469
|
+
"source Electron Framework SHA-256",
|
|
470
|
+
),
|
|
471
|
+
embeddedAsarIntegrity: requiredRecipeString(options.embeddedAsarIntegrity, "embedded ASAR integrity state"),
|
|
472
|
+
asarPath: requiredRecipeString(options.asarPath, "ASAR path"),
|
|
473
|
+
infoPlistPath: requiredRecipeString(options.infoPlistPath, "Info.plist path"),
|
|
474
|
+
integrityKey: requiredRecipeString(options.integrityKey, "ASAR integrity key"),
|
|
475
|
+
dataOffset: parsed.dataOffset,
|
|
476
|
+
sourceAsarSha256,
|
|
477
|
+
sourceHeaderSha256: sha256Hex(parsed.headerBytes),
|
|
478
|
+
patchedAsarSha256: sha256Hex(patchedAsar),
|
|
479
|
+
patchedHeaderSha256: sha256Hex(patchedHeaderBytes),
|
|
480
|
+
...(sourceBundleContent ? { sourceBundleContent } : {}),
|
|
481
|
+
targets: Object.freeze([target]),
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
|
|
329
485
|
export function inspectElectronAsarIntegritySlots(value) {
|
|
330
486
|
const buffer = checkedBuffer(value);
|
|
331
487
|
const sentinel = Buffer.from(ELECTRON_ASAR_INTEGRITY_SENTINEL);
|