rote-toolkit 0.2.1 → 0.3.1

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/README.md CHANGED
@@ -21,10 +21,11 @@ npm install -g rote-toolkit
21
21
  运行以下命令进行全局配置:
22
22
 
23
23
  ```bash
24
- rote login
24
+ rote config
25
25
  ```
26
26
 
27
27
  系统会提示你输入:
28
+
28
29
  1. **Rote API URL**:例如 `https://your-rote-domain.com`
29
30
  2. **OpenKey**:你的 API 密钥
30
31
 
@@ -38,18 +39,26 @@ rote login
38
39
  rote add "今天学到了 MCP 协议,非常有趣!"
39
40
  ```
40
41
 
41
- 附带标签:
42
+ 附带标签、设为公开并置顶:
42
43
 
43
44
  ```bash
44
- rote add "实现了一个新的前端组件" -t "代码,前端,React"
45
+ rote add "实现了一个新的前端组件" -t "代码,前端,React" --public --pin
45
46
  ```
46
47
 
47
- ### 2) 搜索笔记
48
+ ### 2) 搜索和获取笔记
49
+
50
+ 搜索包含 "MCP" 的笔记:
48
51
 
49
52
  ```bash
50
53
  rote search "MCP"
51
54
  ```
52
55
 
56
+ 获取最近的笔记(支持过滤归档和标签):
57
+
58
+ ```bash
59
+ rote list --limit 5 --archived -t "知识管理"
60
+ ```
61
+
53
62
  ## MCP 模式使用指南
54
63
 
55
64
  启动 MCP Server:
@@ -71,11 +80,7 @@ rote-mcp
71
80
  "mcpServers": {
72
81
  "rote-toolkit": {
73
82
  "command": "npx",
74
- "args": [
75
- "-y",
76
- "rote-toolkit",
77
- "mcp"
78
- ]
83
+ "args": ["-y", "rote-toolkit", "mcp"]
79
84
  }
80
85
  }
81
86
  }
@@ -88,7 +93,9 @@ rote-mcp
88
93
  - `rote_list_notes`
89
94
 
90
95
  ## 本地开发
96
+
91
97
  [text](../../../Downloads/API-KEY-GUIDE.md)
98
+
92
99
  ```bash
93
100
  npm install
94
101
  npm run build
