pi-courier 0.1.34 → 0.1.36
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 -4
- package/README.zh-CN.md +5 -3
- package/dist/cli.js +54 -24
- package/dist/cli.js.map +1 -1
- package/dist/log-filter.d.ts +37 -0
- package/dist/log-filter.d.ts.map +1 -0
- package/dist/log-filter.js +63 -0
- package/dist/log-filter.js.map +1 -0
- package/dist/logger.d.ts +9 -3
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +27 -7
- package/dist/logger.js.map +1 -1
- package/dist/project-labels.d.ts +28 -0
- package/dist/project-labels.d.ts.map +1 -0
- package/dist/project-labels.js +44 -0
- package/dist/project-labels.js.map +1 -0
- package/dist/rpc/message-router.d.ts.map +1 -1
- package/dist/rpc/message-router.js +32 -24
- package/dist/rpc/message-router.js.map +1 -1
- package/dist/rpc/pi-rpc.d.ts +5 -0
- package/dist/rpc/pi-rpc.d.ts.map +1 -1
- package/dist/rpc/pi-rpc.js +4 -0
- package/dist/rpc/pi-rpc.js.map +1 -1
- package/dist/rpc/pmctl-controller.d.ts +5 -0
- package/dist/rpc/pmctl-controller.d.ts.map +1 -1
- package/dist/rpc/pmctl-controller.js +34 -7
- package/dist/rpc/pmctl-controller.js.map +1 -1
- package/dist/rpc/project-manager.d.ts +7 -0
- package/dist/rpc/project-manager.d.ts.map +1 -1
- package/dist/rpc/project-manager.js +32 -6
- package/dist/rpc/project-manager.js.map +1 -1
- package/dist/standalone.d.ts.map +1 -1
- package/dist/standalone.js +17 -14
- package/dist/standalone.js.map +1 -1
- package/package.json +3 -1
- package/scripts/ensure-crypto-native.d.mts +19 -0
- package/scripts/ensure-crypto-native.mjs +147 -0
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ npm run build
|
|
|
56
56
|
npm link # make the `pi-courier` command available globally
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
**Do not use `--ignore-scripts`**: the Matrix E2EE library downloads its native binary via postinstall.
|
|
59
|
+
**Do not use `--ignore-scripts`**: the Matrix E2EE library downloads its native binary via postinstall. On npm >= 11 the `allow-scripts` default may block that dependency's postinstall; `pi-courier`'s own postinstall self-checks for it and auto-downloads the missing native binary (one extra download on first install). If you still hit `Cannot find module '@matrix-org/matrix-sdk-crypto-nodejs-linux-x64-gnu'` (e.g. the auto-download was skipped), run manually:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
62
|
cd node_modules/@matrix-org/matrix-sdk-crypto-nodejs
|
|
@@ -218,8 +218,10 @@ One bot account can serve multiple projects — each project gets its own privat
|
|
|
218
218
|
### Managing the service
|
|
219
219
|
|
|
220
220
|
```bash
|
|
221
|
-
pi-courier status # status + recent logs
|
|
221
|
+
pi-courier status # status + recent logs (optionally: pi-courier status <project>)
|
|
222
222
|
pi-courier logs # tail logs (INFO and above)
|
|
223
|
+
pi-courier logs ai-api # multi-project: only this project's tagged lines
|
|
224
|
+
pi-courier logs ai-api www --level debug # several projects, full detail
|
|
223
225
|
pi-courier logs --level debug # tail ALL logs (incl. thinking, stream deltas)
|
|
224
226
|
pi-courier logs --level error # errors only
|
|
225
227
|
pi-courier run --level debug # foreground with full detail
|
|
@@ -233,8 +235,13 @@ pi-courier -v # show the installed version
|
|
|
233
235
|
|
|
234
236
|
Log levels: `debug < info < warn < error`. The service writes everything;
|
|
235
237
|
`logs` shows INFO+ by default, `--level debug` shows the full session replay
|
|
236
|
-
(user messages, thinking, tool calls, replies).
|
|
237
|
-
|
|
238
|
+
(user messages, thinking, tool calls, replies). In multi-project mode every
|
|
239
|
+
project-related line carries a `[project]` tag, and `logs <project>` filters
|
|
240
|
+
by it (case-insensitive; project = the `/pmctl` name, or the working
|
|
241
|
+
directory's name when the project is unnamed). Filtering runs through
|
|
242
|
+
`journalctl --grep` — it requires journald with PCRE2 support (standard on
|
|
243
|
+
Debian/Ubuntu). The complete conversation is always stored in pi's session
|
|
244
|
+
files (`~/.pi/agent/sessions/`).
|
|
238
245
|
|
|
239
246
|
Upgrading **pi** is independent — pi-courier always uses the system pi via `which pi`:
|
|
240
247
|
|
package/README.zh-CN.md
CHANGED
|
@@ -56,7 +56,7 @@ npm run build
|
|
|
56
56
|
npm link # 让 `pi-courier` 命令全局可用
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
**不要用 `--ignore-scripts`**:Matrix E2EE 库的 postinstall
|
|
59
|
+
**不要用 `--ignore-scripts`**:Matrix E2EE 库的 postinstall 会下载原生二进制。npm >= 11 的 `allow-scripts` 默认可能拦截该依赖的 postinstall;`pi-courier` 自己的 postinstall 会自检并**自动补下**缺失的原生二进制(首次安装多下载一次)。若仍报 `Cannot find module '@matrix-org/matrix-sdk-crypto-nodejs-linux-x64-gnu'`(比如自检被跳过),再手动补:
|
|
60
60
|
|
|
61
61
|
```bash
|
|
62
62
|
cd node_modules/@matrix-org/matrix-sdk-crypto-nodejs
|
|
@@ -218,8 +218,10 @@ pi-courier enable # 安装 systemd 服务:开机自启 + 立即启动
|
|
|
218
218
|
### 服务管理
|
|
219
219
|
|
|
220
220
|
```bash
|
|
221
|
-
pi-courier status # 状态 + 最近日志
|
|
221
|
+
pi-courier status # 状态 + 最近日志(可加项目名:pi-courier status <项目>)
|
|
222
222
|
pi-courier logs # 跟踪日志(INFO 及以上)
|
|
223
|
+
pi-courier logs ai-api # 多工程:只看该项目的打标日志
|
|
224
|
+
pi-courier logs ai-api www --level debug # 多项目 + 全量细节
|
|
223
225
|
pi-courier logs --level debug # 跟踪全部日志(含思考、流式增量)
|
|
224
226
|
pi-courier logs --level error # 只看错误
|
|
225
227
|
pi-courier run --level debug # 前台运行,全量显示
|
|
@@ -231,7 +233,7 @@ pi-courier update # 更新 pi-courier 自身
|
|
|
231
233
|
pi-courier -v # 显示当前版本(--version/version 亦可)
|
|
232
234
|
```
|
|
233
235
|
|
|
234
|
-
日志级别:`debug < info < warn < error`。服务会把全部内容写入日志;`logs` 默认显示 INFO 及以上,`--level debug` 显示完整会话回放(用户消息、思考、工具调用、回复)。完整对话始终保存在 pi 的会话文件(`~/.pi/agent/sessions/`)。
|
|
236
|
+
日志级别:`debug < info < warn < error`。服务会把全部内容写入日志;`logs` 默认显示 INFO 及以上,`--level debug` 显示完整会话回放(用户消息、思考、工具调用、回复)。多工程模式下,项目相关日志行带有 `[项目名]` 标签,`logs <项目名>` 即可只看该工程(大小写不敏感;项目名 = `/pmctl` 的名称,未命名时为工作目录的目录名)。过滤经 `journalctl --grep` 实现,要求 journald 支持 PCRE2(Debian/Ubuntu 标准支持)。完整对话始终保存在 pi 的会话文件(`~/.pi/agent/sessions/`)。
|
|
235
237
|
|
|
236
238
|
**升级 pi** 是独立的事 —— pi-courier 始终通过 `which pi` 连接系统 pi:
|
|
237
239
|
|
package/dist/cli.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
* pi-courier enable install a user-level systemd service (auto-start) and start it
|
|
9
9
|
* pi-courier start start the systemd service
|
|
10
10
|
* pi-courier stop stop the systemd service
|
|
11
|
-
* pi-courier status show service status + recent logs
|
|
12
|
-
* pi-courier logs tail the service logs
|
|
11
|
+
* pi-courier status show service status + recent logs (optional project filter)
|
|
12
|
+
* pi-courier logs tail the service logs (optional: <project...> [--level])
|
|
13
13
|
* pi-courier update update this project (git pull + npm install + build)
|
|
14
14
|
* pi-courier -v show the installed version (--version / version)
|
|
15
15
|
*
|
|
@@ -22,6 +22,8 @@ import * as os from "node:os";
|
|
|
22
22
|
import * as path from "node:path";
|
|
23
23
|
import { fileURLToPath } from "node:url";
|
|
24
24
|
import { loadConfig } from "./config.js";
|
|
25
|
+
import { buildLogFilterArgs } from "./log-filter.js";
|
|
26
|
+
import { projectLabelOf } from "./project-labels.js";
|
|
25
27
|
import { suppressKnownWarnings } from "./warnings.js";
|
|
26
28
|
suppressKnownWarnings();
|
|
27
29
|
const SERVICE_NAME = "pi-courier";
|
|
@@ -68,8 +70,9 @@ function usage() {
|
|
|
68
70
|
pi-courier start 启动服务
|
|
69
71
|
pi-courier stop 停止服务
|
|
70
72
|
pi-courier restart 重启服务
|
|
71
|
-
pi-courier status 查看服务状态与最近日志
|
|
72
|
-
pi-courier logs 跟踪服务日志(Ctrl+C 退出)
|
|
73
|
+
pi-courier status 查看服务状态与最近日志(可带项目名过滤)
|
|
74
|
+
pi-courier logs 跟踪服务日志(Ctrl+C 退出);多工程下可加项目名过滤:
|
|
75
|
+
pi-courier logs <项目> [项目...] [--level debug|info|warn|error]
|
|
73
76
|
pi-courier disable 卸载服务(停止 + 取消自启 + 删除 unit 文件)
|
|
74
77
|
pi-courier update 更新本项目(git pull + 安装依赖 + 重新构建)
|
|
75
78
|
pi-courier -v 显示版本号(--version / version 亦可)
|
|
@@ -151,38 +154,65 @@ function runSystemctl(args) {
|
|
|
151
154
|
process.exit(res.status ?? 1);
|
|
152
155
|
}
|
|
153
156
|
}
|
|
157
|
+
/** Project labels from the config (the single source `log-filter` matches against). */
|
|
158
|
+
function projectLabels() {
|
|
159
|
+
const config = loadConfig();
|
|
160
|
+
const projects = config.projects ?? {};
|
|
161
|
+
return { labels: Object.values(projects).map((p) => projectLabelOf(p)), multiProject: config.multiProject === true };
|
|
162
|
+
}
|
|
154
163
|
function cmdService(action, args = []) {
|
|
155
164
|
const unitPath = userUnitPath();
|
|
156
165
|
if (!fs.existsSync(unitPath)) {
|
|
157
166
|
console.error(`❌ 服务未安装。先运行 \`pi-courier enable\` 安装。`);
|
|
158
167
|
process.exit(1);
|
|
159
168
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
169
|
+
if (action === "logs" || action === "status") {
|
|
170
|
+
// status first shows the unit itself (systemctl), then the log window.
|
|
171
|
+
if (action === "status") {
|
|
172
|
+
spawnSync("systemctl", ["--user", "status", SERVICE_NAME], { stdio: "inherit" });
|
|
173
|
+
}
|
|
174
|
+
// Split args: `--level <lvl>` option vs positional project labels.
|
|
163
175
|
let level = "info";
|
|
176
|
+
const positional = [];
|
|
164
177
|
for (let i = 0; i < args.length; i++) {
|
|
165
178
|
if (args[i] === "--level")
|
|
166
|
-
level = args[++i] ??
|
|
179
|
+
level = args[++i] ?? "";
|
|
180
|
+
else
|
|
181
|
+
positional.push(args[i]);
|
|
167
182
|
}
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
183
|
+
const { labels, multiProject } = projectLabels();
|
|
184
|
+
// Single-project mode tags nothing, so a project filter can never match —
|
|
185
|
+
// say so instead of silently presenting an empty view (spec #34).
|
|
186
|
+
if (positional.length > 0 && !multiProject) {
|
|
187
|
+
console.error("❌ 当前为单工程模式,日志不区分项目(多工程模式才打项目标签)。");
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
const filter = buildLogFilterArgs({
|
|
191
|
+
unit: SERVICE_NAME,
|
|
192
|
+
availableLabels: labels,
|
|
193
|
+
requestedProjects: positional,
|
|
194
|
+
level,
|
|
195
|
+
follow: action === "logs",
|
|
196
|
+
lineCount: action === "status" ? 15 : undefined,
|
|
197
|
+
});
|
|
198
|
+
if (!filter.ok) {
|
|
199
|
+
console.error(`❌ ${filter.message}`);
|
|
200
|
+
process.exit(1);
|
|
201
|
+
}
|
|
202
|
+
const journalArgs = action === "status" ? ["--no-pager", ...filter.args] : filter.args;
|
|
203
|
+
const res = spawnSync("journalctl", journalArgs, { stdio: "inherit" });
|
|
204
|
+
// logs runs in follow mode: Ctrl+C can surface a non-zero exit — ignore it
|
|
205
|
+
// (same tolerance as before); status's window exit is meaningful.
|
|
206
|
+
if (res.status !== 0 && action === "status") {
|
|
207
|
+
process.exit(res.status ?? 1);
|
|
208
|
+
}
|
|
209
|
+
return;
|
|
173
210
|
}
|
|
211
|
+
const cmd = ["systemctl", "--user", action, SERVICE_NAME];
|
|
174
212
|
const res = spawnSync(cmd[0], cmd.slice(1), { stdio: "inherit" });
|
|
175
|
-
if (res.status !== 0
|
|
213
|
+
if (res.status !== 0) {
|
|
176
214
|
process.exit(res.status ?? 1);
|
|
177
215
|
}
|
|
178
|
-
if (action === "status") {
|
|
179
|
-
// Append recent logs for convenience
|
|
180
|
-
const logs = spawnSync("journalctl", ["--user", "-u", SERVICE_NAME, "-n", "15", "--no-pager"], {
|
|
181
|
-
encoding: "utf-8",
|
|
182
|
-
});
|
|
183
|
-
if (logs.stdout)
|
|
184
|
-
console.log(logs.stdout);
|
|
185
|
-
}
|
|
186
216
|
}
|
|
187
217
|
function cmdDisable() {
|
|
188
218
|
const unitPath = userUnitPath();
|
|
@@ -283,11 +313,11 @@ async function main() {
|
|
|
283
313
|
case "start":
|
|
284
314
|
case "stop":
|
|
285
315
|
case "restart":
|
|
286
|
-
case "status":
|
|
287
316
|
cmdService(cmd);
|
|
288
317
|
break;
|
|
318
|
+
case "status":
|
|
289
319
|
case "logs":
|
|
290
|
-
cmdService(
|
|
320
|
+
cmdService(cmd, rest);
|
|
291
321
|
break;
|
|
292
322
|
case "disable":
|
|
293
323
|
cmdDisable();
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,qBAAqB,EAAE,CAAC;AAExB,MAAM,YAAY,GAAG,YAAY,CAAC;AAClC,MAAM,YAAY,GAAG,GAAG,YAAY,UAAU,CAAC;AAE/C,+DAA+D;AAC/D,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,cAAc,CAAC,EAAE,OAAO,CAAC,CAAyB,CAAC;QAClH,OAAO,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,SAAS,qBAAqB;IAC5B,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IACjG,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,aAAa,EAAE,0BAA0B,CAAC,CAAC;IAC7F,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,KAAK;IACZ,OAAO,CAAC,GAAG,CAAC
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log-filter — the pure argv builder behind `pi-courier logs/status` (spec #34).
|
|
3
|
+
*
|
|
4
|
+
* Journal filtering works on the LINE, not on journald fields: custom stdout
|
|
5
|
+
* field assignments (PROJECT=…) are not parsed by journald (measured on
|
|
6
|
+
* systemd 257), and the `PRIORITY` field is useless under the default
|
|
7
|
+
* `StandardOutput=inherit` (every line lands at 6) — which is why the old
|
|
8
|
+
* `-p <priority>` --level filter never matched anything real. Instead the
|
|
9
|
+
* bridge writes `[LEVEL] [label]` into each line and this module compiles
|
|
10
|
+
* user requests into an anchored `journalctl --grep` pattern.
|
|
11
|
+
*
|
|
12
|
+
* Requirements: journalctl with PCRE2 (`--grep`, `--case`). Absent → the CLI
|
|
13
|
+
* errors via journalctl itself; no silent fallback (spec #34 decision).
|
|
14
|
+
*/
|
|
15
|
+
export interface LogFilterRequest {
|
|
16
|
+
/** Labels of all registered projects (case-sensitively stored; matched with `--case=0`). */
|
|
17
|
+
availableLabels: string[];
|
|
18
|
+
/** Positional args after the subcommand — each is a project label. */
|
|
19
|
+
requestedProjects: string[];
|
|
20
|
+
/** Already-parsed level option; kept a string so the CLI can report unknown values. */
|
|
21
|
+
level: string;
|
|
22
|
+
/** follow mode (`logs` true, `status` false). */
|
|
23
|
+
follow: boolean;
|
|
24
|
+
/** For status: -n <lineCount> after the filters. */
|
|
25
|
+
lineCount?: number;
|
|
26
|
+
/** Service unit name (cli passes its SERVICE_NAME constant — one owner). */
|
|
27
|
+
unit: string;
|
|
28
|
+
}
|
|
29
|
+
export type LogFilterResult = {
|
|
30
|
+
ok: true;
|
|
31
|
+
args: string[];
|
|
32
|
+
} | {
|
|
33
|
+
ok: false;
|
|
34
|
+
message: string;
|
|
35
|
+
};
|
|
36
|
+
export declare function buildLogFilterArgs(req: LogFilterRequest): LogFilterResult;
|
|
37
|
+
//# sourceMappingURL=log-filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-filter.d.ts","sourceRoot":"","sources":["../src/log-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAaH,MAAM,WAAW,gBAAgB;IAC/B,4FAA4F;IAC5F,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,sEAAsE;IACtE,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,uFAAuF;IACvF,KAAK,EAAE,MAAM,CAAC;IACd,iDAAiD;IACjD,MAAM,EAAE,OAAO,CAAC;IAChB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,eAAe,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAS5F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,eAAe,CAmCzE"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* log-filter — the pure argv builder behind `pi-courier logs/status` (spec #34).
|
|
3
|
+
*
|
|
4
|
+
* Journal filtering works on the LINE, not on journald fields: custom stdout
|
|
5
|
+
* field assignments (PROJECT=…) are not parsed by journald (measured on
|
|
6
|
+
* systemd 257), and the `PRIORITY` field is useless under the default
|
|
7
|
+
* `StandardOutput=inherit` (every line lands at 6) — which is why the old
|
|
8
|
+
* `-p <priority>` --level filter never matched anything real. Instead the
|
|
9
|
+
* bridge writes `[LEVEL] [label]` into each line and this module compiles
|
|
10
|
+
* user requests into an anchored `journalctl --grep` pattern.
|
|
11
|
+
*
|
|
12
|
+
* Requirements: journalctl with PCRE2 (`--grep`, `--case`). Absent → the CLI
|
|
13
|
+
* errors via journalctl itself; no silent fallback (spec #34 decision).
|
|
14
|
+
*/
|
|
15
|
+
import { parseLogLevel } from "./logger.js";
|
|
16
|
+
/** Lower-bound thresholds: `--level X` shows X and everything louder. */
|
|
17
|
+
const LEVEL_ALTERNATIONS = {
|
|
18
|
+
debug: "DEBUG|INFO|WARN|ERROR",
|
|
19
|
+
info: "INFO|WARN|ERROR",
|
|
20
|
+
warn: "WARN|ERROR",
|
|
21
|
+
error: "ERROR",
|
|
22
|
+
};
|
|
23
|
+
/** Escape a literal for the PCRE pattern (labels are user-visible names that
|
|
24
|
+
* validation keeps free of brackets/whitespace, but metacharacters like .
|
|
25
|
+
* remain possible). */
|
|
26
|
+
function escapeRe(s) {
|
|
27
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
28
|
+
}
|
|
29
|
+
export function buildLogFilterArgs(req) {
|
|
30
|
+
const args = ["--user", "-u", req.unit];
|
|
31
|
+
if (req.follow)
|
|
32
|
+
args.push("-f");
|
|
33
|
+
const level = parseLogLevel(req.level);
|
|
34
|
+
if (!level) {
|
|
35
|
+
return { ok: false, message: `未知日志级别: ${req.level}(可选: debug / info / warn / error)` };
|
|
36
|
+
}
|
|
37
|
+
if (req.requestedProjects.length > 0) {
|
|
38
|
+
const unknown = req.requestedProjects.filter((p) => !req.availableLabels.some((l) => l.toLowerCase() === p.toLowerCase()));
|
|
39
|
+
if (unknown.length > 0) {
|
|
40
|
+
const list = req.availableLabels.length > 0 ? req.availableLabels.join(", ") : "(当前无项目)";
|
|
41
|
+
return {
|
|
42
|
+
ok: false,
|
|
43
|
+
message: `未找到项目: ${unknown.join(", ")}\n可用项目: ${list}`,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Case-insensitive exact matching is delegated to `--case=0`: the pattern
|
|
47
|
+
// keeps the user's spelling, journalctl does the folding. The LEVEL group
|
|
48
|
+
// is part of every pattern (debug lists all four names) so the match is
|
|
49
|
+
// always anchored to the level-delimiter boundary — a message body that
|
|
50
|
+
// happens to mention `] [name]` cannot produce a false positive.
|
|
51
|
+
const projects = req.requestedProjects.map(escapeRe).join("|");
|
|
52
|
+
args.push("--grep", `\\[(${LEVEL_ALTERNATIONS[level]})\\] \\[(${projects})\\]`, "--case=0");
|
|
53
|
+
}
|
|
54
|
+
else if (level !== "debug") {
|
|
55
|
+
args.push("--grep", `\\[(${LEVEL_ALTERNATIONS[level]})\\] `, "--case=0");
|
|
56
|
+
}
|
|
57
|
+
// level=debug without projects: no grep — everything passes (matches the
|
|
58
|
+
// pre-spec intent of `--level debug`, which was silently broken via -p).
|
|
59
|
+
if (req.lineCount !== undefined)
|
|
60
|
+
args.push("-n", String(req.lineCount));
|
|
61
|
+
return { ok: true, args };
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=log-filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log-filter.js","sourceRoot":"","sources":["../src/log-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,yEAAyE;AACzE,MAAM,kBAAkB,GAA6B;IACnD,KAAK,EAAE,uBAAuB;IAC9B,IAAI,EAAE,iBAAiB;IACvB,IAAI,EAAE,YAAY;IAClB,KAAK,EAAE,OAAO;CACf,CAAC;AAmBF;;wBAEwB;AACxB,SAAS,QAAQ,CAAC,CAAS;IACzB,OAAO,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAqB;IACtD,MAAM,IAAI,GAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,GAAG,CAAC,MAAM;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhC,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,GAAG,CAAC,KAAK,mCAAmC,EAAE,CAAC;IACzF,CAAC;IAED,IAAI,GAAG,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAC7E,CAAC;QACF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACzF,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,OAAO,EAAE,UAAU,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,EAAE;aACvD,CAAC;QACJ,CAAC;QACD,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,wEAAwE;QACxE,iEAAiE;QACjE,MAAM,QAAQ,GAAG,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,kBAAkB,CAAC,KAAK,CAAC,YAAY,QAAQ,MAAM,EAAE,UAAU,CAAC,CAAC;IAC9F,CAAC;SAAM,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,kBAAkB,CAAC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC3E,CAAC;IACD,yEAAyE;IACzE,yEAAyE;IAEzE,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;IACxE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC"}
|
package/dist/logger.d.ts
CHANGED
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* via `--level debug` (run / logs), and config `logLevel` can lower/raise
|
|
7
7
|
* the write threshold for the service.
|
|
8
8
|
*
|
|
9
|
-
* Output format: `[ISO timestamp] [LEVEL] message` — one line per
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Output format: `[ISO timestamp] [LEVEL] [label] message` — one line per
|
|
10
|
+
* call; the `[label]` segment appears only on `withLabel()` views (project
|
|
11
|
+
* tagging). Objects are JSON-serialized; string args are newline-flattened
|
|
12
|
+
* (⏎) so one call always yields one physical line (journald-friendly, and a
|
|
13
|
+
* tagged line can never be split into unlabeled continuations).
|
|
12
14
|
*/
|
|
13
15
|
export type LogLevel = "debug" | "info" | "warn" | "error";
|
|
14
16
|
export declare function suppressLogLines(...substrings: string[]): () => void;
|
|
@@ -16,6 +18,10 @@ export interface LeveledLogger {
|
|
|
16
18
|
setLogLevel(level: LogLevel): void;
|
|
17
19
|
getLogLevel(): LogLevel;
|
|
18
20
|
isEnabled(level: LogLevel): boolean;
|
|
21
|
+
/** Derive a view that prefixes every line with `[label]` (project tagging).
|
|
22
|
+
* Threshold and suppression are read through to the parent on every call.
|
|
23
|
+
* An empty/undefined label yields the parent itself (no-op derivation). */
|
|
24
|
+
withLabel(label: string | undefined): LeveledLogger;
|
|
19
25
|
debug(...args: unknown[]): void;
|
|
20
26
|
info(...args: unknown[]): void;
|
|
21
27
|
warn(...args: unknown[]): void;
|
package/dist/logger.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAqB3D,wBAAgB,gBAAgB,CAAC,GAAG,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAKpE;AAQD,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IACnC,WAAW,IAAI,QAAQ,CAAC;IACxB,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC;IACpC;;gFAE4E;IAC5E,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;IACpD,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,IAAI,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,QAAiB,GAAG,aAAa,CA2CtE;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAMjE;AAoBD,eAAO,MAAM,MAAM,EAAE,aAA6B,CAAC;AACnD,eAAO,MAAM,WAAW,UA7FH,QAAQ,KAAG,IA6FoB,CAAC;AACrD,eAAO,MAAM,WAAW,QA7FP,QA6FmC,CAAC;AACrD,eAAO,MAAM,SAAS,UA7FH,QAAQ,KAAG,OA6FkB,CAAC"}
|
package/dist/logger.js
CHANGED
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
* via `--level debug` (run / logs), and config `logLevel` can lower/raise
|
|
7
7
|
* the write threshold for the service.
|
|
8
8
|
*
|
|
9
|
-
* Output format: `[ISO timestamp] [LEVEL] message` — one line per
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* Output format: `[ISO timestamp] [LEVEL] [label] message` — one line per
|
|
10
|
+
* call; the `[label]` segment appears only on `withLabel()` views (project
|
|
11
|
+
* tagging). Objects are JSON-serialized; string args are newline-flattened
|
|
12
|
+
* (⏎) so one call always yields one physical line (journald-friendly, and a
|
|
13
|
+
* tagged line can never be split into unlabeled continuations).
|
|
12
14
|
*/
|
|
13
15
|
const LEVEL_ORDER = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
14
16
|
const LEVEL_NAMES = { debug: "DEBUG", info: "INFO", warn: "WARN", error: "ERROR" };
|
|
@@ -48,12 +50,13 @@ function isSuppressed(args) {
|
|
|
48
50
|
export function createLogger(initial = "info") {
|
|
49
51
|
let threshold = initial;
|
|
50
52
|
const isEnabled = (level) => LEVEL_ORDER[level] >= LEVEL_ORDER[threshold];
|
|
51
|
-
const write = (level, args) => {
|
|
53
|
+
const write = (level, args, label) => {
|
|
52
54
|
if (!isEnabled(level))
|
|
53
55
|
return;
|
|
54
56
|
if (isSuppressed(args))
|
|
55
57
|
return;
|
|
56
|
-
const
|
|
58
|
+
const labelPart = label ? [`[${label}]`] : [];
|
|
59
|
+
const line = [`[${new Date().toISOString()}]`, `[${LEVEL_NAMES[level]}]`, ...labelPart, ...args.map(formatArg)].join(" ");
|
|
57
60
|
if (level === "error" || level === "warn") {
|
|
58
61
|
console.error(line);
|
|
59
62
|
}
|
|
@@ -61,17 +64,33 @@ export function createLogger(initial = "info") {
|
|
|
61
64
|
console.log(line);
|
|
62
65
|
}
|
|
63
66
|
};
|
|
64
|
-
|
|
67
|
+
const logger = {
|
|
65
68
|
setLogLevel: (level) => {
|
|
66
69
|
threshold = level;
|
|
67
70
|
},
|
|
68
71
|
getLogLevel: () => threshold,
|
|
69
72
|
isEnabled,
|
|
73
|
+
withLabel: (label) => {
|
|
74
|
+
const trimmed = label?.trim();
|
|
75
|
+
if (!trimmed)
|
|
76
|
+
return logger;
|
|
77
|
+
return {
|
|
78
|
+
setLogLevel: logger.setLogLevel,
|
|
79
|
+
getLogLevel: logger.getLogLevel,
|
|
80
|
+
isEnabled: logger.isEnabled,
|
|
81
|
+
withLabel: (next) => (next?.trim() ? logger.withLabel(next.trim()) : logger),
|
|
82
|
+
debug: (...args) => write("debug", args, trimmed),
|
|
83
|
+
info: (...args) => write("info", args, trimmed),
|
|
84
|
+
warn: (...args) => write("warn", args, trimmed),
|
|
85
|
+
error: (...args) => write("error", args, trimmed),
|
|
86
|
+
};
|
|
87
|
+
},
|
|
70
88
|
debug: (...args) => write("debug", args),
|
|
71
89
|
info: (...args) => write("info", args),
|
|
72
90
|
warn: (...args) => write("warn", args),
|
|
73
91
|
error: (...args) => write("error", args),
|
|
74
92
|
};
|
|
93
|
+
return logger;
|
|
75
94
|
}
|
|
76
95
|
/** Parse a CLI/config level string; undefined when invalid. */
|
|
77
96
|
export function parseLogLevel(value) {
|
|
@@ -86,7 +105,8 @@ export function parseLogLevel(value) {
|
|
|
86
105
|
}
|
|
87
106
|
function formatArg(arg) {
|
|
88
107
|
if (typeof arg === "string") {
|
|
89
|
-
|
|
108
|
+
const oneLine = arg.replace(/\r\n|\r|\n/g, "⏎");
|
|
109
|
+
return oneLine.length > MAX_STRING ? `${oneLine.slice(0, MAX_STRING)}…(+${oneLine.length - MAX_STRING} chars)` : oneLine;
|
|
90
110
|
}
|
|
91
111
|
if (typeof arg === "object" && arg !== null) {
|
|
92
112
|
try {
|
package/dist/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project labels — the single resolution/validation point for the `[标签]`
|
|
3
|
+
* segment on tagged log lines (spec #34).
|
|
4
|
+
*
|
|
5
|
+
* One rule used by three consumers so they can never drift:
|
|
6
|
+
* - log rendering (withLabel on the project's logger view)
|
|
7
|
+
* - /pmctl validation (new + rename reject what the log format cannot carry)
|
|
8
|
+
* - `pi-courier logs <项目>` matching (CLI filters by the same value)
|
|
9
|
+
*
|
|
10
|
+
* Resolution: explicit name, else the workdir basename (never the raw room
|
|
11
|
+
* ID — unreadable as a tag). Validation guards the line format itself: no
|
|
12
|
+
* brackets/whitespace (the tag is delimited by them), length cap (bounded
|
|
13
|
+
* lines), and case-insensitive uniqueness (log filtering is case-insensitive,
|
|
14
|
+
* so two labels differing only in case would collide in `logs <name>`).
|
|
15
|
+
*/
|
|
16
|
+
export interface LabelSource {
|
|
17
|
+
name?: string;
|
|
18
|
+
workdir: string;
|
|
19
|
+
}
|
|
20
|
+
/** The label for a project entry: trimmed name when present, else the
|
|
21
|
+
* workdir basename (empty basename — the root "/" workdir — falls back to
|
|
22
|
+
* the workdir itself, so a label is never empty). */
|
|
23
|
+
export declare function projectLabelOf(entry: LabelSource): string;
|
|
24
|
+
/** Validate a user-supplied label against the format rules and the existing
|
|
25
|
+
* labels (case-insensitive uniqueness). Returns an error message (user-
|
|
26
|
+
* facing, Chinese) or null when the label is acceptable. */
|
|
27
|
+
export declare function validateProjectLabel(candidate: string, existingLabels: string[]): string | null;
|
|
28
|
+
//# sourceMappingURL=project-labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-labels.d.ts","sourceRoot":"","sources":["../src/project-labels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;sDAEsD;AACtD,wBAAgB,cAAc,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAGzD;AAID;;6DAE6D;AAC7D,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAU/F"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project labels — the single resolution/validation point for the `[标签]`
|
|
3
|
+
* segment on tagged log lines (spec #34).
|
|
4
|
+
*
|
|
5
|
+
* One rule used by three consumers so they can never drift:
|
|
6
|
+
* - log rendering (withLabel on the project's logger view)
|
|
7
|
+
* - /pmctl validation (new + rename reject what the log format cannot carry)
|
|
8
|
+
* - `pi-courier logs <项目>` matching (CLI filters by the same value)
|
|
9
|
+
*
|
|
10
|
+
* Resolution: explicit name, else the workdir basename (never the raw room
|
|
11
|
+
* ID — unreadable as a tag). Validation guards the line format itself: no
|
|
12
|
+
* brackets/whitespace (the tag is delimited by them), length cap (bounded
|
|
13
|
+
* lines), and case-insensitive uniqueness (log filtering is case-insensitive,
|
|
14
|
+
* so two labels differing only in case would collide in `logs <name>`).
|
|
15
|
+
*/
|
|
16
|
+
import * as path from "node:path";
|
|
17
|
+
/** The label for a project entry: trimmed name when present, else the
|
|
18
|
+
* workdir basename (empty basename — the root "/" workdir — falls back to
|
|
19
|
+
* the workdir itself, so a label is never empty). */
|
|
20
|
+
export function projectLabelOf(entry) {
|
|
21
|
+
const name = entry.name?.trim();
|
|
22
|
+
return name || path.basename(entry.workdir) || entry.workdir;
|
|
23
|
+
}
|
|
24
|
+
const MAX_LABEL_LENGTH = 30;
|
|
25
|
+
/** Validate a user-supplied label against the format rules and the existing
|
|
26
|
+
* labels (case-insensitive uniqueness). Returns an error message (user-
|
|
27
|
+
* facing, Chinese) or null when the label is acceptable. */
|
|
28
|
+
export function validateProjectLabel(candidate, existingLabels) {
|
|
29
|
+
const name = candidate.trim();
|
|
30
|
+
if (!name)
|
|
31
|
+
return "项目名不能为空";
|
|
32
|
+
if (/[[\]]/.test(name))
|
|
33
|
+
return "项目名不能包含方括号 [ ](会破坏日志格式)";
|
|
34
|
+
if (/\s/.test(name))
|
|
35
|
+
return "项目名不能包含空白字符";
|
|
36
|
+
if (name.length > MAX_LABEL_LENGTH)
|
|
37
|
+
return `项目名最长 ${MAX_LABEL_LENGTH} 字符(当前 ${name.length})`;
|
|
38
|
+
const lower = name.toLowerCase();
|
|
39
|
+
const clash = existingLabels.find((l) => l.toLowerCase() === lower);
|
|
40
|
+
if (clash)
|
|
41
|
+
return `项目名「${name}」与现有项目「${clash}」仅大小写不同(日志过滤按名字匹配,会混淆)`;
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=project-labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-labels.js","sourceRoot":"","sources":["../src/project-labels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAOlC;;sDAEsD;AACtD,MAAM,UAAU,cAAc,CAAC,KAAkB;IAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAChC,OAAO,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC;AAC/D,CAAC;AAED,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAE5B;;6DAE6D;AAC7D,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,cAAwB;IAC9E,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,yBAAyB,CAAC;IACzD,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,aAAa,CAAC;IAC1C,IAAI,IAAI,CAAC,MAAM,GAAG,gBAAgB;QAAE,OAAO,SAAS,gBAAgB,UAAU,IAAI,CAAC,MAAM,GAAG,CAAC;IAC7F,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,CAAC;IACpE,IAAI,KAAK;QAAE,OAAO,OAAO,IAAI,UAAU,KAAK,wBAAwB,CAAC;IACrE,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-router.d.ts","sourceRoot":"","sources":["../../src/rpc/message-router.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,KAAK,aAAa,EAAgB,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,cAAc,CAAC;AAUrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,aAAa,CAAC;AAEhE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,WAAW,iBAAiB;IAChC,oFAAoF;IACpF,cAAc,EAAE,cAAc,CAAC;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,+EAA+E;IAC/E,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,mEAAmE;IACnE,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,kEAAkE;IAClE,KAAK,EAAE,WAAW,CAAC;IACnB;;+BAE2B;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,KAAK,EAAE,eAAe,CAAC;IACvB;;;iDAG6C;IAC7C,6BAA6B,CAAC,EAAE,MAAM,OAAO,CAAC;CAC/C;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD;yEACqE;IACrE,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,CAAC;CAClD;AAmBD;6EAC6E;AAC7E,wBAAgB,cAAc,CAC5B,OAAO,EAAE,gBAAgB,EACzB,aAAa,CAAC,EAAE,OAAO,GACtB;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAUhD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"message-router.d.ts","sourceRoot":"","sources":["../../src/rpc/message-router.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAE,KAAK,aAAa,EAAgB,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,cAAc,CAAC;AAUrE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,aAAa,CAAC;AAEhE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D,MAAM,WAAW,iBAAiB;IAChC,oFAAoF;IACpF,cAAc,EAAE,cAAc,CAAC;IAC/B,IAAI,EAAE,aAAa,CAAC;IACpB,+EAA+E;IAC/E,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,mEAAmE;IACnE,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,kEAAkE;IAClE,KAAK,EAAE,WAAW,CAAC;IACnB;;+BAE2B;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,KAAK,EAAE,eAAe,CAAC;IACvB;;;iDAG6C;IAC7C,6BAA6B,CAAC,EAAE,MAAM,OAAO,CAAC;CAC/C;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD;yEACqE;IACrE,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,GAAG,IAAI,CAAC;CAClD;AAmBD;6EAC6E;AAC7E,wBAAgB,cAAc,CAC5B,OAAO,EAAE,gBAAgB,EACzB,aAAa,CAAC,EAAE,OAAO,GACtB;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAUhD;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,aAAa,CAyQ1E"}
|