freecode-sh 0.1.0-alpha.22 → 0.1.0-alpha.23
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 +10 -0
- package/freecode.mjs +39 -4
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -10,6 +10,9 @@ are not shipped in the npm package.
|
|
|
10
10
|
|
|
11
11
|
Both `freecode` and `freecode-sh` launch the same Free Code CLI.
|
|
12
12
|
|
|
13
|
+
The signed native `alpha` channel is the canonical current release. npm
|
|
14
|
+
`latest` mirrors that version; npm `alpha` is intentionally not used.
|
|
15
|
+
|
|
13
16
|
## Install
|
|
14
17
|
|
|
15
18
|
```bash
|
|
@@ -19,6 +22,13 @@ freecode doctor
|
|
|
19
22
|
freecode
|
|
20
23
|
```
|
|
21
24
|
|
|
25
|
+
For a reproducible clean install of this immutable release:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm install -g freecode-sh@0.1.0-alpha.23
|
|
29
|
+
freecode --version
|
|
30
|
+
```
|
|
31
|
+
|
|
22
32
|
```bash
|
|
23
33
|
freecode logout
|
|
24
34
|
npm uninstall -g freecode-sh
|
package/freecode.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { spawn } from 'node:child_process'
|
|
4
4
|
import { constants } from 'node:fs'
|
|
5
|
-
import { access, readFile, realpath } from 'node:fs/promises'
|
|
5
|
+
import { access, chmod, lstat, mkdir, readFile, realpath, writeFile } from 'node:fs/promises'
|
|
6
6
|
import { homedir } from 'node:os'
|
|
7
7
|
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'
|
|
8
8
|
import { fileURLToPath } from 'node:url'
|
|
@@ -12,7 +12,13 @@ const packageDirectory = dirname(fileURLToPath(import.meta.url))
|
|
|
12
12
|
const bootstrapPath = fileURLToPath(import.meta.url)
|
|
13
13
|
const packageMetadata = JSON.parse(await readFile(join(packageDirectory, 'package.json'), 'utf8'))
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
const releaseContract = packageMetadata.freecodeRelease
|
|
16
|
+
if (
|
|
17
|
+
packageMetadata.name !== 'freecode-sh'
|
|
18
|
+
|| !/^\d+\.\d+\.\d+-alpha\.\d+$/.test(packageMetadata.version)
|
|
19
|
+
|| releaseContract?.channel !== 'alpha'
|
|
20
|
+
|| releaseContract?.nativeVersion !== packageMetadata.version
|
|
21
|
+
) {
|
|
16
22
|
fail('The npm package metadata is invalid. Reinstall freecode-sh and try again.')
|
|
17
23
|
}
|
|
18
24
|
|
|
@@ -59,15 +65,16 @@ if (nativeVersion && compareAlphaVersions(nativeVersion, packageMetadata.version
|
|
|
59
65
|
const installer = windows
|
|
60
66
|
? {
|
|
61
67
|
command: 'powershell.exe',
|
|
62
|
-
args: ['-NoLogo', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', join(packageDirectory, 'install.ps1'), '-Version',
|
|
68
|
+
args: ['-NoLogo', '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', join(packageDirectory, 'install.ps1'), '-Channel', releaseContract.channel, '-Version', releaseContract.nativeVersion],
|
|
63
69
|
}
|
|
64
|
-
: { command: '/bin/sh', args: [join(packageDirectory, 'install.sh'), '--version',
|
|
70
|
+
: { command: '/bin/sh', args: [join(packageDirectory, 'install.sh'), '--channel', releaseContract.channel, '--version', releaseContract.nativeVersion] }
|
|
65
71
|
const installerEnvironment = {
|
|
66
72
|
...process.env,
|
|
67
73
|
FREECODE_INSTALL_ROOT: installRoot,
|
|
68
74
|
FREECODE_BIN_DIR: binDirectory,
|
|
69
75
|
FREECODE_INSTALL_EMBEDDED: 'true',
|
|
70
76
|
}
|
|
77
|
+
const installStartedAt = Date.now()
|
|
71
78
|
const installStatus = await run(
|
|
72
79
|
installer.command,
|
|
73
80
|
installer.args,
|
|
@@ -78,6 +85,11 @@ if (nativeVersion && compareAlphaVersions(nativeVersion, packageMetadata.version
|
|
|
78
85
|
if (!nativeVersion || compareAlphaVersions(nativeVersion, packageMetadata.version) < 0) {
|
|
79
86
|
fail('The signed installer completed without creating a managed Free Code executable.')
|
|
80
87
|
}
|
|
88
|
+
await writeInstallTelemetryReceipt({
|
|
89
|
+
releaseId: packageMetadata.version,
|
|
90
|
+
platform: ['darwin', 'linux', 'win32'].includes(platform) ? platform : 'unknown',
|
|
91
|
+
durationMs: Math.min(86_400_000, Math.max(0, Date.now() - installStartedAt)),
|
|
92
|
+
})
|
|
81
93
|
process.exitCode = await runManaged(nativeExecutable, nativeVersion, process.argv.slice(2))
|
|
82
94
|
}
|
|
83
95
|
|
|
@@ -116,6 +128,29 @@ function runManaged(path, version, args) {
|
|
|
116
128
|
return run(command, args)
|
|
117
129
|
}
|
|
118
130
|
|
|
131
|
+
async function writeInstallTelemetryReceipt({ releaseId, platform: receiptPlatform, durationMs }) {
|
|
132
|
+
const configRoot = windows && process.env.APPDATA ? process.env.APPDATA : join(homeDirectory, '.config')
|
|
133
|
+
const directory = resolve(configRoot, 'freecode')
|
|
134
|
+
const path = join(directory, 'install-receipt.json')
|
|
135
|
+
try {
|
|
136
|
+
await mkdir(directory, { recursive: true, mode: 0o700 })
|
|
137
|
+
if ((await lstat(directory)).isSymbolicLink()) return
|
|
138
|
+
try {
|
|
139
|
+
if ((await lstat(path)).isSymbolicLink()) return
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (error?.code !== 'ENOENT') return
|
|
142
|
+
}
|
|
143
|
+
if (!windows) await chmod(directory, 0o700)
|
|
144
|
+
await writeFile(path, `${JSON.stringify({ version: 1, releaseId, platform: receiptPlatform, durationMs })}\n`, {
|
|
145
|
+
encoding: 'utf8',
|
|
146
|
+
mode: 0o600,
|
|
147
|
+
})
|
|
148
|
+
if (!windows) await chmod(path, 0o600)
|
|
149
|
+
} catch {
|
|
150
|
+
// Install telemetry is best effort and must never fail a verified install.
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
119
154
|
function compareAlphaVersions(left, right) {
|
|
120
155
|
const parse = (version) => {
|
|
121
156
|
const match = version.match(/^(\d+)\.(\d+)\.(\d+)-alpha\.(\d+)$/)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "freecode-sh",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.23",
|
|
4
4
|
"description": "A free coding agent for your terminal.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Free Code",
|
|
@@ -44,5 +44,9 @@
|
|
|
44
44
|
"publishConfig": {
|
|
45
45
|
"access": "public",
|
|
46
46
|
"tag": "latest"
|
|
47
|
+
},
|
|
48
|
+
"freecodeRelease": {
|
|
49
|
+
"channel": "alpha",
|
|
50
|
+
"nativeVersion": "0.1.0-alpha.23"
|
|
47
51
|
}
|
|
48
52
|
}
|