@opentabs-dev/opentabs-plugin-ynab 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 +52 -131
- package/dist/adapter.iife.js +25 -13
- package/dist/adapter.iife.js.map +3 -3
- package/dist/tools.json +1 -1
- package/package.json +10 -4
- package/dist/tools/create-account.d.ts +0 -35
- package/dist/tools/create-account.d.ts.map +0 -1
- package/dist/tools/create-account.js +0 -72
- package/dist/tools/create-account.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,159 +1,80 @@
|
|
|
1
|
-
#
|
|
1
|
+
# YNAB
|
|
2
2
|
|
|
3
|
-
OpenTabs plugin for YNAB (You Need A Budget)
|
|
3
|
+
OpenTabs plugin for YNAB (You Need A Budget) — gives AI agents access to YNAB through your authenticated browser session.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
+
```bash
|
|
8
|
+
opentabs plugin install ynab
|
|
7
9
|
```
|
|
8
|
-
ynab/
|
|
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-ynab",
|
|
28
|
-
"main": "dist/adapter.iife.js",
|
|
29
|
-
"opentabs": {
|
|
30
|
-
"displayName": "YNAB",
|
|
31
|
-
"description": "OpenTabs plugin for YNAB (You Need A Budget)",
|
|
32
|
-
"urlPatterns": ["*://*.app.ynab.com/*"]
|
|
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
10
|
|
|
42
|
-
|
|
11
|
+
Or install globally via npm:
|
|
43
12
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
ynab/
|
|
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-ynab
|
|
53
15
|
```
|
|
54
16
|
|
|
55
|
-
|
|
17
|
+
## Setup
|
|
56
18
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
- If no `icon.svg` is provided, the letter avatar is used automatically
|
|
19
|
+
1. Open [app.ynab.com](https://app.ynab.com) in Chrome and log in
|
|
20
|
+
2. Open the OpenTabs side panel — the YNAB plugin should appear as **ready**
|
|
60
21
|
|
|
61
|
-
|
|
22
|
+
## Tools (15)
|
|
62
23
|
|
|
63
|
-
|
|
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
|
-
|
|
26
|
+
| Tool | Description | Type |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `get_current_user` | Get your YNAB user profile | Read |
|
|
69
29
|
|
|
70
|
-
|
|
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
|
-
```
|
|
30
|
+
### Plans (1)
|
|
77
31
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
```
|
|
32
|
+
| Tool | Description | Type |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `get_plan` | Get the active plan details | Read |
|
|
99
35
|
|
|
100
|
-
|
|
36
|
+
### Accounts (2)
|
|
101
37
|
|
|
102
|
-
|
|
38
|
+
| Tool | Description | Type |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `list_accounts` | List all budget accounts | Read |
|
|
41
|
+
| `get_account` | Get account details by ID | Read |
|
|
103
42
|
|
|
104
|
-
|
|
43
|
+
### Categories (2)
|
|
105
44
|
|
|
106
|
-
|
|
107
|
-
|
|
45
|
+
| Tool | Description | Type |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `list_categories` | List budget categories with balances | Read |
|
|
48
|
+
| `update_category_budget` | Set budgeted amount for a category | Write |
|
|
108
49
|
|
|
109
|
-
|
|
110
|
-
const token = getLocalStorage('token');
|
|
50
|
+
### Payees (1)
|
|
111
51
|
|
|
112
|
-
|
|
113
|
-
|
|
52
|
+
| Tool | Description | Type |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `list_payees` | List all payees | Read |
|
|
114
55
|
|
|
115
|
-
|
|
116
|
-
const appState = getPageGlobal('__APP_STATE__');
|
|
117
|
-
```
|
|
56
|
+
### Transactions (6)
|
|
118
57
|
|
|
119
|
-
|
|
58
|
+
| Tool | Description | Type |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `list_transactions` | List budget transactions | Read |
|
|
61
|
+
| `get_transaction` | Get transaction details by ID | Read |
|
|
62
|
+
| `create_transaction` | Create a new transaction | Write |
|
|
63
|
+
| `update_transaction` | Update a transaction | Write |
|
|
64
|
+
| `delete_transaction` | Delete a transaction | Write |
|
|
65
|
+
| `list_scheduled_transactions` | List scheduled/recurring transactions | Read |
|
|
120
66
|
|
|
121
|
-
|
|
67
|
+
### Months (2)
|
|
122
68
|
|
|
123
|
-
|
|
69
|
+
| Tool | Description | Type |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| `list_months` | List budget months with summaries | Read |
|
|
72
|
+
| `get_month` | Get budget details for a month | Read |
|
|
124
73
|
|
|
125
|
-
|
|
74
|
+
## How It Works
|
|
126
75
|
|
|
127
|
-
|
|
128
|
-
// src/schemas/channel.ts
|
|
129
|
-
import { z } from 'zod';
|
|
76
|
+
This plugin runs inside your YNAB 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.
|
|
130
77
|
|
|
131
|
-
|
|
132
|
-
id: z.string().describe('Channel ID'),
|
|
133
|
-
name: z.string().describe('Channel name'),
|
|
134
|
-
});
|
|
135
|
-
|
|
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
|
-
```
|
|
78
|
+
## License
|
|
158
79
|
|
|
159
|
-
|
|
80
|
+
MIT
|
package/dist/adapter.iife.js
CHANGED
|
@@ -325,6 +325,8 @@
|
|
|
325
325
|
* (e.g., 'https://github.com'), not a match pattern.
|
|
326
326
|
*/
|
|
327
327
|
homepage;
|
|
328
|
+
/** Typed configuration schema — declares settings that users provide via config.json or the side panel. */
|
|
329
|
+
configSchema;
|
|
328
330
|
};
|
|
329
331
|
|
|
330
332
|
// src/ynab-api.ts
|
|
@@ -15092,21 +15094,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15092
15094
|
};
|
|
15093
15095
|
var src_default = new YnabPlugin();
|
|
15094
15096
|
|
|
15095
|
-
// dist/
|
|
15097
|
+
// dist/_adapter_entry_971ef58c-806d-497f-bc65-07b3013a2267.ts
|
|
15096
15098
|
if (!globalThis.__openTabs) {
|
|
15097
15099
|
globalThis.__openTabs = {};
|
|
15098
15100
|
} else {
|
|
15099
15101
|
const desc = Object.getOwnPropertyDescriptor(globalThis.__openTabs, "adapters");
|
|
15100
15102
|
if (desc && !desc.writable) {
|
|
15101
|
-
const
|
|
15103
|
+
const ot3 = globalThis.__openTabs;
|
|
15102
15104
|
const newAdaptersObj = {};
|
|
15103
|
-
if (
|
|
15104
|
-
for (const key of Object.keys(
|
|
15105
|
-
const d = Object.getOwnPropertyDescriptor(
|
|
15105
|
+
if (ot3.adapters) {
|
|
15106
|
+
for (const key of Object.keys(ot3.adapters)) {
|
|
15107
|
+
const d = Object.getOwnPropertyDescriptor(ot3.adapters, key);
|
|
15106
15108
|
if (d) Object.defineProperty(newAdaptersObj, key, d);
|
|
15107
15109
|
}
|
|
15108
15110
|
}
|
|
15109
|
-
globalThis.__openTabs = Object.assign({},
|
|
15111
|
+
globalThis.__openTabs = Object.assign({}, ot3, { adapters: newAdaptersObj });
|
|
15110
15112
|
}
|
|
15111
15113
|
}
|
|
15112
15114
|
if (!globalThis.__openTabs.adapters) {
|
|
@@ -15144,6 +15146,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15144
15146
|
}
|
|
15145
15147
|
};
|
|
15146
15148
|
var restoreTransport = setLogTransport ? setLogTransport(logTransport) : void 0;
|
|
15149
|
+
var ot2 = globalThis.__openTabs;
|
|
15150
|
+
ot2._notifyReadinessChanged = () => {
|
|
15151
|
+
try {
|
|
15152
|
+
const nonce = globalThis.__openTabs?._readinessNonce;
|
|
15153
|
+
if (nonce) {
|
|
15154
|
+
window.postMessage({ type: "opentabs:readiness-changed", plugin: "ynab", nonce }, "*");
|
|
15155
|
+
}
|
|
15156
|
+
} catch {
|
|
15157
|
+
}
|
|
15158
|
+
};
|
|
15147
15159
|
var existing = adapters["ynab"];
|
|
15148
15160
|
if (existing) {
|
|
15149
15161
|
if (typeof existing.teardown === "function") {
|
|
@@ -15155,7 +15167,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15155
15167
|
}
|
|
15156
15168
|
}
|
|
15157
15169
|
if (!Reflect.deleteProperty(adapters, "ynab")) {
|
|
15158
|
-
const
|
|
15170
|
+
const ot3 = globalThis.__openTabs;
|
|
15159
15171
|
const newAdapters = {};
|
|
15160
15172
|
for (const key of Object.keys(adapters)) {
|
|
15161
15173
|
if (key !== "ynab") {
|
|
@@ -15163,7 +15175,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15163
15175
|
if (desc) Object.defineProperty(newAdapters, key, desc);
|
|
15164
15176
|
}
|
|
15165
15177
|
}
|
|
15166
|
-
globalThis.__openTabs = Object.assign({},
|
|
15178
|
+
globalThis.__openTabs = Object.assign({}, ot3, { adapters: newAdapters });
|
|
15167
15179
|
}
|
|
15168
15180
|
var hasLifecycleHooks = typeof src_default.onToolInvocationStart === "function" || typeof src_default.onToolInvocationEnd === "function";
|
|
15169
15181
|
for (const tool of src_default.tools) {
|
|
@@ -15224,12 +15236,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15224
15236
|
}
|
|
15225
15237
|
}
|
|
15226
15238
|
};
|
|
15227
|
-
const
|
|
15228
|
-
if (!
|
|
15239
|
+
const ot3 = globalThis.__openTabs;
|
|
15240
|
+
if (!ot3._navigationInterceptor) {
|
|
15229
15241
|
const origPushState = history.pushState.bind(history);
|
|
15230
15242
|
const origReplaceState = history.replaceState.bind(history);
|
|
15231
15243
|
const callbacks = /* @__PURE__ */ new Map();
|
|
15232
|
-
|
|
15244
|
+
ot3._navigationInterceptor = { callbacks, origPushState, origReplaceState };
|
|
15233
15245
|
history.pushState = function(...args) {
|
|
15234
15246
|
origPushState(...args);
|
|
15235
15247
|
for (const cb of callbacks.values()) {
|
|
@@ -15243,7 +15255,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15243
15255
|
}
|
|
15244
15256
|
};
|
|
15245
15257
|
}
|
|
15246
|
-
const interceptor =
|
|
15258
|
+
const interceptor = ot3._navigationInterceptor;
|
|
15247
15259
|
interceptor.callbacks.set("ynab", checkUrl);
|
|
15248
15260
|
window.addEventListener("popstate", checkUrl);
|
|
15249
15261
|
window.addEventListener("hashchange", checkUrl);
|
|
@@ -15298,5 +15310,5 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15298
15310
|
};
|
|
15299
15311
|
delete src_default.onDeactivate;
|
|
15300
15312
|
}
|
|
15301
|
-
})();(function(){var o=(globalThis).__openTabs;if(o&&o.adapters&&o.adapters["ynab"]){var a=o.adapters["ynab"];a.__adapterHash="
|
|
15313
|
+
})();(function(){var o=(globalThis).__openTabs;if(o&&o.adapters&&o.adapters["ynab"]){var a=o.adapters["ynab"];a.__adapterHash="a9fd44be9fa96e7406c65699f3e22afa18f8378b7e406ad85eed3c11bd226ce3";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,"ynab",{value:a,writable:false,configurable:false,enumerable:true});Object.defineProperty(o,"adapters",{value:o.adapters,writable:false,configurable:false});}})();
|
|
15302
15314
|
//# sourceMappingURL=adapter.iife.js.map
|