@opentabs-dev/opentabs-plugin-microsoft-word 0.0.75 → 0.0.77

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
@@ -1,159 +1,87 @@
1
- # opentabs-plugin-microsoft-word
1
+ # Microsoft Word
2
2
 
3
- OpenTabs plugin for Microsoft Word Online
3
+ OpenTabs plugin for Microsoft Word Online — gives AI agents access to Microsoft Word through your authenticated browser session.
4
4
 
5
- ## Project Structure
5
+ ## Install
6
6
 
7
+ ```bash
8
+ opentabs plugin install microsoft-word
7
9
  ```
8
- microsoft-word/
9
- ├── package.json # Plugin metadata (name, opentabs field, dependencies)
10
- ├── icon.svg # Optional custom icon (square SVG, max 8KB)
11
- ├── icon-inactive.svg # Optional manual inactive icon override
12
- ├── src/
13
- │ ├── index.ts # Plugin class (extends OpenTabsPlugin)
14
- │ └── tools/ # One file per tool (using defineTool)
15
- │ └── example.ts
16
- └── dist/ # Build output (generated)
17
- ├── adapter.iife.js # Bundled adapter injected into matching tabs
18
- └── tools.json # Tool schemas for MCP registration
19
- ```
20
-
21
- ## Configuration
22
-
23
- Plugin metadata is defined in `package.json` under the `opentabs` field:
24
-
25
- ```json
26
- {
27
- "name": "opentabs-plugin-microsoft-word",
28
- "main": "dist/adapter.iife.js",
29
- "opentabs": {
30
- "displayName": "Microsoft Word",
31
- "description": "OpenTabs plugin for Microsoft Word Online",
32
- "urlPatterns": ["*://*.word.cloud.microsoft/*"]
33
- }
34
- }
35
- ```
36
-
37
- - **`main`** — entry point for the bundled adapter IIFE
38
- - **`opentabs.displayName`** — human-readable name shown in the side panel
39
- - **`opentabs.description`** — short description of what the plugin does
40
- - **`opentabs.urlPatterns`** — Chrome match patterns for tabs where the adapter is injected
41
-
42
- ## Custom Icons
43
10
 
44
- By default, the side panel shows a colored letter avatar for your plugin. To use a custom icon, place an `icon.svg` file in the plugin root (next to `package.json`):
11
+ Or install globally via npm:
45
12
 
46
- ```
47
- microsoft-word/
48
- ├── package.json
49
- ├── icon.svg ← custom icon (optional)
50
- ├── icon-inactive.svg ← manual inactive override (optional, requires icon.svg)
51
- ├── src/
52
- │ └── ...
13
+ ```bash
14
+ npm install -g @opentabs-dev/opentabs-plugin-microsoft-word
53
15
  ```
54
16
 
55
- **How it works:**
17
+ ## Setup
56
18
 
