tessl 0.0.0 → 0.63.2

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/LICENSE.md ADDED
@@ -0,0 +1,3 @@
1
+ Copyright 2025 Tessl. All rights reserved.
2
+ This software is proprietary to Tessl and is subject to Tessl's Terms of Service (see: https://tessl.io/policies/terms).
3
+ Unauthorized reproduction or distribution is prohibited.
package/README.md CHANGED
@@ -1,5 +1,33 @@
1
- Coming soon.
1
+ # Tessl
2
2
 
3
- Please follow the early access instructions you were provided with.
3
+ Tessl is an Agent Enablement Platform that gives your agents the context they're missing.
4
4
 
5
- http://tessl.io
5
+ - Install usage docs for your favorite open source library from the Tessl Spec Registry
6
+ - Create your own internal docs and share with your team
7
+
8
+ **Explore more in our [official documentation](https://docs.tessl.io)**.
9
+
10
+ Visit the [Registry](https://tessl.io/registry) to see which open source libraries we provide documentation for.
11
+
12
+ ## Get started
13
+
14
+ 1. Install Tessl:
15
+
16
+ ```sh
17
+ curl -fsSL https://get.tessl.io | sh
18
+ ```
19
+
20
+ 2. Now in your project directory run `tessl`
21
+
22
+ ## Reporting Bugs
23
+
24
+ We love feedback. You can use the `tessl feedback` command to report issues or share feedback directly within Tessl, file a [GitHub issue](https://github.com/tesslio/cli/issues) or just email <support@tessl.io>.
25
+
26
+ ## Connect on Discord
27
+
28
+ You are welcome to join the [Tessl Discord](https://tessl.co/4eV736y) to connect with other developers using Tessl.
29
+
30
+ ## Terms and Conditions
31
+
32
+ - [Terms of Service](https://tessl.io/policies/terms)
33
+ - [Privacy Policy](https://tessl.io/policies/privacy-cookies)
package/bin/tessl.js ADDED
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env node
2
+
3
+ // installer/src/main.ts
4
+ import { existsSync as existsSync3 } from "node:fs";
5
+ import { createInterface } from "node:readline";
6
+
7
+ // installer/src/channels.ts
8
+ async function fetchLatestVersion(channel) {
9
+ const url = getChannelUrl(channel);
10
+ const response = await fetch(url);
11
+ if (!response.ok) {
12
+ throw new Error(`Failed to fetch version from ${url}: ${response.status} ${response.statusText}`);
13
+ }
14
+ const version = (await response.text()).trim();
15
+ if (!version) {
16
+ throw new Error(`Empty version returned from ${url}`);
17
+ }
18
+ return version;
19
+ }
20
+ function getChannelFromVersion(version) {
21
+ if (version.includes("head"))
22
+ return "head";
23
+ if (version.includes("nightly"))
24
+ return "nightly";
25
+ if (version.includes("beta"))
26
+ return "beta";
27
+ return "latest";
28
+ }
29
+ function getChannelUrl(channel) {
30
+ const baseUrl = process.env.TESSL_INSTALL_BASE_URL || "https://install.tessl.io";
31
+ return `${baseUrl}/.well-known/tessl/${channel}.txt`;
32
+ }
33
+ function getBinaryUrl(version, platform) {
34
+ const baseUrl = process.env.TESSL_INSTALL_BASE_URL || "https://install.tessl.io";
35
+ const encodedVersion = encodeURIComponent(version);
36
+ return `${baseUrl}/binaries/${encodedVersion}/tessl-${encodedVersion}-${platform}.tar.gz`;
37
+ }
38
+
39
+ // installer/src/download.ts
40
+ async function downloadTarball(url) {
41
+ const response = await fetch(url);
42
+ if (!response.ok) {
43
+ throw new Error(`Failed to download binary: ${response.status} ${response.statusText}`);
44
+ }
45
+ if (!response.body) {
46
+ throw new Error("Response body is null");
47
+ }
48
+ return response.body;
49
+ }
50
+
51
+ // installer/src/extract.ts
52
+ import { spawn } from "node:child_process";
53
+ import { mkdir } from "node:fs/promises";
54
+ import { pipeline } from "node:stream/promises";
55
+ async function extractTarball(stream, destination) {
56
+ await mkdir(destination, { recursive: true });
57
+ const tar = spawn("tar", ["-xzf", "-", "-C", destination], {
58
+ stdio: ["pipe", "inherit", "inherit"]
59
+ });
60
+ if (!tar.stdin) {
61
+ throw new Error("Failed to open tar stdin");
62
+ }
63
+ const tarExit = new Promise((resolve, reject) => {
64
+ tar.on("exit", (code) => {
65
+ if (code === 0) {
66
+ resolve();
67
+ } else {
68
+ reject(new Error(`tar exited with code ${code}`));
69
+ }
70
+ });
71
+ tar.on("error", reject);
72
+ });
73
+ await pipeline(stream, tar.stdin);
74
+ await tarExit;
75
+ }
76
+
77
+ // installer/src/paths.ts
78
+ import { homedir } from "node:os";
79
+ import { join } from "node:path";
80
+ function getXdgDataHome() {
81
+ return process.env.XDG_DATA_HOME ?? join(homedir(), ".local", "share");
82
+ }
83
+ function getSymlinkPath() {
84
+ return join(homedir(), ".local", "bin", "tessl");
85
+ }
86
+ function getVersionsDirectory() {
87
+ return join(getXdgDataHome(), "tessl", "versions");
88
+ }
89
+ function getBinaryPath(version, platform) {
90
+ return join(getVersionsDirectory(), `tessl-${version}-${platform}`);
91
+ }
92
+
93
+ // installer/src/platform.ts
94
+ import { execSync } from "node:child_process";
95
+ import { existsSync } from "node:fs";
96
+ function getLibcVariant() {
97
+ if (process.platform !== "linux")
98
+ return null;
99
+ try {
100
+ if (existsSync("/etc/alpine-release"))
101
+ return "musl";
102
+ } catch {}
103
+ try {
104
+ const lddOutput = execSync("ldd /bin/ls 2>/dev/null", {
105
+ encoding: "utf-8"
106
+ });
107
+ if (lddOutput.includes("musl"))
108
+ return "musl";
109
+ } catch {}
110
+ return "glibc";
111
+ }
112
+ function getPlatformString() {
113
+ const platform = process.platform;
114
+ const arch = process.arch;
115
+ if (platform === "darwin") {
116
+ if (arch === "arm64")
117
+ return "darwin-arm64";
118
+ if (arch === "x64")
119
+ return "darwin-x64";
120
+ }
121
+ if (platform === "linux") {
122
+ const variant = getLibcVariant();
123
+ if (arch === "x64") {
124
+ return variant === "musl" ? "linux-x64-musl" : "linux-x64";
125
+ }
126
+ if (arch === "arm64") {
127
+ return variant === "musl" ? "linux-arm64-musl" : "linux-arm64";
128
+ }
129
+ }
130
+ return null;
131
+ }
132
+ function getPlatformDescription() {
133
+ const platform = process.platform;
134
+ const arch = process.arch;
135
+ const platformNames = {
136
+ darwin: "macOS",
137
+ linux: "Linux",
138
+ win32: "Windows"
139
+ };
140
+ const archNames = {
141
+ arm64: "ARM64",
142
+ x64: "x64",
143
+ ia32: "x86"
144
+ };
145
+ const platformName = platformNames[platform] ?? platform;
146
+ const archName = archNames[arch] ?? arch;
147
+ return `${platformName} ${archName}`;
148
+ }
149
+
150
+ // installer/src/spawn.ts
151
+ import { spawn as spawn2 } from "node:child_process";
152
+ function spawnBinary(binaryPath, args) {
153
+ const child = spawn2(binaryPath, args, {
154
+ stdio: "inherit",
155
+ env: {
156
+ ...process.env,
157
+ TESSL_MANAGED_BY_NPM: "1"
158
+ }
159
+ });
160
+ const signals = ["SIGINT", "SIGTERM", "SIGHUP"];
161
+ const handlers = new Map;
162
+ for (const signal of signals) {
163
+ const handler = () => {
164
+ child.kill(signal);
165
+ };
166
+ handlers.set(signal, handler);
167
+ process.on(signal, handler);
168
+ }
169
+ child.on("exit", (code, signal) => {
170
+ if (signal) {
171
+ for (const [sig, handler] of handlers) {
172
+ process.removeListener(sig, handler);
173
+ }
174
+ process.kill(process.pid, signal);
175
+ } else {
176
+ process.exit(code ?? 1);
177
+ }
178
+ });
179
+ child.on("error", (err) => {
180
+ console.error(`Failed to spawn binary: ${err.message}`);
181
+ process.exit(1);
182
+ });
183
+ }
184
+
185
+ // installer/src/symlink.ts
186
+ import { existsSync as existsSync2 } from "node:fs";
187
+ import { symlink, rename, unlink, mkdir as mkdir2, readlink } from "node:fs/promises";
188
+ import { dirname, resolve } from "node:path";
189
+ async function getExistingBinaryPath(symlinkPath) {
190
+ if (!existsSync2(symlinkPath)) {
191
+ return null;
192
+ }
193
+ try {
194
+ const binaryPath = await readlink(symlinkPath);
195
+ const resolvedPath = resolve(dirname(symlinkPath), binaryPath);
196
+ if (!existsSync2(resolvedPath)) {
197
+ return null;
198
+ }
199
+ return resolvedPath;
200
+ } catch {
201
+ return null;
202
+ }
203
+ }
204
+ async function createSymlinkAtomic(target, linkPath) {
205
+ const tempPath = `${linkPath}.tmp`;
206
+ await mkdir2(dirname(linkPath), { recursive: true });
207
+ try {
208
+ await unlink(tempPath);
209
+ } catch {}
210
+ await symlink(target, tempPath);
211
+ await rename(tempPath, linkPath);
212
+ }
213
+
214
+ // installer/src/main.ts
215
+ function isInteractive() {
216
+ return process.stdin.isTTY === true && process.stdout.isTTY === true;
217
+ }
218
+ async function promptConfirmation(message) {
219
+ return new Promise((resolve2) => {
220
+ const rl = createInterface({
221
+ input: process.stdin,
222
+ output: process.stdout
223
+ });
224
+ rl.question(`${message} (Y/n) `, (answer) => {
225
+ rl.close();
226
+ const a = answer.trim().toLowerCase();
227
+ resolve2(a === "" || a === "y");
228
+ });
229
+ });
230
+ }
231
+ function printUnsupportedPlatformMessage() {
232
+ console.error("Error: Unsupported platform", getPlatformDescription());
233
+ console.error(`Tessl CLI binaries are available for:
234
+ - macOS (ARM64, x64)
235
+ - Linux (x64, ARM64)
236
+ `);
237
+ }
238
+ async function prepareBinary() {
239
+ const symlinkPath = getSymlinkPath();
240
+ const symlinkTarget = await getExistingBinaryPath(symlinkPath);
241
+ const installerVersion = "0.63.2";
242
+ const isTestOrDevBuild = installerVersion.includes("test") || installerVersion.includes("dev");
243
+ let symlinkMismatch = false;
244
+ if (isTestOrDevBuild && symlinkTarget) {
245
+ const platform2 = getPlatformString();
246
+ if (!platform2) {
247
+ printUnsupportedPlatformMessage();
248
+ return process.exit(1);
249
+ }
250
+ if (symlinkTarget !== getBinaryPath(installerVersion, platform2)) {
251
+ console.log(`Test/dev build - switching to version: ${installerVersion}`);
252
+ symlinkMismatch = true;
253
+ }
254
+ }
255
+ if (symlinkTarget && !symlinkMismatch) {
256
+ return symlinkPath;
257
+ }
258
+ const platform = getPlatformString();
259
+ if (!platform) {
260
+ printUnsupportedPlatformMessage();
261
+ return process.exit(1);
262
+ }
263
+ const version = isTestOrDevBuild ? installerVersion : await fetchLatestVersion(getChannelFromVersion(installerVersion));
264
+ const binaryPath = getBinaryPath(version, platform);
265
+ if (existsSync3(binaryPath)) {
266
+ return binaryPath;
267
+ }
268
+ console.log(`Downloading ${version} for ${platform}`);
269
+ const url = getBinaryUrl(version, platform);
270
+ const progressInterval = setInterval(() => process.stdout.write("."), 500).unref();
271
+ try {
272
+ const tarballStream = await downloadTarball(url);
273
+ const versionsDir = getVersionsDirectory();
274
+ await extractTarball(tarballStream, versionsDir);
275
+ } finally {
276
+ clearInterval(progressInterval);
277
+ console.log("");
278
+ }
279
+ const shouldCreateSymlink = !isInteractive() || await promptConfirmation(`Install Tessl CLI to ${symlinkPath}?`);
280
+ if (shouldCreateSymlink) {
281
+ await createSymlinkAtomic(binaryPath, symlinkPath);
282
+ if (platform.includes("musl")) {
283
+ console.log(`
284
+ This system requires libgcc and libstdc++. Install these using your distribution's package manager.
285
+ On Alpine: apk add libgcc libstdc++
286
+ `);
287
+ }
288
+ return symlinkPath;
289
+ }
290
+ return binaryPath;
291
+ }
292
+ async function main() {
293
+ const path = await prepareBinary();
294
+ spawnBinary(path, process.argv.slice(2));
295
+ }
296
+ main().catch((err) => {
297
+ console.error("Unexpected error:");
298
+ console.error(err);
299
+ process.exit(1);
300
+ });
package/package.json CHANGED
@@ -1,8 +1,18 @@
1
1
  {
2
2
  "name": "tessl",
3
- "version": "0.0.0",
4
- "description": "",
5
- "readme": "README.md",
6
- "homepage": "https://tessl.io",
7
- "license": "UNLICENSED"
3
+ "version": "0.63.2",
4
+ "description": "Tessl CLI",
5
+ "author": "Tessl",
6
+ "license": "SEE LICENSE.md",
7
+ "type": "module",
8
+ "bin": {
9
+ "tessl": "bin/tessl.js"
10
+ },
11
+ "files": [
12
+ "bin"
13
+ ],
14
+ "engines": {
15
+ "node": ">=20"
16
+ },
17
+ "dependencies": {}
8
18
  }