@agenticmail/enterprise 0.5.317 → 0.5.318

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.
@@ -0,0 +1,45 @@
1
+ import {
2
+ AgentRuntime,
3
+ EmailChannel,
4
+ FollowUpScheduler,
5
+ SessionManager,
6
+ SubAgentManager,
7
+ ToolRegistry,
8
+ callLLM,
9
+ createAgentRuntime,
10
+ createNoopHooks,
11
+ createRuntimeHooks,
12
+ estimateMessageTokens,
13
+ estimateTokens,
14
+ executeTool,
15
+ runAgentLoop,
16
+ toolsToDefinitions
17
+ } from "./chunk-MMYBDHDB.js";
18
+ import {
19
+ PROVIDER_REGISTRY,
20
+ listAllProviders,
21
+ resolveApiKeyForProvider,
22
+ resolveProvider
23
+ } from "./chunk-UF3ZJMJO.js";
24
+ import "./chunk-KFQGP6VL.js";
25
+ export {
26
+ AgentRuntime,
27
+ EmailChannel,
28
+ FollowUpScheduler,
29
+ PROVIDER_REGISTRY,
30
+ SessionManager,
31
+ SubAgentManager,
32
+ ToolRegistry,
33
+ callLLM,
34
+ createAgentRuntime,
35
+ createNoopHooks,
36
+ createRuntimeHooks,
37
+ estimateMessageTokens,
38
+ estimateTokens,
39
+ executeTool,
40
+ listAllProviders,
41
+ resolveApiKeyForProvider,
42
+ resolveProvider,
43
+ runAgentLoop,
44
+ toolsToDefinitions
45
+ };
@@ -0,0 +1,28 @@
1
+ import {
2
+ createServer
3
+ } from "./chunk-36XNMIHA.js";
4
+ import "./chunk-DJBCRQTD.js";
5
+ import "./chunk-UF3ZJMJO.js";
6
+ import "./chunk-P3HVY2HS.js";
7
+ import "./chunk-VSBC4SWO.js";
8
+ import "./chunk-AF3WSNVX.js";
9
+ import "./chunk-74ZCQKYU.js";
10
+ import "./chunk-BDCFOP7O.js";
11
+ import "./chunk-C6JP5NR6.js";
12
+ import "./chunk-M6ZIC5H3.js";
13
+ import "./chunk-PWWV2U5P.js";
14
+ import "./chunk-RH7KPWRQ.js";
15
+ import "./chunk-3FMK32KQ.js";
16
+ import "./chunk-Z7NVD3OQ.js";
17
+ import "./chunk-YDD5TC5Q.js";
18
+ import "./chunk-37ABTUFU.js";
19
+ import "./chunk-NU657BBQ.js";
20
+ import "./chunk-PGAU3W3M.js";
21
+ import "./chunk-JGEVQZDR.js";
22
+ import "./chunk-WUAWWKTN.js";
23
+ import "./chunk-HS5YWSGM.js";
24
+ import "./chunk-22U7TZPN.js";
25
+ import "./chunk-KFQGP6VL.js";
26
+ export {
27
+ createServer
28
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ promptCompanyInfo,
3
+ promptDatabase,
4
+ promptDeployment,
5
+ promptDomain,
6
+ promptRegistration,
7
+ provision,
8
+ runSetupWizard
9
+ } from "./chunk-D24JY75H.js";
10
+ import "./chunk-4EKXYIJF.js";
11
+ import "./chunk-KFQGP6VL.js";
12
+ export {
13
+ promptCompanyInfo,
14
+ promptDatabase,
15
+ promptDeployment,
16
+ promptDomain,
17
+ promptRegistration,
18
+ provision,
19
+ runSetupWizard
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticmail/enterprise",
3
- "version": "0.5.317",
3
+ "version": "0.5.318",
4
4
  "description": "AgenticMail Enterprise — cloud-hosted AI agent identity, email, auth & compliance for organizations",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Microsoft Excel Tools
3
+ *
4
+ * Spreadsheet operations via Microsoft Graph API — read/write cells, ranges, tables, worksheets.
5
+ * Works with Excel files stored in OneDrive or SharePoint.
6
+ */
7
+
8
+ import type { AnyAgentTool, ToolCreationOptions } from '../../types.js';
9
+ import { jsonResult, errorResult } from '../../common.js';
10
+ import type { MicrosoftToolsConfig } from './index.js';
11
+ import { graph } from './graph-api.js';
12
+
13
+ function itemPath(p: { itemId?: string; path?: string; driveId?: string }): string {
14
+ if (p.driveId && p.itemId) return `/drives/${p.driveId}/items/${p.itemId}`;
15
+ if (p.itemId) return `/me/drive/items/${p.itemId}`;
16
+ if (p.path) return `/me/drive/root:${p.path}:`;
17
+ throw new Error('Provide itemId or path to the Excel file');
18
+ }
19
+
20
+ export function createExcelTools(config: MicrosoftToolsConfig, _options?: ToolCreationOptions): AnyAgentTool[] {
21
+ const tp = config.tokenProvider;
22
+
23
+ return [
24
+ {
25
+ name: 'excel_list_worksheets',
26
+ description: 'List all worksheets in an Excel workbook.',
27
+ category: 'utility' as const,
28
+ parameters: {
29
+ type: 'object' as const,
30
+ properties: {
31
+ itemId: { type: 'string', description: 'OneDrive/SharePoint item ID of the Excel file' },
32
+ path: { type: 'string', description: 'File path (alternative to itemId, e.g., "/Documents/Budget.xlsx")' },
33
+ driveId: { type: 'string', description: 'Drive ID (for SharePoint drives)' },
34
+ },
35
+ required: [],
36
+ },
37
+ async execute(_id: string, params: any) {
38
+ try {
39
+ const token = await tp.getAccessToken();
40
+ const base = itemPath(params);
41
+ const data = await graph(token, `${base}/workbook/worksheets`);
42
+ const sheets = (data.value || []).map((s: any) => ({
43
+ id: s.id, name: s.name, position: s.position, visibility: s.visibility,
44
+ }));
45
+ return jsonResult({ worksheets: sheets, count: sheets.length });
46
+ } catch (e: any) { return errorResult(e.message); }
47
+ },
48
+ },
49
+
50
+ {
51
+ name: 'excel_read_range',
52
+ description: 'Read a range of cells from an Excel worksheet. Returns values, formulas, and formatting.',
53
+ category: 'utility' as const,
54
+ parameters: {
55
+ type: 'object' as const,
56
+ properties: {
57
+ itemId: { type: 'string', description: 'OneDrive/SharePoint item ID' },
58
+ path: { type: 'string', description: 'File path (alternative to itemId)' },
59
+ driveId: { type: 'string', description: 'Drive ID (for SharePoint)' },
60
+ worksheet: { type: 'string', description: 'Worksheet name (default: first sheet)' },
61
+ range: { type: 'string', description: 'Cell range (e.g., "A1:D10", "Sheet1!A1:Z100"). Omit for used range.' },
62
+ },
63
+ required: [],
64
+ },
65
+ async execute(_id: string, params: any) {
66
+ try {
67
+ const token = await tp.getAccessToken();
68
+ const base = itemPath(params);
69
+ let rangePath: string;
70
+ if (params.range) {
71
+ const ws = params.worksheet ? `/worksheets/${encodeURIComponent(params.worksheet)}` : '/worksheets';
72
+ // If range contains !, it has sheet name embedded
73
+ if (params.range.includes('!')) {
74
+ rangePath = `${base}/workbook/worksheets/${encodeURIComponent(params.range.split('!')[0])}/range(address='${params.range.split('!')[1]}')`;
75
+ } else if (params.worksheet) {
76
+ rangePath = `${base}/workbook/worksheets/${encodeURIComponent(params.worksheet)}/range(address='${params.range}')`;
77
+ } else {
78
+ rangePath = `${base}/workbook/worksheets('Sheet1')/range(address='${params.range}')`;
79
+ }
80
+ } else {
81
+ const ws = params.worksheet || 'Sheet1';
82
+ rangePath = `${base}/workbook/worksheets/${encodeURIComponent(ws)}/usedRange`;
83
+ }
84
+ const data = await graph(token, rangePath, {
85
+ query: { '$select': 'address,values,text,formulas,numberFormat,rowCount,columnCount' }
86
+ });
87
+ return jsonResult({
88
+ address: data.address,
89
+ values: data.values,
90
+ text: data.text,
91
+ formulas: data.formulas,
92
+ rows: data.rowCount,
93
+ columns: data.columnCount,
94
+ });
95
+ } catch (e: any) { return errorResult(e.message); }
96
+ },
97
+ },
98
+
99
+ {
100
+ name: 'excel_write_range',
101
+ description: 'Write values to a range of cells in an Excel worksheet.',
102
+ category: 'utility' as const,
103
+ parameters: {
104
+ type: 'object' as const,
105
+ properties: {
106
+ itemId: { type: 'string', description: 'OneDrive/SharePoint item ID' },
107
+ path: { type: 'string', description: 'File path (alternative to itemId)' },
108
+ driveId: { type: 'string', description: 'Drive ID (for SharePoint)' },
109
+ worksheet: { type: 'string', description: 'Worksheet name (default: Sheet1)' },
110
+ range: { type: 'string', description: 'Cell range to write to (e.g., "A1:C3")' },
111
+ values: { type: 'array', description: 'Array of arrays — each inner array is a row (e.g., [["Name","Age"],["Alice",30]])' },
112
+ },
113
+ required: ['range', 'values'],
114
+ },
115
+ async execute(_id: string, params: any) {
116
+ try {
117
+ const token = await tp.getAccessToken();
118
+ const base = itemPath(params);
119
+ const ws = params.worksheet || 'Sheet1';
120
+ await graph(token, `${base}/workbook/worksheets/${encodeURIComponent(ws)}/range(address='${params.range}')`, {
121
+ method: 'PATCH',
122
+ body: { values: params.values },
123
+ });
124
+ return jsonResult({ written: true, range: params.range, worksheet: ws });
125
+ } catch (e: any) { return errorResult(e.message); }
126
+ },
127
+ },
128
+
129
+ {
130
+ name: 'excel_add_row',
131
+ description: 'Add a row to an Excel table (structured table, not just a range).',
132
+ category: 'utility' as const,
133
+ parameters: {
134
+ type: 'object' as const,
135
+ properties: {
136
+ itemId: { type: 'string', description: 'OneDrive/SharePoint item ID' },
137
+ path: { type: 'string', description: 'File path' },
138
+ driveId: { type: 'string', description: 'Drive ID' },
139
+ worksheet: { type: 'string', description: 'Worksheet name' },
140
+ tableName: { type: 'string', description: 'Table name (default: first table found)' },
141
+ values: { type: 'array', description: 'Row values as array (e.g., ["Alice", 30, "alice@example.com"])' },
142
+ },
143
+ required: ['values'],
144
+ },
145
+ async execute(_id: string, params: any) {
146
+ try {
147
+ const token = await tp.getAccessToken();
148
+ const base = itemPath(params);
149
+ let tablePath: string;
150
+ if (params.tableName) {
151
+ tablePath = params.worksheet
152
+ ? `${base}/workbook/worksheets/${encodeURIComponent(params.worksheet)}/tables/${encodeURIComponent(params.tableName)}`
153
+ : `${base}/workbook/tables/${encodeURIComponent(params.tableName)}`;
154
+ } else {
155
+ // Get first table
156
+ const ws = params.worksheet || 'Sheet1';
157
+ const tables = await graph(token, `${base}/workbook/worksheets/${encodeURIComponent(ws)}/tables`);
158
+ if (!tables.value?.length) throw new Error('No tables found in worksheet. Create a table first or use excel_write_range.');
159
+ tablePath = `${base}/workbook/tables/${tables.value[0].id}`;
160
+ }
161
+ const row = await graph(token, `${tablePath}/rows/add`, {
162
+ method: 'POST',
163
+ body: { values: [params.values] },
164
+ });
165
+ return jsonResult({ added: true, index: row.index });
166
+ } catch (e: any) { return errorResult(e.message); }
167
+ },
168
+ },
169
+
170
+ {
171
+ name: 'excel_list_tables',
172
+ description: 'List all tables in an Excel workbook or specific worksheet.',
173
+ category: 'utility' as const,
174
+ parameters: {
175
+ type: 'object' as const,
176
+ properties: {
177
+ itemId: { type: 'string', description: 'OneDrive/SharePoint item ID' },
178
+ path: { type: 'string', description: 'File path' },
179
+ driveId: { type: 'string', description: 'Drive ID' },
180
+ worksheet: { type: 'string', description: 'Worksheet name (omit for all tables in workbook)' },
181
+ },
182
+ required: [],
183
+ },
184
+ async execute(_id: string, params: any) {
185
+ try {
186
+ const token = await tp.getAccessToken();
187
+ const base = itemPath(params);
188
+ const tablesPath = params.worksheet
189
+ ? `${base}/workbook/worksheets/${encodeURIComponent(params.worksheet)}/tables`
190
+ : `${base}/workbook/tables`;
191
+ const data = await graph(token, tablesPath);
192
+ const tables = (data.value || []).map((t: any) => ({
193
+ id: t.id, name: t.name, rows: t.rowCount,
194
+ columns: t.columns?.length, showHeaders: t.showHeaders,
195
+ style: t.style,
196
+ }));
197
+ return jsonResult({ tables, count: tables.length });
198
+ } catch (e: any) { return errorResult(e.message); }
199
+ },
200
+ },
201
+
202
+ {
203
+ name: 'excel_read_table',
204
+ description: 'Read all data from an Excel table including headers.',
205
+ category: 'utility' as const,
206
+ parameters: {
207
+ type: 'object' as const,
208
+ properties: {
209
+ itemId: { type: 'string', description: 'OneDrive/SharePoint item ID' },
210
+ path: { type: 'string', description: 'File path' },
211
+ driveId: { type: 'string', description: 'Drive ID' },
212
+ tableName: { type: 'string', description: 'Table name or ID' },
213
+ },
214
+ required: ['tableName'],
215
+ },
216
+ async execute(_id: string, params: any) {
217
+ try {
218
+ const token = await tp.getAccessToken();
219
+ const base = itemPath(params);
220
+ const [headerData, bodyData] = await Promise.all([
221
+ graph(token, `${base}/workbook/tables/${encodeURIComponent(params.tableName)}/headerRowRange`),
222
+ graph(token, `${base}/workbook/tables/${encodeURIComponent(params.tableName)}/dataBodyRange`),
223
+ ]);
224
+ return jsonResult({
225
+ headers: headerData.values?.[0],
226
+ rows: bodyData.values,
227
+ rowCount: bodyData.rowCount,
228
+ columnCount: bodyData.columnCount,
229
+ });
230
+ } catch (e: any) { return errorResult(e.message); }
231
+ },
232
+ },
233
+
234
+ {
235
+ name: 'excel_create_worksheet',
236
+ description: 'Add a new worksheet to an Excel workbook.',
237
+ category: 'utility' as const,
238
+ parameters: {
239
+ type: 'object' as const,
240
+ properties: {
241
+ itemId: { type: 'string', description: 'OneDrive/SharePoint item ID' },
242
+ path: { type: 'string', description: 'File path' },
243
+ driveId: { type: 'string', description: 'Drive ID' },
244
+ name: { type: 'string', description: 'Worksheet name' },
245
+ },
246
+ required: ['name'],
247
+ },
248
+ async execute(_id: string, params: any) {
249
+ try {
250
+ const token = await tp.getAccessToken();
251
+ const base = itemPath(params);
252
+ const ws = await graph(token, `${base}/workbook/worksheets/add`, {
253
+ method: 'POST',
254
+ body: { name: params.name },
255
+ });
256
+ return jsonResult({ id: ws.id, name: ws.name, position: ws.position });
257
+ } catch (e: any) { return errorResult(e.message); }
258
+ },
259
+ },
260
+ ];
261
+ }
@@ -19,6 +19,9 @@ export { createOneDriveTools } from './onedrive.js';
19
19
  export { createTeamsTools } from './teams.js';
20
20
  export { createTodoTools } from './todo.js';
21
21
  export { createOutlookContactsTools } from './contacts.js';
22
+ export { createExcelTools } from './excel.js';
23
+ export { createSharePointTools } from './sharepoint.js';
24
+ export { createOneNoteTools } from './onenote.js';
22
25
 
23
26
  import type { AnyAgentTool, ToolCreationOptions } from '../../types.js';
24
27
  import type { TokenProvider } from '../oauth-token-provider.js';
@@ -30,6 +33,9 @@ import { createOneDriveTools } from './onedrive.js';
30
33
  import { createTeamsTools } from './teams.js';
31
34
  import { createTodoTools } from './todo.js';
32
35
  import { createOutlookContactsTools } from './contacts.js';
36
+ import { createExcelTools } from './excel.js';
37
+ import { createSharePointTools } from './sharepoint.js';
38
+ import { createOneNoteTools } from './onenote.js';
33
39
 
34
40
  export interface MicrosoftToolsConfig {
35
41
  tokenProvider: TokenProvider;
@@ -37,7 +43,20 @@ export interface MicrosoftToolsConfig {
37
43
 
38
44
  /**
39
45
  * Create all Microsoft 365 tools for an agent.
40
- * Returns tools covering Outlook Mail, Calendar, OneDrive, Teams, To Do, and Contacts.
46
+ *
47
+ * 9 services, 70+ tools:
48
+ * - Outlook Mail (13 tools) — inbox, send, reply, forward, search, drafts, attachments
49
+ * - Outlook Calendar (7 tools) — events, create, free/busy, respond to invites
50
+ * - OneDrive (7 tools) — files, folders, search, upload, share
51
+ * - Teams (8 tools) — channels, chats, messages, presence
52
+ * - To Do (6 tools) — task lists, tasks CRUD
53
+ * - Contacts (5 tools) — address book, people search
54
+ * - Excel (7 tools) — read/write cells, ranges, tables, worksheets
55
+ * - SharePoint (10 tools) — sites, document libraries, lists, search
56
+ * - OneNote (6 tools) — notebooks, sections, pages, read/write
57
+ *
58
+ * Core services (mail, calendar, onedrive, tasks) load by default.
59
+ * Enable additional services via enabledMicrosoftServices option.
41
60
  */
42
61
  export function createAllMicrosoftTools(config: MicrosoftToolsConfig, options?: ToolCreationOptions): AnyAgentTool[] {
43
62
  const enabled = (options as any)?.enabledMicrosoftServices as string[] | undefined;
@@ -45,11 +64,16 @@ export function createAllMicrosoftTools(config: MicrosoftToolsConfig, options?:
45
64
  const core = !enabled; // default: load core services
46
65
 
47
66
  const tools: AnyAgentTool[] = [];
48
- if (core || has('mail')) tools.push(...createOutlookMailTools(config, options));
49
- if (core || has('calendar')) tools.push(...createOutlookCalendarTools(config, options));
50
- if (core || has('onedrive')) tools.push(...createOneDriveTools(config, options));
51
- if (core || has('tasks')) tools.push(...createTodoTools(config, options));
52
- if (has('teams')) tools.push(...createTeamsTools(config, options));
53
- if (has('contacts')) tools.push(...createOutlookContactsTools(config, options));
67
+ // Core services (always loaded unless explicitly selecting)
68
+ if (core || has('mail')) tools.push(...createOutlookMailTools(config, options));
69
+ if (core || has('calendar')) tools.push(...createOutlookCalendarTools(config, options));
70
+ if (core || has('onedrive')) tools.push(...createOneDriveTools(config, options));
71
+ if (core || has('tasks')) tools.push(...createTodoTools(config, options));
72
+ // Extended services (opt-in)
73
+ if (has('teams')) tools.push(...createTeamsTools(config, options));
74
+ if (has('contacts')) tools.push(...createOutlookContactsTools(config, options));
75
+ if (has('excel')) tools.push(...createExcelTools(config, options));
76
+ if (has('sharepoint')) tools.push(...createSharePointTools(config, options));
77
+ if (has('onenote')) tools.push(...createOneNoteTools(config, options));
54
78
  return tools;
55
79
  }
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Microsoft OneNote Tools
3
+ *
4
+ * Notebooks, sections, and pages via Microsoft Graph API.
5
+ */
6
+
7
+ import type { AnyAgentTool, ToolCreationOptions } from '../../types.js';
8
+ import { jsonResult, errorResult } from '../../common.js';
9
+ import type { MicrosoftToolsConfig } from './index.js';
10
+ import { graph } from './graph-api.js';
11
+
12
+ export function createOneNoteTools(config: MicrosoftToolsConfig, _options?: ToolCreationOptions): AnyAgentTool[] {
13
+ const tp = config.tokenProvider;
14
+
15
+ return [
16
+ {
17
+ name: 'onenote_list_notebooks',
18
+ description: 'List all OneNote notebooks.',
19
+ category: 'utility' as const,
20
+ parameters: { type: 'object' as const, properties: {}, required: [] },
21
+ async execute(_id: string) {
22
+ try {
23
+ const token = await tp.getAccessToken();
24
+ const data = await graph(token, '/me/onenote/notebooks', {
25
+ query: { '$select': 'id,displayName,createdDateTime,lastModifiedDateTime,isShared,links', '$orderby': 'lastModifiedDateTime desc' }
26
+ });
27
+ const notebooks = (data.value || []).map((n: any) => ({
28
+ id: n.id, name: n.displayName, created: n.createdDateTime,
29
+ modified: n.lastModifiedDateTime, isShared: n.isShared,
30
+ webUrl: n.links?.oneNoteWebUrl?.href,
31
+ }));
32
+ return jsonResult({ notebooks, count: notebooks.length });
33
+ } catch (e: any) { return errorResult(e.message); }
34
+ },
35
+ },
36
+
37
+ {
38
+ name: 'onenote_list_sections',
39
+ description: 'List sections in a OneNote notebook.',
40
+ category: 'utility' as const,
41
+ parameters: {
42
+ type: 'object' as const,
43
+ properties: {
44
+ notebookId: { type: 'string', description: 'Notebook ID' },
45
+ },
46
+ required: ['notebookId'],
47
+ },
48
+ async execute(_id: string, params: any) {
49
+ try {
50
+ const token = await tp.getAccessToken();
51
+ const data = await graph(token, `/me/onenote/notebooks/${params.notebookId}/sections`, {
52
+ query: { '$select': 'id,displayName,createdDateTime,lastModifiedDateTime' }
53
+ });
54
+ const sections = (data.value || []).map((s: any) => ({
55
+ id: s.id, name: s.displayName,
56
+ created: s.createdDateTime, modified: s.lastModifiedDateTime,
57
+ }));
58
+ return jsonResult({ sections, count: sections.length });
59
+ } catch (e: any) { return errorResult(e.message); }
60
+ },
61
+ },
62
+
63
+ {
64
+ name: 'onenote_list_pages',
65
+ description: 'List pages in a OneNote section.',
66
+ category: 'utility' as const,
67
+ parameters: {
68
+ type: 'object' as const,
69
+ properties: {
70
+ sectionId: { type: 'string', description: 'Section ID' },
71
+ maxResults: { type: 'number', description: 'Max pages (default: 20)' },
72
+ },
73
+ required: ['sectionId'],
74
+ },
75
+ async execute(_id: string, params: any) {
76
+ try {
77
+ const token = await tp.getAccessToken();
78
+ const data = await graph(token, `/me/onenote/sections/${params.sectionId}/pages`, {
79
+ query: {
80
+ '$top': String(params.maxResults || 20),
81
+ '$select': 'id,title,createdDateTime,lastModifiedDateTime,links,level,order',
82
+ '$orderby': 'lastModifiedDateTime desc',
83
+ }
84
+ });
85
+ const pages = (data.value || []).map((p: any) => ({
86
+ id: p.id, title: p.title,
87
+ created: p.createdDateTime, modified: p.lastModifiedDateTime,
88
+ webUrl: p.links?.oneNoteWebUrl?.href,
89
+ }));
90
+ return jsonResult({ pages, count: pages.length });
91
+ } catch (e: any) { return errorResult(e.message); }
92
+ },
93
+ },
94
+
95
+ {
96
+ name: 'onenote_read_page',
97
+ description: 'Read the HTML content of a OneNote page.',
98
+ category: 'utility' as const,
99
+ parameters: {
100
+ type: 'object' as const,
101
+ properties: {
102
+ pageId: { type: 'string', description: 'Page ID' },
103
+ },
104
+ required: ['pageId'],
105
+ },
106
+ async execute(_id: string, params: any) {
107
+ try {
108
+ const token = await tp.getAccessToken();
109
+ const res = await fetch(`https://graph.microsoft.com/v1.0/me/onenote/pages/${params.pageId}/content`, {
110
+ headers: { Authorization: `Bearer ${token}` },
111
+ });
112
+ if (!res.ok) throw new Error(`OneNote API ${res.status}: ${await res.text()}`);
113
+ const html = await res.text();
114
+ // Strip HTML tags for a cleaner text view
115
+ const text = html.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim();
116
+ return jsonResult({ pageId: params.pageId, html, text: text.substring(0, 10000) });
117
+ } catch (e: any) { return errorResult(e.message); }
118
+ },
119
+ },
120
+
121
+ {
122
+ name: 'onenote_create_page',
123
+ description: 'Create a new page in a OneNote section. Content is HTML.',
124
+ category: 'utility' as const,
125
+ parameters: {
126
+ type: 'object' as const,
127
+ properties: {
128
+ sectionId: { type: 'string', description: 'Section ID to create the page in' },
129
+ title: { type: 'string', description: 'Page title' },
130
+ content: { type: 'string', description: 'Page content (HTML or plain text)' },
131
+ },
132
+ required: ['sectionId', 'title', 'content'],
133
+ },
134
+ async execute(_id: string, params: any) {
135
+ try {
136
+ const token = await tp.getAccessToken();
137
+ const html = `<!DOCTYPE html><html><head><title>${params.title}</title></head><body>${params.content}</body></html>`;
138
+ const res = await fetch(`https://graph.microsoft.com/v1.0/me/onenote/sections/${params.sectionId}/pages`, {
139
+ method: 'POST',
140
+ headers: {
141
+ Authorization: `Bearer ${token}`,
142
+ 'Content-Type': 'application/xhtml+xml',
143
+ },
144
+ body: html,
145
+ });
146
+ if (!res.ok) throw new Error(`OneNote API ${res.status}: ${await res.text()}`);
147
+ const page = await res.json();
148
+ return jsonResult({
149
+ id: page.id, title: page.title,
150
+ webUrl: page.links?.oneNoteWebUrl?.href,
151
+ created: true,
152
+ });
153
+ } catch (e: any) { return errorResult(e.message); }
154
+ },
155
+ },
156
+
157
+ {
158
+ name: 'onenote_update_page',
159
+ description: 'Append content to an existing OneNote page.',
160
+ category: 'utility' as const,
161
+ parameters: {
162
+ type: 'object' as const,
163
+ properties: {
164
+ pageId: { type: 'string', description: 'Page ID' },
165
+ content: { type: 'string', description: 'HTML content to append' },
166
+ position: { type: 'string', description: 'Where to add: after (end of body) or before (start of body). Default: after' },
167
+ },
168
+ required: ['pageId', 'content'],
169
+ },
170
+ async execute(_id: string, params: any) {
171
+ try {
172
+ const token = await tp.getAccessToken();
173
+ await graph(token, `/me/onenote/pages/${params.pageId}/content`, {
174
+ method: 'PATCH',
175
+ body: [{
176
+ target: 'body',
177
+ action: params.position === 'before' ? 'prepend' : 'append',
178
+ content: params.content,
179
+ }],
180
+ });
181
+ return jsonResult({ updated: true, pageId: params.pageId });
182
+ } catch (e: any) { return errorResult(e.message); }
183
+ },
184
+ },
185
+ ];
186
+ }