@ai-coders/installer 0.3.0 → 0.5.0

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +42 -6
  3. package/dist/artifact-client.d.ts +44 -0
  4. package/dist/artifact-client.js +213 -0
  5. package/dist/artifact-client.js.map +1 -0
  6. package/dist/clerk-auth.d.ts +7 -1
  7. package/dist/clerk-auth.js +16 -2
  8. package/dist/clerk-auth.js.map +1 -1
  9. package/dist/cli-command.d.ts +18 -3
  10. package/dist/cli-command.js +48 -2
  11. package/dist/cli-command.js.map +1 -1
  12. package/dist/cli.js +54 -6
  13. package/dist/cli.js.map +1 -1
  14. package/dist/empty-directory.d.ts +2 -0
  15. package/dist/empty-directory.js +22 -0
  16. package/dist/empty-directory.js.map +1 -0
  17. package/dist/i18n.d.ts +18 -0
  18. package/dist/i18n.js +52 -8
  19. package/dist/i18n.js.map +1 -1
  20. package/dist/product-manifest.js +4 -2
  21. package/dist/product-manifest.js.map +1 -1
  22. package/dist/products/second-brain/apply.d.ts +1 -0
  23. package/dist/products/second-brain/apply.js +4 -2
  24. package/dist/products/second-brain/apply.js.map +1 -1
  25. package/dist/products/second-brain/bootstrap.d.ts +1 -1
  26. package/dist/products/second-brain/bootstrap.js +1 -1
  27. package/dist/products/second-brain/bootstrap.js.map +1 -1
  28. package/dist/products/second-brain/envfile.d.ts +2 -0
  29. package/dist/products/second-brain/envfile.js +15 -0
  30. package/dist/products/second-brain/envfile.js.map +1 -1
  31. package/dist/products/second-brain/main.d.ts +1 -0
  32. package/dist/products/second-brain/main.js +3 -0
  33. package/dist/products/second-brain/main.js.map +1 -1
  34. package/dist/products/second-brain/service.d.ts +1 -0
  35. package/dist/products/second-brain/service.js +14 -0
  36. package/dist/products/second-brain/service.js.map +1 -1
  37. package/dist/products/second-brain/source-archive.d.ts +1 -0
  38. package/dist/products/second-brain/source-archive.js +86 -0
  39. package/dist/products/second-brain/source-archive.js.map +1 -0
  40. package/dist/products/severino/main.d.ts +1 -0
  41. package/dist/products/severino/main.js +3 -0
  42. package/dist/products/severino/main.js.map +1 -1
  43. package/dist/products/severino/service.d.ts +1 -0
  44. package/dist/products/severino/service.js +14 -0
  45. package/dist/products/severino/service.js.map +1 -1
  46. package/dist/products/severino/source-archive.d.ts +1 -0
  47. package/dist/products/severino/source-archive.js +86 -0
  48. package/dist/products/severino/source-archive.js.map +1 -0
  49. package/dist/project-bootstrap.d.ts +22 -0
  50. package/dist/project-bootstrap.js +171 -0
  51. package/dist/project-bootstrap.js.map +1 -0
  52. package/dist/safe-archive.d.ts +1 -0
  53. package/dist/safe-archive.js +201 -0
  54. package/dist/safe-archive.js.map +1 -0
  55. package/dist/terminal-input.d.ts +1 -0
  56. package/dist/terminal-input.js +15 -0
  57. package/dist/terminal-input.js.map +1 -0
  58. package/package.json +2 -1