@@ -117,6 +124,7 @@ npm run release:major
117
124
  ```
118
125
 
119
126
  发布脚本会执行:
127
+
120
128
  1. 检查 git 工作区是否干净
121
129
  2. 检查 npm 登录状态
122
130
  3. `npm run build`
package/dist/api.js CHANGED
@@ -16,8 +16,7 @@ export class RoteClient {
16
16
  content: input.content,
17
17
  title: input.title ?? "",
18
18
  tags: input.tags ?? [],
19
- state: input.state ?? "private",
20
- type: input.type ?? "rote",
19
+ state: input.isPublic ? "public" : "private",
21
20
  pin: input.pin ?? false,
22
21
  ...(input.articleId ? { articleId: input.articleId } : {}),
23
22
  };
@@ -37,6 +36,12 @@ export class RoteClient {
37
36
  limit: String(input.limit ?? 10),
38
37
  skip: String(input.skip ?? 0),
39
38
  });
39
+ if (input.archived !== undefined) {
40
+ params.set("archived", String(input.archived));
41
+ }
42
+ if (input.tag) {
43
+ input.tag.forEach((t) => params.append("tag", t));
44
+ }
40
45
  return this.request(`/v2/api/openkey/notes/search?${params.toString()}`);
41
46
  }
42
47
  async listNotes(input = {}) {
@@ -45,6 +50,12 @@ export class RoteClient {
45
50
  limit: String(input.limit ?? 10),
46
51
  skip: String(input.skip ?? 0),
47
52
  });
53
+ if (input.archived !== undefined) {
54
+ params.set("archived", String(input.archived));
55
+ }
56
+ if (input.tag) {
57
+ input.tag.forEach((t) => params.append("tag", t));
58
+ }
48
59
  return this.request(`/v2/api/openkey/notes?${params.toString()}`);
49
60
  }
50
61
  async createArticle(input) {
package/dist/cli.js CHANGED
@@ -9,7 +9,8 @@ import { startMcpServer } from "./mcp.js";
9
9
  const program = new Command();
10
10
  program.name("rote").description("Rote Toolkit CLI").version("0.1.0");
11
11
  program
12
- .command("login")
12
+ .command("config")
13
+ .alias("login")
13
14
  .description("Configure Rote API URL and OpenKey")
14
15
  .action(async () => {
15
16
  const rl = createInterface({ input, output });
@@ -29,7 +30,8 @@ program
29
30
  .argument("<content>", "note content")
30
31
  .option("-t, --tags <tags>", "comma-separated tags")
31
32
  .option("--title <title>", "title")
32
- .option("--state <state>", "note state", "private")
33
+ .option("--public", "publish as public note")
34
+ .option("--pin", "pin the note")
33
35
  .option("--article-id <articleId>", "bind to an existing article")
34
36
  .action(async (content, options) => {
35
37
  const client = new RoteClient();
@@ -38,7 +40,8 @@ program
38
40
  content,
39
41
  tags,
40
42
  title: options.title,
41
- state: options.state,
43
+ isPublic: options.public,
44
+ pin: options.pin,
42
45
  articleId: options.articleId,
43
46
  });
44
47
  console.log(`Created note: ${note.id}`);
@@ -84,6 +87,8 @@ program
84
87
  .argument("<action>", "action to perform (get|update)")
85
88
  .option("--nickname <nickname>", "new nickname")
86
89
  .option("--description <description>", "new description")
90
+ .option("--avatar <url>", "new avatar URL")
91
+ .option("--cover <url>", "new cover URL")
87
92
  .option("--username <username>", "new username")
88
93
  .action(async (action, options) => {
89
94
  const client = new RoteClient();
@@ -95,6 +100,8 @@ program
95
100
  const profile = await client.updateProfile({
96
101
  nickname: options.nickname,
97
102
  description: options.description,
103
+ avatar: options.avatar,
104
+ cover: options.cover,
98
105
  username: options.username,
99
106
  });
100
107
  console.log(`Updated profile for: ${profile.username}`);
@@ -117,12 +124,35 @@ program
117
124
  .argument("<keyword>", "search keyword")
118
125
  .option("-l, --limit <limit>", "max results", parseInt, 10)
119
126
  .option("-s, --skip <skip>", "offset", parseInt, 0)
127
+ .option("--archived", "include archived notes")
128
+ .option("-t, --tag <tags>", "comma-separated tags to filter by")
120
129
  .action(async (keyword, options) => {
121
130
  const client = new RoteClient();
131
+ const tag = parseTags(options.tag);
122
132
  const notes = await client.searchNotes({
123
133
  keyword,
124
134
  limit: options.limit,
125
135
  skip: options.skip,
136
+ archived: options.archived,
137
+ tag: tag.length > 0 ? tag : undefined,
138
+ });
139
+ printNotes(notes);
140
+ });
141
+ program
142
+ .command("list")
143
+ .description("List recent notes")
144
+ .option("-l, --limit <limit>", "max results", parseInt, 10)
145
+ .option("-s, --skip <skip>", "offset", parseInt, 0)
146
+ .option("--archived", "include archived notes")
147
+ .option("-t, --tag <tags>", "comma-separated tags to filter by")
148
+ .action(async (options) => {
149
+ const client = new RoteClient();
150
+ const tag = parseTags(options.tag);
151
+ const notes = await client.listNotes({
152
+ limit: options.limit,
153
+ skip: options.skip,
154
+ archived: options.archived,
155
+ tag: tag.length > 0 ? tag : undefined,
126
156
  });
127
157
  printNotes(notes);
128
158
  });
package/dist/config.js CHANGED
@@ -19,12 +19,12 @@ export function saveConfig(config) {
19
19
  }
20
20
  export function loadConfig() {
21
21
  if (!existsSync(CONFIG_PATH)) {
22
- throw new Error(`Config not found at ${CONFIG_PATH}. Run "rote login" first.`);
22
+ throw new Error(`Config not found at ${CONFIG_PATH}. Run "rote config" first.`);
23
23
  }
24
24
  const raw = readFileSync(CONFIG_PATH, 'utf8');
25
25
  const parsed = JSON.parse(raw);
26
26
  if (!parsed.apiUrl || !parsed.openKey) {
27
- throw new Error(`Invalid config at ${CONFIG_PATH}. Run "rote login" again.`);
27
+ throw new Error(`Invalid config at ${CONFIG_PATH}. Run "rote config" again.`);
28
28
  }
29
29
  return {
30
30
  apiUrl: normalizeApiUrl(parsed.apiUrl),
package/dist/mcp.js CHANGED
@@ -15,18 +15,20 @@ export async function startMcpServer() {
15
15
  content: z.string().min(1).describe("Note content"),
16
16
  title: z.string().optional().describe("Optional note title"),
17
17
  tags: z.array(z.string()).optional().describe("Optional list of tags"),
18
- state: z.string().optional().describe("Note state, default private"),
18
+ isPublic: z.boolean().optional().describe("Publish as public note"),
19
+ pin: z.boolean().optional().describe("Whether to pin the note"),
19
20
  articleId: z
20
21
  .string()
21
22
  .optional()
22
23
  .describe("Optional article ID to bind to"),
23
24
  },
24
- }, async ({ content, title, tags, state, articleId }) => {
25
+ }, async ({ content, title, tags, isPublic, pin, articleId }) => {
25
26
  const note = await client.createNote({
26
27
  content,
27
28
  title,
28
29
  tags,
29
- state,
30
+ isPublic,
31
+ pin,
30
32
  articleId,
31
33
  });
32
34
  return {
@@ -163,9 +165,17 @@ export async function startMcpServer() {
163
165
  .min(0)
164
166
  .optional()
165
167
  .describe("Pagination offset, default 0"),
168
+ archived: z.boolean().optional().describe("Include archived notes"),
169
+ tag: z.array(z.string()).optional().describe("Tag filter"),
166
170
  },
167
- }, async ({ keyword, limit, skip }) => {
168
- const notes = await client.searchNotes({ keyword, limit, skip });
171
+ }, async ({ keyword, limit, skip, archived, tag }) => {
172
+ const notes = await client.searchNotes({
173
+ keyword,
174
+ limit,
175
+ skip,
176
+ archived,
177
+ tag,
178
+ });
169
179
  const lines = notes.map((note, i) => `${i + 1}. ${truncateSingleLine(note.content, 100)}`);
170
180
  return {
171
181
  content: [
@@ -192,9 +202,11 @@ export async function startMcpServer() {
192
202
  .min(0)
193
203
  .optional()
194
204
  .describe("Pagination offset, default 0"),
205
+ archived: z.boolean().optional().describe("Include archived notes"),
206
+ tag: z.array(z.string()).optional().describe("Tag filter"),
195
207
  },
196
- }, async ({ limit, skip }) => {
197
- const notes = await client.listNotes({ limit, skip });
208
+ }, async ({ limit, skip, archived, tag }) => {
209
+ const notes = await client.listNotes({ limit, skip, archived, tag });
198
210
  const lines = notes.map((note, i) => `${i + 1}. ${truncateSingleLine(note.content, 100)}`);
199
211
  return {
200
212
  content: [
package/dist/types.d.ts CHANGED
@@ -8,7 +8,6 @@ export interface RoteNote {
8
8
  title?: string;
9
9
  tags?: string[];
10
10
  state?: string;
11
- type?: string;
12
11
  createdAt?: string;
13
12
  updatedAt?: string;
14
13
  }
@@ -21,8 +20,7 @@ export interface CreateNoteInput {
21
20
  content: string;
22
21
  title?: string;
23
22
  tags?: string[];
24
- state?: string;
25
- type?: string;
23
+ isPublic?: boolean;
26
24
  pin?: boolean;
27
25
  articleId?: string;
28
26
  }
@@ -83,8 +81,12 @@ export interface SearchNotesInput {
83
81
  keyword: string;
84
82
  limit?: number;
85
83
  skip?: number;
84
+ archived?: boolean;
85
+ tag?: string[];
86
86
  }
87
87
  export interface ListNotesInput {
88
88
  limit?: number;
89
89
  skip?: number;
90
+ archived?: boolean;
91
+ tag?: string[];
90
92
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rote-toolkit",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "CLI and MCP toolkit for Rote OpenKey API",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",