@vite-plugin-opencode-assistant/opencode 1.0.59 → 1.0.60

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.
@@ -2,191 +2,134 @@ import { tool } from "@opencode-ai/plugin";
2
2
  import fs from "fs";
3
3
  import path from "path";
4
4
  import { c as createLogger } from "./logger.js";
5
- var __defProp = Object.defineProperty;
6
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
8
- const log$1 = createLogger("FileLogWatcher");
9
- class FileLogBuffer {
10
- constructor(options) {
11
- __publicField(this, "buffer", []);
12
- __publicField(this, "maxSize");
13
- __publicField(this, "name");
14
- __publicField(this, "filePath");
15
- __publicField(this, "lastPosition", 0);
16
- __publicField(this, "watcher", null);
17
- __publicField(this, "enabled", false);
18
- var _a;
19
- this.name = options.name;
20
- this.filePath = options.filePath;
21
- this.maxSize = (_a = options.maxBufferSize) != null ? _a : 200;
22
- this.enabled = true;
23
- }
24
- start(projectRoot) {
25
- const resolvedPath = this.resolvePath(projectRoot);
26
- if (!fs.existsSync(resolvedPath)) {
27
- log$1.debug(`Log file does not exist: ${resolvedPath}`);
28
- return;
29
- }
30
- const stat = fs.statSync(resolvedPath);
31
- this.lastPosition = stat.size;
32
- this.watcher = fs.watch(resolvedPath, (eventType) => {
33
- if (eventType === "change") {
34
- this.readNewLogs(resolvedPath);
5
+ var __async = (__this, __arguments, generator) => {
6
+ return new Promise((resolve, reject) => {
7
+ var fulfilled = (value) => {
8
+ try {
9
+ step(generator.next(value));
10
+ } catch (e) {
11
+ reject(e);
35
12
  }
36
- });
37
- this.watcher.on("error", (err) => {
38
- log$1.error(`Error watching file ${resolvedPath}`, { error: err });
39
- });
40
- log$1.info(`Started watching log file: ${resolvedPath}`);
13
+ };
14
+ var rejected = (value) => {
15
+ try {
16
+ step(generator.throw(value));
17
+ } catch (e) {
18
+ reject(e);
19
+ }
20
+ };
21
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
22
+ step((generator = generator.apply(__this, __arguments)).next());
23
+ });
24
+ };
25
+ const log$1 = createLogger("FileLogReader");
26
+ function detectLogLevel(line) {
27
+ const lowerLine = line.toLowerCase();
28
+ if (lowerLine.includes("error") || lowerLine.includes("err") || lowerLine.includes("fatal")) {
29
+ return "error";
41
30
  }
42
- stop() {
43
- if (this.watcher) {
44
- this.watcher.close();
45
- this.watcher = null;
46
- log$1.debug(`Stopped watching log file: ${this.filePath}`);
47
- }
31
+ if (lowerLine.includes("warn") || lowerLine.includes("warning")) {
32
+ return "warn";
48
33
  }
49
- resolvePath(projectRoot) {
50
- if (path.isAbsolute(this.filePath)) {
51
- return this.filePath;
52
- }
53
- if (projectRoot) {
54
- return path.resolve(projectRoot, this.filePath);
34
+ return "info";
35
+ }
36
+ function parseLogTimestamp(line) {
37
+ const timestampPatterns = [
38
+ /(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z?)/,
39
+ /(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/,
40
+ /(\[([^\]]+)\])/
41
+ ];
42
+ for (const pattern of timestampPatterns) {
43
+ const match = line.match(pattern);
44
+ if (match) {
45
+ const timestampStr = match[1];
46
+ const date = new Date(timestampStr);
47
+ if (!isNaN(date.getTime())) {
48
+ return date.toISOString();
49
+ }
55
50
  }
56
- return path.resolve(process.cwd(), this.filePath);
57
51
  }
58
- readNewLogs(filePath) {
52
+ return null;
53
+ }
54
+ function readLogFileTail(options) {
55
+ return __async(this, null, function* () {
56
+ const { name, filePath, projectRoot, lines = 200, limit, level, since } = options;
57
+ const resolvedPath = resolvePath(filePath, projectRoot);
58
+ if (!fs.existsSync(resolvedPath)) {
59
+ log$1.debug(`Log file does not exist: ${resolvedPath}`);
60
+ return [];
61
+ }
59
62
  try {
60
- const stat = fs.statSync(filePath);
61
- if (stat.size <= this.lastPosition) {
62
- return;
63
+ const stat = fs.statSync(resolvedPath);
64
+ const fd = fs.openSync(resolvedPath, "r");
65
+ const chunkSize = 16 * 1024;
66
+ let position = stat.size;
67
+ let buffer = Buffer.alloc(0);
68
+ const lineCount = 0;
69
+ while (position > 0 && lineCount <= lines) {
70
+ const readSize = Math.min(chunkSize, position);
71
+ position -= readSize;
72
+ const chunk = Buffer.alloc(readSize);
73
+ fs.readSync(fd, chunk, 0, readSize, position);
74
+ buffer = Buffer.concat([chunk, buffer]);
75
+ const newLineCount = buffer.filter((byte) => byte === 10).length;
76
+ if (newLineCount >= lines) {
77
+ const linesArray = buffer.toString("utf-8").split("\n");
78
+ const excessLines = newLineCount - lines;
79
+ let charsToRemove = 0;
80
+ let count = 0;
81
+ for (let i = 0; i < linesArray.length; i++) {
82
+ count += linesArray[i].length + 1;
83
+ if (count > excessLines) {
84
+ charsToRemove = linesArray.slice(0, i + 1).join("\n").length + 1;
85
+ break;
86
+ }
87
+ }
88
+ buffer = buffer.slice(charsToRemove);
89
+ break;
90
+ }
63
91
  }
64
- const fd = fs.openSync(filePath, "r");
65
- const buffer = Buffer.alloc(stat.size - this.lastPosition);
66
- fs.readSync(fd, buffer, 0, buffer.length, this.lastPosition);
67
92
  fs.closeSync(fd);
68
- this.lastPosition = stat.size;
69
93
  const content = buffer.toString("utf-8").trim();
70
- if (content) {
71
- this.processLogContent(content);
94
+ const logLines = content.split("\n").filter((line) => line.trim());
95
+ const entries = [];
96
+ const sinceDate = since ? new Date(since) : null;
97
+ for (const line of logLines) {
98
+ const entry = {
99
+ level: detectLogLevel(line),
100
+ message: line,
101
+ timestamp: parseLogTimestamp(line) || (/* @__PURE__ */ new Date()).toISOString(),
102
+ source: `file:${name}`
103
+ };
104
+ if (sinceDate && new Date(entry.timestamp) < sinceDate) {
105
+ continue;
106
+ }
107
+ if (level) {
108
+ const levels = Array.isArray(level) ? level : [level];
109
+ if (!levels.includes(entry.level)) {
110
+ continue;
111
+ }
112
+ }
113
+ entries.push(entry);
114
+ }
115
+ if (limit && limit > 0) {
116
+ return entries.slice(-limit);
72
117
  }
118
+ return entries;
73
119
  } catch (err) {
74
- log$1.error(`Error reading log file ${filePath}`, { error: err });
75
- }
76
- }
77
- processLogContent(content) {
78
- const lines = content.split("\n");
79
- for (const line of lines) {
80
- if (!line.trim()) continue;
81
- this.addEntry({
82
- level: this.detectLogLevel(line),
83
- message: line,
84
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
85
- source: `file:${this.name}`
86
- });
87
- }
88
- }
89
- detectLogLevel(line) {
90
- const lowerLine = line.toLowerCase();
91
- if (lowerLine.includes("error") || lowerLine.includes("err") || lowerLine.includes("fatal")) {
92
- return "error";
93
- }
94
- if (lowerLine.includes("warn") || lowerLine.includes("warning")) {
95
- return "warn";
96
- }
97
- return "info";
98
- }
99
- addEntry(entry) {
100
- if (!this.enabled) return;
101
- if (this.buffer.length >= this.maxSize) {
102
- this.buffer.shift();
120
+ log$1.error(`Error reading log file ${resolvedPath}`, { error: err });
121
+ return [];
103
122
  }
104
- this.buffer.push(entry);
105
- }
106
- getLogs(options = {}) {
107
- let logs = [...this.buffer];
108
- if (options.level) {
109
- const levels = Array.isArray(options.level) ? options.level : [options.level];
110
- logs = logs.filter((log2) => levels.includes(log2.level));
111
- }
112
- if (options.since) {
113
- const sinceDate = new Date(options.since);
114
- logs = logs.filter((log2) => new Date(log2.timestamp) >= sinceDate);
115
- }
116
- if (options.limit && options.limit > 0) {
117
- logs = logs.slice(-options.limit);
118
- }
119
- return logs;
120
- }
121
- clear() {
122
- this.buffer = [];
123
- }
124
- size() {
125
- return this.buffer.length;
126
- }
127
- setEnabled(enabled) {
128
- this.enabled = enabled;
129
- }
130
- isEnabled() {
131
- return this.enabled;
132
- }
133
- getName() {
134
- return this.name;
135
- }
136
- getFilePath() {
137
- return this.filePath;
138
- }
123
+ });
139
124
  }
140
- class ServiceLogWatcher {
141
- constructor() {
142
- __publicField(this, "buffers", /* @__PURE__ */ new Map());
143
- __publicField(this, "projectRoot", null);
144
- }
145
- setProjectRoot(root) {
146
- this.projectRoot = root;
147
- }
148
- addLogFile(options) {
149
- var _a;
150
- if (this.buffers.has(options.name)) {
151
- log$1.warn(`Log file "${options.name}" already exists, skipping`);
152
- return;
153
- }
154
- const buffer = new FileLogBuffer(options);
155
- buffer.start((_a = this.projectRoot) != null ? _a : void 0);
156
- this.buffers.set(options.name, buffer);
157
- log$1.info(`Added log file watcher: ${options.name} -> ${options.filePath}`);
158
- }
159
- removeLogFile(name) {
160
- const buffer = this.buffers.get(name);
161
- if (buffer) {
162
- buffer.stop();
163
- this.buffers.delete(name);
164
- log$1.info(`Removed log file watcher: ${name}`);
165
- }
166
- }
167
- getBuffer(name) {
168
- return this.buffers.get(name);
169
- }
170
- getAllBuffers() {
171
- return this.buffers;
172
- }
173
- stopAll() {
174
- for (const [name, buffer] of this.buffers) {
175
- buffer.stop();
176
- log$1.debug(`Stopped log file watcher: ${name}`);
177
- }
178
- this.buffers.clear();
125
+ function resolvePath(filePath, projectRoot) {
126
+ if (path.isAbsolute(filePath)) {
127
+ return filePath;
179
128
  }
180
- getLogFileNames() {
181
- return Array.from(this.buffers.keys());
129
+ if (projectRoot) {
130
+ return path.resolve(projectRoot, filePath);
182
131
  }
183
- }
184
- let globalWatcher = null;
185
- function getServiceLogWatcher() {
186
- if (!globalWatcher) {
187
- globalWatcher = new ServiceLogWatcher();
188
- }
189
- return globalWatcher;
132
+ return path.resolve(process.cwd(), filePath);
190
133
  }
191
134
  const log = createLogger("ServiceLogsPlugin");
192
135
  const ServiceLogsPlugin = async () => {
@@ -209,17 +152,6 @@ const ServiceLogsPlugin = async () => {
209
152
  log.debug("No log files configured, plugin will not register any tools");
210
153
  return {};
211
154
  }
212
- const watcher = getServiceLogWatcher();
213
- watcher.setProjectRoot(process.cwd());
214
- for (const logFileConfig of logFiles) {
215
- watcher.addLogFile({
216
- name: logFileConfig.name,
217
- filePath: logFileConfig.path,
218
- maxBufferSize: logFileConfig.maxBufferSize,
219
- watchExisting: logFileConfig.watchExisting
220
- });
221
- log.debug(`Added log file watcher: ${logFileConfig.name} -> ${logFileConfig.path}`);
222
- }
223
155
  const tools = {};
224
156
  for (const logFileConfig of logFiles) {
225
157
  const toolName = `get_${logFileConfig.name}_logs`;
@@ -230,7 +162,7 @@ ${logFileConfig.description}
230
162
 
231
163
  **日志内容**:
232
164
  - 来自日志文件 ${logFileConfig.path} 的实时日志
233
- - 最多保留 ${logFileConfig.maxBufferSize ?? 200} 条日志`;
165
+ - 默认返回最近 200 行日志`;
234
166
  const getLogsTool = tool({
235
167
  description,
236
168
  args: {
@@ -247,28 +179,28 @@ ${logFileConfig.description}
247
179
  sessionID: context.sessionID,
248
180
  directory: context.directory
249
181
  });
250
- const buffer = watcher.getBuffer(logFileConfig.name);
251
- if (!buffer) {
252
- return `日志文件 "${logFileConfig.name}" 未找到。请检查配置。`;
253
- }
254
- const logs = buffer.getLogs({
182
+ const entries = await readLogFileTail({
183
+ name: logFileConfig.name,
184
+ filePath: logFileConfig.path,
185
+ projectRoot: process.cwd(),
186
+ lines: limit ? Math.max(limit, 200) : 200,
255
187
  level: level ? level.split(",").map((l) => l.trim()) : void 0,
256
- limit,
257
188
  since
258
189
  });
259
- if (logs.length === 0) {
260
- return `当前没有符合条件的日志(缓冲区共 ${buffer.size()} 条)。
190
+ const filteredEntries = entries.slice(0, limit ?? 50);
191
+ if (filteredEntries.length === 0) {
192
+ return `当前没有符合条件的日志。
261
193
 
262
194
  建议:
263
195
  - 不指定参数获取所有日志
264
196
  - 使用 level=error,warn 获取错误和警告`;
265
197
  }
266
- const formattedLogs = logs.map((entry) => {
198
+ const formattedLogs = filteredEntries.map((entry) => {
267
199
  const time = new Date(entry.timestamp).toLocaleTimeString();
268
200
  const levelIcon = entry.level === "error" ? "❌" : entry.level === "warn" ? "⚠️" : "ℹ️";
269
201
  return `${time} ${levelIcon} ${entry.message}`;
270
202
  }).join("\n");
271
- return `${logFileConfig.name} 日志(${logs.length}/${buffer.size()} 条):
203
+ return `${logFileConfig.name} 日志(${filteredEntries.length} 条):
272
204
 
273
205
  ${formattedLogs}`;
274
206
  }
@@ -19,10 +19,9 @@ var __async = (__this, __arguments, generator) => {
19
19
  });
20
20
  };
21
21
  import { tool } from "@opencode-ai/plugin";
22
- import { createLogger, getServiceLogWatcher } from "@vite-plugin-opencode-assistant/shared";
22
+ import { readLogFileTail, createLogger } from "@vite-plugin-opencode-assistant/shared";
23
23
  const log = createLogger("ServiceLogsPlugin");
24
24
  const ServiceLogsPlugin = () => __async(null, null, function* () {
25
- var _a;
26
25
  log.debug("ServiceLogsPlugin loading...");
27
26
  const logFilesJson = process.env.OPENCODE_LOG_FILES_JSON;
28
27
  log.debug("Log files JSON from env:", { logFilesJson: logFilesJson ? "set" : "not set" });
@@ -42,20 +41,9 @@ const ServiceLogsPlugin = () => __async(null, null, function* () {
42
41
  log.debug("No log files configured, plugin will not register any tools");
43
42
  return {};
44
43
  }
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
44
  const tools = {};
57
45
  for (const logFileConfig of logFiles) {
58
- let _b;
46
+ let _a;
59
47
  const toolName = `get_${logFileConfig.name}_logs`;
60
48
  const description = `\u83B7\u53D6 ${logFileConfig.name} \u7684\u65E5\u5FD7\u3002
61
49
 
@@ -64,7 +52,7 @@ ${logFileConfig.description}
64
52
 
65
53
  **\u65E5\u5FD7\u5185\u5BB9**\uFF1A
66
54
  - \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`;
55
+ - \u9ED8\u8BA4\u8FD4\u56DE\u6700\u8FD1 200 \u884C\u65E5\u5FD7`;
68
56
  const getLogsTool = tool({
69
57
  description,
70
58
  args: {
@@ -82,28 +70,28 @@ ${logFileConfig.description}
82
70
  sessionID: context.sessionID,
83
71
  directory: context.directory
84
72
  });
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({
73
+ const entries = yield readLogFileTail({
74
+ name: logFileConfig.name,
75
+ filePath: logFileConfig.path,
76
+ projectRoot: process.cwd(),
77
+ lines: limit ? Math.max(limit, 200) : 200,
90
78
  level: level ? level.split(",").map((l) => l.trim()) : void 0,
91
- limit,
92
79
  since
93
80
  });
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
81
+ const filteredEntries = entries.slice(0, limit != null ? limit : 50);
82
+ if (filteredEntries.length === 0) {
83
+ return `\u5F53\u524D\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u65E5\u5FD7\u3002
96
84
 
97
85
  \u5EFA\u8BAE\uFF1A
98
86
  - \u4E0D\u6307\u5B9A\u53C2\u6570\u83B7\u53D6\u6240\u6709\u65E5\u5FD7
99
87
  - \u4F7F\u7528 level=error,warn \u83B7\u53D6\u9519\u8BEF\u548C\u8B66\u544A`;
100
88
  }
101
- const formattedLogs = logs.map((entry) => {
89
+ const formattedLogs = filteredEntries.map((entry) => {
102
90
  const time = new Date(entry.timestamp).toLocaleTimeString();
103
91
  const levelIcon = entry.level === "error" ? "\u274C" : entry.level === "warn" ? "\u26A0\uFE0F" : "\u2139\uFE0F";
104
92
  return `${time} ${levelIcon} ${entry.message}`;
105
93
  }).join("\n");
106
- return `${logFileConfig.name} \u65E5\u5FD7\uFF08${logs.length}/${buffer.size()} \u6761\uFF09\uFF1A
94
+ return `${logFileConfig.name} \u65E5\u5FD7\uFF08${filteredEntries.length} \u6761\uFF09\uFF1A
107
95
 
108
96
  ${formattedLogs}`;
109
97
  });
@@ -45,7 +45,6 @@ var import_plugin = require("@opencode-ai/plugin");
45
45
  var import_shared = require("@vite-plugin-opencode-assistant/shared");
46
46
  const log = (0, import_shared.createLogger)("ServiceLogsPlugin");
47
47
  const ServiceLogsPlugin = () => __async(null, null, function* () {
48
- var _a;
49
48
  log.debug("ServiceLogsPlugin loading...");
50
49
  const logFilesJson = process.env.OPENCODE_LOG_FILES_JSON;
51
50
  log.debug("Log files JSON from env:", { logFilesJson: logFilesJson ? "set" : "not set" });
@@ -65,20 +64,9 @@ const ServiceLogsPlugin = () => __async(null, null, function* () {
65
64
  log.debug("No log files configured, plugin will not register any tools");
66
65
  return {};
67
66
  }
68
- const watcher = (0, import_shared.getServiceLogWatcher)();
69
- watcher.setProjectRoot(process.cwd());
70
- for (const logFileConfig of logFiles) {
71
- watcher.addLogFile({
72
- name: logFileConfig.name,
73
- filePath: logFileConfig.path,
74
- maxBufferSize: logFileConfig.maxBufferSize,
75
- watchExisting: logFileConfig.watchExisting
76
- });
77
- log.debug(`Added log file watcher: ${logFileConfig.name} -> ${logFileConfig.path}`);
78
- }
79
67
  const tools = {};
80
68
  for (const logFileConfig of logFiles) {
81
- let _b;
69
+ let _a;
82
70
  const toolName = `get_${logFileConfig.name}_logs`;
83
71
  const description = `\u83B7\u53D6 ${logFileConfig.name} \u7684\u65E5\u5FD7\u3002
84
72
 
@@ -87,7 +75,7 @@ ${logFileConfig.description}
87
75
 
88
76
  **\u65E5\u5FD7\u5185\u5BB9**\uFF1A
89
77
  - \u6765\u81EA\u65E5\u5FD7\u6587\u4EF6 ${logFileConfig.path} \u7684\u5B9E\u65F6\u65E5\u5FD7
90
- - \u6700\u591A\u4FDD\u7559 ${(_a = logFileConfig.maxBufferSize) != null ? _a : 200} \u6761\u65E5\u5FD7`;
78
+ - \u9ED8\u8BA4\u8FD4\u56DE\u6700\u8FD1 200 \u884C\u65E5\u5FD7`;
91
79
  const getLogsTool = (0, import_plugin.tool)({
92
80
  description,
93
81
  args: {
@@ -105,28 +93,28 @@ ${logFileConfig.description}
105
93
  sessionID: context.sessionID,
106
94
  directory: context.directory
107
95
  });
108
- const buffer = watcher.getBuffer(logFileConfig.name);
109
- if (!buffer) {
110
- return `\u65E5\u5FD7\u6587\u4EF6 "${logFileConfig.name}" \u672A\u627E\u5230\u3002\u8BF7\u68C0\u67E5\u914D\u7F6E\u3002`;
111
- }
112
- const logs = buffer.getLogs({
96
+ const entries = yield (0, import_shared.readLogFileTail)({
97
+ name: logFileConfig.name,
98
+ filePath: logFileConfig.path,
99
+ projectRoot: process.cwd(),
100
+ lines: limit ? Math.max(limit, 200) : 200,
113
101
  level: level ? level.split(",").map((l) => l.trim()) : void 0,
114
- limit,
115
102
  since
116
103
  });
117
- if (logs.length === 0) {
118
- return `\u5F53\u524D\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u65E5\u5FD7\uFF08\u7F13\u51B2\u533A\u5171 ${buffer.size()} \u6761\uFF09\u3002
104
+ const filteredEntries = entries.slice(0, limit != null ? limit : 50);
105
+ if (filteredEntries.length === 0) {
106
+ return `\u5F53\u524D\u6CA1\u6709\u7B26\u5408\u6761\u4EF6\u7684\u65E5\u5FD7\u3002
119
107
 
120
108
  \u5EFA\u8BAE\uFF1A
121
109
  - \u4E0D\u6307\u5B9A\u53C2\u6570\u83B7\u53D6\u6240\u6709\u65E5\u5FD7
122
110
  - \u4F7F\u7528 level=error,warn \u83B7\u53D6\u9519\u8BEF\u548C\u8B66\u544A`;
123
111
  }
124
- const formattedLogs = logs.map((entry) => {
112
+ const formattedLogs = filteredEntries.map((entry) => {
125
113
  const time = new Date(entry.timestamp).toLocaleTimeString();
126
114
  const levelIcon = entry.level === "error" ? "\u274C" : entry.level === "warn" ? "\u26A0\uFE0F" : "\u2139\uFE0F";
127
115
  return `${time} ${levelIcon} ${entry.message}`;
128
116
  }).join("\n");
129
- return `${logFileConfig.name} \u65E5\u5FD7\uFF08${logs.length}/${buffer.size()} \u6761\uFF09\uFF1A
117
+ return `${logFileConfig.name} \u65E5\u5FD7\uFF08${filteredEntries.length} \u6761\uFF09\uFF1A
130
118
 
131
119
  ${formattedLogs}`;
132
120
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vite-plugin-opencode-assistant/opencode",
3
- "version": "1.0.59",
3
+ "version": "1.0.60",
4
4
  "type": "module",
5
5
  "main": "lib/index.cjs",
6
6
  "module": "es/index.mjs",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "execa": "^9.6.1",
25
- "@vite-plugin-opencode-assistant/shared": "1.0.59"
25
+ "@vite-plugin-opencode-assistant/shared": "1.0.60"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@opencode-ai/plugin": "^1.3.15",