feat: 模块统一 ias- 前缀、独立版本与内网地址支持 (0.1.7)

- 所有 Rust crate 统一加 ias- 前缀:ai → ias-ai、common → ias-common、context → ias-context、mail → ias-mail、service → ias-service、wechat → ias-wechat
- 新增 ias-main 模块承载 CLI 入口和二进制打包
- 各模块开始独立维护版本号,ias-main 0.1.7 代表整体版本
- 新增 IA_WEB_INTERNAL_URL 环境变量,版本通知同时发送公网和内网链接
- 将已有升级日志翻译为中文
- ias_upgrade_logs 新增 modules JSONB 字段
- 新增 VERSION 文件和 CHANGELOG.md
- 新增 AGENTS.md 项目规则文件
This commit is contained in:
2026-07-06 17:57:48 +08:00
parent ed7f89d44f
commit 25dd0daa8b
91 changed files with 5546 additions and 777 deletions
@@ -0,0 +1,12 @@
-- Add migration script here
CREATE TABLE ias_wechat_accounts (
id BIGSERIAL PRIMARY KEY,
user_name VARCHAR(100) NOT NULL,
token VARCHAR(255),
account_id VARCHAR(255),
base_url VARCHAR(255),
user_id VARCHAR(255),
updates_buf VARCHAR(255),
user_status INTEGER,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
@@ -0,0 +1,13 @@
CREATE TABLE ias_web_pages (
id BIGSERIAL PRIMARY KEY,
slug VARCHAR(64) NOT NULL UNIQUE,
page_type VARCHAR(64) NOT NULL,
title VARCHAR(255) NOT NULL,
summary TEXT,
content TEXT NOT NULL,
source_label VARCHAR(255),
metadata TEXT NOT NULL DEFAULT '{}',
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_ias_web_pages_type_slug ON ias_web_pages(page_type, slug);
@@ -0,0 +1,66 @@
CREATE TABLE ias_long_term_memories (
id BIGSERIAL PRIMARY KEY,
scope_key VARCHAR(768) NOT NULL,
channel VARCHAR(64) NOT NULL,
account_id VARCHAR(255) NOT NULL,
from_user_id VARCHAR(255) NOT NULL,
context_label TEXT,
content TEXT NOT NULL,
metadata TEXT NOT NULL DEFAULT '{}',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMP
);
CREATE INDEX idx_ias_long_term_memories_scope_updated
ON ias_long_term_memories(scope_key, updated_at DESC)
WHERE deleted_at IS NULL;
CREATE TABLE ias_context_sessions (
id BIGSERIAL PRIMARY KEY,
scope_key VARCHAR(768) NOT NULL,
channel VARCHAR(64) NOT NULL,
account_id VARCHAR(255) NOT NULL,
from_user_id VARCHAR(255) NOT NULL,
context_label TEXT,
started_at TIMESTAMP NOT NULL DEFAULT NOW(),
last_message_at TIMESTAMP NOT NULL DEFAULT NOW(),
ended_at TIMESTAMP,
end_reason VARCHAR(64),
summary TEXT
);
CREATE INDEX idx_ias_context_sessions_active
ON ias_context_sessions(scope_key, started_at DESC)
WHERE ended_at IS NULL;
CREATE INDEX idx_ias_context_sessions_ended
ON ias_context_sessions(scope_key, ended_at DESC)
WHERE ended_at IS NOT NULL;
CREATE TABLE ias_context_messages (
id BIGSERIAL PRIMARY KEY,
session_id BIGINT NOT NULL REFERENCES ias_context_sessions(id) ON DELETE CASCADE,
role VARCHAR(32) NOT NULL,
content TEXT NOT NULL,
tool_call_id VARCHAR(255),
tool_calls TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_ias_context_messages_session
ON ias_context_messages(session_id, id);
CREATE TABLE ias_context_summaries (
id BIGSERIAL PRIMARY KEY,
scope_key VARCHAR(768) NOT NULL,
summary_type VARCHAR(32) NOT NULL,
source_session_id BIGINT REFERENCES ias_context_sessions(id) ON DELETE SET NULL,
content TEXT NOT NULL,
started_at TIMESTAMP,
ended_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_ias_context_summaries_latest
ON ias_context_summaries(scope_key, summary_type, created_at DESC);
@@ -0,0 +1,23 @@
ALTER TABLE ias_long_term_memories
ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC',
ALTER COLUMN updated_at TYPE TIMESTAMPTZ USING updated_at AT TIME ZONE 'UTC',
ALTER COLUMN deleted_at TYPE TIMESTAMPTZ USING deleted_at AT TIME ZONE 'UTC',
ALTER COLUMN created_at SET DEFAULT NOW(),
ALTER COLUMN updated_at SET DEFAULT NOW();
ALTER TABLE ias_context_sessions
ALTER COLUMN started_at TYPE TIMESTAMPTZ USING started_at AT TIME ZONE 'UTC',
ALTER COLUMN last_message_at TYPE TIMESTAMPTZ USING last_message_at AT TIME ZONE 'UTC',
ALTER COLUMN ended_at TYPE TIMESTAMPTZ USING ended_at AT TIME ZONE 'UTC',
ALTER COLUMN started_at SET DEFAULT NOW(),
ALTER COLUMN last_message_at SET DEFAULT NOW();
ALTER TABLE ias_context_messages
ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC',
ALTER COLUMN created_at SET DEFAULT NOW();
ALTER TABLE ias_context_summaries
ALTER COLUMN started_at TYPE TIMESTAMPTZ USING started_at AT TIME ZONE 'UTC',
ALTER COLUMN ended_at TYPE TIMESTAMPTZ USING ended_at AT TIME ZONE 'UTC',
ALTER COLUMN created_at TYPE TIMESTAMPTZ USING created_at AT TIME ZONE 'UTC',
ALTER COLUMN created_at SET DEFAULT NOW();
@@ -0,0 +1,29 @@
UPDATE ias_long_term_memories
SET scope_key = channel || ':' || account_id || ':' || from_user_id;
UPDATE ias_context_sessions
SET scope_key = channel || ':' || account_id || ':' || from_user_id;
UPDATE ias_context_summaries AS summary
SET scope_key = session.scope_key
FROM ias_context_sessions AS session
WHERE summary.source_session_id = session.id;
WITH ranked AS (
SELECT
id,
ROW_NUMBER() OVER (
PARTITION BY scope_key
ORDER BY started_at DESC, id DESC
) AS rank
FROM ias_context_sessions
WHERE ended_at IS NULL
)
UPDATE ias_context_sessions AS session
SET
ended_at = last_message_at,
end_reason = 'scope_normalized',
summary = COALESCE(summary, '旧上下文 scope 合并时自动结束。')
FROM ranked
WHERE session.id = ranked.id
AND ranked.rank > 1;
@@ -0,0 +1,62 @@
CREATE TABLE ias_upgrade_logs (
id BIGSERIAL PRIMARY KEY,
version VARCHAR(64) NOT NULL UNIQUE,
released_at TIMESTAMPTZ NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
changes JSONB NOT NULL DEFAULT '[]'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_ias_upgrade_logs_released
ON ias_upgrade_logs(released_at DESC);
INSERT INTO ias_upgrade_logs (
version,
released_at,
title,
description,
changes
) VALUES (
'0.1.1',
'2026-07-06T00:00:00+08:00',
'Context management and startup notices',
'Added standalone context management, memory tooling, session summaries, LLM response compatibility, startup online notices, and initial version/changelog files.',
'[
"Added the standalone Rust context module for long-term memories, session context, session summaries, and recent-week summaries.",
"Added timestamped memory records and context APIs for querying, creating, updating, and deleting memories.",
"Added context-window rollover rules for /new, two-hour inactivity, and token-limit thresholds.",
"Added automatic session summary generation when a new context is opened.",
"Added memory tools so the assistant can query and update user memories during conversation.",
"Fixed LLM response parsing so router responses without service_tier are accepted.",
"Added startup online notices so users receive a friendly message after the service comes back online.",
"Added the project version file and changelog, and documented the version/changelog rule."
]'::jsonb
) ON CONFLICT (version) DO UPDATE SET
released_at = EXCLUDED.released_at,
title = EXCLUDED.title,
description = EXCLUDED.description,
changes = EXCLUDED.changes;
INSERT INTO ias_upgrade_logs (
version,
released_at,
title,
description,
changes
) VALUES (
'0.1.2',
'2026-07-06T00:00:00+08:00',
'Persisted upgrade logs and Codex rules',
'Added persisted upgrade records and clarified that version/changelog rules must live in the AGENTS.md file Codex reads for the current context.',
'[
"Added the ias_upgrade_logs database table for persisted upgrade records.",
"Added migration-seeded upgrade records for versions 0.1.1 and 0.1.2.",
"Updated Codex project rules in AGENTS.md so version bumps update VERSION, crate versions, CHANGELOG.md, and database upgrade records together.",
"Clarified that project rules should live in the AGENTS.md file Codex actually reads for the current context."
]'::jsonb
) ON CONFLICT (version) DO UPDATE SET
released_at = EXCLUDED.released_at,
title = EXCLUDED.title,
description = EXCLUDED.description,
changes = EXCLUDED.changes;
@@ -0,0 +1,21 @@
INSERT INTO ias_upgrade_logs (
version,
released_at,
title,
description,
changes
) VALUES (
'0.1.3',
'2026-07-06T00:00:00+08:00',
'Detached background service startup',
'Fixed the service supervisor so background start and restart detach the child process from the invoking command session, then recorded the upgrade in the database.',
'[
"Fixed background service startup so ias service start/restart detaches the child service process from the invoking command session.",
"Added a database upgrade-log migration for version 0.1.3.",
"Verified service health using ias service status after restart."
]'::jsonb
) ON CONFLICT (version) DO UPDATE SET
released_at = EXCLUDED.released_at,
title = EXCLUDED.title,
description = EXCLUDED.description,
changes = EXCLUDED.changes;
@@ -0,0 +1,48 @@
CREATE TABLE ias_mail_messages (
id BIGSERIAL PRIMARY KEY,
source_key VARCHAR(512) NOT NULL,
mailbox VARCHAR(255) NOT NULL,
uid VARCHAR(255) NOT NULL,
message_id TEXT,
from_label TEXT NOT NULL DEFAULT '',
subject TEXT NOT NULL DEFAULT '',
summary TEXT NOT NULL DEFAULT '',
content_preview TEXT NOT NULL DEFAULT '',
preview_page_id BIGINT REFERENCES ias_web_pages(id) ON DELETE SET NULL,
preview_url TEXT,
received_at TIMESTAMPTZ,
raw_size BIGINT NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (source_key, mailbox, uid)
);
CREATE INDEX idx_ias_mail_messages_created
ON ias_mail_messages(created_at DESC);
CREATE INDEX idx_ias_mail_messages_received
ON ias_mail_messages(received_at DESC);
INSERT INTO ias_upgrade_logs (
version,
released_at,
title,
description,
changes
) VALUES (
'0.1.4',
'2026-07-06T00:00:00+08:00',
'Mail polling and standalone HTTP module',
'Added a standalone mail module for IMAP polling and notifications, moved HTTP serving and web preview pages into a standalone Rust module, and added mail persistence tables.',
'[
"Added the standalone Rust mail module for IMAP mailbox polling, message parsing, database deduplication, preview-page creation, and user notifications.",
"Added the standalone Rust ias-http module for HTTP serving, health checks, and reusable web preview pages.",
"Moved the existing web preview routes out of service and into ias-http.",
"Added /mail-api/messages and /mail-api/messages/{id} for inspecting stored mail records.",
"Added the ias_mail_messages database table and persisted the 0.1.4 upgrade record.",
"Added mail polling configuration through IA_MAIL_* environment variables; polling stays disabled when mailbox settings are absent."
]'::jsonb
) ON CONFLICT (version) DO UPDATE SET
released_at = EXCLUDED.released_at,
title = EXCLUDED.title,
description = EXCLUDED.description,
changes = EXCLUDED.changes;
@@ -0,0 +1,56 @@
CREATE TABLE ias_mail_accounts (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
source_key VARCHAR(512) NOT NULL UNIQUE,
imap_host VARCHAR(255) NOT NULL,
imap_port INTEGER NOT NULL DEFAULT 993,
imap_username TEXT NOT NULL,
imap_password TEXT NOT NULL,
mailbox VARCHAR(255) NOT NULL DEFAULT 'INBOX',
notify_account_id VARCHAR(255) NOT NULL,
notify_user_id VARCHAR(255) NOT NULL,
poll_seconds INTEGER NOT NULL DEFAULT 60,
fetch_limit INTEGER NOT NULL DEFAULT 10,
accept_invalid_certs BOOLEAN NOT NULL DEFAULT FALSE,
enabled BOOLEAN NOT NULL DEFAULT TRUE,
last_checked_at TIMESTAMPTZ,
last_error TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_ias_mail_accounts_enabled
ON ias_mail_accounts(enabled, id);
ALTER TABLE ias_mail_messages
ADD COLUMN mail_account_id BIGINT REFERENCES ias_mail_accounts(id) ON DELETE SET NULL,
ADD COLUMN content TEXT NOT NULL DEFAULT '',
ADD COLUMN raw_headers TEXT;
CREATE INDEX idx_ias_mail_messages_account
ON ias_mail_messages(mail_account_id, created_at DESC);
INSERT INTO ias_upgrade_logs (
version,
released_at,
title,
description,
changes
) VALUES (
'0.1.5',
'2026-07-06T00:00:00+08:00',
'Database-backed mail auth and cache',
'Added guided mail account configuration with ias mail auth, persisted mail accounts in the database, and expanded mail message caching.',
'[
"Added database-backed mail account configuration through the guided ias mail auth command.",
"Added the ias_mail_accounts table and linked cached mail messages back to their configured account.",
"Extended the mail cache to persist full parsed mail content and raw headers in ias_mail_messages.",
"Updated mail polling to load enabled mail accounts from the database first, while keeping environment-based configuration as a fallback.",
"Added mail account listing through ias mail list.",
"Persisted the 0.1.5 upgrade record."
]'::jsonb
) ON CONFLICT (version) DO UPDATE SET
released_at = EXCLUDED.released_at,
title = EXCLUDED.title,
description = EXCLUDED.description,
changes = EXCLUDED.changes;
@@ -0,0 +1,28 @@
CREATE TABLE ias_version_notifications (
version VARCHAR(64) PRIMARY KEY,
notified_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
recipient_count INTEGER NOT NULL DEFAULT 0
);
INSERT INTO ias_upgrade_logs (
version,
released_at,
title,
description,
changes
) VALUES (
'0.1.6',
'2026-07-06T00:00:00+08:00',
'Version update notifications and changelog pages',
'Added HTTP upgrade-log pages and one-time startup notifications that tell users which version the service updated to.',
'[
"Added HTTP-rendered upgrade log pages at /updates and /updates/{version}.",
"Added one-time startup notifications for new service versions, including the updated version number and an HTTP upgrade-log link.",
"Added persisted version notification state so users are not notified repeatedly after ordinary restarts.",
"Persisted the 0.1.6 upgrade record."
]'::jsonb
) ON CONFLICT (version) DO UPDATE SET
released_at = EXCLUDED.released_at,
title = EXCLUDED.title,
description = EXCLUDED.description,
changes = EXCLUDED.changes;
@@ -0,0 +1,73 @@
-- 将已有升级日志翻译为中文
UPDATE ias_upgrade_logs SET
title = '上下文管理和启动通知',
description = '新增独立的上下文管理模块、记忆工具、会话摘要、LLM 响应兼容性、启动上线通知,以及初始版本和更新日志文件。',
changes = '[
"新增独立的 Rust context 模块,支持长期记忆、会话上下文、会话摘要和近一周摘要。",
"新增带时间戳的记忆记录和上下文 API,支持查询、创建、更新和删除记忆。",
"新增上下文窗口切换规则,涵盖 /new 命令、两小时不活跃和 token 上限阈值。",
"新增开启新上下文时自动生成会话摘要。",
"新增记忆工具,使助手在对话中可以查询和更新用户记忆。",
"修复 LLM 响应解析,使不带 service_tier 的路由响应也能正常接受。",
"新增启动上线通知,服务恢复后向用户发送友好提示消息。",
"新增项目版本文件和更新日志,并记录版本/更新日志规则。"
]'::jsonb
WHERE version = '0.1.1';
UPDATE ias_upgrade_logs SET
title = '持久化升级日志和 Codex 规则',
description = '新增持久化升级记录,并明确版本/更新日志规则必须写在 Codex 实际读取的 AGENTS.md 文件中。',
changes = '[
"新增 ias_upgrade_logs 数据库表,用于持久化升级记录。",
"新增迁移种子数据,写入 0.1.1 和 0.1.2 的升级记录。",
"更新 AGENTS.md 中的 Codex 项目规则,使版本升级同步更新 VERSION、crate 版本、CHANGELOG.md 和数据库升级记录。",
"明确项目规则应写在 Codex 实际读取的 AGENTS.md 文件中。"
]'::jsonb
WHERE version = '0.1.2';
UPDATE ias_upgrade_logs SET
title = '分离后台服务启动进程',
description = '修复服务管理器,使后台启动和重启能将子进程与调用命令的会话分离,并在数据库中记录本次升级。',
changes = '[
"修复后台服务启动问题,使 ias service start/restart 能将子服务进程与调用命令的会话分离。",
"新增版本 0.1.3 的数据库升级日志迁移。",
"重启后通过 ias service status 验证服务健康状态。"
]'::jsonb
WHERE version = '0.1.3';
UPDATE ias_upgrade_logs SET
title = '邮件轮询和独立 HTTP 模块',
description = '新增独立的邮件模块用于 IMAP 轮询和通知,将 HTTP 服务和网页预览页面迁移到独立 Rust 模块,并新增邮件持久化表。',
changes = '[
"新增独立的 Rust mail 模块,实现 IMAP 邮箱轮询、邮件解析、数据库去重、预览页面创建和用户通知。",
"新增独立的 Rust ias-http 模块,提供 HTTP 服务、健康检查和可复用的网页预览页面。",
"将现有的网页预览路由从 service 迁移至 ias-http。",
"新增 /mail-api/messages 和 /mail-api/messages/{id} 接口,用于查看存储的邮件记录。",
"新增 ias_mail_messages 数据库表,持久化 0.1.4 升级记录。",
"新增通过 IA_MAIL_* 环境变量配置邮件轮询;未配置邮箱时轮询保持禁用。"
]'::jsonb
WHERE version = '0.1.4';
UPDATE ias_upgrade_logs SET
title = '基于数据库的邮件认证和缓存',
description = '新增通过 ias mail auth 引导命令配置邮件账号,将邮件账号持久化到数据库,并扩展邮件消息缓存。',
changes = '[
"新增基于数据库的邮件账号配置,通过 ias mail auth 引导命令完成。",
"新增 ias_mail_accounts 表,并将缓存的邮件消息关联到对应配置账号。",
"扩展邮件缓存,在 ias_mail_messages 中持久化完整解析后的邮件内容和原始头信息。",
"更新邮件轮询逻辑,优先从数据库加载启用的邮件账号,同时保留环境变量配置作为回退方案。",
"新增 ias mail list 命令查看邮件账号列表。",
"持久化 0.1.5 升级记录。"
]'::jsonb
WHERE version = '0.1.5';
UPDATE ias_upgrade_logs SET
title = '版本更新通知和更新日志页面',
description = '新增 HTTP 更新日志页面和一次性启动通知,告知用户服务更新到了哪个版本。',
changes = '[
"新增 HTTP 渲染的更新日志页面,路由为 /updates 和 /updates/{version}。",
"新增服务版本一次性启动通知,包含更新的版本号和 HTTP 更新日志链接。",
"新增持久化的版本通知状态,避免普通重启后重复通知用户。",
"持久化 0.1.6 升级记录。"
]'::jsonb
WHERE version = '0.1.6';
@@ -0,0 +1,38 @@
INSERT INTO ias_upgrade_logs (
version,
released_at,
title,
description,
changes,
modules
) VALUES (
'0.1.7',
'2026-07-06T00:00:00+08:00',
'模块统一 ias 前缀、独立版本与内网地址支持',
'所有 Rust crate 统一加 ias- 前缀,各模块开始独立维护版本号,新增内网地址环境变量,版本通知同时发送公网和内网链接,并将已有升级日志翻译为中文。',
'[
"所有 Rust crate 统一加 ias- 前缀:ai → ias-ai、common → ias-common、context → ias-context、mail → ias-mail、service → ias-service、wechat → ias-wechat。",
"新增 ias-main 模块承载 CLI 入口和二进制打包。",
"各模块开始独立维护版本号,ias-main 0.1.7 代表整体版本。",
"新增 IA_WEB_INTERNAL_URL 环境变量,用于配置内网可访问的基础 URL。",
"新增 internal_url_for_path() 函数,版本更新通知同时发送公网和内网地址的 Markdown 链接。",
"将已有升级日志的 title、description、changes 翻译为中文。",
"ias_upgrade_logs 新增 modules JSONB 字段记录各模块独立版本。",
"持久化 0.1.7 升级记录。"
]'::jsonb,
'{
"ias-common": "0.1.0",
"ias-ai": "0.1.0",
"ias-wechat": "0.1.0",
"ias-context": "0.1.0",
"ias-http": "0.1.0",
"ias-mail": "0.1.0",
"ias-service": "0.1.0",
"ias-main": "0.1.7"
}'::jsonb
) ON CONFLICT (version) DO UPDATE SET
released_at = EXCLUDED.released_at,
title = EXCLUDED.title,
description = EXCLUDED.description,
changes = EXCLUDED.changes,
modules = EXCLUDED.modules;
@@ -0,0 +1,27 @@
-- 新增 modules 字段,记录各模块独立版本
ALTER TABLE ias_upgrade_logs
ADD COLUMN modules JSONB NOT NULL DEFAULT '{}'::jsonb;
-- 更新已有记录的模块版本信息
UPDATE ias_upgrade_logs SET modules = '{
"ias-common": "0.1.0",
"ias-ai": "0.1.0",
"ias-wechat": "0.1.0",
"ias-context": "0.1.0",
"ias-http": "0.1.0",
"ias-mail": "0.1.0",
"ias-service": "0.1.0",
"ias-main": "0.1.0"
}'::jsonb WHERE version IN ('0.1.1', '0.1.2', '0.1.3', '0.1.4', '0.1.5', '0.1.6');
-- 更新 0.1.7 的记录
UPDATE ias_upgrade_logs SET modules = '{
"ias-common": "0.1.0",
"ias-ai": "0.1.0",
"ias-wechat": "0.1.0",
"ias-context": "0.1.0",
"ias-http": "0.1.0",
"ias-mail": "0.1.0",
"ias-service": "0.1.0",
"ias-main": "0.1.7"
}'::jsonb WHERE version = '0.1.7';