@vite-plugin-opencode-assistant/opencode 1.0.56 → 1.0.58
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/es/plugins/page-context.js +2 -2
- package/es/plugins/page-context.mjs +2 -2
- package/es/plugins/service-logs.d.ts +3 -0
- package/es/plugins/service-logs.js +212 -0
- package/es/plugins/service-logs.mjs +124 -0
- package/es/plugins/tool.js +9389 -0
- package/es/plugins/vite-logs.js +36 -9421
- package/es/web.mjs +21 -5
- package/lib/plugins/page-context.cjs +2 -2
- package/lib/plugins/service-logs.cjs +147 -0
- package/lib/plugins/service-logs.d.ts +3 -0
- package/lib/web.cjs +21 -5
- package/package.json +2 -2
|
@@ -24,7 +24,7 @@ const l = async () => {
|
|
|
24
24
|
|
|
25
25
|
## ⚠️ 重要:页面上下文优先级规则
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
**当用户在不同页面提问时,你必须优先根据用户当前浏览页面的上下文来理解问题,禁止依赖会话历史记录或其他上下文。**
|
|
28
28
|
|
|
29
29
|
用户可能在不同页面之间切换,每次提问都应该基于当前页面上下文:
|
|
30
30
|
|
|
@@ -37,7 +37,7 @@ const l = async () => {
|
|
|
37
37
|
1. **当前页面上下文**(最高优先级) - 根据用户当前所在页面的 URL 和标题理解问题背景
|
|
38
38
|
2. **用户选中的元素** - 如果用户选中了页面元素,这些元素信息是理解问题的关键
|
|
39
39
|
3. **用户当前输入** - 用户本次发送的具体问题内容
|
|
40
|
-
4. **会话历史**(最低优先级) -
|
|
40
|
+
4. **会话历史**(最低优先级) - 仅作为辅助参考,绝不能优先于当前页面上下文
|
|
41
41
|
|
|
42
42
|
## 你的工作环境
|
|
43
43
|
|
|
@@ -57,7 +57,7 @@ const PageContextPlugin = () => __async(null, null, function* () {
|
|
|
57
57
|
|
|
58
58
|
## \u26A0\uFE0F \u91CD\u8981\uFF1A\u9875\u9762\u4E0A\u4E0B\u6587\u4F18\u5148\u7EA7\u89C4\u5219
|
|
59
59
|
|
|
60
|
-
**\u5F53\u7528\u6237\u5728\u4E0D\u540C\u9875\u9762\u63D0\u95EE\u65F6\uFF0C\u4F60\u5FC5\u987B\u4F18\u5148\u6839\u636E\u7528\u6237\u5F53\u524D\u6D4F\u89C8\u9875\u9762\u7684\u4E0A\u4E0B\u6587\u6765\u7406\u89E3\u95EE\u9898\uFF0C\
|
|
60
|
+
**\u5F53\u7528\u6237\u5728\u4E0D\u540C\u9875\u9762\u63D0\u95EE\u65F6\uFF0C\u4F60\u5FC5\u987B\u4F18\u5148\u6839\u636E\u7528\u6237\u5F53\u524D\u6D4F\u89C8\u9875\u9762\u7684\u4E0A\u4E0B\u6587\u6765\u7406\u89E3\u95EE\u9898\uFF0C\u7981\u6B62\u4F9D\u8D56\u4F1A\u8BDD\u5386\u53F2\u8BB0\u5F55\u6216\u5176\u4ED6\u4E0A\u4E0B\u6587\u3002**
|
|
61
61
|
|
|
62
62
|
\u7528\u6237\u53EF\u80FD\u5728\u4E0D\u540C\u9875\u9762\u4E4B\u95F4\u5207\u6362\uFF0C\u6BCF\u6B21\u63D0\u95EE\u90FD\u5E94\u8BE5\u57FA\u4E8E\u5F53\u524D\u9875\u9762\u4E0A\u4E0B\u6587\uFF1A
|
|
63
63
|
|
|
@@ -70,7 +70,7 @@ const PageContextPlugin = () => __async(null, null, function* () {
|
|
|
70
70
|
1. **\u5F53\u524D\u9875\u9762\u4E0A\u4E0B\u6587**\uFF08\u6700\u9AD8\u4F18\u5148\u7EA7\uFF09 - \u6839\u636E\u7528\u6237\u5F53\u524D\u6240\u5728\u9875\u9762\u7684 URL \u548C\u6807\u9898\u7406\u89E3\u95EE\u9898\u80CC\u666F
|
|
71
71
|
2. **\u7528\u6237\u9009\u4E2D\u7684\u5143\u7D20** - \u5982\u679C\u7528\u6237\u9009\u4E2D\u4E86\u9875\u9762\u5143\u7D20\uFF0C\u8FD9\u4E9B\u5143\u7D20\u4FE1\u606F\u662F\u7406\u89E3\u95EE\u9898\u7684\u5173\u952E
|
|
72
72
|
3. **\u7528\u6237\u5F53\u524D\u8F93\u5165** - \u7528\u6237\u672C\u6B21\u53D1\u9001\u7684\u5177\u4F53\u95EE\u9898\u5185\u5BB9
|
|
73
|
-
4. **\u4F1A\u8BDD\u5386\u53F2**\uFF08\u6700\u4F4E\u4F18\u5148\u7EA7\uFF09 - \u4EC5\u4F5C\u4E3A\u8F85\u52A9\u53C2\u8003\uFF0C\u4E0D\
|
|
73
|
+
4. **\u4F1A\u8BDD\u5386\u53F2**\uFF08\u6700\u4F4E\u4F18\u5148\u7EA7\uFF09 - \u4EC5\u4F5C\u4E3A\u8F85\u52A9\u53C2\u8003\uFF0C\u7EDD\u4E0D\u80FD\u4F18\u5148\u4E8E\u5F53\u524D\u9875\u9762\u4E0A\u4E0B\u6587
|
|
74
74
|
|
|
75
75
|
## \u4F60\u7684\u5DE5\u4F5C\u73AF\u5883
|
|
76
76
|
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { t as h } from "./tool.js";
|
|
2
|
+
import { c as v } from "./logger.js";
|
|
3
|
+
const o = {};
|
|
4
|
+
var y = Object.defineProperty, E = (s, e, t) => e in s ? y(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t, n = (s, e, t) => E(s, typeof e != "symbol" ? e + "" : e, t);
|
|
5
|
+
const a = v("FileLogWatcher");
|
|
6
|
+
class F {
|
|
7
|
+
constructor(e) {
|
|
8
|
+
n(this, "buffer", []), n(this, "maxSize"), n(this, "name"), n(this, "filePath"), n(this, "lastPosition", 0), n(this, "watcher", null), n(this, "enabled", !1);
|
|
9
|
+
var t;
|
|
10
|
+
this.name = e.name, this.filePath = e.filePath, this.maxSize = (t = e.maxBufferSize) != null ? t : 200, this.enabled = !0;
|
|
11
|
+
}
|
|
12
|
+
start(e) {
|
|
13
|
+
const t = this.resolvePath(e);
|
|
14
|
+
if (!o.existsSync(t)) {
|
|
15
|
+
a.debug(`Log file does not exist: ${t}`);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const i = o.statSync(t);
|
|
19
|
+
this.lastPosition = i.size, this.watcher = o.watch(t, (r) => {
|
|
20
|
+
r === "change" && this.readNewLogs(t);
|
|
21
|
+
}), this.watcher.on("error", (r) => {
|
|
22
|
+
a.error(`Error watching file ${t}`, { error: r });
|
|
23
|
+
}), a.info(`Started watching log file: ${t}`);
|
|
24
|
+
}
|
|
25
|
+
stop() {
|
|
26
|
+
this.watcher && (this.watcher.close(), this.watcher = null, a.debug(`Stopped watching log file: ${this.filePath}`));
|
|
27
|
+
}
|
|
28
|
+
resolvePath(e) {
|
|
29
|
+
return o.isAbsolute(this.filePath) ? this.filePath : e ? o.resolve(e, this.filePath) : o.resolve(process.cwd(), this.filePath);
|
|
30
|
+
}
|
|
31
|
+
readNewLogs(e) {
|
|
32
|
+
try {
|
|
33
|
+
const t = o.statSync(e);
|
|
34
|
+
if (t.size <= this.lastPosition)
|
|
35
|
+
return;
|
|
36
|
+
const i = o.openSync(e, "r"), r = Buffer.alloc(t.size - this.lastPosition);
|
|
37
|
+
o.readSync(i, r, 0, r.length, this.lastPosition), o.closeSync(i), this.lastPosition = t.size;
|
|
38
|
+
const f = r.toString("utf-8").trim();
|
|
39
|
+
f && this.processLogContent(f);
|
|
40
|
+
} catch (t) {
|
|
41
|
+
a.error(`Error reading log file ${e}`, { error: t });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
processLogContent(e) {
|
|
45
|
+
const t = e.split(`
|
|
46
|
+
`);
|
|
47
|
+
for (const i of t)
|
|
48
|
+
i.trim() && this.addEntry({
|
|
49
|
+
level: this.detectLogLevel(i),
|
|
50
|
+
message: i,
|
|
51
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
52
|
+
source: `file:${this.name}`
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
detectLogLevel(e) {
|
|
56
|
+
const t = e.toLowerCase();
|
|
57
|
+
return t.includes("error") || t.includes("err") || t.includes("fatal") ? "error" : t.includes("warn") || t.includes("warning") ? "warn" : "info";
|
|
58
|
+
}
|
|
59
|
+
addEntry(e) {
|
|
60
|
+
this.enabled && (this.buffer.length >= this.maxSize && this.buffer.shift(), this.buffer.push(e));
|
|
61
|
+
}
|
|
62
|
+
getLogs(e = {}) {
|
|
63
|
+
let t = [...this.buffer];
|
|
64
|
+
if (e.level) {
|
|
65
|
+
const i = Array.isArray(e.level) ? e.level : [e.level];
|
|
66
|
+
t = t.filter((r) => i.includes(r.level));
|
|
67
|
+
}
|
|
68
|
+
if (e.since) {
|
|
69
|
+
const i = new Date(e.since);
|
|
70
|
+
t = t.filter((r) => new Date(r.timestamp) >= i);
|
|
71
|
+
}
|
|
72
|
+
return e.limit && e.limit > 0 && (t = t.slice(-e.limit)), t;
|
|
73
|
+
}
|
|
74
|
+
clear() {
|
|
75
|
+
this.buffer = [];
|
|
76
|
+
}
|
|
77
|
+
size() {
|
|
78
|
+
return this.buffer.length;
|
|
79
|
+
}
|
|
80
|
+
setEnabled(e) {
|
|
81
|
+
this.enabled = e;
|
|
82
|
+
}
|
|
83
|
+
isEnabled() {
|
|
84
|
+
return this.enabled;
|
|
85
|
+
}
|
|
86
|
+
getName() {
|
|
87
|
+
return this.name;
|
|
88
|
+
}
|
|
89
|
+
getFilePath() {
|
|
90
|
+
return this.filePath;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
class z {
|
|
94
|
+
constructor() {
|
|
95
|
+
n(this, "buffers", /* @__PURE__ */ new Map()), n(this, "projectRoot", null);
|
|
96
|
+
}
|
|
97
|
+
setProjectRoot(e) {
|
|
98
|
+
this.projectRoot = e;
|
|
99
|
+
}
|
|
100
|
+
addLogFile(e) {
|
|
101
|
+
var t;
|
|
102
|
+
if (this.buffers.has(e.name)) {
|
|
103
|
+
a.warn(`Log file "${e.name}" already exists, skipping`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const i = new F(e);
|
|
107
|
+
i.start((t = this.projectRoot) != null ? t : void 0), this.buffers.set(e.name, i), a.info(`Added log file watcher: ${e.name} -> ${e.filePath}`);
|
|
108
|
+
}
|
|
109
|
+
removeLogFile(e) {
|
|
110
|
+
const t = this.buffers.get(e);
|
|
111
|
+
t && (t.stop(), this.buffers.delete(e), a.info(`Removed log file watcher: ${e}`));
|
|
112
|
+
}
|
|
113
|
+
getBuffer(e) {
|
|
114
|
+
return this.buffers.get(e);
|
|
115
|
+
}
|
|
116
|
+
getAllBuffers() {
|
|
117
|
+
return this.buffers;
|
|
118
|
+
}
|
|
119
|
+
stopAll() {
|
|
120
|
+
for (const [e, t] of this.buffers)
|
|
121
|
+
t.stop(), a.debug(`Stopped log file watcher: ${e}`);
|
|
122
|
+
this.buffers.clear();
|
|
123
|
+
}
|
|
124
|
+
getLogFileNames() {
|
|
125
|
+
return Array.from(this.buffers.keys());
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
let d = null;
|
|
129
|
+
function N() {
|
|
130
|
+
return d || (d = new z()), d;
|
|
131
|
+
}
|
|
132
|
+
const l = v("ServiceLogsPlugin"), B = async () => {
|
|
133
|
+
l.debug("ServiceLogsPlugin loading...");
|
|
134
|
+
const s = process.env.OPENCODE_LOG_FILES_JSON;
|
|
135
|
+
if (l.debug("Log files JSON from env:", { logFilesJson: s ? "set" : "not set" }), !s)
|
|
136
|
+
return l.debug("OPENCODE_LOG_FILES_JSON is not set, service logs plugin will not register tools"), {};
|
|
137
|
+
let e;
|
|
138
|
+
try {
|
|
139
|
+
e = JSON.parse(s), l.debug("Parsed log files config", { count: e.length });
|
|
140
|
+
} catch (r) {
|
|
141
|
+
return l.error("Failed to parse OPENCODE_LOG_FILES_JSON", { error: r }), {};
|
|
142
|
+
}
|
|
143
|
+
if (!e || e.length === 0)
|
|
144
|
+
return l.debug("No log files configured, plugin will not register any tools"), {};
|
|
145
|
+
const t = N();
|
|
146
|
+
t.setProjectRoot(process.cwd());
|
|
147
|
+
for (const r of e)
|
|
148
|
+
t.addLogFile({
|
|
149
|
+
name: r.name,
|
|
150
|
+
filePath: r.path,
|
|
151
|
+
maxBufferSize: r.maxBufferSize,
|
|
152
|
+
watchExisting: r.watchExisting
|
|
153
|
+
}), l.debug(`Added log file watcher: ${r.name} -> ${r.path}`);
|
|
154
|
+
const i = {};
|
|
155
|
+
for (const r of e) {
|
|
156
|
+
const f = `get_${r.name}_logs`, L = `获取 ${r.name} 的日志。
|
|
157
|
+
|
|
158
|
+
**何时使用此工具**:
|
|
159
|
+
${r.description}
|
|
160
|
+
|
|
161
|
+
**日志内容**:
|
|
162
|
+
- 来自日志文件 ${r.path} 的实时日志
|
|
163
|
+
- 最多保留 ${r.maxBufferSize ?? 200} 条日志`, S = h({
|
|
164
|
+
description: L,
|
|
165
|
+
args: {
|
|
166
|
+
level: h.schema.string().optional().describe(
|
|
167
|
+
"日志级别过滤:error(错误)、warn(警告)、info(信息)。多个用逗号分隔,如 'error,warn'"
|
|
168
|
+
),
|
|
169
|
+
limit: h.schema.number().int().min(1).max(200).optional().default(50).describe("返回条数,默认 50,最大 200"),
|
|
170
|
+
since: h.schema.string().optional().describe("起始时间(ISO 格式),获取此时间之后的日志")
|
|
171
|
+
},
|
|
172
|
+
async execute(m, b) {
|
|
173
|
+
const { level: w, limit: p, since: P } = m;
|
|
174
|
+
l.debug(`${f} called`, {
|
|
175
|
+
args: m,
|
|
176
|
+
sessionID: b.sessionID,
|
|
177
|
+
directory: b.directory
|
|
178
|
+
});
|
|
179
|
+
const g = t.getBuffer(r.name);
|
|
180
|
+
if (!g)
|
|
181
|
+
return `日志文件 "${r.name}" 未找到。请检查配置。`;
|
|
182
|
+
const u = g.getLogs({
|
|
183
|
+
level: w ? w.split(",").map((c) => c.trim()) : void 0,
|
|
184
|
+
limit: p,
|
|
185
|
+
since: P
|
|
186
|
+
});
|
|
187
|
+
if (u.length === 0)
|
|
188
|
+
return `当前没有符合条件的日志(缓冲区共 ${g.size()} 条)。
|
|
189
|
+
|
|
190
|
+
建议:
|
|
191
|
+
- 不指定参数获取所有日志
|
|
192
|
+
- 使用 level=error,warn 获取错误和警告`;
|
|
193
|
+
const $ = u.map((c) => {
|
|
194
|
+
const _ = new Date(c.timestamp).toLocaleTimeString(), O = c.level === "error" ? "❌" : c.level === "warn" ? "⚠️" : "ℹ️";
|
|
195
|
+
return `${_} ${O} ${c.message}`;
|
|
196
|
+
}).join(`
|
|
197
|
+
`);
|
|
198
|
+
return `${r.name} 日志(${u.length}/${g.size()} 条):
|
|
199
|
+
|
|
200
|
+
${$}`;
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
i[f] = S, l.debug(`Registered tool: ${f}`);
|
|
204
|
+
}
|
|
205
|
+
return l.debug(`Plugin initialized with ${Object.keys(i).length} log tools`), {
|
|
206
|
+
tool: i
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
export {
|
|
210
|
+
B as ServiceLogsPlugin,
|
|
211
|
+
B as default
|
|
212
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
var __async = (__this, __arguments, generator) => {
|
|
2
|
+
return new Promise((resolve, reject) => {
|
|
3
|
+
var fulfilled = (value) => {
|
|
4
|
+
try {
|
|
5
|
+
step(generator.next(value));
|
|
6
|
+
} catch (e) {
|
|
7
|
+
reject(e);
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
var rejected = (value) => {
|
|
11
|
+
try {
|
|
12
|
+
step(generator.throw(value));
|
|
13
|
+
} catch (e) {
|
|
14
|
+
reject(e);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
18
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
import { tool } from "@opencode-ai/plugin";
|
|
22
|
+
import { createLogger, getServiceLogWatcher } from "@vite-plugin-opencode-assistant/shared";
|
|
23
|
+
const log = createLogger("ServiceLogsPlugin");
|
|
24
|
+
const ServiceLogsPlugin = () => __async(null, null, function* () {
|
|
25
|
+
var _a;
|
|
26
|
+
log.debug("ServiceLogsPlugin loading...");
|
|
27
|
+
const logFilesJson = process.env.OPENCODE_LOG_FILES_JSON;
|
|
28
|
+
log.debug("Log files JSON from env:", { logFilesJson: logFilesJson ? "set" : "not set" });
|
|
29
|
+
if (!logFilesJson) {
|
|
30
|
+
log.debug("OPENCODE_LOG_FILES_JSON is not set, service logs plugin will not register tools");
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
let logFiles;
|
|
34
|
+
try {
|
|
35
|
+
logFiles = JSON.parse(logFilesJson);
|
|
36
|
+
log.debug("Parsed log files config", { count: logFiles.length });
|
|
37
|
+
} catch (e) {
|
|
38
|
+
log.error("Failed to parse OPENCODE_LOG_FILES_JSON", { error: e });
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
if (!logFiles || logFiles.length === 0) {
|
|
42
|
+
log.debug("No log files configured, plugin will not register any tools");
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
const watcher = getServiceLogWatcher();
|
|
46
|
+
watcher.setProjectRoot(process.cwd());
|
|
47
|
+
for (const logFileConfig of logFiles) {
|
|
48
|
+
watcher.addLogFile({
|
|
49
|
+
name: logFileConfig.name,
|
|
50
|
+
filePath: logFileConfig.path,
|
|
51
|
+
maxBufferSize: logFileConfig.maxBufferSize,
|
|
52
|
+
watchExisting: logFileConfig.watchExisting
|
|
53
|
+
});
|
|
54
|
+
log.debug(`Added log file watcher: ${logFileConfig.name} -> ${logFileConfig.path}`);
|
|
55
|
+
}
|
|
56
|
+
const tools = {};
|
|
57
|
+
for (const logFileConfig of logFiles) {
|
|
58
|
+
let _b;
|
|
59
|
+
const toolName = `get_${logFileConfig.name}_logs`;
|
|
60
|
+
const description = `\u83B7\u53D6 ${logFileConfig.name} \u7684\u65E5\u5FD7\u3002
|
|
61
|
+
|
|
62
|
+
**\u4F55\u65F6\u4F7F\u7528\u6B64\u5DE5\u5177**\uFF1A
|
|
63
|
+
${logFileConfig.description}
|
|
64
|
+
|
|
65
|
+
**\u65E5\u5FD7\u5185\u5BB9**\uFF1A
|
|
66
|
+
- \u6765\u81EA\u65E5\u5FD7\u6587\u4EF6 ${logFileConfig.path} \u7684\u5B9E\u65F6\u65E5\u5FD7
|
|
67
|
+
- \u6700\u591A\u4FDD\u7559 ${(_a = logFileConfig.maxBufferSize) != null ? _a : 200} \u6761\u65E5\u5FD7`;
|
|
68
|
+
const getLogsTool = tool({
|
|
69
|
+
description,
|
|
70
|
+
args: {
|
|
71
|
+
level: tool.schema.string().optional().describe(
|
|
72
|
+
"\u65E5\u5FD7\u7EA7\u522B\u8FC7\u6EE4\uFF1Aerror(\u9519\u8BEF)\u3001warn(\u8B66\u544A)\u3001info(\u4FE1\u606F)\u3002\u591A\u4E2A\u7528\u9017\u53F7\u5206\u9694\uFF0C\u5982 'error,warn'"
|
|
73
|
+
),
|
|
74
|
+
limit: tool.schema.number().int().min(1).max(200).optional().default(50).describe("\u8FD4\u56DE\u6761\u6570\uFF0C\u9ED8\u8BA4 50\uFF0C\u6700\u5927 200"),
|
|
75
|
+
since: tool.schema.string().optional().describe("\u8D77\u59CB\u65F6\u95F4\uFF08ISO \u683C\u5F0F\uFF09\uFF0C\u83B7\u53D6\u6B64\u65F6\u95F4\u4E4B\u540E\u7684\u65E5\u5FD7")
|
|
76
|
+
},
|
|
77
|
+
execute(args, context) {
|
|
78
|
+
return __async(this, null, function* () {
|
|
79
|
+
const { level, limit, since } = args;
|
|
80
|
+
log.debug(`${toolName} called`, {
|
|
81
|
+
args,
|
|
82
|
+
sessionID: context.sessionID,
|
|
83
|
+
directory: context.directory
|
|
84
|
+
});
|
|
85
|
+
const buffer = watcher.getBuffer(logFileConfig.name);
|
|
86
|
+
if (!buffer) {
|
|
87
|
+
return `\u65E5\u5FD7\u6587\u4EF6 "${logFileConfig.name}" \u672A\u627E\u5230\u3002\u8BF7\u68C0\u67E5\u914D\u7F6E\u3002`;
|
|
88
|
+
}
|
|
89
|
+
const logs = buffer.getLogs({
|
|
90
|
+
level: level ? level.split(",").map((l) => l.trim()) : void 0,
|
|
91
|
+
limit,
|
|
92
|
+
since
|
|
93
|
+
});
|
|
94
|
+
if (logs.length === 0) {
|
|
95
|
+
return `\u5F53\u524D\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u65E5\u5FD7\uFF08\u7F13\u51B2\u533A\u5171 ${buffer.size()} \u6761\uFF09\u3002
|
|
96
|
+
|
|
97
|
+
\u5EFA\u8BAE\uFF1A
|
|
98
|
+
- \u4E0D\u6307\u5B9A\u53C2\u6570\u83B7\u53D6\u6240\u6709\u65E5\u5FD7
|
|
99
|
+
- \u4F7F\u7528 level=error,warn \u83B7\u53D6\u9519\u8BEF\u548C\u8B66\u544A`;
|
|
100
|
+
}
|
|
101
|
+
const formattedLogs = logs.map((entry) => {
|
|
102
|
+
const time = new Date(entry.timestamp).toLocaleTimeString();
|
|
103
|
+
const levelIcon = entry.level === "error" ? "\u274C" : entry.level === "warn" ? "\u26A0\uFE0F" : "\u2139\uFE0F";
|
|
104
|
+
return `${time} ${levelIcon} ${entry.message}`;
|
|
105
|
+
}).join("\n");
|
|
106
|
+
return `${logFileConfig.name} \u65E5\u5FD7\uFF08${logs.length}/${buffer.size()} \u6761\uFF09\uFF1A
|
|
107
|
+
|
|
108
|
+
${formattedLogs}`;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
tools[toolName] = getLogsTool;
|
|
113
|
+
log.debug(`Registered tool: ${toolName}`);
|
|
114
|
+
}
|
|
115
|
+
log.debug(`Plugin initialized with ${Object.keys(tools).length} log tools`);
|
|
116
|
+
return {
|
|
117
|
+
tool: tools
|
|
118
|
+
};
|
|
119
|
+
});
|
|
120
|
+
var service_logs_default = ServiceLogsPlugin;
|
|
121
|
+
export {
|
|
122
|
+
ServiceLogsPlugin,
|
|
123
|
+
service_logs_default as default
|
|
124
|
+
};
|