初始化插件:oc-session-all - 显示所有会话记录,绕过目录过滤
This commit is contained in:
@@ -0,0 +1,96 @@
|
|||||||
|
# oc-session-all
|
||||||
|
|
||||||
|
OpenCode 插件:在任意目录下显示所有会话记录,绕过目录过滤限制。
|
||||||
|
|
||||||
|
## 功能
|
||||||
|
|
||||||
|
- 拦截 `/session` 命令,显示所有项目的会话记录,而不仅仅是当前目录的
|
||||||
|
- 提供 `/sessions-all` 命令作为替代方案
|
||||||
|
- 按更新时间倒序显示会话列表
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
### 方法 1:全局安装(推荐)
|
||||||
|
|
||||||
|
1. 将 `src/index.ts` 复制到全局插件目录:
|
||||||
|
```bash
|
||||||
|
# Windows
|
||||||
|
mkdir -p %USERPROFILE%\.config\opencode\plugins
|
||||||
|
copy src\index.ts %USERPROFILE%\.config\opencode\plugins\oc-session-all.ts
|
||||||
|
|
||||||
|
# Linux/macOS
|
||||||
|
mkdir -p ~/.config/opencode/plugins
|
||||||
|
cp src/index.ts ~/.config/opencode/plugins/oc-session-all.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 重启 OpenCode
|
||||||
|
|
||||||
|
### 方法 2:项目级安装
|
||||||
|
|
||||||
|
1. 将 `src/index.ts` 复制到项目目录:
|
||||||
|
```bash
|
||||||
|
mkdir -p .opencode/plugins
|
||||||
|
cp src/index.ts .opencode/plugins/oc-session-all.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 重启 OpenCode
|
||||||
|
|
||||||
|
## 使用方法
|
||||||
|
|
||||||
|
### 方法 1:拦截 /session 命令
|
||||||
|
|
||||||
|
插件会自动拦截 `/session` 命令,显示所有会话记录。
|
||||||
|
|
||||||
|
### 方法 2:使用新命令
|
||||||
|
|
||||||
|
运行 `/sessions-all` 命令来显示所有会话记录。
|
||||||
|
|
||||||
|
## 输出示例
|
||||||
|
|
||||||
|
```
|
||||||
|
=== All Sessions (across all projects) ===
|
||||||
|
|
||||||
|
ID: ses_12af0b69cffeAMR3VcfAdp94Hi
|
||||||
|
Title: OpenCode WSL 迁移
|
||||||
|
Directory: C:/Users/ypshidifu
|
||||||
|
Created: 2026/9/20 10:00:00
|
||||||
|
Updated: 2026/9/20 15:30:00
|
||||||
|
---
|
||||||
|
ID: ses_12aeb915effez1zEjjIqf6yl1c
|
||||||
|
Title: Session 2
|
||||||
|
Directory: D:/桌面/源码/mc_plugn/windowmsgbot
|
||||||
|
Created: 2026/9/20 09:00:00
|
||||||
|
Updated: 2026/9/20 14:00:00
|
||||||
|
---
|
||||||
|
|
||||||
|
Total: 68 sessions
|
||||||
|
```
|
||||||
|
|
||||||
|
## 工作原理
|
||||||
|
|
||||||
|
插件通过两种方式获取所有会话:
|
||||||
|
|
||||||
|
1. **OpenCode Client API**:尝试使用 OpenCode 的客户端 API 获取会话列表
|
||||||
|
2. **数据库直接查询**:如果 API 不可用,直接查询 SQLite 数据库
|
||||||
|
|
||||||
|
## 配置
|
||||||
|
|
||||||
|
插件无需额外配置,安装后即可使用。
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
如果插件不工作:
|
||||||
|
|
||||||
|
1. 确保插件文件已正确放置在插件目录
|
||||||
|
2. 重启 OpenCode
|
||||||
|
3. 检查控制台日志是否有错误信息
|
||||||
|
4. 确保 SQLite3 命令行工具可用(用于数据库查询回退方案)
|
||||||
|
|
||||||
|
## 依赖
|
||||||
|
|
||||||
|
- OpenCode 1.18.11 或更新版本
|
||||||
|
- SQLite3 命令行工具(可选,用于数据库查询回退方案)
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
MIT
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "oc-session-all",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "OpenCode plugin to show all sessions regardless of current directory",
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "tsc",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": ["opencode", "plugin", "session"],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@opencode-ai/plugin": "latest"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
+157
@@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
* OpenCode Plugin: Show All Sessions
|
||||||
|
*
|
||||||
|
* This plugin provides /sessions-all command to show all sessions
|
||||||
|
* regardless of the current working directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { tool } from "@opencode-ai/plugin";
|
||||||
|
import { exec } from "child_process";
|
||||||
|
import { promisify } from "util";
|
||||||
|
import { join } from "path";
|
||||||
|
import { existsSync } from "fs";
|
||||||
|
|
||||||
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
|
interface Session {
|
||||||
|
id: string;
|
||||||
|
project_id: string;
|
||||||
|
directory: string;
|
||||||
|
title: string | null;
|
||||||
|
time_created: number;
|
||||||
|
time_updated: number;
|
||||||
|
cost: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to the opencode database
|
||||||
|
*/
|
||||||
|
function getDbPath(): string {
|
||||||
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
||||||
|
|
||||||
|
// Windows path
|
||||||
|
const winPath = join(homeDir, "AppData", "Roaming", "opencode", "opencode.db");
|
||||||
|
if (existsSync(winPath)) return winPath;
|
||||||
|
|
||||||
|
// Linux/macOS path
|
||||||
|
const unixPath = join(homeDir, ".local", "share", "opencode", "opencode.db");
|
||||||
|
if (existsSync(unixPath)) return unixPath;
|
||||||
|
|
||||||
|
// Fallback to Windows AppData
|
||||||
|
return winPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query all sessions from the database
|
||||||
|
*/
|
||||||
|
async function getAllSessionsFromDb(): Promise<Session[]> {
|
||||||
|
try {
|
||||||
|
const dbPath = getDbPath();
|
||||||
|
console.log(`[oc-session-all] Database path: ${dbPath}`);
|
||||||
|
|
||||||
|
const query = `
|
||||||
|
SELECT id, project_id, directory, title, time_created, time_updated, cost
|
||||||
|
FROM session_v2
|
||||||
|
ORDER BY time_updated DESC;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const { stdout } = await execAsync(`sqlite3 "${dbPath}" "${query}"`);
|
||||||
|
|
||||||
|
if (!stdout.trim()) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const sessions: Session[] = [];
|
||||||
|
const lines = stdout.trim().split("\n");
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const parts = line.split("|");
|
||||||
|
if (parts.length >= 7) {
|
||||||
|
sessions.push({
|
||||||
|
id: parts[0],
|
||||||
|
project_id: parts[1],
|
||||||
|
directory: parts[2],
|
||||||
|
title: parts[3] || null,
|
||||||
|
time_created: parseInt(parts[4]) || 0,
|
||||||
|
time_updated: parseInt(parts[5]) || 0,
|
||||||
|
cost: parseFloat(parts[6]) || 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessions;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[oc-session-all] Failed to query database:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a timestamp to local string
|
||||||
|
*/
|
||||||
|
function formatTime(timestamp: number): string {
|
||||||
|
if (!timestamp) return "Unknown";
|
||||||
|
return new Date(timestamp * 1000).toLocaleString("zh-CN");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format cost to display string
|
||||||
|
*/
|
||||||
|
function formatCost(cost: number): string {
|
||||||
|
if (!cost) return "Free";
|
||||||
|
return `$${cost.toFixed(4)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OcSessionAll = async ({ project, client, $ }: any) => {
|
||||||
|
console.log("[oc-session-all] Plugin loaded");
|
||||||
|
|
||||||
|
return {
|
||||||
|
tool: {
|
||||||
|
"sessions-all": tool({
|
||||||
|
description: "显示所有项目的会话记录,绕过目录过滤限制。Show all sessions from all projects.",
|
||||||
|
args: {},
|
||||||
|
async execute() {
|
||||||
|
const sessions = await getAllSessionsFromDb();
|
||||||
|
|
||||||
|
if (!sessions || sessions.length === 0) {
|
||||||
|
return "没有找到任何会话记录。No sessions found.";
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = "=== 所有会话记录 (All Sessions) ===\n\n";
|
||||||
|
|
||||||
|
// Group sessions by project
|
||||||
|
const byProject = new Map<string, Session[]>();
|
||||||
|
for (const session of sessions) {
|
||||||
|
const key = session.project_id || "unknown";
|
||||||
|
if (!byProject.has(key)) {
|
||||||
|
byProject.set(key, []);
|
||||||
|
}
|
||||||
|
byProject.get(key)!.push(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display sessions
|
||||||
|
let index = 1;
|
||||||
|
for (const session of sessions) {
|
||||||
|
const created = formatTime(session.time_created);
|
||||||
|
const updated = formatTime(session.time_updated);
|
||||||
|
const cost = formatCost(session.cost);
|
||||||
|
|
||||||
|
output += `${index}. ${session.title || "Untitled"}\n`;
|
||||||
|
output += ` ID: ${session.id}\n`;
|
||||||
|
output += ` 目录: ${session.directory}\n`;
|
||||||
|
output += ` 创建: ${created} | 更新: ${updated}\n`;
|
||||||
|
output += ` 费用: ${cost}\n\n`;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
output += `共 ${sessions.length} 个会话`;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OcSessionAll;
|
||||||
Reference in New Issue
Block a user