57
- - `opentabs-plugin build` reads `icon.svg`, validates it, auto-generates a grayscale inactive variant, and embeds both in `dist/tools.json`
58
- - To override the auto-generated inactive icon, provide `icon-inactive.svg` (must use only grayscale colors)
59
- - If no `icon.svg` is provided, the letter avatar is used automatically
19
+ 1. Open [word.cloud.microsoft](https://word.cloud.microsoft) in Chrome and log in
20
+ 2. Open the OpenTabs side panel the Microsoft Word plugin should appear as **ready**
60
21
 
61
- **Icon requirements:**
22
+ ## Tools (27)
62
23
 
63
- - Square SVG with a `viewBox` attribute (e.g., `viewBox="0 0 32 32"`)
64
- - Maximum 8 KB file size
65
- - No embedded `<image>`, `<script>`, or event handler attributes (`onclick`, etc.)
66
- - Manual `icon-inactive.svg` must use only achromatic (grayscale) colors
24
+ ### Account (1)
67
25
 
68
- ## Development
26
+ | Tool | Description | Type |
27
+ |---|---|---|
28
+ | `get_current_user` | Get the current user profile | Read |
69
29
 
70
- ```bash
71
- npm install
72
- npm run build # tsc && opentabs-plugin build
73
- npm run dev # watch mode (tsc --watch + opentabs-plugin build --watch)
74
- npm run type-check # tsc --noEmit
75
- npm run lint # biome
76
- ```
77
-
78
- ## Adding Tools
79
-
80
- Create a new file in `src/tools/` using `defineTool`:
81
-
82
- ```ts
83
- import { z } from 'zod';
84
- import { defineTool } from '@opentabs-dev/plugin-sdk';
85
-
86
- export const myTool = defineTool({
87
- name: 'my_tool',
88
- displayName: 'My Tool',
89
- description: 'What this tool does',
90
- icon: 'wrench',
91
- input: z.object({ /* ... */ }),
92
- output: z.object({ /* ... */ }),
93
- handle: async (params) => {
94
- // Tool implementation runs in the browser tab context
95
- return { /* ... */ };
96
- },
97
- });
98
- ```
99
-
100
- Then register it in `src/index.ts` by adding it to the `tools` array.
30
+ ### Drive (1)
101
31
 
102
- ## Authentication
32
+ | Tool | Description | Type |
33
+ |---|---|---|
34
+ | `get_drive` | Get OneDrive details | Read |
103
35
 
104
- Plugin tools run in the browser tab context, so they can read auth tokens directly from the page. The SDK provides utilities for the most common patterns:
36
+ ### Documents (6)
105
37
 
106
- ```ts
107
- import { getLocalStorage, getCookie, getPageGlobal } from '@opentabs-dev/plugin-sdk';
38
+ | Tool | Description | Type |
39
+ |---|---|---|
40
+ | `get_active_document` | Get the currently open document | Read |
41
+ | `get_document_text` | Extract text from a Word document | Read |
42
+ | `create_document` | Create a new Word document with text | Write |
43
+ | `update_document` | Replace all text in a Word document | Write |
44
+ | `append_to_document` | Append paragraphs to a Word document | Write |
45
+ | `replace_text_in_document` | Find and replace text in a Word document | Write |
108
46
 
109
- // localStorage — most common
110
- const token = getLocalStorage('token');
47
+ ### Files (14)
111
48
 
112
- // Cookies session tokens, JWTs
113
- const session = getCookie('session_id');
49
+ | Tool | Description | Type |
50
+ |---|---|---|
51
+ | `get_file_content` | Read text content of a file | Read |
52
+ | `list_recent_documents` | List recent documents | Read |
53
+ | `list_children` | List files and folders | Read |
54
+ | `get_item` | Get file or folder details | Read |
55
+ | `search_files` | Search files and folders | Read |
56
+ | `create_folder` | Create a folder | Write |
57
+ | `upload_file` | Upload a text file to OneDrive | Write |
58
+ | `update_file_content` | Update a file's content | Write |
59
+ | `rename_item` | Rename a file or folder | Write |
60
+ | `move_item` | Move a file or folder | Write |
61
+ | `copy_item` | Copy a file or folder | Write |
62
+ | `delete_item` | Delete a file or folder | Write |
63
+ | `list_shared_with_me` | List files shared with me | Read |
64
+ | `get_preview_url` | Get a document preview URL | Read |
114
65
 
115
- // Page globals — SPA boot data (e.g., window.__APP_STATE__)
116
- const appState = getPageGlobal('__APP_STATE__');
117
- ```
118
-
119
- **Iframe fallback:** Some apps (e.g., Discord) delete `window.localStorage` after boot. `getLocalStorage` automatically tries a hidden same-origin iframe fallback before returning `null`, so you don't need to handle this case manually.
66
+ ### Sharing (3)
120
67
 
121
- **SPA hydration:** Auth tokens may not be available immediately on page load. Implement polling in `isReady()` to wait until the app has hydrated before your tools run. See the comments in `src/index.ts` for an example polling pattern.
68
+ | Tool | Description | Type |
69
+ |---|---|---|
70
+ | `create_sharing_link` | Create a sharing link for a file or folder | Write |
71
+ | `list_permissions` | List sharing permissions | Read |
72
+ | `delete_permission` | Remove a sharing permission | Write |
122
73
 
123
- ## Shared Schemas
74
+ ### Versions (2)
124
75
 
125
- When 3 or more tools share the same input or output shape, extract common Zod schemas into a shared file to avoid duplication:
76
+ | Tool | Description | Type |
77
+ |---|---|---|
78
+ | `list_versions` | List file version history | Read |
79
+ | `restore_version` | Restore a file version | Write |
126
80
 
127
- ```ts
128
- // src/schemas/channel.ts
129
- import { z } from 'zod';
81
+ ## How It Works
130
82
 
131
- export const channelSchema = z.object({
132
- id: z.string().describe('Channel ID'),
133
- name: z.string().describe('Channel name'),
134
- });
83
+ This plugin runs inside your Microsoft Word tab through the [OpenTabs](https://opentabs.dev) Chrome extension. It uses your existing browser session — no API tokens or OAuth apps required. All operations happen as you, with your permissions.
135
84
 
136
- export type Channel = z.infer<typeof channelSchema>;
137
- ```
138
-
139
- Then import and reuse in your tools:
140
-
141
- ```ts
142
- // src/tools/list-channels.ts
143
- import { channelSchema } from '../schemas/channel.js';
144
-
145
- export const listChannels = defineTool({
146
- name: 'list_channels',
147
- displayName: 'List Channels',
148
- description: 'List all available channels',
149
- icon: 'list',
150
- input: z.object({}),
151
- output: z.object({ channels: z.array(channelSchema) }),
152
- handle: async () => {
153
- // ...
154
- return { channels: [] };
155
- },
156
- });
157
- ```
85
+ ## License
158
86
 
159
- This keeps your tool schemas DRY and makes it easy to evolve shared types in one place.
87
+ MIT
@@ -248,18 +248,18 @@
248
248
 
249
249
  // node_modules/@opentabs-dev/plugin-sdk/dist/storage.js
250
250
  var getLocalStorage = (key) => {
251
- try {
252
- return localStorage.getItem(key);
253
- } catch {
254
- }
255
251
  let storage;
256
252
  try {
257
- storage = localStorage;
253
+ storage = window.localStorage;
258
254
  } catch {
259
255
  return null;
260
256
  }
261
- if (storage !== void 0) {
262
- return null;
257
+ if (storage) {
258
+ try {
259
+ return storage.getItem(key);
260
+ } catch {
261
+ return null;
262
+ }
263
263
  }
264
264
  try {
265
265
  const iframe = document.createElement("iframe");
@@ -287,18 +287,19 @@
287
287
  }
288
288
  return null;
289
289
  };
290
- try {
291
- return search(localStorage);
292
- } catch {
293
- }
294
290
  let storage;
295
291
  try {
296
- storage = localStorage;
292
+ storage = window.localStorage;
297
293
  } catch {
298
294
  return null;
299
295
  }
300
- if (storage !== void 0)
301
- return null;
296
+ if (storage) {
297
+ try {
298
+ return search(storage);
299
+ } catch {
300
+ return null;
301
+ }
302
+ }
302
303
  try {
303
304
  const iframe = document.createElement("iframe");
304
305
  iframe.style.display = "none";
@@ -364,6 +365,8 @@
364
365
  * (e.g., 'https://github.com'), not a match pattern.
365
366
  */
366
367
  homepage;
368
+ /** Typed configuration schema — declares settings that users provide via config.json or the side panel. */
369
+ configSchema;
367
370
  };
368
371
 
369
372
  // src/microsoft-word-api.ts
@@ -15653,21 +15656,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15653
15656
  };
15654
15657
  var src_default = new MicrosoftWordPlugin();
15655
15658
 
15656
- // dist/_adapter_entry_c537bceb-a306-43a7-a859-aab859a56c7b.ts
15659
+ // dist/_adapter_entry_0965f804-0cca-408d-832b-ab16d60163f1.ts
15657
15660
  if (!globalThis.__openTabs) {
15658
15661
  globalThis.__openTabs = {};
15659
15662
  } else {
15660
15663
  const desc = Object.getOwnPropertyDescriptor(globalThis.__openTabs, "adapters");
15661
15664
  if (desc && !desc.writable) {
15662
- const ot2 = globalThis.__openTabs;
15665
+ const ot3 = globalThis.__openTabs;
15663
15666
  const newAdaptersObj = {};
15664
- if (ot2.adapters) {
15665
- for (const key of Object.keys(ot2.adapters)) {
15666
- const d = Object.getOwnPropertyDescriptor(ot2.adapters, key);
15667
+ if (ot3.adapters) {
15668
+ for (const key of Object.keys(ot3.adapters)) {
15669
+ const d = Object.getOwnPropertyDescriptor(ot3.adapters, key);
15667
15670
  if (d) Object.defineProperty(newAdaptersObj, key, d);
15668
15671
  }
15669
15672
  }
15670
- globalThis.__openTabs = Object.assign({}, ot2, { adapters: newAdaptersObj });
15673
+ globalThis.__openTabs = Object.assign({}, ot3, { adapters: newAdaptersObj });
15671
15674
  }
15672
15675
  }
15673
15676
  if (!globalThis.__openTabs.adapters) {
@@ -15705,6 +15708,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15705
15708
  }
15706
15709
  };
15707
15710
  var restoreTransport = setLogTransport ? setLogTransport(logTransport) : void 0;
15711
+ var ot2 = globalThis.__openTabs;
15712
+ ot2._notifyReadinessChanged = () => {
15713
+ try {
15714
+ const nonce = globalThis.__openTabs?._readinessNonce;
15715
+ if (nonce) {
15716
+ window.postMessage({ type: "opentabs:readiness-changed", plugin: "microsoft-word", nonce }, "*");
15717
+ }
15718
+ } catch {
15719
+ }
15720
+ };
15708
15721
  var existing = adapters["microsoft-word"];
15709
15722
  if (existing) {
15710
15723
  if (typeof existing.teardown === "function") {
@@ -15716,7 +15729,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15716
15729
  }
15717
15730
  }
15718
15731
  if (!Reflect.deleteProperty(adapters, "microsoft-word")) {
15719
- const ot2 = globalThis.__openTabs;
15732
+ const ot3 = globalThis.__openTabs;
15720
15733
  const newAdapters = {};
15721
15734
  for (const key of Object.keys(adapters)) {
15722
15735
  if (key !== "microsoft-word") {
@@ -15724,7 +15737,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15724
15737
  if (desc) Object.defineProperty(newAdapters, key, desc);
15725
15738
  }
15726
15739
  }
15727
- globalThis.__openTabs = Object.assign({}, ot2, { adapters: newAdapters });
15740
+ globalThis.__openTabs = Object.assign({}, ot3, { adapters: newAdapters });
15728
15741
  }
15729
15742
  var hasLifecycleHooks = typeof src_default.onToolInvocationStart === "function" || typeof src_default.onToolInvocationEnd === "function";
15730
15743
  for (const tool of src_default.tools) {
@@ -15785,12 +15798,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15785
15798
  }
15786
15799
  }
15787
15800
  };