@@ -0,0 +1,171 @@
1
+ import { createHash, timingSafeEqual } from "node:crypto";
2
+ import { lstat, mkdir, mkdtemp, readdir, rm, stat, } from "node:fs/promises";
3
+ import { createReadStream, createWriteStream } from "node:fs";
4
+ import { tmpdir } from "node:os";
5
+ import path from "node:path";
6
+ import { pipeline } from "node:stream/promises";
7
+ import {} from "./clerk-auth.js";
8
+ import { isDirectoryEffectivelyEmpty } from "./empty-directory.js";
9
+ import { cliMessages } from "./i18n.js";
10
+ import { loadInstallerProject, } from "./product-manifest.js";
11
+ import { extractSafeTarGz } from "./safe-archive.js";
12
+ function checksumMatches(archive, expected) {
13
+ const received = createHash("sha256").update(archive).digest("hex");
14
+ const receivedBuffer = Buffer.from(received);
15
+ const expectedBuffer = Buffer.from(expected);
16
+ return (receivedBuffer.length === expectedBuffer.length &&
17
+ timingSafeEqual(receivedBuffer, expectedBuffer));
18
+ }
19
+ function verifyArchive(archive, descriptor) {
20
+ if (archive.byteLength !== descriptor.byteSize ||
21
+ !checksumMatches(archive, descriptor.sha256)) {
22
+ throw new Error(cliMessages.artifactChecksumMismatch);
23
+ }
24
+ }
25
+ const copyStagedFile = async (source, destination, mode) => {
26
+ await pipeline(createReadStream(source), createWriteStream(destination, { flags: "wx", mode }));
27
+ };
28
+ async function collectPaths(root, relativePath = "") {
29
+ const absolutePath = path.join(root, relativePath);
30
+ const entries = await readdir(absolutePath, { withFileTypes: true });
31
+ const paths = [];
32
+ for (const entry of entries) {
33
+ const childRelativePath = relativePath === "" ? entry.name : `${relativePath}/${entry.name}`;
34
+ const childAbsolutePath = path.join(root, childRelativePath);
35
+ if (entry.isDirectory()) {
36
+ paths.push({
37
+ relativePath: childRelativePath,
38
+ absolutePath: childAbsolutePath,
39
+ kind: "directory",
40
+ });
41
+ paths.push(...(await collectPaths(root, childRelativePath)));
42
+ }
43
+ else if (entry.isFile()) {
44
+ const information = await stat(childAbsolutePath);
45
+ paths.push({
46
+ relativePath: childRelativePath,
47
+ absolutePath: childAbsolutePath,
48
+ kind: "file",
49
+ mode: information.mode,
50
+ });
51
+ }
52
+ else {
53
+ throw new Error(cliMessages.archiveInvalid);
54
+ }
55
+ }
56
+ return paths;
57
+ }
58
+ async function ensureParentDirectory(targetRoot, relativePath, createdDirectories) {
59
+ const parent = path.dirname(path.join(targetRoot, relativePath));
60
+ const parentRelative = path.relative(targetRoot, parent);
61
+ if (parentRelative === "")
62
+ return;
63
+ const segments = parentRelative.split(path.sep);
64
+ let currentRoot = targetRoot;
65
+ let currentRelative = "";
66
+ for (const segment of segments) {
67
+ currentRoot = path.join(currentRoot, segment);
68
+ currentRelative =
69
+ currentRelative === "" ? segment : `${currentRelative}/${segment}`;
70
+ let created = false;
71
+ try {
72
+ await lstat(currentRoot);
73
+ }
74
+ catch (error) {
75
+ if (error.code !== "ENOENT")
76
+ throw error;
77
+ await mkdir(currentRoot, { mode: 0o755 });
78
+ created = true;
79
+ }
80
+ if (created)
81
+ createdDirectories.push(currentRoot);
82
+ }
83
+ }
84
+ async function copyStagedProject(stagingRoot, targetRoot, copyFileImplementation = copyStagedFile) {
85
+ const stagedPaths = await collectPaths(stagingRoot);
86
+ const createdFiles = [];
87
+ const createdDirectories = [];
88
+ try {
89
+ for (const directory of stagedPaths
90
+ .filter((entry) => entry.kind === "directory")
91
+ .sort((left, right) => left.relativePath.length - right.relativePath.length)) {
92
+ const target = path.join(targetRoot, directory.relativePath);
93
+ let created = false;
94
+ try {
95
+ await lstat(target);
96
+ }
97
+ catch (error) {
98
+ if (error.code !== "ENOENT")
99
+ throw error;
100
+ await ensureParentDirectory(targetRoot, directory.relativePath, createdDirectories);
101
+ await mkdir(target, { mode: 0o755 });
102
+ created = true;
103
+ }
104
+ if (created)
105
+ createdDirectories.push(target);
106
+ }
107
+ for (const file of stagedPaths.filter((entry) => entry.kind === "file")) {
108
+ const target = path.join(targetRoot, file.relativePath);
109
+ await ensureParentDirectory(targetRoot, file.relativePath, createdDirectories);
110
+ createdFiles.push(target);
111
+ await copyFileImplementation(file.absolutePath, target, (file.mode ?? 0o644) & 0o111 ? 0o755 : 0o644);
112
+ }
113
+ }
114
+ catch (error) {
115
+ for (const createdFile of createdFiles.reverse()) {
116
+ await rm(createdFile, { force: true }).catch(() => { });
117
+ }
118
+ for (const createdDirectory of [...createdDirectories].reverse()) {
119
+ await rm(createdDirectory, { force: true, recursive: true }).catch(() => { });
120
+ }
121
+ throw error;
122
+ }
123
+ }
124
+ export async function bootstrapProductProject(options) {
125
+ if (!(await isDirectoryEffectivelyEmpty(options.cwd))) {
126
+ throw new Error(cliMessages.bootstrapTargetChanged);
127
+ }
128
+ const descriptor = await options.session.withAccessToken(options.requestArtifact);
129
+ if (descriptor.product !== options.product) {
130
+ throw new Error(cliMessages.artifactProductMismatch(descriptor.product, options.product));
131
+ }
132
+ options.writeOutput(cliMessages.bootstrapPrompt(options.product, descriptor.version));
133
+ const accepted = await options.confirmBootstrap({
134
+ product: options.product,
135
+ version: descriptor.version,
136
+ });
137
+ if (!accepted) {
138
+ options.writeOutput(cliMessages.bootstrapDeclined);
139
+ return null;
140
+ }
141
+ options.writeOutput(cliMessages.bootstrapDownloadStarted(options.product, descriptor.version));
142
+ const archive = await options.downloadArtifact(descriptor);
143
+ verifyArchive(archive, descriptor);
144
+ const stagingRoot = await mkdtemp(path.join(tmpdir(), "ai-coders-bootstrap-"));
145
+ try {
146
+ await extractSafeTarGz(archive, stagingRoot);
147
+ let manifestVersion;
148
+ try {
149
+ const stagedProject = await loadInstallerProject(stagingRoot, options.product);
150
+ manifestVersion = stagedProject.manifest.version;
151
+ }
152
+ catch {
153
+ throw new Error(cliMessages.archiveInvalid);
154
+ }
155
+ if (manifestVersion !== descriptor.version) {
156
+ throw new Error(cliMessages.artifactVersionMismatch(descriptor.version, manifestVersion));
157
+ }
158
+ if (!(await isDirectoryEffectivelyEmpty(options.cwd))) {
159
+ throw new Error(cliMessages.bootstrapTargetChanged);
160
+ }
161
+ await copyStagedProject(stagingRoot, options.cwd, options.copyStagedFile === undefined
162
+ ? copyStagedFile
163
+ : options.copyStagedFile);
164
+ options.writeOutput(cliMessages.bootstrapCompleted(options.product, descriptor.version));
165
+ return { descriptor, sourceArchive: archive };
166
+ }
167
+ finally {
168
+ await rm(stagingRoot, { force: true, recursive: true }).catch(() => { });
169
+ }
170
+ }
171
+ //# sourceMappingURL=project-bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-bootstrap.js","sourceRoot":"","sources":["../src/project-bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function extractSafeTarGz(archive: Buffer, destination: string): Promise<void>;
@@ -0,0 +1,201 @@
1
+ import { mkdir, open, rm, stat, writeFile, } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { Parser } from "tar";
4
+ import { cliMessages } from "./i18n.js";
5
+ const maximumEntries = 10_000;
6
+ const maximumUncompressedBytes = 512 * 1024 * 1024;
7
+ const maximumPathLength = 1024;
8
+ const allowedEntryTypes = new Set([
9
+ "File",
10
+ "OldFile",
11
+ "ContiguousFile",
12
+ "Directory",
13
+ ]);
14
+ function invalidArchive() {
15
+ return new Error(cliMessages.archiveInvalid);
16
+ }
17
+ function normalizeArchivePath(value) {
18
+ if (value === "" ||
19
+ value.length > maximumPathLength ||
20
+ value.includes("\0") ||
21
+ value.includes("\\") ||
22
+ value.includes(":") ||
23
+ path.posix.isAbsolute(value) ||
24
+ path.win32.isAbsolute(value)) {
25
+ throw invalidArchive();
26
+ }
27
+ const segments = value.split("/");
28
+ if (segments.some((segment) => segment === "" || segment === "." || segment === "..")) {
29
+ throw invalidArchive();
30
+ }
31
+ return segments.join("/");
32
+ }
33
+ function isForbidden(relativePath) {
34
+ const segments = relativePath.split("/");
35
+ const fileName = segments.at(-1) ?? "";
36
+ const lowerCaseFileName = fileName.toLowerCase();
37
+ return (segments.some((segment) => segment === ".git" || segment === "node_modules" || segment === ".output") ||
38
+ fileName === ".env" ||
39
+ (fileName.startsWith(".env.") && fileName !== ".env.example") ||
40
+ fileName === ".installer-state.json" ||
41
+ (segments[0] === ".claude" && segments[1] === "worktrees") ||
42
+ (segments[0] === ".eve" && segments[1] === ".workflow-data") ||
43
+ relativePath === ".claude/settings.local.json" ||
44
+ relativePath === ".claude/.credentials.json" ||
45
+ relativePath === ".codex/auth.json" ||
46
+ fileName === "credentials.json" ||
47
+ fileName === ".npmrc" ||
48
+ fileName === "id_rsa" ||
49
+ fileName === "id_ed25519" ||
50
+ /\.(?:pem|key|p12|pfx)$/.test(lowerCaseFileName));
51
+ }
52
+ function planEntry(entry) {
53
+ if (!allowedEntryTypes.has(entry.type) || entry.meta || entry.invalid) {
54
+ throw invalidArchive();
55
+ }
56
+ if (entry.linkpath !== undefined || entry.type === "Directory") {
57
+ if (entry.linkpath !== undefined)
58
+ throw invalidArchive();
59
+ }
60
+ const relativePath = normalizeArchivePath(entry.path);
61
+ if (isForbidden(relativePath))
62
+ throw invalidArchive();
63
+ const byteSize = entry.type === "Directory" ? 0 : entry.size;
64
+ if (!Number.isSafeInteger(byteSize) || byteSize < 0) {
65
+ throw invalidArchive();
66
+ }
67
+ return {
68
+ path: relativePath,
69
+ type: entry.type === "Directory" ? "directory" : "file",
70
+ byteSize,
71
+ };
72
+ }
73
+ function validatePlans(plans) {
74
+ if (plans.length === 0 || plans.length > maximumEntries) {
75
+ throw invalidArchive();
76
+ }
77
+ const totalBytes = plans.reduce((total, entry) => total + entry.byteSize, 0);
78
+ if (totalBytes > maximumUncompressedBytes)
79
+ throw invalidArchive();
80
+ const seen = new Set();
81
+ const files = new Set();
82
+ const directories = new Set();
83
+ for (const entry of plans) {
84
+ if (seen.has(entry.path))
85
+ throw invalidArchive();
86
+ if (entry.type === "file" && directories.has(entry.path)) {
87
+ throw invalidArchive();
88
+ }
89
+ if (entry.type === "directory" && files.has(entry.path)) {
90
+ throw invalidArchive();
91
+ }
92
+ const segments = entry.path.split("/");
93
+ for (let index = 1; index < segments.length; index += 1) {
94
+ const parent = segments.slice(0, index).join("/");
95
+ if (files.has(parent))
96
+ throw invalidArchive();
97
+ }
98
+ seen.add(entry.path);
99
+ if (entry.type === "file")
100
+ files.add(entry.path);
101
+ else
102
+ directories.add(entry.path);
103
+ }
104
+ }
105
+ async function parsePlans(archive) {
106
+ const parser = new Parser({ strict: true });
107
+ const plans = [];
108
+ const finished = new Promise((resolve, reject) => {
109
+ parser.once("error", reject);
110
+ parser.once("end", () => resolve());
111
+ });
112
+ parser.on("entry", (entry) => {
113
+ try {
114
+ plans.push(planEntry(entry));
115
+ entry.resume();
116
+ }
117
+ catch (error) {
118
+ parser.abort(error instanceof Error ? error : invalidArchive());
119
+ }
120
+ });
121
+ parser.end(archive);
122
+ await finished;
123
+ validatePlans(plans);
124
+ return plans;
125
+ }
126
+ async function safeWrite(destinationRoot, relativePath, execute) {
127
+ const absolutePath = path.join(destinationRoot, ...relativePath.split("/"));
128
+ const relative = path.relative(destinationRoot, absolutePath);
129
+ if (relative === "" ||
130
+ relative.startsWith("..") ||
131
+ path.isAbsolute(relative)) {
132
+ throw invalidArchive();
133
+ }
134
+ await execute();
135
+ }
136
+ export async function extractSafeTarGz(archive, destination) {
137
+ const plans = await parsePlans(archive);
138
+ await mkdir(destination, { recursive: true, mode: 0o700 });
139
+ const createdPaths = [];
140
+ try {
141
+ const parser = new Parser({ strict: true });
142
+ const writes = [];
143
+ const finished = new Promise((resolve, reject) => {
144
+ parser.once("error", reject);
145
+ parser.once("end", () => resolve());
146
+ });
147
+ parser.on("entry", (entry) => {
148
+ try {
149
+ const plan = planEntry(entry);
150
+ if (plan.type === "directory") {
151
+ entry.resume();
152
+ writes.push(safeWrite(destination, plan.path, async () => {
153
+ await mkdir(path.join(destination, plan.path), {
154
+ recursive: true,
155
+ mode: 0o755,
156
+ });
157
+ createdPaths.push(path.join(destination, plan.path));
158
+ }));
159
+ return;
160
+ }
161
+ writes.push(entry
162
+ .concat()
163
+ .then(async (content) => {
164
+ if (content.byteLength !== plan.byteSize)
165
+ throw invalidArchive();
166
+ await safeWrite(destination, plan.path, async () => {
167
+ await mkdir(path.dirname(path.join(destination, plan.path)), {
168
+ recursive: true,
169
+ mode: 0o755,
170
+ });
171
+ const handle = await open(path.join(destination, plan.path), "wx", (entry.mode ?? 0o644) & 0o111 ? 0o755 : 0o644);
172
+ try {
173
+ await writeFile(handle, content);
174
+ createdPaths.push(path.join(destination, plan.path));
175
+ }
176
+ finally {
177
+ await handle.close();
178
+ }
179
+ });
180
+ })
181
+ .catch((error) => {
182
+ throw error instanceof Error ? error : invalidArchive();
183
+ }));
184
+ }
185
+ catch (error) {
186
+ parser.abort(error instanceof Error ? error : invalidArchive());
187
+ }
188
+ });
189
+ parser.end(archive);
190
+ await finished;
191
+ await Promise.all(writes);
192
+ await stat(destination);
193
+ }
194
+ catch (error) {
195
+ for (const createdPath of createdPaths.sort().reverse()) {
196
+ await rm(createdPath, { force: true, recursive: true }).catch(() => { });
197
+ }
198
+ throw error instanceof Error ? error : invalidArchive();
199
+ }
200
+ }
201
+ //# sourceMappingURL=safe-archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safe-archive.js","sourceRoot":"","sources":["../src/safe-archive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function confirmBootstrapDownload(): Promise<boolean>;
@@ -0,0 +1,15 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ export async function confirmBootstrapDownload() {
3
+ const readline = createInterface({
4
+ input: process.stdin,
5
+ output: process.stdout,
6
+ });
7
+ try {
8
+ const answer = await readline.question("");
9
+ return answer.trim().toLowerCase() === "yes";
10
+ }
11
+ finally {
12
+ readline.close();
13
+ }
14
+ }
15
+ //# sourceMappingURL=terminal-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal-input.js","sourceRoot":"","sources":["../src/terminal-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,wBAAwB;IAC5C,MAAM,QAAQ,GAAG,eAAe,CAAC;QAC/B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CAAC;IACH,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC3C,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC;IAC/C,CAAC;YAAS,CAAC;QACT,QAAQ,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-coders/installer",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "AI Coders product installers.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -38,6 +38,7 @@
38
38
  "@invokta/mcp": "0.5.0",
39
39
  "libsodium-wrappers": "^0.8.4",
40
40
  "ssh2": "^1.17.0",
41
+ "tar": "7.5.22",
41
42
  "zod": "4.4.3"
42
43
  },
43
44
  "devDependencies": {