omnicrawl-cli 0.2.8 → 0.3.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/README.md CHANGED
@@ -60,8 +60,8 @@ node packages/cli/scripts/install-smoke.mjs # 安装冒烟:干净前缀里
60
60
  npm test -w omnicrawl-cli # e2e:真二进制 + 协议 v1
61
61
  ```
62
62
 
63
- 宿主载荷是纯 Rust 产物,按构建机的目标构建即可(`omnicrawl-tts` 的 ONNX 运行时已改成可选
64
- feature,所以 musl 静态宿主载荷在 Windows 上交叉编译也能过,本机实测见
63
+ 宿主载荷是纯 Rust 产物,按构建机的目标构建即可(TTS 已改为云服务,`omnicrawl-tts` 只剩
64
+ HTTP 与音频 I/O,原先挡住 musl 的 `ort` / `espeak-ng` 已移出依赖树,本机实测见
65
65
  `rust/docs/python-free-build.md` 第 7 节):Windows 侧用 `--target` 指到与内核相同的三元组目录,
66
66
  Linux 侧目前仍按 runner 原生 gnu 目标构建(aarch64 musl 宿主在 arm runner 上还没验证过)。
67
67
  若目标无法在构建机上构建(或宿主没接线),启动器会退回协议直连内核——内核可以单独交叉编译成
package/bin/omnicrawl.mjs CHANGED
@@ -1,173 +1,173 @@
1
- #!/usr/bin/env node
2
- // OmniCrawl 启动器:按 platform/arch 选出平台分包,默认启动完整宿主(工作台 / api / plugin 指令),
3
- // `kernel` 子命令把 stdio 交给内核二进制(协议调试与 e2e)。
4
- //
5
- // 两个逃生口(开发与协议测试用):
6
- // OMNICRAWL_HOST=<可执行文件> 直接指定宿主,跳过平台分包
7
- // OMNICRAWL_BINARY=<可执行文件> 直接指定内核;此时启动器退化为纯透传,便于协议测试
8
- import { spawn } from 'node:child_process'
9
- import { chmodSync, existsSync, readFileSync, statSync } from 'node:fs'
10
- import { createRequire } from 'node:module'
11
- import { dirname, join } from 'node:path'
12
- import process from 'node:process'
13
- import { fileURLToPath } from 'node:url'
14
-
15
- import { runStartupUpdateIfDue, shouldCheckUpdate } from './update.mjs'
16
-
17
- const PLATFORM_PACKAGES = {
18
- 'linux-x64': '@omnicrawl/cli-linux-x64',
19
- 'linux-arm': '@omnicrawl/cli-linux-arm-musl',
20
- 'linux-arm64': '@omnicrawl/cli-linux-arm64-musl',
21
- 'win32-x64': '@omnicrawl/cli-win32-x64',
22
- 'win32-ia32': '@omnicrawl/cli-win32-ia32',
23
- }
24
-
25
- const IS_WINDOWS = process.platform === 'win32'
26
- const HOST_FILE = IS_WINDOWS ? 'omnicrawl-host.exe' : 'omnicrawl-host'
27
- const KERNEL_FILE = IS_WINDOWS ? 'omnicrawl.exe' : 'omnicrawl'
28
- const KERNEL_COMMAND = 'kernel'
29
-
30
- const launcherVersion = JSON.parse(
31
- readFileSync(new URL('../package.json', import.meta.url), 'utf8'),
32
- ).version
33
-
34
- function fail(message) {
35
- console.error(message)
36
- process.exit(1)
37
- }
38
-
39
- /** 解析平台分包根目录;拿不到分包时抛出可直接展示的错误。 */
40
- function resolvePlatform() {
41
- const key = `${process.platform}-${process.arch}`
42
- const packageName = PLATFORM_PACKAGES[key]
43
- if (!packageName) {
44
- throw new Error(`不支持的平台 ${key};已支持:${Object.keys(PLATFORM_PACKAGES).join('、')}`)
45
- }
46
- const require = createRequire(import.meta.url)
47
- return { packageName, root: dirname(require.resolve(`${packageName}/package.json`)) }
48
- }
49
-
50
- /** 目标可执行文件:宿主优先,内核兜底;两个环境变量各自覆盖。 */
51
- function resolveTargets() {
52
- if (process.env.OMNICRAWL_HOST) {
53
- return { host: process.env.OMNICRAWL_HOST, kernel: process.env.OMNICRAWL_BINARY ?? null, passthrough: false }
54
- }
55
- if (process.env.OMNICRAWL_BINARY) {
56
- return { host: null, kernel: process.env.OMNICRAWL_BINARY, passthrough: true }
57
- }
58
- const { packageName, root } = resolvePlatform()
59
- return {
60
- host: join(root, 'host', HOST_FILE),
61
- kernel: join(root, 'bin', KERNEL_FILE),
62
- packageName,
63
- root,
64
- passthrough: false,
65
- }
66
- }
67
-
68
- function readPayloadMeta(root) {
69
- if (!root) return null
70
- try {
71
- return JSON.parse(readFileSync(join(root, 'version.json'), 'utf8'))
72
- } catch {
73
- return null
74
- }
75
- }
76
-
77
- function printVersion(targets) {
78
- const meta = readPayloadMeta(targets.root)
79
- const lines = [`omnicrawl ${launcherVersion}`]
80
- lines.push(
81
- targets.packageName
82
- ? `${targets.packageName} ${meta?.version ?? '未知'}(${process.platform}-${process.arch} 平台包)`
83
- : `omnicrawl-cli ${launcherVersion}(启动器)`,
84
- )
85
- if (meta?.hostVersion) lines.push(`omnicrawl-agent ${meta.hostVersion}(宿主)`)
86
- if (meta?.kernelVersion) lines.push(`omnicrawl ${meta.kernelVersion}(内核)`)
87
- console.log(lines.join('\n'))
88
- }
89
-
90
- function printHelp() {
91
- console.log(
92
- `用法:omnicrawl [选项] [指令]\n\n\
93
- 无参数 启动工作台(TUI)\n\
94
- api 启动本地 HTTP 服务(无头/服务器场景)\n\
95
- plugin ... 插件管理\n\
96
- kernel ... 直连内核进程(协议调试)\n\n\
97
- --resume <会话 ID> 启动时恢复指定会话\n\
98
- --version, -V 打印启动器、平台包、宿主与内核版本\n\
99
- --help, -h 打印本说明`,
100
- )
101
- }
102
-
103
- /** npm 打包会把未在 bin 里声明的文件权限位归一化成 0644,POSIX 下按需补回可执行位。 */
104
- function ensureExecutable(path) {
105
- if (IS_WINDOWS) return
106
- try {
107
- const mode = statSync(path).mode
108
- if ((mode & 0o111) === 0) chmodSync(path, mode | 0o755)
109
- } catch {
110
- // 权限改不动(只读文件系统等)时交给 spawn 的错误说明原因。
111
- }
112
- }
113
-
114
- /** 把 stdio 交给目标可执行文件,并把它的退出码/信号作为本次退出状态。 */
115
- function run(executable, args) {
116
- if (!executable || !existsSync(executable)) {
117
- fail(`omnicrawl:找不到可执行文件 ${executable ?? '(未解析到)'}。请重装对应的平台包。`)
118
- }
119
- ensureExecutable(executable)
120
- const child = spawn(executable, args, { stdio: 'inherit' })
121
-
122
- child.on('error', (error) => {
123
- console.error(`omnicrawl:无法启动 ${executable}:${error.message}`)
124
- process.exit(1)
125
- })
126
-
127
- child.on('exit', (code, signal) => {
128
- if (signal) {
129
- console.error(`omnicrawl:${executable} 被信号 ${signal} 终止`)
130
- process.exit(1)
131
- }
132
- process.exit(code ?? 0)
133
- })
134
- }
135
-
136
- async function main() {
137
- let targets
138
- try {
139
- targets = resolveTargets()
140
- } catch (error) {
141
- fail(`omnicrawl:${error.message}`)
142
- }
143
-
144
- const args = process.argv.slice(2)
145
-
146
- // 内核透传模式(OMNICRAWL_BINARY):启动器不介入 stdio 上的协议帧。
147
- if (targets.passthrough) return run(targets.kernel, args)
148
-
149
- if (args[0] === KERNEL_COMMAND) return run(targets.kernel, args.slice(1))
150
- if (args.includes('--version') || args.includes('-V')) return printVersion(targets)
151
- if (args.includes('--help') || args.includes('-h')) return printHelp()
152
-
153
- // 启动自动更新只走默认工作台路径;升级成功后重新拉起并沿用子进程退出码。
154
- if (shouldCheckUpdate(args, process.env)) {
155
- const code = await runStartupUpdateIfDue({
156
- argv: args,
157
- currentVersion: launcherVersion,
158
- launcherPath: fileURLToPath(import.meta.url),
159
- })
160
- if (code !== null) process.exit(code)
161
- }
162
-
163
- if (targets.host && existsSync(targets.host)) return run(targets.host, args)
164
-
165
- // 嵌入式目标(armv7 等)没有宿主载荷:退回内核直连,并说明这一平台的边界。
166
- console.error(
167
- `omnicrawl:平台包 ${targets.packageName ?? '(未指定)'} 没有宿主载荷,退回内核直连;` +
168
- '该平台只支持协议模式(用 omnicrawl kernel 显式进入)。',
169
- )
170
- return run(targets.kernel, args)
171
- }
172
-
173
- main().catch((error) => fail(`omnicrawl:${error.message}`))
1
+ #!/usr/bin/env node
2
+ // OmniCrawl 启动器:按 platform/arch 选出平台分包,默认启动完整宿主(工作台 / api / plugin 指令),
3
+ // `kernel` 子命令把 stdio 交给内核二进制(协议调试与 e2e)。
4
+ //
5
+ // 两个逃生口(开发与协议测试用):
6
+ // OMNICRAWL_HOST=<可执行文件> 直接指定宿主,跳过平台分包
7
+ // OMNICRAWL_BINARY=<可执行文件> 直接指定内核;此时启动器退化为纯透传,便于协议测试
8
+ import { spawn } from 'node:child_process'
9
+ import { chmodSync, existsSync, readFileSync, statSync } from 'node:fs'
10
+ import { createRequire } from 'node:module'
11
+ import { dirname, join } from 'node:path'
12
+ import process from 'node:process'
13
+ import { fileURLToPath } from 'node:url'
14
+
15
+ import { runStartupUpdateIfDue, shouldCheckUpdate } from './update.mjs'
16
+
17
+ const PLATFORM_PACKAGES = {
18
+ 'linux-x64': '@omnicrawl/cli-linux-x64',
19
+ 'linux-arm': '@omnicrawl/cli-linux-arm-musl',
20
+ 'linux-arm64': '@omnicrawl/cli-linux-arm64-musl',
21
+ 'win32-x64': '@omnicrawl/cli-win32-x64',
22
+ 'win32-ia32': '@omnicrawl/cli-win32-ia32',
23
+ }
24
+
25
+ const IS_WINDOWS = process.platform === 'win32'
26
+ const HOST_FILE = IS_WINDOWS ? 'omnicrawl-host.exe' : 'omnicrawl-host'
27
+ const KERNEL_FILE = IS_WINDOWS ? 'omnicrawl.exe' : 'omnicrawl'
28
+ const KERNEL_COMMAND = 'kernel'
29
+
30
+ const launcherVersion = JSON.parse(
31
+ readFileSync(new URL('../package.json', import.meta.url), 'utf8'),
32
+ ).version
33
+
34
+ function fail(message) {
35
+ console.error(message)
36
+ process.exit(1)
37
+ }
38
+
39
+ /** 解析平台分包根目录;拿不到分包时抛出可直接展示的错误。 */
40
+ function resolvePlatform() {
41
+ const key = `${process.platform}-${process.arch}`
42
+ const packageName = PLATFORM_PACKAGES[key]
43
+ if (!packageName) {
44
+ throw new Error(`不支持的平台 ${key};已支持:${Object.keys(PLATFORM_PACKAGES).join('、')}`)
45
+ }
46
+ const require = createRequire(import.meta.url)
47
+ return { packageName, root: dirname(require.resolve(`${packageName}/package.json`)) }
48
+ }
49
+
50
+ /** 目标可执行文件:宿主优先,内核兜底;两个环境变量各自覆盖。 */
51
+ function resolveTargets() {
52
+ if (process.env.OMNICRAWL_HOST) {
53
+ return { host: process.env.OMNICRAWL_HOST, kernel: process.env.OMNICRAWL_BINARY ?? null, passthrough: false }
54
+ }
55
+ if (process.env.OMNICRAWL_BINARY) {
56
+ return { host: null, kernel: process.env.OMNICRAWL_BINARY, passthrough: true }
57
+ }
58
+ const { packageName, root } = resolvePlatform()
59
+ return {
60
+ host: join(root, 'host', HOST_FILE),
61
+ kernel: join(root, 'bin', KERNEL_FILE),
62
+ packageName,
63
+ root,
64
+ passthrough: false,
65
+ }
66
+ }
67
+
68
+ function readPayloadMeta(root) {
69
+ if (!root) return null
70
+ try {
71
+ return JSON.parse(readFileSync(join(root, 'version.json'), 'utf8'))
72
+ } catch {
73
+ return null
74
+ }
75
+ }
76
+
77
+ function printVersion(targets) {
78
+ const meta = readPayloadMeta(targets.root)
79
+ const lines = [`omnicrawl ${launcherVersion}`]
80
+ lines.push(
81
+ targets.packageName
82
+ ? `${targets.packageName} ${meta?.version ?? '未知'}(${process.platform}-${process.arch} 平台包)`
83
+ : `omnicrawl-cli ${launcherVersion}(启动器)`,
84
+ )
85
+ if (meta?.hostVersion) lines.push(`omnicrawl-agent ${meta.hostVersion}(宿主)`)
86
+ if (meta?.kernelVersion) lines.push(`omnicrawl ${meta.kernelVersion}(内核)`)
87
+ console.log(lines.join('\n'))
88
+ }
89
+
90
+ function printHelp() {
91
+ console.log(
92
+ `用法:omnicrawl [选项] [指令]\n\n\
93
+ 无参数 启动工作台(TUI)\n\
94
+ api 启动本地 HTTP 服务(无头/服务器场景)\n\
95
+ plugin ... 插件管理\n\
96
+ kernel ... 直连内核进程(协议调试)\n\n\
97
+ --resume <会话 ID> 启动时恢复指定会话\n\
98
+ --version, -V 打印启动器、平台包、宿主与内核版本\n\
99
+ --help, -h 打印本说明`,
100
+ )
101
+ }
102
+
103
+ /** npm 打包会把未在 bin 里声明的文件权限位归一化成 0644,POSIX 下按需补回可执行位。 */
104
+ function ensureExecutable(path) {
105
+ if (IS_WINDOWS) return
106
+ try {
107
+ const mode = statSync(path).mode
108
+ if ((mode & 0o111) === 0) chmodSync(path, mode | 0o755)
109
+ } catch {
110
+ // 权限改不动(只读文件系统等)时交给 spawn 的错误说明原因。
111
+ }
112
+ }
113
+
114
+ /** 把 stdio 交给目标可执行文件,并把它的退出码/信号作为本次退出状态。 */
115
+ function run(executable, args) {
116
+ if (!executable || !existsSync(executable)) {
117
+ fail(`omnicrawl:找不到可执行文件 ${executable ?? '(未解析到)'}。请重装对应的平台包。`)
118
+ }
119
+ ensureExecutable(executable)
120
+ const child = spawn(executable, args, { stdio: 'inherit' })
121
+
122
+ child.on('error', (error) => {
123
+ console.error(`omnicrawl:无法启动 ${executable}:${error.message}`)
124
+ process.exit(1)
125
+ })
126
+
127
+ child.on('exit', (code, signal) => {
128
+ if (signal) {
129
+ console.error(`omnicrawl:${executable} 被信号 ${signal} 终止`)
130
+ process.exit(1)
131
+ }
132
+ process.exit(code ?? 0)
133
+ })
134
+ }
135
+
136
+ async function main() {
137
+ let targets
138
+ try {
139
+ targets = resolveTargets()
140
+ } catch (error) {
141
+ fail(`omnicrawl:${error.message}`)
142
+ }
143
+
144
+ const args = process.argv.slice(2)
145
+
146
+ // 内核透传模式(OMNICRAWL_BINARY):启动器不介入 stdio 上的协议帧。
147
+ if (targets.passthrough) return run(targets.kernel, args)
148
+
149
+ if (args[0] === KERNEL_COMMAND) return run(targets.kernel, args.slice(1))
150
+ if (args.includes('--version') || args.includes('-V')) return printVersion(targets)
151
+ if (args.includes('--help') || args.includes('-h')) return printHelp()
152
+
153
+ // 启动自动更新只走默认工作台路径;升级成功后重新拉起并沿用子进程退出码。
154
+ if (shouldCheckUpdate(args, process.env)) {
155
+ const code = await runStartupUpdateIfDue({
156
+ argv: args,
157
+ currentVersion: launcherVersion,
158
+ launcherPath: fileURLToPath(import.meta.url),
159
+ })
160
+ if (code !== null) process.exit(code)
161
+ }
162
+
163
+ if (targets.host && existsSync(targets.host)) return run(targets.host, args)
164
+
165
+ // 嵌入式目标(armv7 等)没有宿主载荷:退回内核直连,并说明这一平台的边界。
166
+ console.error(
167
+ `omnicrawl:平台包 ${targets.packageName ?? '(未指定)'} 没有宿主载荷,退回内核直连;` +
168
+ '该平台只支持协议模式(用 omnicrawl kernel 显式进入)。',
169
+ )
170
+ return run(targets.kernel, args)
171
+ }
172
+
173
+ main().catch((error) => fail(`omnicrawl:${error.message}`))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnicrawl-cli",
3
- "version": "0.2.8",
3
+ "version": "0.3.0",
4
4
  "description": "OmniCrawl 启动器:按平台启动完整宿主(工作台 / api / 插件)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,10 +25,10 @@
25
25
  },
26
26
  "license": "MIT",
27
27
  "optionalDependencies": {
28
- "@omnicrawl/cli-win32-x64": "0.2.8",
29
- "@omnicrawl/cli-win32-ia32": "0.2.8",
30
- "@omnicrawl/cli-linux-x64": "0.2.8",
31
- "@omnicrawl/cli-linux-arm-musl": "0.2.8",
32
- "@omnicrawl/cli-linux-arm64-musl": "0.2.8"
28
+ "@omnicrawl/cli-win32-x64": "0.3.0",
29
+ "@omnicrawl/cli-win32-ia32": "0.3.0",
30
+ "@omnicrawl/cli-linux-x64": "0.3.0",
31
+ "@omnicrawl/cli-linux-arm-musl": "0.3.0",
32
+ "@omnicrawl/cli-linux-arm64-musl": "0.3.0"
33
33
  }
34
34
  }