@centralu/darwin-arm64 0.1.0-beta.12 → 0.1.0-beta.14
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/Centralu.app/Contents/Info.plist +2 -2
- package/Centralu.app/Contents/MacOS/centralu +0 -0
- package/Centralu.app/Contents/MacOS/centralu-keeper +0 -0
- package/Centralu.app/Contents/Resources/content/centralu-keeper +0 -0
- package/Centralu.app/Contents/Resources/content/content-manifest.json +18 -6
- package/Centralu.app/Contents/Resources/content/content-manifest.json.sig +1 -1
- package/Centralu.app/Contents/Resources/content/host/bundle-info.json +2 -2
- package/Centralu.app/Contents/Resources/content/host/main.mjs +1397 -391
- package/Centralu.app/Contents/Resources/content/host/remote-install.mjs +290 -0
- package/Centralu.app/Contents/Resources/content/host/remote-runtime.json +21 -0
- package/Centralu.app/Contents/Resources/resources/host/bundle-info.json +2 -2
- package/Centralu.app/Contents/Resources/resources/host/main.mjs +1397 -391
- package/Centralu.app/Contents/Resources/resources/host/remote-install.mjs +290 -0
- package/Centralu.app/Contents/Resources/resources/host/remote-runtime.json +21 -0
- package/Centralu.app/Contents/_CodeSignature/CodeResources +60 -16
- package/package.json +1 -1
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
// Centralu's remote installer, step 2 (docs/plans/remote-hub.md §10.2). The hub sends this file over
|
|
2
|
+
// ssh and runs it on the pinned Node that step 1 placed; it never runs on the hub. It imports Node's
|
|
3
|
+
// own modules only, and reads one argument: the base64 of a JSON object the hub wrote
|
|
4
|
+
// ({ version, node, platform, hub, packages: [{ name, tarball, integrity }], activate? }), or for the
|
|
5
|
+
// update's later steps ({ action: 'pointers', current, previous } and { action: 'prune' }; plan §10.5).
|
|
6
|
+
//
|
|
7
|
+
// It prints one line for the hub to read, `CENTRALU-INSTALL done <json>` or
|
|
8
|
+
// `CENTRALU-INSTALL fail <code> <detail>`, and nothing that matters on its exit code (exit codes do
|
|
9
|
+
// not survive the way back from Windows; tunnel.ts). The sentences for the person are the hub's.
|
|
10
|
+
import { spawnSync } from 'node:child_process'
|
|
11
|
+
import { createHash, randomBytes } from 'node:crypto'
|
|
12
|
+
import { chmodSync, existsSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs'
|
|
13
|
+
import { homedir } from 'node:os'
|
|
14
|
+
import { join } from 'node:path'
|
|
15
|
+
import { pathToFileURL } from 'node:url'
|
|
16
|
+
|
|
17
|
+
const WORD = /^[0-9A-Za-z][0-9A-Za-z.+-]{0,63}$/
|
|
18
|
+
|
|
19
|
+
class Refusal extends Error {
|
|
20
|
+
constructor(code, detail = '') {
|
|
21
|
+
super(`${code} ${detail}`.trim())
|
|
22
|
+
this.code = code
|
|
23
|
+
this.detail = detail
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** The data folder: `CC_DATA_DIR`, else `~/.centralu`, the rule `serve` and the host use */
|
|
28
|
+
export function remoteLayout(dataDir) {
|
|
29
|
+
const root = join(dataDir, 'remote')
|
|
30
|
+
return { root, current: join(root, 'current'), previous: join(root, 'previous'), versions: join(root, 'versions'), node: join(root, 'node'), bin: join(root, 'bin'), lock: join(root, 'install.lock') }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** `current` / `previous`: "<centralu version> <node version>", two plain words, or null */
|
|
34
|
+
export function readPointer(file) {
|
|
35
|
+
try {
|
|
36
|
+
const m = /^\s*(\S+)[ \t]+(\S+)\s*$/.exec(readFileSync(file, 'utf8'))
|
|
37
|
+
return m && WORD.test(m[1]) && WORD.test(m[2]) ? { version: m[1], node: m[2] } : null
|
|
38
|
+
} catch {
|
|
39
|
+
return null
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Replaces `file` by a rename over it, so a reader (the launcher, `serve --connection`) sees the old
|
|
45
|
+
* line or the new one and never half of one. Atomic on posix, and measured atomic on Windows
|
|
46
|
+
* (`renameSync` over an existing file replaces it; plan §10.1)
|
|
47
|
+
*/
|
|
48
|
+
export function writeAtomic(file, text) {
|
|
49
|
+
const tmp = `${file}.${process.pid}-${randomBytes(4).toString('hex')}.tmp`
|
|
50
|
+
writeFileSync(tmp, text)
|
|
51
|
+
renameSync(tmp, file)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Points `current` at `next`, the old `current` becoming `previous` (plan §10.5 step 3) */
|
|
55
|
+
export function switchTo(l, next) {
|
|
56
|
+
const cur = readPointer(l.current)
|
|
57
|
+
if (cur && cur.version === next.version && cur.node === next.node) return { current: next, previous: readPointer(l.previous) }
|
|
58
|
+
if (cur) writeAtomic(l.previous, `${cur.version} ${cur.node}\n`)
|
|
59
|
+
writeAtomic(l.current, `${next.version} ${next.node}\n`)
|
|
60
|
+
return { current: next, previous: cur ?? readPointer(l.previous) }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Removes every version that is neither `current` nor `previous`, and every Node neither uses. A
|
|
65
|
+
* folder that cannot go (a Windows program still running from it) stays and is named, never fatal
|
|
66
|
+
*/
|
|
67
|
+
export function prune(l) {
|
|
68
|
+
const keep = [readPointer(l.current), readPointer(l.previous)].filter(Boolean)
|
|
69
|
+
const removed = []
|
|
70
|
+
const left = []
|
|
71
|
+
const sweep = (dir, kept) => {
|
|
72
|
+
let names = []
|
|
73
|
+
try {
|
|
74
|
+
names = readdirSync(dir)
|
|
75
|
+
} catch {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
for (const name of names) {
|
|
79
|
+
if (kept.has(name) || name.startsWith('.')) continue
|
|
80
|
+
try {
|
|
81
|
+
rmSync(join(dir, name), { recursive: true, force: true })
|
|
82
|
+
removed.push(name)
|
|
83
|
+
} catch {
|
|
84
|
+
left.push(name)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
sweep(l.versions, new Set(keep.map((p) => p.version)))
|
|
89
|
+
sweep(l.node, new Set(keep.map((p) => `v${p.node}`)))
|
|
90
|
+
return { removed, left }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** One installer at a time per data folder; a lock whose process is gone is taken over */
|
|
94
|
+
function lock(l) {
|
|
95
|
+
for (let i = 0; i < 2; i++) {
|
|
96
|
+
try {
|
|
97
|
+
mkdirSync(l.lock)
|
|
98
|
+
writeFileSync(join(l.lock, 'pid'), String(process.pid))
|
|
99
|
+
return () => rmSync(l.lock, { recursive: true, force: true })
|
|
100
|
+
} catch (err) {
|
|
101
|
+
if (err.code !== 'EEXIST') throw err
|
|
102
|
+
const pid = Number(readFileSafe(join(l.lock, 'pid')))
|
|
103
|
+
if (pid > 0 && alive(pid)) throw new Refusal('busy', String(pid))
|
|
104
|
+
rmSync(l.lock, { recursive: true, force: true })
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
throw new Refusal('busy')
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function readFileSafe(file) {
|
|
111
|
+
try {
|
|
112
|
+
return readFileSync(file, 'utf8')
|
|
113
|
+
} catch {
|
|
114
|
+
return ''
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function alive(pid) {
|
|
119
|
+
try {
|
|
120
|
+
process.kill(pid, 0)
|
|
121
|
+
return true
|
|
122
|
+
} catch (err) {
|
|
123
|
+
return err.code === 'EPERM'
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** The system's tar. On Windows the one in System32 (bsdtar): a GNU tar on PATH reads `C:` as a host */
|
|
128
|
+
function tarProgram() {
|
|
129
|
+
return process.platform === 'win32' ? join(process.env.SystemRoot || 'C:\\Windows', 'System32', 'tar.exe') : 'tar'
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** The tarball's bytes, refused unless their sha512 is the integrity the hub read from the signed metadata */
|
|
133
|
+
export async function fetchChecked(pkg) {
|
|
134
|
+
let res
|
|
135
|
+
try {
|
|
136
|
+
res = await fetch(pkg.tarball, { signal: AbortSignal.timeout(300_000) })
|
|
137
|
+
} catch (err) {
|
|
138
|
+
throw new Refusal('download', `${pkg.name}: ${err.cause?.message ?? err.message}`)
|
|
139
|
+
}
|
|
140
|
+
if (!res.ok) throw new Refusal('download', `${pkg.name}: HTTP ${res.status}`)
|
|
141
|
+
const bytes = Buffer.from(await res.arrayBuffer())
|
|
142
|
+
const have = `sha512-${createHash('sha512').update(bytes).digest('base64')}`
|
|
143
|
+
if (have !== pkg.integrity) throw new Refusal('integrity', pkg.name)
|
|
144
|
+
return bytes
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Where the host sits in the platform package, and what of the package a remote never runs (plan S6) */
|
|
148
|
+
function platformParts(platform) {
|
|
149
|
+
if (platform === 'win32-x64') return { host: join('Centralu', 'resources', 'host', 'main.mjs'), drop: [join('Centralu', 'centralu.exe')] }
|
|
150
|
+
return { host: join('host', 'main.mjs'), drop: ['Centralu.AppImage'] }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function sameInstall(dir, p) {
|
|
154
|
+
try {
|
|
155
|
+
const was = JSON.parse(readFileSync(join(dir, 'install.json'), 'utf8'))
|
|
156
|
+
return was.version === p.version && p.packages.every((pkg) => was.packages?.some((w) => w.name === pkg.name && w.integrity === pkg.integrity))
|
|
157
|
+
} catch {
|
|
158
|
+
return false
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** Installs `p.version` beside what is there, switches `current` to it, and keeps `previous` */
|
|
163
|
+
export async function install(p, { dataDir = process.env.CC_DATA_DIR || join(homedir(), '.centralu'), platform = process.platform } = {}) {
|
|
164
|
+
if (!WORD.test(p.version) || !WORD.test(p.node)) throw new Refusal('params', 'version')
|
|
165
|
+
const l = remoteLayout(dataDir)
|
|
166
|
+
mkdirSync(l.root, { recursive: true })
|
|
167
|
+
const unlock = lock(l)
|
|
168
|
+
try {
|
|
169
|
+
const dir = join(l.versions, p.version)
|
|
170
|
+
const parts = platformParts(p.platform)
|
|
171
|
+
if (!sameInstall(dir, p)) {
|
|
172
|
+
// Everything lands in a folder of its own first; the version's folder appears by one rename
|
|
173
|
+
const partial = join(l.root, `.partial-${p.version}-${process.pid}`)
|
|
174
|
+
rmSync(partial, { recursive: true, force: true })
|
|
175
|
+
try {
|
|
176
|
+
for (const [i, pkg] of p.packages.entries()) {
|
|
177
|
+
const bytes = await fetchChecked(pkg)
|
|
178
|
+
const file = join(partial, `${i}.tgz`)
|
|
179
|
+
const dest = join(partial, 'node_modules', ...pkg.name.split('/'))
|
|
180
|
+
mkdirSync(dest, { recursive: true })
|
|
181
|
+
writeFileSync(file, bytes)
|
|
182
|
+
const r = spawnSync(tarProgram(), ['-xzf', file, '-C', dest, '--strip-components', '1'], { encoding: 'utf8', windowsHide: true })
|
|
183
|
+
if (r.status !== 0) throw new Refusal('unpack', `${pkg.name}: ${(r.stderr || r.error?.message || '').trim().split('\n').at(-1)}`)
|
|
184
|
+
rmSync(file, { force: true })
|
|
185
|
+
}
|
|
186
|
+
const pkgDir = join(partial, 'node_modules', '@centralu', p.platform)
|
|
187
|
+
if (!existsSync(join(pkgDir, parts.host))) throw new Refusal('no_host', p.platform)
|
|
188
|
+
for (const d of parts.drop) rmSync(join(pkgDir, d), { force: true })
|
|
189
|
+
writeFileSync(
|
|
190
|
+
join(partial, 'install.json'),
|
|
191
|
+
JSON.stringify({ version: p.version, node: p.node, platform: p.platform, packages: p.packages.map(({ name, integrity }) => ({ name, integrity })), installedAt: new Date().toISOString(), by: p.hub ?? null }, null, 2) + '\n',
|
|
192
|
+
)
|
|
193
|
+
mkdirSync(l.versions, { recursive: true })
|
|
194
|
+
rmSync(dir, { recursive: true, force: true })
|
|
195
|
+
renameSync(partial, dir)
|
|
196
|
+
} finally {
|
|
197
|
+
rmSync(partial, { recursive: true, force: true })
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
// An update installs beside and switches later, once the running host is stopped (plan §10.5):
|
|
201
|
+
// nothing is pointed at the new version and nothing is removed yet. Without a `current`, no
|
|
202
|
+
// launcher either, so the lookup still finds the Centralu that runs now
|
|
203
|
+
if (p.activate === false) {
|
|
204
|
+
return { installed: { version: p.version, node: p.node }, current: readPointer(l.current), previous: readPointer(l.previous), removed: [], left: [] }
|
|
205
|
+
}
|
|
206
|
+
const launcher = await ensureManagedLauncher(l, dir, p.version, platform)
|
|
207
|
+
const pointers = switchTo(l, { version: p.version, node: p.node })
|
|
208
|
+
return { ...pointers, ...prune(l), launcher }
|
|
209
|
+
} finally {
|
|
210
|
+
unlock()
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function launcherPath(l, platform) {
|
|
215
|
+
return join(l.bin, platform === 'win32' ? 'centralu.cmd' : 'centralu')
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** The launcher reads `current` at every start and never changes (S8): written once, never over */
|
|
219
|
+
async function ensureManagedLauncher(l, dir, version, platform) {
|
|
220
|
+
const launcher = launcherPath(l, platform)
|
|
221
|
+
if (!existsSync(launcher)) {
|
|
222
|
+
const serve = await import(pathToFileURL(join(dir, 'node_modules', 'centralu', 'bin', 'serve.mjs')).href)
|
|
223
|
+
if (typeof serve.managedLauncherScript !== 'function') throw new Refusal('no_launcher', version)
|
|
224
|
+
mkdirSync(l.bin, { recursive: true })
|
|
225
|
+
writeAtomic(launcher, serve.managedLauncherScript(platform))
|
|
226
|
+
if (platform !== 'win32') chmodSync(launcher, 0o755)
|
|
227
|
+
}
|
|
228
|
+
return launcher
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const pointerOf = (v) => (v && WORD.test(v.version) && WORD.test(v.node) ? { version: v.version, node: v.node } : null)
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Writes both pointers as given (plan §10.5 steps 3 and 5, and rollback): `previous` first, then
|
|
235
|
+
* `current`, each by rename; a null `previous` removes that file. `current` must name a version and a
|
|
236
|
+
* Node that are both there. A null `current` puts the machine back to having no managed version: the
|
|
237
|
+
* pointers and the launcher go, so the lookup finds the Centralu it ran before (an npm install).
|
|
238
|
+
* Nothing is removed from `versions/` or `node/`
|
|
239
|
+
*/
|
|
240
|
+
export async function setPointers(p, { dataDir = process.env.CC_DATA_DIR || join(homedir(), '.centralu'), platform = process.platform } = {}) {
|
|
241
|
+
const l = remoteLayout(dataDir)
|
|
242
|
+
mkdirSync(l.root, { recursive: true })
|
|
243
|
+
const unlock = lock(l)
|
|
244
|
+
try {
|
|
245
|
+
const current = pointerOf(p.current)
|
|
246
|
+
const previous = pointerOf(p.previous)
|
|
247
|
+
if (!current) {
|
|
248
|
+
for (const f of [l.previous, l.current, launcherPath(l, platform)]) rmSync(f, { force: true })
|
|
249
|
+
return { current: null, previous: null }
|
|
250
|
+
}
|
|
251
|
+
const dir = join(l.versions, current.version)
|
|
252
|
+
const node = join(l.node, `v${current.node}`)
|
|
253
|
+
if (!existsSync(join(dir, 'install.json')) || !existsSync(node)) throw new Refusal('missing', `${current.version} ${current.node}`)
|
|
254
|
+
await ensureManagedLauncher(l, dir, current.version, platform)
|
|
255
|
+
if (previous) writeAtomic(l.previous, `${previous.version} ${previous.node}\n`)
|
|
256
|
+
else rmSync(l.previous, { force: true })
|
|
257
|
+
writeAtomic(l.current, `${current.version} ${current.node}\n`)
|
|
258
|
+
return { current, previous }
|
|
259
|
+
} finally {
|
|
260
|
+
unlock()
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** Plan §10.5 step 6, on its own: what is neither `current` nor `previous` goes */
|
|
265
|
+
export function pruneNow({ dataDir = process.env.CC_DATA_DIR || join(homedir(), '.centralu') } = {}) {
|
|
266
|
+
const l = remoteLayout(dataDir)
|
|
267
|
+
mkdirSync(l.root, { recursive: true })
|
|
268
|
+
const unlock = lock(l)
|
|
269
|
+
try {
|
|
270
|
+
return { current: readPointer(l.current), previous: readPointer(l.previous), ...prune(l) }
|
|
271
|
+
} finally {
|
|
272
|
+
unlock()
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
async function main() {
|
|
277
|
+
try {
|
|
278
|
+
const p = JSON.parse(Buffer.from(process.argv[2] ?? '', 'base64').toString('utf8'))
|
|
279
|
+
const r = p.action === 'pointers' ? await setPointers(p) : p.action === 'prune' ? pruneNow() : await install(p)
|
|
280
|
+
process.stdout.write(`CENTRALU-INSTALL done ${JSON.stringify(r)}\n`)
|
|
281
|
+
} catch (err) {
|
|
282
|
+
const code = err instanceof Refusal ? err.code : 'error'
|
|
283
|
+
const detail = err instanceof Refusal ? err.detail : err.message
|
|
284
|
+
process.stdout.write(`CENTRALU-INSTALL fail ${code} ${String(detail).replace(/\s+/g, ' ')}\n`)
|
|
285
|
+
process.exitCode = 1
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Run as a program (not imported by a test). Node names its main module by its real path: compare that
|
|
290
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href) await main()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"node": {
|
|
3
|
+
"version": "24.21.0",
|
|
4
|
+
"signedBy": "5BE8A3F6C8A5C01D106C0AD820B1A390B168D356",
|
|
5
|
+
"releaseKeys": "481637f813e912c4aa3622d7964ab426c97b8e8d",
|
|
6
|
+
"archives": {
|
|
7
|
+
"linux-arm64": {
|
|
8
|
+
"file": "node-v24.21.0-linux-arm64.tar.gz",
|
|
9
|
+
"sha256": "724282c3b43aec998aa9527380465b45d229e021b58035f5f4f63095eabfe5d5"
|
|
10
|
+
},
|
|
11
|
+
"linux-x64": {
|
|
12
|
+
"file": "node-v24.21.0-linux-x64.tar.gz",
|
|
13
|
+
"sha256": "6e1db87ef58b8819e5d5402eff1536491b18edd8eb7bee5ef7897876e88dc5ff"
|
|
14
|
+
},
|
|
15
|
+
"win32-x64": {
|
|
16
|
+
"file": "node-v24.21.0-win-x64.zip",
|
|
17
|
+
"sha256": "158f7685b44de51f6c0df1d153526cbcd3e1bc739a8dfc607721cef75de9e541"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
<dict>
|
|
7
7
|
<key>Resources/content/centralu-keeper</key>
|
|
8
8
|
<data>
|
|
9
|
-
|
|
9
|
+
S7v2PfHWBgngchkj8HFntKoLjkg=
|
|
10
10
|
</data>
|
|
11
11
|
<key>Resources/content/content-manifest.json</key>
|
|
12
12
|
<data>
|
|
13
|
-
|
|
13
|
+
l8oZ2yfkDpa0RG9k9n3ggrgll0o=
|
|
14
14
|
</data>
|
|
15
15
|
<key>Resources/content/content-manifest.json.sig</key>
|
|
16
16
|
<data>
|
|
17
|
-
|
|
17
|
+
w6R1VzpdNe393HUjLUrXFIc3lSg=
|
|
18
18
|
</data>
|
|
19
19
|
<key>Resources/content/host/app-template/AGENTS.md</key>
|
|
20
20
|
<data>
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
</data>
|
|
59
59
|
<key>Resources/content/host/bundle-info.json</key>
|
|
60
60
|
<data>
|
|
61
|
-
|
|
61
|
+
//UCqNhQ9W91KcpU1LrZRc87ueE=
|
|
62
62
|
</data>
|
|
63
63
|
<key>Resources/content/host/codex-orchestrator-bridge.mjs</key>
|
|
64
64
|
<data>
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
</data>
|
|
67
67
|
<key>Resources/content/host/main.mjs</key>
|
|
68
68
|
<data>
|
|
69
|
-
|
|
69
|
+
zi5y0ODJw4+mh9+aEN+6JZ3fNOs=
|
|
70
70
|
</data>
|
|
71
71
|
<key>Resources/content/host/node_modules/better-sqlite3/build/Release/better_sqlite3.node</key>
|
|
72
72
|
<data>
|
|
@@ -336,6 +336,14 @@
|
|
|
336
336
|
<data>
|
|
337
337
|
1+oViP+ynn67yvWRtjtBa0o44U4=
|
|
338
338
|
</data>
|
|
339
|
+
<key>Resources/content/host/remote-install.mjs</key>
|
|
340
|
+
<data>
|
|
341
|
+
oBEeGV3tzhnPu+t4hbKvmwGeK8A=
|
|
342
|
+
</data>
|
|
343
|
+
<key>Resources/content/host/remote-runtime.json</key>
|
|
344
|
+
<data>
|
|
345
|
+
mErFPiPmd+t1wnFkXnow4FgoOY4=
|
|
346
|
+
</data>
|
|
339
347
|
<key>Resources/content/host/schema.sql</key>
|
|
340
348
|
<data>
|
|
341
349
|
5B/+lAptHFTev2TqTwV6i518j4k=
|
|
@@ -386,7 +394,7 @@
|
|
|
386
394
|
</data>
|
|
387
395
|
<key>Resources/resources/host/bundle-info.json</key>
|
|
388
396
|
<data>
|
|
389
|
-
|
|
397
|
+
//UCqNhQ9W91KcpU1LrZRc87ueE=
|
|
390
398
|
</data>
|
|
391
399
|
<key>Resources/resources/host/codex-orchestrator-bridge.mjs</key>
|
|
392
400
|
<data>
|
|
@@ -394,7 +402,7 @@
|
|
|
394
402
|
</data>
|
|
395
403
|
<key>Resources/resources/host/main.mjs</key>
|
|
396
404
|
<data>
|
|
397
|
-
|
|
405
|
+
zi5y0ODJw4+mh9+aEN+6JZ3fNOs=
|
|
398
406
|
</data>
|
|
399
407
|
<key>Resources/resources/host/node_modules/better-sqlite3/build/Release/better_sqlite3.node</key>
|
|
400
408
|
<data>
|
|
@@ -664,6 +672,14 @@
|
|
|
664
672
|
<data>
|
|
665
673
|
1+oViP+ynn67yvWRtjtBa0o44U4=
|
|
666
674
|
</data>
|
|
675
|
+
<key>Resources/resources/host/remote-install.mjs</key>
|
|
676
|
+
<data>
|
|
677
|
+
oBEeGV3tzhnPu+t4hbKvmwGeK8A=
|
|
678
|
+
</data>
|
|
679
|
+
<key>Resources/resources/host/remote-runtime.json</key>
|
|
680
|
+
<data>
|
|
681
|
+
mErFPiPmd+t1wnFkXnow4FgoOY4=
|
|
682
|
+
</data>
|
|
667
683
|
<key>Resources/resources/host/schema.sql</key>
|
|
668
684
|
<data>
|
|
669
685
|
5B/+lAptHFTev2TqTwV6i518j4k=
|
|
@@ -695,30 +711,30 @@
|
|
|
695
711
|
<dict>
|
|
696
712
|
<key>cdhash</key>
|
|
697
713
|
<data>
|
|
698
|
-
|
|
714
|
+
TYOZDMNCfHV/xonCXdmbeHEcvu8=
|
|
699
715
|
</data>
|
|
700
716
|
<key>requirement</key>
|
|
701
|
-
<string>cdhash H"
|
|
717
|
+
<string>cdhash H"4d83990cc3427c757fc689c25dd99b78711cbeef"</string>
|
|
702
718
|
</dict>
|
|
703
719
|
<key>Resources/content/centralu-keeper</key>
|
|
704
720
|
<dict>
|
|
705
721
|
<key>hash2</key>
|
|
706
722
|
<data>
|
|
707
|
-
|
|
723
|
+
mT/KBgb3VSMXaLyvH6R3M7HSWZ5U5yIJQjBxjvG5bTI=
|
|
708
724
|
</data>
|
|
709
725
|
</dict>
|
|
710
726
|
<key>Resources/content/content-manifest.json</key>
|
|
711
727
|
<dict>
|
|
712
728
|
<key>hash2</key>
|
|
713
729
|
<data>
|
|
714
|
-
|
|
730
|
+
Zi9WNUkuR5eGyb732JhIpjs+bm84f0ZsZs0G/pu2n8k=
|
|
715
731
|
</data>
|
|
716
732
|
</dict>
|
|
717
733
|
<key>Resources/content/content-manifest.json.sig</key>
|
|
718
734
|
<dict>
|
|
719
735
|
<key>hash2</key>
|
|
720
736
|
<data>
|
|
721
|
-
|
|
737
|
+
GJT7ghepd8Hzl//eUZiFJv7/uGRoNeZ9dOL60urMs74=
|
|
722
738
|
</data>
|
|
723
739
|
</dict>
|
|
724
740
|
<key>Resources/content/host/app-template/AGENTS.md</key>
|
|
@@ -795,7 +811,7 @@
|
|
|
795
811
|
<dict>
|
|
796
812
|
<key>hash2</key>
|
|
797
813
|
<data>
|
|
798
|
-
|
|
814
|
+
M9oPlezP2R7RPxfStrDSAgd3Es0NNDdgC5zda+/LIe4=
|
|
799
815
|
</data>
|
|
800
816
|
</dict>
|
|
801
817
|
<key>Resources/content/host/codex-orchestrator-bridge.mjs</key>
|
|
@@ -809,7 +825,7 @@
|
|
|
809
825
|
<dict>
|
|
810
826
|
<key>hash2</key>
|
|
811
827
|
<data>
|
|
812
|
-
|
|
828
|
+
2q/GzFq/mtLIXcGZfYcteqGx5pKyL/3DKg/fmE4CGCI=
|
|
813
829
|
</data>
|
|
814
830
|
</dict>
|
|
815
831
|
<key>Resources/content/host/node_modules/better-sqlite3/build/Release/better_sqlite3.node</key>
|
|
@@ -1281,6 +1297,20 @@
|
|
|
1281
1297
|
IcWJEJvKQ+KH34hPPDSriIAzqDkn6n0nOUmsUDBYPyY=
|
|
1282
1298
|
</data>
|
|
1283
1299
|
</dict>
|
|
1300
|
+
<key>Resources/content/host/remote-install.mjs</key>
|
|
1301
|
+
<dict>
|
|
1302
|
+
<key>hash2</key>
|
|
1303
|
+
<data>
|
|
1304
|
+
fXZNRS0VI+EkGDBqdBHPzXK+T2KBvjEHC+Q87j86oYc=
|
|
1305
|
+
</data>
|
|
1306
|
+
</dict>
|
|
1307
|
+
<key>Resources/content/host/remote-runtime.json</key>
|
|
1308
|
+
<dict>
|
|
1309
|
+
<key>hash2</key>
|
|
1310
|
+
<data>
|
|
1311
|
+
zeEPtrcWlLe8VUzYLm54plQrFiQ2io5jFJwpnAe24TY=
|
|
1312
|
+
</data>
|
|
1313
|
+
</dict>
|
|
1284
1314
|
<key>Resources/content/host/schema.sql</key>
|
|
1285
1315
|
<dict>
|
|
1286
1316
|
<key>hash2</key>
|
|
@@ -1369,7 +1399,7 @@
|
|
|
1369
1399
|
<dict>
|
|
1370
1400
|
<key>hash2</key>
|
|
1371
1401
|
<data>
|
|
1372
|
-
|
|
1402
|
+
M9oPlezP2R7RPxfStrDSAgd3Es0NNDdgC5zda+/LIe4=
|
|
1373
1403
|
</data>
|
|
1374
1404
|
</dict>
|
|
1375
1405
|
<key>Resources/resources/host/codex-orchestrator-bridge.mjs</key>
|
|
@@ -1383,7 +1413,7 @@
|
|
|
1383
1413
|
<dict>
|
|
1384
1414
|
<key>hash2</key>
|
|
1385
1415
|
<data>
|
|
1386
|
-
|
|
1416
|
+
2q/GzFq/mtLIXcGZfYcteqGx5pKyL/3DKg/fmE4CGCI=
|
|
1387
1417
|
</data>
|
|
1388
1418
|
</dict>
|
|
1389
1419
|
<key>Resources/resources/host/node_modules/better-sqlite3/build/Release/better_sqlite3.node</key>
|
|
@@ -1855,6 +1885,20 @@
|
|
|
1855
1885
|
IcWJEJvKQ+KH34hPPDSriIAzqDkn6n0nOUmsUDBYPyY=
|
|
1856
1886
|
</data>
|
|
1857
1887
|
</dict>
|
|
1888
|
+
<key>Resources/resources/host/remote-install.mjs</key>
|
|
1889
|
+
<dict>
|
|
1890
|
+
<key>hash2</key>
|
|
1891
|
+
<data>
|
|
1892
|
+
fXZNRS0VI+EkGDBqdBHPzXK+T2KBvjEHC+Q87j86oYc=
|
|
1893
|
+
</data>
|
|
1894
|
+
</dict>
|
|
1895
|
+
<key>Resources/resources/host/remote-runtime.json</key>
|
|
1896
|
+
<dict>
|
|
1897
|
+
<key>hash2</key>
|
|
1898
|
+
<data>
|
|
1899
|
+
zeEPtrcWlLe8VUzYLm54plQrFiQ2io5jFJwpnAe24TY=
|
|
1900
|
+
</data>
|
|
1901
|
+
</dict>
|
|
1858
1902
|
<key>Resources/resources/host/schema.sql</key>
|
|
1859
1903
|
<dict>
|
|
1860
1904
|
<key>hash2</key>
|