@opentabs-dev/opentabs-plugin-priceline 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 +37 -138
- package/dist/adapter.iife.js +32 -20
- package/dist/adapter.iife.js.map +3 -3
- package/dist/tools.json +1 -1
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -1,159 +1,58 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Priceline
|
|
2
2
|
|
|
3
|
-
OpenTabs plugin for Priceline
|
|
3
|
+
OpenTabs plugin for Priceline — gives AI agents access to Priceline through your authenticated browser session.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
```
|
|
8
|
-
priceline
|
|
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-priceline",
|
|
28
|
-
"main": "dist/adapter.iife.js",
|
|
29
|
-
"opentabs": {
|
|
30
|
-
"displayName": "Priceline",
|
|
31
|
-
"description": "OpenTabs plugin for Priceline",
|
|
32
|
-
"urlPatterns": ["*://*.priceline.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
|
-
|
|
42
|
-
## Custom Icons
|
|
43
|
-
|
|
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`):
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
priceline/
|
|
48
|
-
├── package.json
|
|
49
|
-
├── icon.svg ← custom icon (optional)
|
|
50
|
-
├── icon-inactive.svg ← manual inactive override (optional, requires icon.svg)
|
|
51
|
-
├── src/
|
|
52
|
-
│ └── ...
|
|
7
|
+
```bash
|
|
8
|
+
opentabs plugin install priceline
|
|
53
9
|
```
|
|
54
10
|
|
|
55
|
-
|
|
56
|
-
|
|
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
|
|
60
|
-
|
|
61
|
-
**Icon requirements:**
|
|
62
|
-
|
|
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
|
|
67
|
-
|
|
68
|
-
## Development
|
|
11
|
+
Or install globally via npm:
|
|
69
12
|
|
|
70
13
|
```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
|
-
});
|
|
14
|
+
npm install -g @opentabs-dev/opentabs-plugin-priceline
|
|
98
15
|
```
|
|
99
16
|
|
|
100
|
-
|
|
17
|
+
## Setup
|
|
101
18
|
|
|
102
|
-
|
|
19
|
+
1. Open [priceline.com](https://www.priceline.com) in Chrome and log in
|
|
20
|
+
2. Open the OpenTabs side panel — the Priceline plugin should appear as **ready**
|
|
103
21
|
|
|
104
|
-
|
|
22
|
+
## Tools (13)
|
|
105
23
|
|
|
106
|
-
|
|
107
|
-
import { getLocalStorage, getCookie, getPageGlobal } from '@opentabs-dev/plugin-sdk';
|
|
24
|
+
### Search (3)
|
|
108
25
|
|
|
109
|
-
|
|
110
|
-
|
|
26
|
+
| Tool | Description | Type |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| `search_locations` | Search destinations by keyword | Read |
|
|
29
|
+
| `search_points_of_interest` | Find top attractions in a city | Read |
|
|
30
|
+
| `navigate_to_search` | Open hotel search results page | Write |
|
|
111
31
|
|
|
112
|
-
|
|
113
|
-
const session = getCookie('session_id');
|
|
32
|
+
### Hotels (6)
|
|
114
33
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
34
|
+
| Tool | Description | Type |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| `search_hotels` | Search hotels by city and dates | Read |
|
|
37
|
+
| `get_hotel_descriptions` | Get short descriptions for hotels | Read |
|
|
38
|
+
| `get_hotel_filters` | Get available hotel search filters | Read |
|
|
39
|
+
| `get_merchandising_badges` | Get top-rated/top-booked badges for hotels | Read |
|
|
40
|
+
| `get_price_guidance` | Get hotel price trends for a city | Read |
|
|
41
|
+
| `navigate_to_hotel` | Open a hotel detail page | Write |
|
|
122
42
|
|
|
123
|
-
|
|
43
|
+
### Account (4)
|
|
124
44
|
|
|
125
|
-
|
|
45
|
+
| Tool | Description | Type |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `get_customer_profile` | Get your Priceline profile | Read |
|
|
48
|
+
| `get_customer_coupons` | Get your available coupons | Read |
|
|
49
|
+
| `get_favorite_hotels` | Get your saved hotels in a city | Read |
|
|
50
|
+
| `get_abandoned_items` | Get your abandoned cart items | Read |
|
|
126
51
|
|
|
127
|
-
|
|
128
|
-
// src/schemas/channel.ts
|
|
129
|
-
import { z } from 'zod';
|
|
52
|
+
## How It Works
|
|
130
53
|
|
|
131
|
-
|
|
132
|
-
id: z.string().describe('Channel ID'),
|
|
133
|
-
name: z.string().describe('Channel name'),
|
|
134
|
-
});
|
|
54
|
+
This plugin runs inside your Priceline 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
55
|
|
|
136
|
-
|
|
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
|
-
```
|
|
56
|
+
## License
|
|
158
57
|
|
|
159
|
-
|
|
58
|
+
MIT
|
package/dist/adapter.iife.js
CHANGED
|
@@ -349,18 +349,18 @@
|
|
|
349
349
|
|
|
350
350
|
// node_modules/@opentabs-dev/plugin-sdk/dist/storage.js
|
|
351
351
|
var getLocalStorage = (key) => {
|
|
352
|
-
try {
|
|
353
|
-
return localStorage.getItem(key);
|
|
354
|
-
} catch {
|
|
355
|
-
}
|
|
356
352
|
let storage;
|
|
357
353
|
try {
|
|
358
|
-
storage = localStorage;
|
|
354
|
+
storage = window.localStorage;
|
|
359
355
|
} catch {
|
|
360
356
|
return null;
|
|
361
357
|
}
|
|
362
|
-
if (storage
|
|
363
|
-
|
|
358
|
+
if (storage) {
|
|
359
|
+
try {
|
|
360
|
+
return storage.getItem(key);
|
|
361
|
+
} catch {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
364
|
}
|
|
365
365
|
try {
|
|
366
366
|
const iframe = document.createElement("iframe");
|
|
@@ -441,6 +441,8 @@
|
|
|
441
441
|
* (e.g., 'https://github.com'), not a match pattern.
|
|
442
442
|
*/
|
|
443
443
|
homepage;
|
|
444
|
+
/** Typed configuration schema — declares settings that users provide via config.json or the side panel. */
|
|
445
|
+
configSchema;
|
|
444
446
|
};
|
|
445
447
|
|
|
446
448
|
// src/priceline-api.ts
|
|
@@ -15000,21 +15002,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15000
15002
|
};
|
|
15001
15003
|
var src_default = new PricelinePlugin();
|
|
15002
15004
|
|
|
15003
|
-
// dist/
|
|
15005
|
+
// dist/_adapter_entry_ad661d68-a6ab-4dcc-a605-b31b19618971.ts
|
|
15004
15006
|
if (!globalThis.__openTabs) {
|
|
15005
15007
|
globalThis.__openTabs = {};
|
|
15006
15008
|
} else {
|
|
15007
15009
|
const desc = Object.getOwnPropertyDescriptor(globalThis.__openTabs, "adapters");
|
|
15008
15010
|
if (desc && !desc.writable) {
|
|
15009
|
-
const
|
|
15011
|
+
const ot3 = globalThis.__openTabs;
|
|
15010
15012
|
const newAdaptersObj = {};
|
|
15011
|
-
if (
|
|
15012
|
-
for (const key of Object.keys(
|
|
15013
|
-
const d = Object.getOwnPropertyDescriptor(
|
|
15013
|
+
if (ot3.adapters) {
|
|
15014
|
+
for (const key of Object.keys(ot3.adapters)) {
|
|
15015
|
+
const d = Object.getOwnPropertyDescriptor(ot3.adapters, key);
|
|
15014
15016
|
if (d) Object.defineProperty(newAdaptersObj, key, d);
|
|
15015
15017
|
}
|
|
15016
15018
|
}
|
|
15017
|
-
globalThis.__openTabs = Object.assign({},
|
|
15019
|
+
globalThis.__openTabs = Object.assign({}, ot3, { adapters: newAdaptersObj });
|
|
15018
15020
|
}
|
|
15019
15021
|
}
|
|
15020
15022
|
if (!globalThis.__openTabs.adapters) {
|
|
@@ -15052,6 +15054,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15052
15054
|
}
|
|
15053
15055
|
};
|
|
15054
15056
|
var restoreTransport = setLogTransport ? setLogTransport(logTransport) : void 0;
|
|
15057
|
+
var ot2 = globalThis.__openTabs;
|
|
15058
|
+
ot2._notifyReadinessChanged = () => {
|
|
15059
|
+
try {
|
|
15060
|
+
const nonce = globalThis.__openTabs?._readinessNonce;
|
|
15061
|
+
if (nonce) {
|
|
15062
|
+
window.postMessage({ type: "opentabs:readiness-changed", plugin: "priceline", nonce }, "*");
|
|
15063
|
+
}
|
|
15064
|
+
} catch {
|
|
15065
|
+
}
|
|
15066
|
+
};
|
|
15055
15067
|
var existing = adapters["priceline"];
|
|
15056
15068
|
if (existing) {
|
|
15057
15069
|
if (typeof existing.teardown === "function") {
|
|
@@ -15063,7 +15075,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15063
15075
|
}
|
|
15064
15076
|
}
|
|
15065
15077
|
if (!Reflect.deleteProperty(adapters, "priceline")) {
|
|
15066
|
-
const
|
|
15078
|
+
const ot3 = globalThis.__openTabs;
|
|
15067
15079
|
const newAdapters = {};
|
|
15068
15080
|
for (const key of Object.keys(adapters)) {
|
|
15069
15081
|
if (key !== "priceline") {
|
|
@@ -15071,7 +15083,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15071
15083
|
if (desc) Object.defineProperty(newAdapters, key, desc);
|
|
15072
15084
|
}
|
|
15073
15085
|
}
|
|
15074
|
-
globalThis.__openTabs = Object.assign({},
|
|
15086
|
+
globalThis.__openTabs = Object.assign({}, ot3, { adapters: newAdapters });
|
|
15075
15087
|
}
|
|
15076
15088
|
var hasLifecycleHooks = typeof src_default.onToolInvocationStart === "function" || typeof src_default.onToolInvocationEnd === "function";
|
|
15077
15089
|
for (const tool of src_default.tools) {
|
|
@@ -15132,12 +15144,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15132
15144
|
}
|
|
15133
15145
|
}
|
|
15134
15146
|
};
|
|
15135
|
-
const
|
|
15136
|
-
if (!
|
|
15147
|
+
const ot3 = globalThis.__openTabs;
|
|
15148
|
+
if (!ot3._navigationInterceptor) {
|
|
15137
15149
|
const origPushState = history.pushState.bind(history);
|
|
15138
15150
|
const origReplaceState = history.replaceState.bind(history);
|
|
15139
15151
|
const callbacks = /* @__PURE__ */ new Map();
|
|
15140
|
-
|
|
15152
|
+
ot3._navigationInterceptor = { callbacks, origPushState, origReplaceState };
|
|
15141
15153
|
history.pushState = function(...args) {
|
|
15142
15154
|
origPushState(...args);
|
|
15143
15155
|
for (const cb of callbacks.values()) {
|
|
@@ -15151,7 +15163,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15151
15163
|
}
|
|
15152
15164
|
};
|
|
15153
15165
|
}
|
|
15154
|
-
const interceptor =
|
|
15166
|
+
const interceptor = ot3._navigationInterceptor;
|
|
15155
15167
|
interceptor.callbacks.set("priceline", checkUrl);
|
|
15156
15168
|
window.addEventListener("popstate", checkUrl);
|
|
15157
15169
|
window.addEventListener("hashchange", checkUrl);
|
|
@@ -15206,5 +15218,5 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15206
15218
|
};
|
|
15207
15219
|
delete src_default.onDeactivate;
|
|
15208
15220
|
}
|
|
15209
|
-
})();(function(){var o=(globalThis).__openTabs;if(o&&o.adapters&&o.adapters["priceline"]){var a=o.adapters["priceline"];a.__adapterHash="
|
|
15221
|
+
})();(function(){var o=(globalThis).__openTabs;if(o&&o.adapters&&o.adapters["priceline"]){var a=o.adapters["priceline"];a.__adapterHash="aa86ee49169c5d612454b2de9d35d21f28d87f9a2f36ea25c470aa42a55464a9";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,"priceline",{value:a,writable:false,configurable:false,enumerable:true});Object.defineProperty(o,"adapters",{value:o.adapters,writable:false,configurable:false});}})();
|
|
15210
15222
|
//# sourceMappingURL=adapter.iife.js.map
|