dsh-plugin-onenote 0.0.0-stage → 0.2.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 hestudio-community
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,151 @@
1
- # Temporary Holding Version
1
+ # dsh-plugin-onenote
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Read the Microsoft OneNote notebooks **you choose** from inside
4
+ [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness).
5
+
6
+ Sign in once, tick the notebooks this agent may read, and everything else stays
7
+ invisible. The allow-list is enforced inside the plugin before any Microsoft
8
+ Graph request, so a page that tries to talk the model into reading another
9
+ notebook has nothing to call.
10
+
11
+ > 中文文档:[README.zh.md](./README.zh.md)
12
+
13
+ ## What it looks like
14
+
15
+ The settings card (Settings → Plugins → OneNote) is the only place to sign in or
16
+ change which notebooks are readable:
17
+
18
+ ```
19
+ ┌ OneNote ──────────────────────────────────────────────┐
20
+ │ Connected │
21
+ │ Signed in as you@example.com [ Sign out ] │
22
+ ├───────────────────────────────────────────────────────┤
23
+ │ Readable notebooks [ Refresh list ] │
24
+ │ Only the notebooks you tick can be listed, searched, │
25
+ │ or read. │
26
+ │ [x] Work default │
27
+ │ [ ] Team wiki shared │
28
+ │ [ ] Journal │
29
+ │ 1 of 3 allowed [Allow none] │
30
+ │ [Save] │
31
+ └───────────────────────────────────────────────────────┘
32
+ ```
33
+
34
+ ## Tools
35
+
36
+ The agent gets four read-only tools. None of them can sign in, sign out, or
37
+ change the allow-list — those are user actions in the settings card.
38
+
39
+ | Tool | What it does |
40
+ | --- | --- |
41
+ | `onenote_status` | Reports the account and which notebooks are readable. |
42
+ | `onenote_list_pages` | Browses allowed notebooks → sections → pages. |
43
+ | `onenote_search` | Matches page titles first, then the opening text of recent pages. |
44
+ | `onenote_read_page` | Reads one page as Markdown (headings, lists, tables, links, code). |
45
+
46
+ ## Install
47
+
48
+ ```bash
49
+ # From the plugin manager (recommended)
50
+ dsh plugin install hestudio-community/dsh-plugin-onenote
51
+
52
+ # Or from npm
53
+ dsh plugin install dsh-plugin-onenote
54
+ ```
55
+
56
+ Then open **Settings → Plugins → OneNote** and sign in.
57
+
58
+ ## Azure app registration
59
+
60
+ The bundle ships a public client ID so it works out of the box. To use your own
61
+ app registration instead (recommended for anything beyond personal use), create
62
+ one in about two minutes — no paid subscription is needed:
63
+
64
+ 1. Open [App registrations](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)
65
+ → **New registration**.
66
+ 2. **Name**: anything, e.g. `DSH-OneNote`.
67
+ 3. **Supported account types**: *Accounts in any organizational directory and
68
+ personal Microsoft accounts*. Choose a single-tenant option instead if every
69
+ user is in one tenant.
70
+ 4. **Redirect URI**: leave empty — the device-code flow needs none.
71
+ 5. **Register**, then copy **Application (client) ID**.
72
+ 6. **Authentication → Advanced settings → Allow public client flows** = **Yes**,
73
+ then **Save**. Without this, sign-in fails with `unauthorized_client`.
74
+ 7. **API permissions → Add a permission → Microsoft Graph → Delegated permissions**:
75
+ - `Notes.Read` — read the user's notebooks
76
+ - `offline_access` — keep the session alive between turns
77
+ - `User.Read` — name the signed-in account
78
+ 8. No client secret and no admin consent are needed for a personal account. A
79
+ work account may need an admin to grant consent once.
80
+
81
+ Then point the plugin at your app by adding a patch layer of your own:
82
+
83
+ ```yaml
84
+ # ~/.dsh/cordis.patch.yml (applies to every profile) or the profile's cordis.patch.yml
85
+ - id: onenote
86
+ name: 'dsh-plugin-onenote'
87
+ config:
88
+ clientId: 00000000-0000-0000-0000-000000000000
89
+ tenant: common
90
+ ```
91
+
92
+ `config` replaces the row's config wholesale, so restate every field you need.
93
+
94
+ ## Configuration
95
+
96
+ | Field | Default | Meaning |
97
+ | --- | --- | --- |
98
+ | `clientId` | the bundled public app | Azure application (client) ID. |
99
+ | `tenant` | `common` | Tenant id or domain. `common` accepts work and personal accounts. |
100
+ | `maxPagesPerList` | `100` | Default page cap for `onenote_list_pages`. |
101
+ | `maxPageChars` | `60000` | Default Markdown cap for `onenote_read_page`. |
102
+
103
+ ## Where state lives
104
+
105
+ `$DSH_HOME/onenote/` (usually `~/.dsh/onenote/`), mode `0600`:
106
+
107
+ | File | Contents |
108
+ | --- | --- |
109
+ | `tokens.json` | Access and refresh token. |
110
+ | `signin.json` | The pending device-code attempt, so a reload continues the same code. |
111
+ | `settings.json` | The notebook allow-list. |
112
+
113
+ Delete the directory to reset everything. Nothing is written into your
114
+ workspace.
115
+
116
+ ## How the privacy boundary works
117
+
118
+ 1. The allow-list is a list of notebook ids in `settings.json`.
119
+ 2. Every read resolves the **owning notebook first** — from the page, the
120
+ section, or the notebook itself — and asserts the allow-list before fetching
121
+ content. Guessing a section id does not bypass it.
122
+ 3. The agent tools cannot write the allow-list. Only the settings card can, and
123
+ only through `POST /api/onenote/notebooks`.
124
+ 4. The system prompt tells the model the readable notebook names and that
125
+ everything else is unreadable by design.
126
+
127
+ ## Notes on the Graph API
128
+
129
+ - OneNote does not support app-only authentication, so a signed-in user is
130
+ required; `Notes.Read` is delegated.
131
+ - `GET /me/onenote/pages?$search=` was retired in 2024
132
+ ([announcement](https://devblogs.microsoft.com/microsoft365dev/onenote-get-pagessearch-api-deprecation)),
133
+ so search lists page metadata per allowed notebook and matches titles
134
+ locally, then reads the opening text of the most recently modified pages. That
135
+ keeps the cost bounded and never leaves the allowed set.
136
+ - Page content arrives as OneNote's HTML dialect; `src/parser.js` converts it to
137
+ Markdown without a third-party dependency and never downloads media.
138
+
139
+ ## Development
140
+
141
+ ```bash
142
+ npm test # 97 tests, no network, no host required
143
+ npm run pack:check
144
+ ```
145
+
146
+ The suite stubs `@deepseek-ai/dsh-tools` (a host-provided peer) through a Node
147
+ module hook, so a bare checkout runs without installing the harness.
148
+
149
+ ## License
150
+
151
+ MIT — see [LICENSE](./LICENSE).
package/README.zh.md ADDED
@@ -0,0 +1,135 @@
1
+ # dsh-plugin-onenote
2
+
3
+ 在 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 里读取**你亲自勾选**的
4
+ Microsoft OneNote 笔记本。
5
+
6
+ 登录一次,勾选允许本助手读取的笔记本,其余笔记本对它完全不可见。白名单在插件内部、在发出任何
7
+ Microsoft Graph 请求之前强制校验,所以即使某篇笔记试图诱导模型去读别的笔记本,它也没有可用的接口。
8
+
9
+ > English: [README.md](./README.md)
10
+
11
+ ## 界面
12
+
13
+ 设置卡片(设置 → 插件 → OneNote)是唯一可以登录、修改可读笔记本的地方:
14
+
15
+ ```
16
+ ┌ OneNote ──────────────────────────────────────────────┐
17
+ │ 已连接 │
18
+ │ 已登录:you@example.com [ 退出登录 ] │
19
+ ├───────────────────────────────────────────────────────┤
20
+ │ 可读笔记本 [ 刷新列表 ] │
21
+ │ 只有勾选的笔记本可以被列出、搜索和读取。 │
22
+ │ [x] 工作 默认 │
23
+ │ [ ] 团队 wiki 共享 │
24
+ │ [ ] 日记 │
25
+ │ 已授权 1 / 3 [ 全部取消 ] │
26
+ │ [保存] │
27
+ └───────────────────────────────────────────────────────┘
28
+ ```
29
+
30
+ ## 工具
31
+
32
+ 助手只能使用 4 个**只读**工具。它们都无法登录、登出或修改白名单——那些是设置卡片里的用户操作。
33
+
34
+ | 工具 | 作用 |
35
+ | --- | --- |
36
+ | `onenote_status` | 报告登录账号与当前可读的笔记本。 |
37
+ | `onenote_list_pages` | 浏览已授权笔记本 → 分区 → 页面。 |
38
+ | `onenote_search` | 先匹配页面标题,再匹配最近页面的开头正文。 |
39
+ | `onenote_read_page` | 把一页读成 Markdown(标题、列表、表格、链接、代码)。 |
40
+
41
+ ## 安装
42
+
43
+ ```bash
44
+ # 通过插件管理器(推荐)
45
+ dsh plugin install hestudio-community/dsh-plugin-onenote
46
+
47
+ # 或从 npm 安装
48
+ dsh plugin install dsh-plugin-onenote
49
+ ```
50
+
51
+ 安装后打开 **设置 → 插件 → OneNote** 登录。
52
+
53
+ ## Azure 应用注册
54
+
55
+ 插件内置了一个公共 Client ID,开箱即可使用。如果要用自己的应用注册(除个人使用外建议这样做),
56
+ 大约两分钟即可完成,无需付费订阅:
57
+
58
+ 1. 打开 [应用注册](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade)
59
+ → **新注册**。
60
+ 2. **名称**:任意,例如 `DSH-OneNote`。
61
+ 3. **受支持的账户类型**:选择 *任何组织目录中的帐户和个人 Microsoft 帐户*。如果所有用户都在同一租户,
62
+ 可以选单租户。
63
+ 4. **重定向 URI**:留空——设备码流程不需要。
64
+ 5. 点击 **注册**,复制 **应用程序(客户端) ID**。
65
+ 6. **身份验证 → 高级设置 → 允许公共客户端流** = **是**,然后 **保存**。不做这一步会报
66
+ `unauthorized_client`。
67
+ 7. **API 权限 → 添加权限 → Microsoft Graph → 委托的权限**:
68
+ - `Notes.Read` —— 读取用户的笔记本
69
+ - `offline_access` —— 让会话在轮次之间保持有效
70
+ - `User.Read` —— 显示登录账号名
71
+ 8. 个人账户不需要客户端密码,也不需要管理员同意。工作账户可能需要管理员授权一次。
72
+
73
+ 然后在自己的 patch 层里指向你的应用:
74
+
75
+ ```yaml
76
+ # ~/.dsh/cordis.patch.yml(对所有 profile 生效)或某个 profile 的 cordis.patch.yml
77
+ - id: onenote
78
+ name: 'dsh-plugin-onenote'
79
+ config:
80
+ clientId: 00000000-0000-0000-0000-000000000000
81
+ tenant: common
82
+ ```
83
+
84
+ `config` 会整体替换该行的配置,所以要把需要的字段全部写全。
85
+
86
+ ## 配置项
87
+
88
+ | 字段 | 默认值 | 含义 |
89
+ | --- | --- | --- |
90
+ | `clientId` | 内置公共应用 | Azure 应用程序(客户端) ID。 |
91
+ | `tenant` | `common` | 租户 ID 或域名。`common` 同时接受工作与个人账户。 |
92
+ | `maxPagesPerList` | `100` | `onenote_list_pages` 的默认页面上限。 |
93
+ | `maxPageChars` | `60000` | `onenote_read_page` 的默认 Markdown 上限。 |
94
+
95
+ ## 状态存放位置
96
+
97
+ `$DSH_HOME/onenote/`(通常是 `~/.dsh/onenote/`),权限 `0600`:
98
+
99
+ | 文件 | 内容 |
100
+ | --- | --- |
101
+ | `tokens.json` | 访问令牌与刷新令牌。 |
102
+ | `signin.json` | 进行中的设备码尝试,刷新页面后可以接着等同一个码。 |
103
+ | `settings.json` | 笔记本白名单。 |
104
+
105
+ 删除整个目录即可重置。不会往你的工作区写任何文件。
106
+
107
+ ## 隐私边界如何实现
108
+
109
+ 1. 白名单就是 `settings.json` 里的一组笔记本 ID。
110
+ 2. 每次读取都**先解析所属笔记本**——从页面、分区或笔记本本身取——再校验白名单,最后才取正文。
111
+ 猜一个分区 ID 无法绕过。
112
+ 3. 助手工具无法写白名单。只有设置卡片能写,且只通过 `POST /api/onenote/notebooks`。
113
+ 4. 系统提示会告诉模型哪些笔记本可读,并说明其余笔记本按设计不可读。
114
+
115
+ ## 关于 Graph API 的说明
116
+
117
+ - OneNote 不支持仅应用身份认证,因此必须有登录用户;`Notes.Read` 属于委托权限。
118
+ - `GET /me/onenote/pages?$search=` 已于 2024 年下线
119
+ ([官方公告](https://devblogs.microsoft.com/microsoft365dev/onenote-get-pagessearch-api-deprecation)),
120
+ 所以搜索改为:按已授权笔记本列出页面元数据、本地匹配标题,再读取最近修改页面的开头正文。
121
+ 这样开销可控,且永远不会越出白名单。
122
+ - 页面正文是 OneNote 特有的 HTML;`src/parser.js` 不依赖第三方库把它转成 Markdown,且从不下载媒体文件。
123
+
124
+ ## 开发
125
+
126
+ ```bash
127
+ npm test # 97 个测试,不需要网络,也不需要宿主
128
+ npm run pack:check
129
+ ```
130
+
131
+ 测试通过 Node 模块钩子替换了 `@deepseek-ai/dsh-tools`(由宿主提供的 peer),所以裸仓库即可运行。
132
+
133
+ ## 许可证
134
+
135
+ MIT —— 见 [LICENSE](./LICENSE)。