stella-coder 3.9.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.
- package/(/320/270/320/274/321/217 +0 -0
- package/.env.example +4 -0
- package/README.md +72 -0
- package/STELLA.md +6 -0
- package/antimalware/database.mjs +871 -0
- package/antimalware/index.mjs +8 -0
- package/antimalware/scanner.mjs +591 -0
- package/antimalware/ui.mjs +570 -0
- package/components.json +21 -0
- package/create_cats_pptx.py +121 -0
- package/eslint.config.mjs +16 -0
- package/hello.py +2 -0
- package/install.bat +35 -0
- package/next-env.d.ts +6 -0
- package/next.config.mjs +11 -0
- package/package.json +58 -0
- package/pnpm-workspace.yaml +7 -0
- package/postcss.config.mjs +8 -0
- package/publish.mjs +52 -0
- package/stella-cli/banner.mjs +46 -0
- package/stella-cli/build.mjs +151 -0
- package/stella-cli/index.mjs +3073 -0
- package/stella-cli/markdown.mjs +100 -0
- package/stella-cli/sea-config.json +5 -0
- package/stella-cli/security.mjs +237 -0
- package/stella-cli/theme.mjs +89 -0
- package/stella-cli/tools.mjs +3145 -0
- package/tsconfig.json +41 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from pptx import Presentation
|
|
2
|
+
from pptx.util import Inches, Pt, Emu
|
|
3
|
+
from pptx.dml.color import RGBColor
|
|
4
|
+
from pptx.enum.text import PP_ALIGN
|
|
5
|
+
|
|
6
|
+
prs = Presentation()
|
|
7
|
+
prs.slide_width = Inches(13.333)
|
|
8
|
+
prs.slide_height = Inches(7.5)
|
|
9
|
+
|
|
10
|
+
# Цвета
|
|
11
|
+
ORANGE = RGBColor(0xFF, 0x8C, 0x00)
|
|
12
|
+
DARK = RGBColor(0x2D, 0x2D, 0x2D)
|
|
13
|
+
WHITE = RGBColor(0xFF, 0xFF, 0xFF)
|
|
14
|
+
LIGHT_BG = RGBColor(0xFF, 0xF5, 0xE6)
|
|
15
|
+
|
|
16
|
+
def set_slide_bg(slide, r, g, b):
|
|
17
|
+
background = slide.background
|
|
18
|
+
fill = background.fill
|
|
19
|
+
fill.solid()
|
|
20
|
+
fill.fore_color.rgb = RGBColor(r, g, b)
|
|
21
|
+
|
|
22
|
+
def add_text_box(slide, left, top, width, height, text, font_size=24, bold=False, color=DARK, alignment=PP_ALIGN.LEFT):
|
|
23
|
+
txBox = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
|
|
24
|
+
tf = txBox.text_frame
|
|
25
|
+
tf.word_wrap = True
|
|
26
|
+
p = tf.paragraphs[0]
|
|
27
|
+
p.text = text
|
|
28
|
+
p.font.size = Pt(font_size)
|
|
29
|
+
p.font.bold = bold
|
|
30
|
+
p.font.color.rgb = color
|
|
31
|
+
p.alignment = alignment
|
|
32
|
+
return txBox
|
|
33
|
+
|
|
34
|
+
def add_bullets(slide, left, top, width, height, items, font_size=20, color=DARK):
|
|
35
|
+
txBox = slide.shapes.add_textbox(Inches(left), Inches(top), Inches(width), Inches(height))
|
|
36
|
+
tf = txBox.text_frame
|
|
37
|
+
tf.word_wrap = True
|
|
38
|
+
for i, item in enumerate(items):
|
|
39
|
+
if i == 0:
|
|
40
|
+
p = tf.paragraphs[0]
|
|
41
|
+
else:
|
|
42
|
+
p = tf.add_paragraph()
|
|
43
|
+
p.text = item
|
|
44
|
+
p.font.size = Pt(font_size)
|
|
45
|
+
p.font.color.rgb = color
|
|
46
|
+
p.space_after = Pt(12)
|
|
47
|
+
p.level = 0
|
|
48
|
+
return txBox
|
|
49
|
+
|
|
50
|
+
# Слайд 1 — Титульный
|
|
51
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6]) # Blank
|
|
52
|
+
set_slide_bg(slide, 0xFF, 0x8C, 0x00)
|
|
53
|
+
add_text_box(slide, 1, 1.5, 11, 2, "🐱 КОТЫ", font_size=72, bold=True, color=WHITE, alignment=PP_ALIGN.CENTER)
|
|
54
|
+
add_text_box(slide, 1, 3.5, 11, 1.5, "Лучшие друзья человека", font_size=36, color=WHITE, alignment=PP_ALIGN.CENTER)
|
|
55
|
+
add_text_box(slide, 1, 5.5, 11, 1, "🐾 🐾 🐾 🐾 🐾", font_size=36, color=WHITE, alignment=PP_ALIGN.CENTER)
|
|
56
|
+
|
|
57
|
+
# Слайд 2 — Интересные факты
|
|
58
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6])
|
|
59
|
+
set_slide_bg(slide, 0xFF, 0xF5, 0xE6)
|
|
60
|
+
add_text_box(slide, 0.5, 0.5, 12, 1.2, "🔍 Интересные факты о котах", font_size=40, bold=True, color=ORANGE, alignment=PP_ALIGN.CENTER)
|
|
61
|
+
facts = [
|
|
62
|
+
"😴 Коты проводят 70% своей жизни во сне",
|
|
63
|
+
"👃 У каждого кота уникальный рисунок носа — как отпечаток пальца",
|
|
64
|
+
"🔊 Коты могут издавать более 100 различных звуков",
|
|
65
|
+
"🏆 Самый старый кот прожил 38 лет",
|
|
66
|
+
"🏃 Коты бегают со скоростью до 48 км/ч",
|
|
67
|
+
"❤️ Коты мурлыкают на частоте 25-150 Гц — это помогает заживлению тканей",
|
|
68
|
+
]
|
|
69
|
+
add_bullets(slide, 1.5, 2, 10, 5, facts, font_size=24, color=DARK)
|
|
70
|
+
|
|
71
|
+
# Слайд 3 — Популярные породы
|
|
72
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6])
|
|
73
|
+
set_slide_bg(slide, 0xFF, 0xF5, 0xE6)
|
|
74
|
+
add_text_box(slide, 0.5, 0.5, 12, 1.2, "🐈 Популярные породы", font_size=40, bold=True, color=ORANGE, alignment=PP_ALIGN.CENTER)
|
|
75
|
+
breeds = [
|
|
76
|
+
"🦁 Мейн-кун — гигант среди домашних котов (до 12 кг!)",
|
|
77
|
+
"👻 Сфинкс — бесшёрстная, но очень ласковая порода",
|
|
78
|
+
"🇬🇧 Британская короткошёрстная — классика жанра",
|
|
79
|
+
"🦄 Шотландская вислоухая — с милыми загнутыми ушами",
|
|
80
|
+
"🇹🇭 Сиамская — умная и голосистая порода",
|
|
81
|
+
"👑 Персидская — царственная красота и спокойный характер",
|
|
82
|
+
]
|
|
83
|
+
add_bullets(slide, 1.5, 2, 10, 5, breeds, font_size=24, color=DARK)
|
|
84
|
+
|
|
85
|
+
# Слайд 4 — Польза для здоровья
|
|
86
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6])
|
|
87
|
+
set_slide_bg(slide, 0xFF, 0xF5, 0xE6)
|
|
88
|
+
add_text_box(slide, 0.5, 0.5, 12, 1.2, "💚 Польза котов для здоровья", font_size=40, bold=True, color=ORANGE, alignment=PP_ALIGN.CENTER)
|
|
89
|
+
health = [
|
|
90
|
+
"😌 Снижают уровень стресса и тревожности",
|
|
91
|
+
"🎵 Мурлыкание помогает заживлять кости и ткани",
|
|
92
|
+
"💊 Понижают давление и уровень холестерина",
|
|
93
|
+
"🫀 Уменьшают риск инфаркта на 40%",
|
|
94
|
+
"🤗 Помогают бороться с одиночеством",
|
|
95
|
+
"👶 Дети, растущие с котами, реже болеют аллергией",
|
|
96
|
+
]
|
|
97
|
+
add_bullets(slide, 1.5, 2, 10, 5, health, font_size=24, color=DARK)
|
|
98
|
+
|
|
99
|
+
# Слайд 5 — Коты в культуре
|
|
100
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6])
|
|
101
|
+
set_slide_bg(slide, 0xFF, 0xF5, 0xE6)
|
|
102
|
+
add_text_box(slide, 0.5, 0.5, 12, 1.2, "🌍 Коты в культуре", font_size=40, bold=True, color=ORANGE, alignment=PP_ALIGN.CENTER)
|
|
103
|
+
culture = [
|
|
104
|
+
"🏛️ В Древнем Египте котов боготворили и мумифицировали",
|
|
105
|
+
"📱 Интернет-мемы сделали котов самыми популярными животными онлайн",
|
|
106
|
+
"🎨 Сальвадор Дали был известным любителем котов",
|
|
107
|
+
"🇯🇵 В Японии манэки-нэко (кот-привет) приносит удачу",
|
|
108
|
+
"🐈 Кот Боб — знаменитый рыжий уличный кот из Лондона",
|
|
109
|
+
"📚 Кошка Бегемот из «Мастера и Маргариты» — один из самых известных котов в литературе",
|
|
110
|
+
]
|
|
111
|
+
add_bullets(slide, 1.5, 2, 10, 5, culture, font_size=24, color=DARK)
|
|
112
|
+
|
|
113
|
+
# Слайд 6 — Заключительный
|
|
114
|
+
slide = prs.slides.add_slide(prs.slide_layouts[6])
|
|
115
|
+
set_slide_bg(slide, 0xFF, 0x8C, 0x00)
|
|
116
|
+
add_text_box(slide, 1, 2, 11, 2, "Спасибо за внимание!", font_size=60, bold=True, color=WHITE, alignment=PP_ALIGN.CENTER)
|
|
117
|
+
add_text_box(slide, 1, 4.2, 11, 1.5, "🐾 Возьмите кота — и ваша жизнь станет ярче! 🐾", font_size=28, color=WHITE, alignment=PP_ALIGN.CENTER)
|
|
118
|
+
|
|
119
|
+
output = r"C:\Users\user\Desktop\cats.pptx"
|
|
120
|
+
prs.save(output)
|
|
121
|
+
print(f"Презентация сохранена: {output}")
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { dirname } from "node:path"
|
|
2
|
+
import { fileURLToPath } from "node:url"
|
|
3
|
+
import { FlatCompat } from "@eslint/eslintrc"
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
6
|
+
const __dirname = dirname(__filename)
|
|
7
|
+
|
|
8
|
+
const compat = new FlatCompat({
|
|
9
|
+
baseDirectory: __dirname,
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
const eslintConfig = [
|
|
13
|
+
...compat.extends("next/core-web-vitals", "next/typescript"),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
export default eslintConfig
|
package/hello.py
ADDED
package/install.bat
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
echo.
|
|
3
|
+
echo ✦ Stella Coder 3.9 — Установка
|
|
4
|
+
echo.
|
|
5
|
+
|
|
6
|
+
:: Check Node.js
|
|
7
|
+
where node >nul 2>nul
|
|
8
|
+
if %errorlevel% neq 0 (
|
|
9
|
+
echo ОШИБКА: Node.js не установлен
|
|
10
|
+
echo Скачайте: https://nodejs.org
|
|
11
|
+
pause
|
|
12
|
+
exit /b 1
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
:: Check npm
|
|
16
|
+
where npm >nul 2>nul
|
|
17
|
+
if %errorlevel% neq 0 (
|
|
18
|
+
echo ОШИБКА: npm не установлен
|
|
19
|
+
pause
|
|
20
|
+
exit /b 1
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
echo [1/3] Установка зависимостей...
|
|
24
|
+
call npm install
|
|
25
|
+
|
|
26
|
+
echo [2/3] Установка команд...
|
|
27
|
+
call npm link
|
|
28
|
+
|
|
29
|
+
echo [3/3] Проверка...
|
|
30
|
+
node stella-cli/index.mjs --version
|
|
31
|
+
|
|
32
|
+
echo.
|
|
33
|
+
echo ✓ Готово! Запуск: stella
|
|
34
|
+
echo.
|
|
35
|
+
pause
|
package/next-env.d.ts
ADDED
package/next.config.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stella-coder",
|
|
3
|
+
"version": "3.9.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Stella Coder 3.9 — AI coding agent with computer control, smart home, Office automation, and antivirus",
|
|
6
|
+
"bin": {
|
|
7
|
+
"stella": "./stella-cli/index.mjs",
|
|
8
|
+
"stellar-av": "./antimalware/index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"stella": "node stella-cli/index.mjs",
|
|
12
|
+
"stellar-av": "node antimalware/index.mjs",
|
|
13
|
+
"dev": "next dev",
|
|
14
|
+
"build": "next build",
|
|
15
|
+
"build:cli": "node stella-cli/build.mjs",
|
|
16
|
+
"start": "next start",
|
|
17
|
+
"lint": "eslint .",
|
|
18
|
+
"publish": "node publish.mjs"
|
|
19
|
+
},
|
|
20
|
+
"keywords": ["ai", "coding", "agent", "terminal", "smart-home", "antivirus"],
|
|
21
|
+
"author": "codex alex",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@ai-sdk/openai": "^4.0.7",
|
|
25
|
+
"@ai-sdk/openai-compatible": "^3.0.5",
|
|
26
|
+
"@ai-sdk/react": "^4.0.16",
|
|
27
|
+
"@base-ui/react": "^1.5.0",
|
|
28
|
+
"@vercel/analytics": "1.6.1",
|
|
29
|
+
"ai": "^7.0.15",
|
|
30
|
+
"class-variance-authority": "^0.7.1",
|
|
31
|
+
"clsx": "^2.1.1",
|
|
32
|
+
"lucide-react": "^1.16.0",
|
|
33
|
+
"next": "16.2.6",
|
|
34
|
+
"react": "^19",
|
|
35
|
+
"react-dom": "^19",
|
|
36
|
+
"shadcn": "^4.8.0",
|
|
37
|
+
"tailwind-merge": "^3.3.1",
|
|
38
|
+
"tw-animate-css": "^1.4.0",
|
|
39
|
+
"zod": "^4.4.3"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@eslint/eslintrc": "^3.3.0",
|
|
43
|
+
"@tailwindcss/postcss": "^4.2.0",
|
|
44
|
+
"@types/node": "^24",
|
|
45
|
+
"@types/react": "^19",
|
|
46
|
+
"@types/react-dom": "^19",
|
|
47
|
+
"eslint": "^9.28.0",
|
|
48
|
+
"eslint-config-next": "^16.2.0",
|
|
49
|
+
"postcss": "^8.5",
|
|
50
|
+
"tailwindcss": "^4.2.0",
|
|
51
|
+
"typescript": "5.7.3"
|
|
52
|
+
},
|
|
53
|
+
"pnpm": {
|
|
54
|
+
"overrides": {
|
|
55
|
+
"hono": "4.12.25"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
package/publish.mjs
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Stella Coder — Publish to npm
|
|
3
|
+
import { execSync } from "node:child_process"
|
|
4
|
+
import fs from "node:fs"
|
|
5
|
+
import path from "node:path"
|
|
6
|
+
|
|
7
|
+
console.log("\n ✦ Stella Coder — Publish to npm\n")
|
|
8
|
+
|
|
9
|
+
// Check if logged in
|
|
10
|
+
try {
|
|
11
|
+
execSync("npm whoami", { stdio: "pipe" })
|
|
12
|
+
} catch {
|
|
13
|
+
console.log(" Вы не авторизованы в npm.")
|
|
14
|
+
console.log(" Выполните: npm login\n")
|
|
15
|
+
process.exit(1)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Get version from package.json
|
|
19
|
+
const pkg = JSON.parse(fs.readFileSync("package.json", "utf8"))
|
|
20
|
+
console.log(` Версия: ${pkg.version}`)
|
|
21
|
+
console.log(` Имя: ${pkg.name}\n`)
|
|
22
|
+
|
|
23
|
+
// Build
|
|
24
|
+
console.log(" [1/3] Сборка...")
|
|
25
|
+
try {
|
|
26
|
+
execSync("npm run build:cli", { stdio: "inherit" })
|
|
27
|
+
} catch {
|
|
28
|
+
console.log(" ⚠ Ошибка сборки, продолжаем...\n")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Publish
|
|
32
|
+
console.log(" [2/3] Публикация...")
|
|
33
|
+
try {
|
|
34
|
+
execSync("npm publish --access public", { stdio: "inherit" })
|
|
35
|
+
console.log("\n ✓ Опубликовано!\n")
|
|
36
|
+
} catch (e) {
|
|
37
|
+
console.error("\n ✗ Ошибка публикации:", e.message)
|
|
38
|
+
process.exit(1)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Tag
|
|
42
|
+
console.log(" [3/3] Создание тега...")
|
|
43
|
+
try {
|
|
44
|
+
execSync(`git tag -a v${pkg.version} -m "Release v${pkg.version}"`, { stdio: "inherit" })
|
|
45
|
+
execSync(`git push origin v${pkg.version}`, { stdio: "inherit" })
|
|
46
|
+
console.log(` ✓ Тег v${pkg.version} создан\n`)
|
|
47
|
+
} catch {
|
|
48
|
+
console.log(" ⚠ Тег не создан (нужен git репозиторий)\n")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log(" Установка для пользователей:")
|
|
52
|
+
console.log(` npm install -g ${pkg.name}\n`)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { gradient, dim, violet, blue, gray, box, bold, purple } from "./theme.mjs"
|
|
2
|
+
|
|
3
|
+
const LOGO = String.raw`
|
|
4
|
+
███████╗████████╗███████╗██╗ ██╗ █████╗
|
|
5
|
+
██╔════╝╚══██╔══╝██╔════╝██║ ██║ ██╔══██╗
|
|
6
|
+
███████╗ ██║ █████╗ ██║ ██║ ███████║
|
|
7
|
+
╚════██║ ██║ ██╔══╝ ██║ ██║ ██╔══██║
|
|
8
|
+
███████║ ██║ ███████╗███████╗███████╗██║ ██║
|
|
9
|
+
╚══════╝ ╚═╝ ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝
|
|
10
|
+
██████╗ ██████╗ ██████╗ ███████╗██████╗
|
|
11
|
+
██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗
|
|
12
|
+
██║ ██║ ██║██║ ██║█████╗ ██████╔╝
|
|
13
|
+
██║ ██║ ██║██║ ██║██╔══╝ ██╔══██╗
|
|
14
|
+
╚██████╗╚██████╔╝██████╔╝███████╗██║ ██║
|
|
15
|
+
╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝`
|
|
16
|
+
|
|
17
|
+
export function printBanner({ model, cwd, version }) {
|
|
18
|
+
console.log(gradient(LOGO))
|
|
19
|
+
console.log()
|
|
20
|
+
console.log(
|
|
21
|
+
" " +
|
|
22
|
+
gradient("✦ Stella Coder") +
|
|
23
|
+
" " +
|
|
24
|
+
bold(violet(`v${version}`)) +
|
|
25
|
+
dim(" · powered by ") +
|
|
26
|
+
bold(blue("codex")) +
|
|
27
|
+
dim(" alex"),
|
|
28
|
+
)
|
|
29
|
+
console.log()
|
|
30
|
+
console.log(
|
|
31
|
+
box(
|
|
32
|
+
[
|
|
33
|
+
violet("✻") + " Добро пожаловать в " + bold(violet("Stella Coder 3.9")) + "!",
|
|
34
|
+
"",
|
|
35
|
+
dim(" модель: ") + blue(model),
|
|
36
|
+
dim(" папка: ") + gray(cwd),
|
|
37
|
+
"",
|
|
38
|
+
dim(" ") + purple("/help") + dim(" — все команды ") + purple("/model") + dim(" — сменить модель"),
|
|
39
|
+
dim(" ") + purple("!cmd") + dim(" — запустить shell-команду напрямую"),
|
|
40
|
+
dim(" ") + purple("Ctrl+C") + dim(" — прервать ответ, дважды — выход"),
|
|
41
|
+
],
|
|
42
|
+
{ title: "✦ System", padding: 2 },
|
|
43
|
+
),
|
|
44
|
+
)
|
|
45
|
+
console.log()
|
|
46
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Stella Coder — Build Script (SEA: Single Executable Application)
|
|
3
|
+
import fs from "node:fs"
|
|
4
|
+
import path from "node:path"
|
|
5
|
+
import { execSync } from "node:child_process"
|
|
6
|
+
import { fileURLToPath } from "node:url"
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
9
|
+
const __dirname = path.dirname(__filename)
|
|
10
|
+
|
|
11
|
+
const DIST = path.join(__dirname, "..", "dist")
|
|
12
|
+
const SEA_BLOB = path.join(DIST, "sea-prep.blob")
|
|
13
|
+
const EXE_NAME = process.platform === "win32" ? "stella.exe" : "stella"
|
|
14
|
+
const OUTPUT = path.join(DIST, EXE_NAME)
|
|
15
|
+
|
|
16
|
+
console.log()
|
|
17
|
+
console.log("\x1b[38;2;167;139;250m ✦ Stella Coder — Build SEA Executable\x1b[0m")
|
|
18
|
+
console.log()
|
|
19
|
+
|
|
20
|
+
// 1. Clean dist
|
|
21
|
+
console.log(" [1/5] Очистка dist/...")
|
|
22
|
+
if (fs.existsSync(DIST)) fs.rmSync(DIST, { recursive: true })
|
|
23
|
+
fs.mkdirSync(DIST, { recursive: true })
|
|
24
|
+
|
|
25
|
+
// 2. Create single entry point that bundles all modules
|
|
26
|
+
console.log(" [2/5] Создание bundled entry point...")
|
|
27
|
+
|
|
28
|
+
const entryContent = `#!/usr/bin/env node
|
|
29
|
+
// Stella Coder — Bundled Single Executable
|
|
30
|
+
// This file bundles all CLI modules into one for SEA compilation
|
|
31
|
+
|
|
32
|
+
import { createRequire } from "node:module"
|
|
33
|
+
const require = createRequire(import.meta.url)
|
|
34
|
+
|
|
35
|
+
// Inline all modules
|
|
36
|
+
${inlineModule("stella-cli/theme.mjs")}
|
|
37
|
+
${inlineModule("stella-cli/banner.mjs")}
|
|
38
|
+
${inlineModule("stella-cli/markdown.mjs")}
|
|
39
|
+
${inlineModule("stella-cli/tools.mjs")}
|
|
40
|
+
${inlineModule("stella-cli/security.mjs")}
|
|
41
|
+
|
|
42
|
+
// Re-export for index.mjs
|
|
43
|
+
export {
|
|
44
|
+
bold, dim, violet, purple, indigo, blue, cyan, green, red, yellow, gray, darkGray, white,
|
|
45
|
+
gradientLine, box, SPINNER_FRAMES, SPINNER_WORDS,
|
|
46
|
+
} from "./theme.mjs"
|
|
47
|
+
|
|
48
|
+
export { printBanner } from "./banner.mjs"
|
|
49
|
+
export { createStreamRenderer, renderMarkdown } from "./markdown.mjs"
|
|
50
|
+
export { createTools } from "./tools.mjs"
|
|
51
|
+
export {
|
|
52
|
+
verifyCodeIntegrity, getApiKey, saveApiKey, deleteApiKey,
|
|
53
|
+
getHardwareInfo, saveIntegrityHash,
|
|
54
|
+
} from "./security.mjs"
|
|
55
|
+
`
|
|
56
|
+
|
|
57
|
+
// Actually, for SEA we need a simpler approach — just copy all files to dist
|
|
58
|
+
console.log(" [2/5] Копирование модулей в dist/...")
|
|
59
|
+
|
|
60
|
+
const filesToCopy = [
|
|
61
|
+
"index.mjs",
|
|
62
|
+
"tools.mjs",
|
|
63
|
+
"banner.mjs",
|
|
64
|
+
"theme.mjs",
|
|
65
|
+
"markdown.mjs",
|
|
66
|
+
"security.mjs",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
for (const file of filesToCopy) {
|
|
70
|
+
const src = path.join(__dirname, file)
|
|
71
|
+
const dst = path.join(DIST, file)
|
|
72
|
+
if (fs.existsSync(src)) {
|
|
73
|
+
fs.copyFileSync(src, dst)
|
|
74
|
+
console.log(` ${file}`)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Also copy antimalware directory
|
|
79
|
+
const antimalwareSrc = path.join(__dirname, "..", "antimalware")
|
|
80
|
+
const antimalwareDst = path.join(DIST, "antimalware")
|
|
81
|
+
if (fs.existsSync(antimalwareSrc)) {
|
|
82
|
+
fs.cpSync(antimalwareSrc, antimalwareDst, { recursive: true })
|
|
83
|
+
console.log(" antimalware/")
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// 3. Create SEA blob
|
|
87
|
+
console.log(" [3/5] Создание SEA blob...")
|
|
88
|
+
const seaConfig = {
|
|
89
|
+
main: "index.mjs",
|
|
90
|
+
disableExperimentalSEAWarning: true,
|
|
91
|
+
}
|
|
92
|
+
fs.writeFileSync(path.join(DIST, "sea-config.json"), JSON.stringify(seaConfig, null, 2))
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
execSync(`node --experimental-sea-config ${path.join(DIST, "sea-config.json")}`, {
|
|
96
|
+
cwd: DIST,
|
|
97
|
+
stdio: "inherit",
|
|
98
|
+
})
|
|
99
|
+
} catch (e) {
|
|
100
|
+
console.log(" ⚠ SEA config не поддерживается этой версией Node.js")
|
|
101
|
+
console.log(" Используйте Node.js 20+ или pkg для компиляции")
|
|
102
|
+
console.log()
|
|
103
|
+
console.log(" Альтернатива: npm install -g pkg && pkg --targets node18-win-x64 .")
|
|
104
|
+
console.log()
|
|
105
|
+
process.exit(0)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 4. Copy node executable
|
|
109
|
+
console.log(" [4/5] Копирование Node.js executable...")
|
|
110
|
+
const nodeExe = process.execPath
|
|
111
|
+
const targetExe = path.join(DIST, EXE_NAME)
|
|
112
|
+
fs.copyFileSync(nodeExe, targetExe)
|
|
113
|
+
|
|
114
|
+
// 5. Inject SEA blob into executable
|
|
115
|
+
console.log(" [5/5] Инжектирование blob в executable...")
|
|
116
|
+
try {
|
|
117
|
+
const { execSync: exec } = await import("node:child_process")
|
|
118
|
+
if (process.platform === "win32") {
|
|
119
|
+
exec(`npx postject ${targetExe} NODE_SEA_BLOB ${SEA_BLOB} --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2`, {
|
|
120
|
+
cwd: DIST,
|
|
121
|
+
stdio: "inherit",
|
|
122
|
+
})
|
|
123
|
+
} else {
|
|
124
|
+
exec(`npx postject ${targetExe} NODE_SEA_BLOB ${SEA_BLOB} --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2`, {
|
|
125
|
+
cwd: DIST,
|
|
126
|
+
stdio: "inherit",
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
console.log(" ⚠ Postject не удался. Попробуйте:")
|
|
131
|
+
console.log(" npm install -g postject")
|
|
132
|
+
console.log(" postject stella.exe NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2")
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Cleanup
|
|
136
|
+
try { fs.unlinkSync(path.join(DIST, "sea-prep.blob")) } catch {}
|
|
137
|
+
try { fs.unlinkSync(path.join(DIST, "sea-config.json")) } catch {}
|
|
138
|
+
|
|
139
|
+
console.log()
|
|
140
|
+
console.log(`\x1b[38;2;0;200;100m ✓ Готово: ${OUTPUT}\x1b[0m`)
|
|
141
|
+
console.log(dim(` Размер: ${(fs.statSync(targetExe).size / 1024 / 1024).toFixed(1)} MB`))
|
|
142
|
+
console.log()
|
|
143
|
+
|
|
144
|
+
function inlineModule(relativePath) {
|
|
145
|
+
const fullPath = path.join(__dirname, "..", relativePath)
|
|
146
|
+
try {
|
|
147
|
+
return fs.readFileSync(fullPath, "utf8")
|
|
148
|
+
} catch {
|
|
149
|
+
return `// ${relativePath} not found`
|
|
150
|
+
}
|
|
151
|
+
}
|