Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

**English** · [简体中文](./README.zh-CN.md)

[![Version](https://img.shields.io/badge/version-v0.0.24-8b5cf6)](https://github.com/ackness/covel/releases/tag/v0.0.24)
[![Version](https://img.shields.io/badge/version-v0.0.25-8b5cf6)](https://github.com/ackness/covel/releases/tag/v0.0.25)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
[![Stage](https://img.shields.io/badge/stage-early--access-orange)](<>)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ackness/covel)
Expand All @@ -13,7 +13,7 @@

Covel is an AI RPG where the world keeps running between your turns: NPCs track how they feel about you, lore accumulates as you play, and memory carries the thread across the session. Every mechanic behind that is an **autonomous agent shipped as a plugin** — disable one, swap one, or write your own.

> **Current public release: v0.0.24**, early access — APIs, data formats, and plugin frontmatter may change between versions. Prebuilt binaries target macOS Apple Silicon and Windows x64; other platforms build from source.
> **Current public release: v0.0.25**, early access — APIs, data formats, and plugin frontmatter may change between versions. Prebuilt binaries target macOS Apple Silicon and Windows x64; other platforms build from source.

## Highlights

Expand Down
4 changes: 2 additions & 2 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

[English](./README.md) · **简体中文**

[![Version](https://img.shields.io/badge/version-v0.0.24-8b5cf6)](https://github.com/ackness/covel/releases/tag/v0.0.24)
[![Version](https://img.shields.io/badge/version-v0.0.25-8b5cf6)](https://github.com/ackness/covel/releases/tag/v0.0.25)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
[![Stage](https://img.shields.io/badge/stage-early--access-orange)](<>)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ackness/covel)
Expand All @@ -13,7 +13,7 @@

Covel 是一款 AI 驱动的 RPG,回合之间世界仍在运转:NPC 记录着对你的态度、世界典籍随游玩积累、记忆贯穿整局。支撑这一切的每个机制都是一个**以插件形式分发的自主 agent** —— 禁用一个、替换一个,或者自己写一个。

> **当前公开版本:v0.0.24**,早期阶段 —— API、数据格式、插件 frontmatter 可能随版本变化。官方预编译包面向 macOS Apple Silicon 与 Windows x64,其余平台从源码构建。
> **当前公开版本:v0.0.25**,早期阶段 —— API、数据格式、插件 frontmatter 可能随版本变化。官方预编译包面向 macOS Apple Silicon 与 Windows x64,其余平台从源码构建。

## 亮点

Expand Down
4 changes: 2 additions & 2 deletions apps/desktop/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@covel/desktop",
"version": "0.0.24",
"version": "0.0.25",
"private": true,
"type": "module",
"main": "dist/main.mjs",
Expand All @@ -12,7 +12,7 @@
"dev": "node scripts/dev.mjs",
"build": "node scripts/build.mjs",
"lint": "tsc --noEmit",
"test": "tsx src/zip-extract.selfcheck.ts && tsx src/trusted-origin.selfcheck.ts",
"test": "tsx src/zip-extract.selfcheck.ts && tsx src/trusted-origin.selfcheck.ts && tsx src/logging.selfcheck.ts",
"pack": "pnpm build && electron-builder --dir",
"dist": "pnpm build && electron-builder",
"dist:mac": "pnpm build && electron-builder --mac",
Expand Down
25 changes: 25 additions & 0 deletions apps/desktop/src/logging.selfcheck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import assert from "node:assert/strict";
import { classifyServerStreamLine } from "./logging.js";

assert.deepEqual(
classifyServerStreamLine(
"stderr",
"[covel:warn] [turn-executor] same-layer effects hazard (policy: warn)",
),
{
level: "warn",
source: "server.err",
message: "[turn-executor] same-layer effects hazard (policy: warn)",
},
);

assert.equal(
classifyServerStreamLine("stderr", "fatal sidecar failure").level,
"error",
);
assert.equal(
classifyServerStreamLine("stdout", "server started").level,
"info",
);

console.log("logging self-check passed");
35 changes: 32 additions & 3 deletions apps/desktop/src/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import path from "node:path";

export type LogLevel = "info" | "warn" | "error";

// stderr does not carry console.warn/console.error metadata. Server code uses
// this prefix for recoverable warnings so both desktop and standalone log
// collectors can preserve the intended level.
const SERVER_WARNING_PREFIX = "[covel:warn]";

export interface LogRotation {
readonly maxSizeMb: number;
readonly maxFiles: number;
Expand Down Expand Up @@ -141,7 +146,31 @@ export function writeServerStreamLine(
line: string,
): void {
if (!line || !line.trim()) return;
const level: LogLevel = origin === "stderr" ? "error" : "info";
const source = origin === "stderr" ? "server.err" : "server";
writeChannel(serverChannel, ndjsonLine(level, source, line));
const classified = classifyServerStreamLine(origin, line);
writeChannel(
serverChannel,
ndjsonLine(classified.level, classified.source, classified.message),
);
}

export function classifyServerStreamLine(
origin: "stdout" | "stderr",
line: string,
): {
readonly level: LogLevel;
readonly source: "server" | "server.err";
readonly message: string;
} {
if (origin === "stdout") {
return { level: "info", source: "server", message: line };
}
const trimmed = line.trimStart();
if (trimmed.startsWith(SERVER_WARNING_PREFIX)) {
return {
level: "warn",
source: "server.err",
message: trimmed.slice(SERVER_WARNING_PREFIX.length).trimStart(),
};
}
return { level: "error", source: "server.err", message: line };
}
2 changes: 1 addition & 1 deletion apps/server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@covel/server",
"version": "0.0.24",
"version": "0.0.25",
"private": true,
"type": "module",
"files": [
Expand Down
Loading