15788
- const ot2 = globalThis.__openTabs;
15789
- if (!ot2._navigationInterceptor) {
15801
+ const ot3 = globalThis.__openTabs;
15802
+ if (!ot3._navigationInterceptor) {
15790
15803
  const origPushState = history.pushState.bind(history);
15791
15804
  const origReplaceState = history.replaceState.bind(history);
15792
15805
  const callbacks = /* @__PURE__ */ new Map();
15793
- ot2._navigationInterceptor = { callbacks, origPushState, origReplaceState };
15806
+ ot3._navigationInterceptor = { callbacks, origPushState, origReplaceState };
15794
15807
  history.pushState = function(...args) {
15795
15808
  origPushState(...args);
15796
15809
  for (const cb of callbacks.values()) {
@@ -15804,7 +15817,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15804
15817
  }
15805
15818
  };
15806
15819
  }
15807
- const interceptor = ot2._navigationInterceptor;
15820
+ const interceptor = ot3._navigationInterceptor;
15808
15821
  interceptor.callbacks.set("microsoft-word", checkUrl);
15809
15822
  window.addEventListener("popstate", checkUrl);
15810
15823
  window.addEventListener("hashchange", checkUrl);
@@ -15859,5 +15872,5 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15859
15872
  };
15860
15873
  delete src_default.onDeactivate;
