@aalis/runtime 0.15.0 → 0.16.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 +11 -2
- package/dist/config-store.d.ts +49 -12
- package/dist/config-store.d.ts.map +1 -1
- package/dist/config-store.js +419 -58
- package/dist/config-store.js.map +1 -1
- package/dist/config-sync.d.ts +19 -8
- package/dist/config-sync.d.ts.map +1 -1
- package/dist/config-sync.js +81 -58
- package/dist/config-sync.js.map +1 -1
- package/dist/console-sink.d.ts +1 -1
- package/dist/file-logger.d.ts +4 -4
- package/dist/file-logger.d.ts.map +1 -1
- package/dist/file-logger.js +6 -5
- package/dist/file-logger.js.map +1 -1
- package/dist/home.d.ts +64 -0
- package/dist/home.d.ts.map +1 -0
- package/dist/home.js +229 -0
- package/dist/home.js.map +1 -0
- package/dist/host-logs.d.ts +9 -0
- package/dist/host-logs.d.ts.map +1 -0
- package/dist/host-logs.js +104 -0
- package/dist/host-logs.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -4
- package/dist/index.js.map +1 -1
- package/dist/instance-lock.d.ts +56 -0
- package/dist/instance-lock.d.ts.map +1 -0
- package/dist/instance-lock.js +281 -0
- package/dist/instance-lock.js.map +1 -0
- package/dist/node-modules-loader.d.ts +2 -2
- package/dist/node-modules-loader.d.ts.map +1 -1
- package/dist/node-modules-loader.js +8 -4
- package/dist/node-modules-loader.js.map +1 -1
- package/dist/plugin-discovery.d.ts +9 -4
- package/dist/plugin-discovery.d.ts.map +1 -1
- package/dist/plugin-discovery.js +28 -16
- package/dist/plugin-discovery.js.map +1 -1
- package/dist/providers.d.ts +38 -13
- package/dist/providers.d.ts.map +1 -1
- package/dist/providers.js +92 -216
- package/dist/providers.js.map +1 -1
- package/dist/secrets.d.ts +44 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +104 -0
- package/dist/secrets.js.map +1 -0
- package/dist/start.d.ts +19 -12
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +166 -43
- package/dist/start.js.map +1 -1
- package/dist/yaml-file.d.ts +35 -0
- package/dist/yaml-file.d.ts.map +1 -0
- package/dist/yaml-file.js +213 -0
- package/dist/yaml-file.js.map +1 -0
- package/package.json +13 -7
package/dist/home.js
ADDED
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { chmodSync, existsSync, mkdirSync, readdirSync, realpathSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { basename, isAbsolute, join, normalize, resolve } from 'node:path';
|
|
4
|
+
import { CORE_CONFIG_SCHEMA, defaultsFrom } from '@aalis/schema-config';
|
|
5
|
+
import { stringify as stringifyYaml } from 'yaml';
|
|
6
|
+
// ============================================================
|
|
7
|
+
// 家目录:解析、路径派生与初始化
|
|
8
|
+
// ============================================================
|
|
9
|
+
//
|
|
10
|
+
// 家目录装着一个实例的全部状态与密钥,只在这里解析,core 不参与。进程的 cwd 不带语义:
|
|
11
|
+
// 唯一的例外是命令行与环境变量里写的相对路径,它们按启动时的 cwd 解析一次(那是用户在 shell 里的意图),
|
|
12
|
+
// 之后全程只用绝对路径。
|
|
13
|
+
/** 宿主件的路径参数必须是绝对路径:相对路径会按调用那一刻的 cwd 解析,而 cwd 不带语义 */
|
|
14
|
+
export function assertAbsolute(what, p) {
|
|
15
|
+
if (!isFullyAbsolute(p))
|
|
16
|
+
throw new Error(`${what}必须是绝对路径:${p}`);
|
|
17
|
+
}
|
|
18
|
+
/** profile 名既拼进 `~/.aalis-<profile>`,也拼进数据库名:只许小写字母、数字与连字符,挡住 `../x` 这类跳出。 */
|
|
19
|
+
const PROFILE_PATTERN = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
20
|
+
const CONFIG_FILE = 'aalis.config.yaml';
|
|
21
|
+
const SECRETS_FILE = 'secrets.yaml';
|
|
22
|
+
/** `--init` 只在空目录、或只有布局自己的条目(上次初始化中途失败留下的)的目录里做 */
|
|
23
|
+
const LAYOUT_ENTRIES = new Set([
|
|
24
|
+
'state',
|
|
25
|
+
'logs',
|
|
26
|
+
'cache',
|
|
27
|
+
'run',
|
|
28
|
+
'tmp',
|
|
29
|
+
'self',
|
|
30
|
+
'stage',
|
|
31
|
+
SECRETS_FILE,
|
|
32
|
+
'.DS_Store',
|
|
33
|
+
]);
|
|
34
|
+
/**
|
|
35
|
+
* 绝对路径。Windows 上还要带盘符或 UNC 前缀:`\aalis` 这类按当前盘解析,仍然依赖 cwd。
|
|
36
|
+
*/
|
|
37
|
+
export function isFullyAbsolute(p, platform = process.platform) {
|
|
38
|
+
return platform === 'win32' ? /^(?:[A-Za-z]:[\\/]|\\\\)/.test(p) : isAbsolute(p);
|
|
39
|
+
}
|
|
40
|
+
/** 家目录相关的输入有误(参数缺值、profile 名不合法、来源冲突):宿主据此一行报错退出。 */
|
|
41
|
+
export class HomeArgsError extends Error {
|
|
42
|
+
name = 'HomeArgsError';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 只认开头的宿主参数(`--home <dir>`、`--home=<dir>`、`--profile`、`--init`、`--service`),遇到第一个别的参数即停:
|
|
46
|
+
* 之后的都属于子命令,子命令自己的参数里出现同名写法也不会被吃掉。
|
|
47
|
+
* 开头这一段里的 `--` 跳过:`pnpm dev -- --init` 会把 `--` 原样传进来。
|
|
48
|
+
*/
|
|
49
|
+
export function parseHostArgs(argv) {
|
|
50
|
+
const out = { init: false, service: false, rest: [] };
|
|
51
|
+
let i = 0;
|
|
52
|
+
for (; i < argv.length; i++) {
|
|
53
|
+
const arg = argv[i];
|
|
54
|
+
if (arg === '--')
|
|
55
|
+
continue;
|
|
56
|
+
if (arg === '--init' || arg === '--service') {
|
|
57
|
+
out[arg === '--init' ? 'init' : 'service'] = true;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const m = /^--(home|profile)(?:=(.*))?$/.exec(arg);
|
|
61
|
+
if (!m)
|
|
62
|
+
break;
|
|
63
|
+
const key = m[1];
|
|
64
|
+
const value = m[2] ?? argv[++i];
|
|
65
|
+
if (!value)
|
|
66
|
+
throw new HomeArgsError(`--${key} 缺少取值`);
|
|
67
|
+
out[key] = value;
|
|
68
|
+
}
|
|
69
|
+
out.rest = argv.slice(i);
|
|
70
|
+
return out;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 家目录的覆盖顺序:`--home` → `AALIS_HOME` → `--profile` / `AALIS_PROFILE`(`~/.aalis-<p>`)→ 宿主的 defaultHome → `~/.aalis`。
|
|
74
|
+
* 指定了 profile、同时又有更高优先级的 `--home` 或 `AALIS_HOME` 时报错,不静默忽略 profile:
|
|
75
|
+
* 以为进了测试实例、实际写进主实例,是这类配置错误最坏的后果。
|
|
76
|
+
*/
|
|
77
|
+
export function resolveHome(input) {
|
|
78
|
+
const { args, env } = input;
|
|
79
|
+
const userHome = input.userHome ?? homedir();
|
|
80
|
+
// 环境变量设成空串(`AALIS_HOME=` 用来清掉它)视同没设
|
|
81
|
+
const explicit = args.home ?? nonEmpty(env.AALIS_HOME);
|
|
82
|
+
const profile = args.profile ?? nonEmpty(env.AALIS_PROFILE);
|
|
83
|
+
// defaultHome 是宿主代码写死的值:写错了不论这次谁胜出都报,免得换一台没设环境变量的机器才暴露
|
|
84
|
+
if (input.defaultHome !== undefined && !isFullyAbsolute(input.defaultHome)) {
|
|
85
|
+
throw new HomeArgsError(`defaultHome 必须是绝对路径:${input.defaultHome}`);
|
|
86
|
+
}
|
|
87
|
+
if (explicit !== undefined && profile !== undefined) {
|
|
88
|
+
const homeSource = args.home !== undefined ? '--home' : 'AALIS_HOME';
|
|
89
|
+
const profileSource = args.profile !== undefined ? '--profile' : 'AALIS_PROFILE';
|
|
90
|
+
throw new HomeArgsError(`同时指定了 ${homeSource} 与 ${profileSource},只能选一个`);
|
|
91
|
+
}
|
|
92
|
+
if (explicit !== undefined)
|
|
93
|
+
return withProfile(toAbsolute(explicit, userHome, input.cwd), userHome);
|
|
94
|
+
if (profile !== undefined) {
|
|
95
|
+
if (!PROFILE_PATTERN.test(profile)) {
|
|
96
|
+
throw new HomeArgsError(`profile 名「${profile}」不合法:只能用小写字母、数字与连字符,以字母或数字开头,最长 32 个字符`);
|
|
97
|
+
}
|
|
98
|
+
return { home: join(userHome, `.aalis-${profile}`), profile };
|
|
99
|
+
}
|
|
100
|
+
if (input.defaultHome !== undefined)
|
|
101
|
+
return withProfile(normalize(input.defaultHome), userHome);
|
|
102
|
+
return { home: join(userHome, '.aalis') };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* `~/.aalis-<p>` 就是 profile p 的家目录:经 `--home`、`AALIS_HOME` 或 defaultHome 选中它时同样带上 profile,
|
|
106
|
+
* 插件按 profile 派生的名字(如记忆库名)对同一个家目录才一样。这里按路径的写法认,认不出的写法由
|
|
107
|
+
* {@link profileOfRealHome} 按真实路径补认。
|
|
108
|
+
*/
|
|
109
|
+
function withProfile(home, userHome) {
|
|
110
|
+
const profile = /^\.aalis-(.+)$/.exec(basename(home))?.[1];
|
|
111
|
+
if (profile === undefined || !PROFILE_PATTERN.test(profile))
|
|
112
|
+
return { home };
|
|
113
|
+
return resolve(home) === resolve(userHome, `.aalis-${profile}`) ? { home, profile } : { home };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* 按真实路径补认 profile:家目录的真实路径就是 `~/.aalis-<p>` 的真实路径时为 p。补上按写法认不出的情形:
|
|
117
|
+
* 大小写写错、经指向它的符号链接选中、用户主目录本身是符号链接。`~/.aalis-<p>` 自己是指向别处的链接时,
|
|
118
|
+
* 经那个别处的路径选中仍认不出。用户主目录不存在时没有 profile。
|
|
119
|
+
*/
|
|
120
|
+
export function profileOfRealHome(realHome, userHome = homedir()) {
|
|
121
|
+
let realUserHome;
|
|
122
|
+
try {
|
|
123
|
+
realUserHome = realpathSync.native(userHome);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
return withProfile(realHome, realUserHome).profile;
|
|
129
|
+
}
|
|
130
|
+
function nonEmpty(value) {
|
|
131
|
+
return value === '' ? undefined : value;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* 命令行与环境变量里的家目录写法转成绝对路径。开头的 `~` 展开成用户主目录:`--home=~/x` 不经 shell 展开,
|
|
135
|
+
* launchd、systemd 与容器的环境变量也不展开,不处理就会在 cwd 下建出一个名叫 `~` 的目录。
|
|
136
|
+
*/
|
|
137
|
+
function toAbsolute(value, userHome, cwd) {
|
|
138
|
+
if (value === '~')
|
|
139
|
+
return userHome;
|
|
140
|
+
if (/^~[\\/]/.test(value))
|
|
141
|
+
return join(userHome, value.slice(2));
|
|
142
|
+
if (value.startsWith('~'))
|
|
143
|
+
throw new HomeArgsError(`不支持「~用户名」写法,请写绝对路径:${value}`);
|
|
144
|
+
if (isFullyAbsolute(value))
|
|
145
|
+
return normalize(value);
|
|
146
|
+
if (cwd === undefined)
|
|
147
|
+
throw new HomeArgsError(`当前目录已不存在,家目录请写绝对路径:${value}`);
|
|
148
|
+
return resolve(cwd, value);
|
|
149
|
+
}
|
|
150
|
+
/** 由家目录与安装集派生全部路径(家目录布局见计划书「家目录布局」)。 */
|
|
151
|
+
export function derivePaths(home, app, profile) {
|
|
152
|
+
// 冻结:同一个对象交给每个插件,任何一处改了它(例如改 app)都会把别的插件的装卸目录一起带偏
|
|
153
|
+
return Object.freeze({
|
|
154
|
+
home,
|
|
155
|
+
...(profile !== undefined ? { profile } : {}),
|
|
156
|
+
app,
|
|
157
|
+
config: join(home, CONFIG_FILE),
|
|
158
|
+
secrets: join(home, SECRETS_FILE),
|
|
159
|
+
state: join(home, 'state'),
|
|
160
|
+
logs: join(home, 'logs'),
|
|
161
|
+
cache: join(home, 'cache'),
|
|
162
|
+
run: join(home, 'run'),
|
|
163
|
+
tmp: join(home, 'tmp'),
|
|
164
|
+
self: Object.freeze({
|
|
165
|
+
personas: join(home, 'self', 'personas'),
|
|
166
|
+
skills: join(home, 'self', 'skills'),
|
|
167
|
+
workflows: join(home, 'self', 'workflows'),
|
|
168
|
+
}),
|
|
169
|
+
stage: Object.freeze({
|
|
170
|
+
drafts: join(home, 'stage', 'drafts'),
|
|
171
|
+
public: join(home, 'stage', 'public'),
|
|
172
|
+
paper: join(home, 'stage', 'paper'),
|
|
173
|
+
}),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/** 初始化的判据:主配置文件存在。 */
|
|
177
|
+
export function isHomeInitialized(paths) {
|
|
178
|
+
return existsSync(paths.config);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* 只有 owner 进得来的平台(本地终端、单 token 的 WebUI)的平台档开箱给全部工具分组,无条件写:平台没装时这一层不起作用,
|
|
182
|
+
* 之后从市场装上即生效。多人平台不代开:带分组的工具默认不暴露,public 工具在群里的可达性靠这道分组闸。与 create-aalis 生成的平台档一致
|
|
183
|
+
*/
|
|
184
|
+
const OWNER_PLATFORM_PROFILES = { cli: { enabledToolGroups: ['*'] }, webui: { enabledToolGroups: ['*'] } };
|
|
185
|
+
/**
|
|
186
|
+
* 建家目录:目录 0700,写默认主配置与空的密钥文件(0600),建布局里的子目录。主配置里写上 owner 平台的平台档。
|
|
187
|
+
* 已初始化时拒绝,不覆盖任何文件。目录已存在时只接受空目录,或只有布局自己条目的目录(上次初始化中途失败),
|
|
188
|
+
* 沿用并收紧为 0700:`--home ~ --init` 这类笔误不能把用户主目录改成 0700、再往里铺一层布局。
|
|
189
|
+
*/
|
|
190
|
+
export function initHome(paths) {
|
|
191
|
+
if (isHomeInitialized(paths))
|
|
192
|
+
throw new HomeArgsError(`家目录已经初始化过:${paths.home}`);
|
|
193
|
+
if (existsSync(paths.home)) {
|
|
194
|
+
const foreign = readdirSync(paths.home).filter(name => !LAYOUT_ENTRIES.has(name));
|
|
195
|
+
if (foreign.length > 0) {
|
|
196
|
+
const shown = foreign.slice(0, 3).join('、') + (foreign.length > 3 ? ' 等' : '');
|
|
197
|
+
throw new HomeArgsError(`目录不是空的(有 ${shown}),不能在这里初始化家目录:${paths.home}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
mkdirSync(paths.home, { recursive: true, mode: 0o700 });
|
|
201
|
+
chmodSync(paths.home, 0o700);
|
|
202
|
+
for (const dir of [
|
|
203
|
+
paths.state,
|
|
204
|
+
paths.logs,
|
|
205
|
+
paths.cache,
|
|
206
|
+
paths.run,
|
|
207
|
+
paths.self.personas,
|
|
208
|
+
paths.self.skills,
|
|
209
|
+
paths.self.workflows,
|
|
210
|
+
paths.stage.drafts,
|
|
211
|
+
paths.stage.public,
|
|
212
|
+
paths.stage.paper,
|
|
213
|
+
]) {
|
|
214
|
+
mkdirSync(dir, { recursive: true });
|
|
215
|
+
}
|
|
216
|
+
mkdirSync(paths.tmp, { recursive: true, mode: 0o700 });
|
|
217
|
+
// 密钥文件先建:主配置是初始化的判据,最后写,中途失败时下次仍能重新初始化
|
|
218
|
+
if (existsSync(paths.secrets))
|
|
219
|
+
chmodSync(paths.secrets, 0o600);
|
|
220
|
+
else
|
|
221
|
+
writeFileSync(paths.secrets, '', { mode: 0o600, flag: 'wx' });
|
|
222
|
+
const { name, logLevel } = defaultsFrom(CORE_CONFIG_SCHEMA);
|
|
223
|
+
const sessionConfig = { platforms: OWNER_PLATFORM_PROFILES };
|
|
224
|
+
writeFileSync(paths.config, stringifyYaml({ name, logLevel, plugins: {}, sessionConfig }), {
|
|
225
|
+
mode: 0o600,
|
|
226
|
+
flag: 'wx',
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=home.js.map
|
package/dist/home.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"home.js","sourceRoot":"","sources":["../src/home.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrG,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AAElD,+DAA+D;AAC/D,kBAAkB;AAClB,+DAA+D;AAC/D,EAAE;AACF,kDAAkD;AAClD,4DAA4D;AAC5D,cAAc;AAEd,qDAAqD;AACrD,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,CAAS;IACpD,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,WAAW,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,8EAA8E;AAC9E,MAAM,eAAe,GAAG,2BAA2B,CAAC;AAEpD,MAAM,WAAW,GAAG,mBAAmB,CAAC;AACxC,MAAM,YAAY,GAAG,cAAc,CAAC;AAEpC,mDAAmD;AACnD,MAAM,cAAc,GAAwB,IAAI,GAAG,CAAC;IAClD,OAAO;IACP,MAAM;IACN,OAAO;IACP,KAAK;IACL,KAAK;IACL,MAAM;IACN,OAAO;IACP,YAAY;IACZ,WAAW;CACZ,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,WAA4B,OAAO,CAAC,QAAQ;IACrF,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC;AAED,qDAAqD;AACrD,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC7B,IAAI,GAAG,eAAe,CAAC;CACjC;AAcD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAuB;IACnD,MAAM,GAAG,GAAa,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IAChE,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,GAAG,KAAK,IAAI;YAAE,SAAS;QAC3B,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;YAC5C,GAAG,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;YAClD,SAAS;QACX,CAAC;QACD,MAAM,CAAC,GAAG,8BAA8B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC,CAAC;YAAE,MAAM;QACd,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAuB,CAAC;QACvC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,aAAa,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACzB,OAAO,GAAG,CAAC;AACb,CAAC;AAaD;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,OAAO,EAAE,CAAC;IAC7C,oCAAoC;IACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC5D,uDAAuD;IACvD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,aAAa,CAAC,uBAAuB,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACpD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;QACrE,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC;QACjF,MAAM,IAAI,aAAa,CAAC,SAAS,UAAU,MAAM,aAAa,QAAQ,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;IACpG,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,MAAM,IAAI,aAAa,CACrB,aAAa,OAAO,wCAAwC,CAC7D,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,UAAU,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;IAChE,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAC;IAChG,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,SAAS,WAAW,CAAC,IAAY,EAAE,QAAgB;IACjD,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC3D,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAC7E,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,QAAQ,EAAE,UAAU,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;AACjG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,WAAmB,OAAO,EAAE;IAC9E,IAAI,YAAoB,CAAC;IACzB,IAAI,CAAC;QACH,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,WAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC,OAAO,CAAC;AACrD,CAAC;AAED,SAAS,QAAQ,CAAC,KAAyB;IACzC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU,CAAC,KAAa,EAAE,QAAgB,EAAE,GAAuB;IAC1E,IAAI,KAAK,KAAK,GAAG;QAAE,OAAO,QAAQ,CAAC;IACnC,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,IAAI,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,aAAa,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;IAClF,IAAI,eAAe,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,sBAAsB,KAAK,EAAE,CAAC,CAAC;IAC9E,OAAO,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,GAAW,EAAE,OAAgB;IACrE,kDAAkD;IAClD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,IAAI;QACJ,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,GAAG;QACH,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC;QAC/B,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;QACjC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;QAC1B,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;QACxB,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;QAC1B,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;QACtB,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC;YAClB,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC;YACxC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC;YACpC,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC;SAC3C,CAAC;QACF,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;YACnB,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC;YACrC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC;YACrC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC;SACpC,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAED,sBAAsB;AACtB,MAAM,UAAU,iBAAiB,CAAC,KAAgB;IAChD,OAAO,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,iBAAiB,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;AAE3G;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAgB;IACvC,IAAI,iBAAiB,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,aAAa,CAAC,aAAa,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACjF,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAClF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC/E,MAAM,IAAI,aAAa,CAAC,YAAY,KAAK,iBAAiB,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI;QAChB,KAAK,CAAC,KAAK;QACX,KAAK,CAAC,IAAI;QACV,KAAK,CAAC,KAAK;QACX,KAAK,CAAC,GAAG;QACT,KAAK,CAAC,IAAI,CAAC,QAAQ;QACnB,KAAK,CAAC,IAAI,CAAC,MAAM;QACjB,KAAK,CAAC,IAAI,CAAC,SAAS;QACpB,KAAK,CAAC,KAAK,CAAC,MAAM;QAClB,KAAK,CAAC,KAAK,CAAC,MAAM;QAClB,KAAK,CAAC,KAAK,CAAC,KAAK;KAClB,EAAE,CAAC;QACF,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IACD,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,uCAAuC;IACvC,IAAI,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;;QAC1D,aAAa,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,kBAAkB,CAAC,CAAC;IAC5D,MAAM,aAAa,GAAG,EAAE,SAAS,EAAE,uBAAuB,EAAE,CAAC;IAC7D,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE;QACzF,IAAI,EAAE,KAAK;QACX,IAAI,EAAE,IAAI;KACX,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { HostLogs } from '@aalis/api-host-logs';
|
|
2
|
+
import type { Logger, LogHub } from '@aalis/core';
|
|
3
|
+
import type { FileLoggerHandle } from './file-logger.js';
|
|
4
|
+
/**
|
|
5
|
+
* host-logs 服务的实现:历史读文件日志(先等它把已记下的写完),实时接中枢。`file` 不给时没有历史。
|
|
6
|
+
* 订阅带历史时先攒着实时的,历史送完再接着送比它新的,之后直通;补发途中 listener 抛错只丢掉那一条,与中枢同一规则
|
|
7
|
+
*/
|
|
8
|
+
export declare function createHostLogs(hub: LogHub, file: Pick<FileLoggerHandle, 'path' | 'flush'> | undefined, logger: Logger): HostLogs;
|
|
9
|
+
//# sourceMappingURL=host-logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-logs.d.ts","sourceRoot":"","sources":["../src/host-logs.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAY,MAAM,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAoDzD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,SAAS,EAC1D,MAAM,EAAE,MAAM,GACb,QAAQ,CA4CV"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { open } from 'node:fs/promises';
|
|
2
|
+
import { parseLogLine } from '@aalis/schema-log';
|
|
3
|
+
/** 从文件末尾往前最多扫这么多字节:筛得很窄、往前翻得很深时也有界,更早的去看 logs/latest.log 本体 */
|
|
4
|
+
const SCAN_BYTES = 16 * 1024 * 1024;
|
|
5
|
+
const CHUNK_BYTES = 64 * 1024;
|
|
6
|
+
/**
|
|
7
|
+
* 文件末尾往前分块读,返回最后 limit 条符合 accept 的日志(文件内的先后)。latest.log 可能几百 MB,不整个载入。
|
|
8
|
+
* 按字节切行:UTF-8 的多字节序列里没有 0x0A,块边界劈不开字符。文件不在时没有历史
|
|
9
|
+
*/
|
|
10
|
+
async function readTail(path, limit, accept) {
|
|
11
|
+
let file;
|
|
12
|
+
try {
|
|
13
|
+
file = await open(path, 'r');
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err.code === 'ENOENT')
|
|
17
|
+
return [];
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const { size } = await file.stat();
|
|
22
|
+
const batches = [];
|
|
23
|
+
let count = 0;
|
|
24
|
+
let pos = size;
|
|
25
|
+
// 已读、开头可能是半行的字节:留着与前一块拼起来
|
|
26
|
+
let carry = Buffer.alloc(0);
|
|
27
|
+
while (pos > 0 && count < limit && size - pos < SCAN_BYTES) {
|
|
28
|
+
const start = Math.max(0, pos - CHUNK_BYTES);
|
|
29
|
+
const chunk = Buffer.alloc(pos - start);
|
|
30
|
+
await file.read(chunk, 0, chunk.length, start);
|
|
31
|
+
pos = start;
|
|
32
|
+
const bytes = Buffer.concat([chunk, carry]);
|
|
33
|
+
const cut = pos > 0 ? bytes.indexOf(0x0a) + 1 : 0;
|
|
34
|
+
if (pos > 0 && cut === 0) {
|
|
35
|
+
carry = bytes;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
carry = bytes.subarray(0, cut);
|
|
39
|
+
const batch = bytes
|
|
40
|
+
.subarray(cut)
|
|
41
|
+
.toString('utf8')
|
|
42
|
+
.split('\n')
|
|
43
|
+
.map(parseLogLine)
|
|
44
|
+
.filter((entry) => entry !== null && accept(entry));
|
|
45
|
+
batches.push(batch);
|
|
46
|
+
count += batch.length;
|
|
47
|
+
}
|
|
48
|
+
return batches.reverse().flat().slice(-limit);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
await file.close();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* host-logs 服务的实现:历史读文件日志(先等它把已记下的写完),实时接中枢。`file` 不给时没有历史。
|
|
56
|
+
* 订阅带历史时先攒着实时的,历史送完再接着送比它新的,之后直通;补发途中 listener 抛错只丢掉那一条,与中枢同一规则
|
|
57
|
+
*/
|
|
58
|
+
export function createHostLogs(hub, file, logger) {
|
|
59
|
+
const recent = async (limit, options = {}) => {
|
|
60
|
+
if (!file || limit <= 0)
|
|
61
|
+
return [];
|
|
62
|
+
await file.flush();
|
|
63
|
+
const { before, match } = options;
|
|
64
|
+
return readTail(file.path, limit, entry => (before === undefined || entry.seq < before) && (match?.(entry) ?? true));
|
|
65
|
+
};
|
|
66
|
+
return {
|
|
67
|
+
recent,
|
|
68
|
+
subscribe(listener, options = {}) {
|
|
69
|
+
const history = options.history ?? 0;
|
|
70
|
+
if (history <= 0)
|
|
71
|
+
return hub.onEntry(listener);
|
|
72
|
+
let last = Number.NEGATIVE_INFINITY;
|
|
73
|
+
let queued = [];
|
|
74
|
+
let closed = false;
|
|
75
|
+
const deliver = (entry) => {
|
|
76
|
+
if (closed || entry.seq <= last)
|
|
77
|
+
return;
|
|
78
|
+
last = entry.seq;
|
|
79
|
+
// 订阅者就是日志的去处,它的错误(含返回被拒的 Promise)无处可报
|
|
80
|
+
try {
|
|
81
|
+
Promise.resolve(listener(entry)).catch(() => { });
|
|
82
|
+
}
|
|
83
|
+
catch { }
|
|
84
|
+
};
|
|
85
|
+
const off = hub.onEntry(entry => (queued ? queued.push(entry) : deliver(entry)));
|
|
86
|
+
void recent(history)
|
|
87
|
+
.catch(err => {
|
|
88
|
+
logger.warn('日志订阅没能补发历史,只送此后的:', err);
|
|
89
|
+
return [];
|
|
90
|
+
})
|
|
91
|
+
.then(tail => {
|
|
92
|
+
const pending = queued ?? [];
|
|
93
|
+
queued = undefined;
|
|
94
|
+
for (const entry of [...tail, ...pending])
|
|
95
|
+
deliver(entry);
|
|
96
|
+
});
|
|
97
|
+
return () => {
|
|
98
|
+
closed = true;
|
|
99
|
+
off();
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=host-logs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-logs.js","sourceRoot":"","sources":["../src/host-logs.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export { getBootstrapBuffer, installBootstrapBuffer } from './bootstrap-buffer.js';
|
|
2
|
-
export { type ConfigProvider, type ConfigStore, createConfigStore, installHostConfig } from './config-store.js';
|
|
2
|
+
export { type ConfigProvider, type ConfigStore, createConfigStore, installHostConfig, type SecretProvider, type SecretStoreInit, } from './config-store.js';
|
|
3
3
|
export { type ConfigSyncOptions, handleConfigChanged, installConfigHotReload, syncPluginDefaults, withPluginConfigSync, } from './config-sync.js';
|
|
4
4
|
export { type ConsoleSinkHandle, installConsoleSink } from './console-sink.js';
|
|
5
|
-
export { appendCrashLog,
|
|
5
|
+
export { appendCrashLog, type FileLoggerHandle, setupFileLogger } from './file-logger.js';
|
|
6
|
+
export { derivePaths, HomeArgsError, type HostArgs, initHome, isHomeInitialized, parseHostArgs, profileOfRealHome, type ResolveHomeInput, resolveHome, } from './home.js';
|
|
7
|
+
export { createHostLogs } from './host-logs.js';
|
|
6
8
|
export { createNodeModulesPluginLoader } from './node-modules-loader.js';
|
|
7
9
|
export { createPluginDiscovery, type PluginDescriptor, type PluginDiscovery, type PluginLoader, } from './plugin-discovery.js';
|
|
8
|
-
export { buildRespawnCommand, createFsPluginLoader, createFsYamlConfigProvider, createProcessRespawnStrategy, isRestartRollback, READY_MESSAGE, type RespawnOptions, type RestartRollback, } from './providers.js';
|
|
10
|
+
export { buildRespawnCommand, createFsPluginLoader, createFsSecretsProvider, createFsYamlConfigProvider, createProcessRespawnStrategy, createServiceRestartStrategy, isRestartRollback, READY_MESSAGE, type RespawnOptions, type RestartRollback, SERVICE_RESTART_EXIT_CODE, } from './providers.js';
|
|
9
11
|
export { type StartAalisOptions, startAalis } from './start.js';
|
|
10
12
|
export { tryDispatchSubcommand } from './subcommand.js';
|
|
11
13
|
export { installTerminalStateRestorer, restoreTerminalState } from './terminal.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,iBAAiB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,KAAK,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,KAAK,gBAAgB,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EACL,WAAW,EACX,aAAa,EACb,KAAK,QAAQ,EACb,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,0BAA0B,EAC1B,4BAA4B,EAC5B,4BAA4B,EAC5B,iBAAiB,EACjB,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,KAAK,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,18 +6,21 @@
|
|
|
6
6
|
// - createFsPluginLoader:monorepo 自托管(扫描 packages/ 目录)
|
|
7
7
|
// - createPluginDiscovery:把加载器发现的插件整批交给 core,并提供热扫描(plugin-source 服务的实现)
|
|
8
8
|
// - createConfigStore / installHostConfig:配置文档与 host-config 服务(core 只持运行态)
|
|
9
|
+
// - createHostLogs:host-logs 服务(读日志:文件日志里的历史 + 中枢的实时)
|
|
9
10
|
// - withPluginConfigSync:导入定义后、登记前把 schema 派生默认值深合并进文档
|
|
10
|
-
// - createFsYamlConfigProvider / createProcessRespawnStrategy:YAML
|
|
11
|
+
// - createFsYamlConfigProvider / createFsSecretsProvider / createProcessRespawnStrategy:YAML 配置与密钥文件 + 进程级重启
|
|
11
12
|
// - startAalis:组装以上 + 宿主件为实例并启动(带 options 开关,默认独立部署)
|
|
12
13
|
// - install*/setup*/tryDispatchSubcommand:宿主件,供高级 opt-in 组装
|
|
13
14
|
export { getBootstrapBuffer, installBootstrapBuffer } from './bootstrap-buffer.js';
|
|
14
|
-
export { createConfigStore, installHostConfig } from './config-store.js';
|
|
15
|
+
export { createConfigStore, installHostConfig, } from './config-store.js';
|
|
15
16
|
export { handleConfigChanged, installConfigHotReload, syncPluginDefaults, withPluginConfigSync, } from './config-sync.js';
|
|
16
17
|
export { installConsoleSink } from './console-sink.js';
|
|
17
|
-
export { appendCrashLog,
|
|
18
|
+
export { appendCrashLog, setupFileLogger } from './file-logger.js';
|
|
19
|
+
export { derivePaths, HomeArgsError, initHome, isHomeInitialized, parseHostArgs, profileOfRealHome, resolveHome, } from './home.js';
|
|
20
|
+
export { createHostLogs } from './host-logs.js';
|
|
18
21
|
export { createNodeModulesPluginLoader } from './node-modules-loader.js';
|
|
19
22
|
export { createPluginDiscovery, } from './plugin-discovery.js';
|
|
20
|
-
export { buildRespawnCommand, createFsPluginLoader, createFsYamlConfigProvider, createProcessRespawnStrategy, isRestartRollback, READY_MESSAGE, } from './providers.js';
|
|
23
|
+
export { buildRespawnCommand, createFsPluginLoader, createFsSecretsProvider, createFsYamlConfigProvider, createProcessRespawnStrategy, createServiceRestartStrategy, isRestartRollback, READY_MESSAGE, SERVICE_RESTART_EXIT_CODE, } from './providers.js';
|
|
21
24
|
export { startAalis } from './start.js';
|
|
22
25
|
export { tryDispatchSubcommand } from './subcommand.js';
|
|
23
26
|
export { installTerminalStateRestorer, restoreTerminalState } from './terminal.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,EAAE;AACF,uDAAuD;AACvD,8DAA8D;AAC9D,oEAAoE;AACpE,yDAAyD;AACzD,2EAA2E;AAC3E,6EAA6E;AAC7E,yDAAyD;AACzD
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,EAAE;AACF,uDAAuD;AACvD,8DAA8D;AAC9D,oEAAoE;AACpE,yDAAyD;AACzD,2EAA2E;AAC3E,6EAA6E;AAC7E,wDAAwD;AACxD,yDAAyD;AACzD,+GAA+G;AAC/G,uDAAuD;AACvD,8DAA8D;AAE9D,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAGL,iBAAiB,EACjB,iBAAiB,GAGlB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAA0B,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAyB,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC1F,OAAO,EACL,WAAW,EACX,aAAa,EAEb,QAAQ,EACR,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EAEjB,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EACL,qBAAqB,GAItB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,0BAA0B,EAC1B,4BAA4B,EAC5B,4BAA4B,EAC5B,iBAAiB,EACjB,aAAa,EAGb,yBAAyB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAA0B,UAAU,EAAE,MAAM,YAAY,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,4BAA4B,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** 锁文件内容 */
|
|
2
|
+
export interface LockHolder {
|
|
3
|
+
pid: number;
|
|
4
|
+
/** 进程启动标识,见 {@link ProcessProbe.startId};查不了时没有 */
|
|
5
|
+
startId?: string;
|
|
6
|
+
/** 本次开机的标识;查不了时没有 */
|
|
7
|
+
bootId?: string;
|
|
8
|
+
/** pid 命名空间(Linux);查不了时没有 */
|
|
9
|
+
pidNs?: string;
|
|
10
|
+
/** 交接令牌的 sha256 */
|
|
11
|
+
handoffHash: string;
|
|
12
|
+
}
|
|
13
|
+
/** 查询本机进程的那几样东西,测试里换成替身 */
|
|
14
|
+
export interface ProcessProbe {
|
|
15
|
+
/** 本进程的 pid */
|
|
16
|
+
pid: number;
|
|
17
|
+
now(): number;
|
|
18
|
+
/** 本次开机的标识:Linux 的 boot_id、macOS 的 kern.bootsessionuuid;别的平台没有 */
|
|
19
|
+
bootId(): string | undefined;
|
|
20
|
+
/** 本进程的 pid 命名空间(Linux);别的平台没有 */
|
|
21
|
+
pidNs(): string | undefined;
|
|
22
|
+
/** pid 是否存在 */
|
|
23
|
+
exists(pid: number): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* 进程启动标识,只用来比相等:Linux 是 `/proc/<pid>/stat` 的 starttime(开机以来的时钟滴答,与墙上时钟无关),
|
|
26
|
+
* 其它 POSIX 是 UTC 下 `ps -o lstart=` 的原文(进程创建时记下的时刻,之后不随时钟步进变)。查不了时为 undefined。
|
|
27
|
+
*/
|
|
28
|
+
startId(pid: number): string | undefined;
|
|
29
|
+
}
|
|
30
|
+
export declare const nodeProcessProbe: ProcessProbe;
|
|
31
|
+
export interface InstanceLock {
|
|
32
|
+
/** 本进程持有的锁文件 */
|
|
33
|
+
readonly file: string;
|
|
34
|
+
/** 交接令牌:respawn 时经环境变量交给新进程 */
|
|
35
|
+
readonly handoffToken: string;
|
|
36
|
+
/** 删掉本进程的锁文件:只在它仍是本进程那份时删(交接后可能已被清掉,同名的也可能是别的实例的);靠内容比对,重复调用不会误删 */
|
|
37
|
+
release(): void;
|
|
38
|
+
}
|
|
39
|
+
type AcquireResult = {
|
|
40
|
+
ok: true;
|
|
41
|
+
lock: InstanceLock;
|
|
42
|
+
} | {
|
|
43
|
+
ok: false;
|
|
44
|
+
holder: LockHolder;
|
|
45
|
+
file: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* 取实例锁。`handoffToken` 是旧实例 respawn 时交过来的令牌:与锁里的哈希对得上的那份按已交接处理;
|
|
49
|
+
* 否则按持有者死活决定取锁还是报占用。
|
|
50
|
+
*/
|
|
51
|
+
export declare function acquireInstanceLock(runDir: string, opts?: {
|
|
52
|
+
handoffToken?: string;
|
|
53
|
+
probe?: ProcessProbe;
|
|
54
|
+
}): AcquireResult;
|
|
55
|
+
export {};
|
|
56
|
+
//# sourceMappingURL=instance-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance-lock.d.ts","sourceRoot":"","sources":["../src/instance-lock.ts"],"names":[],"mappings":"AAyCA,YAAY;AACZ,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qBAAqB;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6BAA6B;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,2BAA2B;AAC3B,MAAM,WAAW,YAAY;IAC3B,eAAe;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,IAAI,MAAM,CAAC;IACd,kEAAkE;IAClE,MAAM,IAAI,MAAM,GAAG,SAAS,CAAC;IAC7B,kCAAkC;IAClC,KAAK,IAAI,MAAM,GAAG,SAAS,CAAC;IAC5B,eAAe;IACf,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;IAC7B;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC1C;AAgBD,eAAO,MAAM,gBAAgB,EAAE,YA2C9B,CAAC;AAEF,MAAM,WAAW,YAAY;IAC3B,gBAAgB;IAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,oEAAoE;IACpE,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,KAAK,aAAa,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAuDxG;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,YAAY,CAAA;CAAO,GACzD,aAAa,CAoEf"}
|