15861
15874
  }
15862
- })();(function(){var o=(globalThis).__openTabs;if(o&&o.adapters&&o.adapters["microsoft-word"]){var a=o.adapters["microsoft-word"];a.__adapterHash="c9582a6cf42e8e0f427d82c37d9589c50c4b4e2b0df5b6776c70dfff3f8b1b57";if(a.tools&&Array.isArray(a.tools)){for(var i=0;i<a.tools.length;i++){Object.freeze(a.tools[i]);}Object.freeze(a.tools);}Object.freeze(a);Object.defineProperty(o.adapters,"microsoft-word",{value:a,writable:false,configurable:false,enumerable:true});Object.defineProperty(o,"adapters",{value:o.adapters,writable:false,configurable:false});}})();
15875
+ })();(function(){var o=(globalThis).__openTabs;if(o&&o.adapters&&o.adapters["microsoft-word"]){var a=o.adapters["microsoft-word"];a.__adapterHash="6fc1f6fc3b766ecb52568d6141d0a378c3ff666d5bc0255b8cc8be3f7887569d";if(a.tools&&Array.isArray(a.tools)){for(var i=0;i<a.tools.length;i++){Object.freeze(a.tools[i]);}Object.freeze(a.tools);}Object.freeze(a);Object.defineProperty(o.adapters,"microsoft-word",{value:a,writable:false,configurable:false,enumerable:true});Object.defineProperty(o,"adapters",{value:o.adapters,writable:false,configurable:false});}})();
15863
15876
  //# sourceMappingURL=adapter.iife.js.map