@jobshimo/browser-link 0.0.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 +21 -0
- package/README.md +83 -0
- package/dist/auth/allowlist.d.ts +2 -0
- package/dist/auth/allowlist.js +53 -0
- package/dist/auth/allowlist.js.map +1 -0
- package/dist/auth/process-identity.d.ts +19 -0
- package/dist/auth/process-identity.js +106 -0
- package/dist/auth/process-identity.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +116 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/about.d.ts +23 -0
- package/dist/commands/about.js +248 -0
- package/dist/commands/about.js.map +1 -0
- package/dist/commands/doctor.d.ts +29 -0
- package/dist/commands/doctor.js +110 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/extension.d.ts +12 -0
- package/dist/commands/extension.js +76 -0
- package/dist/commands/extension.js.map +1 -0
- package/dist/commands/install.d.ts +19 -0
- package/dist/commands/install.js +52 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/menu.d.ts +26 -0
- package/dist/commands/menu.js +187 -0
- package/dist/commands/menu.js.map +1 -0
- package/dist/commands/tty.d.ts +51 -0
- package/dist/commands/tty.js +148 -0
- package/dist/commands/tty.js.map +1 -0
- package/dist/commands/uninstall.d.ts +8 -0
- package/dist/commands/uninstall.js +10 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/welcome.d.ts +33 -0
- package/dist/commands/welcome.js +177 -0
- package/dist/commands/welcome.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.js +35 -0
- package/dist/config.js.map +1 -0
- package/dist/entry-info.d.ts +12 -0
- package/dist/entry-info.js +15 -0
- package/dist/entry-info.js.map +1 -0
- package/dist/extension/background.d.ts +1 -0
- package/dist/extension/background.js +490 -0
- package/dist/extension/background.js.map +1 -0
- package/dist/extension/icons/icon-128.png +0 -0
- package/dist/extension/icons/icon-16.png +0 -0
- package/dist/extension/icons/icon-32.png +0 -0
- package/dist/extension/icons/icon-48.png +0 -0
- package/dist/extension/icons/icon.svg +14 -0
- package/dist/extension/manifest.json +28 -0
- package/dist/extension/popup.d.ts +13 -0
- package/dist/extension/popup.html +88 -0
- package/dist/extension/popup.js +78 -0
- package/dist/extension/popup.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/installers/claude.d.ts +2 -0
- package/dist/installers/claude.js +77 -0
- package/dist/installers/claude.js.map +1 -0
- package/dist/installers/index.d.ts +9 -0
- package/dist/installers/index.js +14 -0
- package/dist/installers/index.js.map +1 -0
- package/dist/installers/opencode.d.ts +2 -0
- package/dist/installers/opencode.js +39 -0
- package/dist/installers/opencode.js.map +1 -0
- package/dist/installers/types.d.ts +30 -0
- package/dist/installers/types.js +2 -0
- package/dist/installers/types.js.map +1 -0
- package/dist/map/db.d.ts +3 -0
- package/dist/map/db.js +81 -0
- package/dist/map/db.js.map +1 -0
- package/dist/map/paths.d.ts +12 -0
- package/dist/map/paths.js +22 -0
- package/dist/map/paths.js.map +1 -0
- package/dist/map/queries.d.ts +72 -0
- package/dist/map/queries.js +162 -0
- package/dist/map/queries.js.map +1 -0
- package/dist/map/tools.d.ts +8 -0
- package/dist/map/tools.js +143 -0
- package/dist/map/tools.js.map +1 -0
- package/dist/messages.d.ts +42 -0
- package/dist/messages.js +9 -0
- package/dist/messages.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +217 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/browser-definitions.d.ts +7 -0
- package/dist/tools/browser-definitions.js +127 -0
- package/dist/tools/browser-definitions.js.map +1 -0
- package/dist/tools/browser-dispatch.d.ts +20 -0
- package/dist/tools/browser-dispatch.js +75 -0
- package/dist/tools/browser-dispatch.js.map +1 -0
- package/dist/tools/responses.d.ts +19 -0
- package/dist/tools/responses.js +27 -0
- package/dist/tools/responses.js.map +1 -0
- package/dist/tools/server-instructions.d.ts +3 -0
- package/dist/tools/server-instructions.js +50 -0
- package/dist/tools/server-instructions.js.map +1 -0
- package/dist/tools/types.d.ts +6 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/utils/open-url.d.ts +4 -0
- package/dist/utils/open-url.js +37 -0
- package/dist/utils/open-url.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { getDb } from './db.js';
|
|
2
|
+
function now() {
|
|
3
|
+
return new Date().toISOString();
|
|
4
|
+
}
|
|
5
|
+
function parsePayload(raw) {
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(raw);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return raw;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
function hydrate(row) {
|
|
14
|
+
return { ...row, payload: parsePayload(row.payload) };
|
|
15
|
+
}
|
|
16
|
+
function slugify(text) {
|
|
17
|
+
return text
|
|
18
|
+
.normalize('NFD')
|
|
19
|
+
.replace(/[̀-ͯ]/g, '')
|
|
20
|
+
.toLowerCase()
|
|
21
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
22
|
+
.replace(/^-+|-+$/g, '');
|
|
23
|
+
}
|
|
24
|
+
function deriveAppKey(origin, title) {
|
|
25
|
+
if (title && title.trim().length > 0) {
|
|
26
|
+
const slug = slugify(title);
|
|
27
|
+
if (slug.length > 0)
|
|
28
|
+
return slug;
|
|
29
|
+
}
|
|
30
|
+
// last-resort: use origin host as key
|
|
31
|
+
try {
|
|
32
|
+
return slugify(new URL(origin).host);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return slugify(origin) || 'app';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export function upsertApp(input) {
|
|
39
|
+
const db = getDb();
|
|
40
|
+
const ts = now();
|
|
41
|
+
const app_key = input.app_key && input.app_key.trim().length > 0
|
|
42
|
+
? slugify(input.app_key)
|
|
43
|
+
: deriveAppKey(input.origin, input.title);
|
|
44
|
+
const existing = db
|
|
45
|
+
.prepare('SELECT * FROM apps WHERE origin = ? AND app_key = ?')
|
|
46
|
+
.get(input.origin, app_key);
|
|
47
|
+
if (existing) {
|
|
48
|
+
db.prepare(`UPDATE apps SET title = COALESCE(?, title), notes = COALESCE(?, notes), last_seen_at = ? WHERE id = ?`).run(input.title ?? null, input.notes ?? null, ts, existing.id);
|
|
49
|
+
return db.prepare('SELECT * FROM apps WHERE id = ?').get(existing.id);
|
|
50
|
+
}
|
|
51
|
+
const info = db
|
|
52
|
+
.prepare(`INSERT INTO apps (origin, app_key, title, notes, created_at, last_seen_at)
|
|
53
|
+
VALUES (?, ?, ?, ?, ?, ?)`)
|
|
54
|
+
.run(input.origin, app_key, input.title ?? null, input.notes ?? null, ts, ts);
|
|
55
|
+
return db.prepare('SELECT * FROM apps WHERE id = ?').get(info.lastInsertRowid);
|
|
56
|
+
}
|
|
57
|
+
export function saveEntry(input) {
|
|
58
|
+
const app = upsertApp({
|
|
59
|
+
origin: input.origin,
|
|
60
|
+
app_key: input.app_key ?? null,
|
|
61
|
+
title: input.title ?? null,
|
|
62
|
+
});
|
|
63
|
+
const ts = now();
|
|
64
|
+
const payloadJson = JSON.stringify(input.payload);
|
|
65
|
+
const db = getDb();
|
|
66
|
+
const existing = db
|
|
67
|
+
.prepare(`SELECT * FROM entries WHERE app_id = ? AND url_pattern = ? AND kind = ? AND purpose = ?`)
|
|
68
|
+
.get(app.id, input.url_pattern, input.kind, input.purpose);
|
|
69
|
+
if (existing) {
|
|
70
|
+
db.prepare(`UPDATE entries
|
|
71
|
+
SET payload = ?, notes = COALESCE(?, notes), verified_at = ?, failed_at = NULL, updated_at = ?
|
|
72
|
+
WHERE id = ?`).run(payloadJson, input.notes ?? null, ts, ts, existing.id);
|
|
73
|
+
const updated = db
|
|
74
|
+
.prepare('SELECT * FROM entries WHERE id = ?')
|
|
75
|
+
.get(existing.id);
|
|
76
|
+
return { app, entry: hydrate(updated) };
|
|
77
|
+
}
|
|
78
|
+
const info = db
|
|
79
|
+
.prepare(`INSERT INTO entries (app_id, url_pattern, kind, purpose, payload, verified_at, notes, created_at, updated_at)
|
|
80
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
81
|
+
.run(app.id, input.url_pattern, input.kind, input.purpose, payloadJson, ts, input.notes ?? null, ts, ts);
|
|
82
|
+
const inserted = db
|
|
83
|
+
.prepare('SELECT * FROM entries WHERE id = ?')
|
|
84
|
+
.get(info.lastInsertRowid);
|
|
85
|
+
return { app, entry: hydrate(inserted) };
|
|
86
|
+
}
|
|
87
|
+
export function recall(input) {
|
|
88
|
+
const db = getDb();
|
|
89
|
+
// Resolve app: prefer (origin, app_key) if provided; otherwise pick the most-recent app for this origin.
|
|
90
|
+
let app;
|
|
91
|
+
if (input.app_key && input.app_key.trim().length > 0) {
|
|
92
|
+
app = db
|
|
93
|
+
.prepare('SELECT * FROM apps WHERE origin = ? AND app_key = ?')
|
|
94
|
+
.get(input.origin, slugify(input.app_key));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
app = db
|
|
98
|
+
.prepare('SELECT * FROM apps WHERE origin = ? ORDER BY last_seen_at DESC LIMIT 1')
|
|
99
|
+
.get(input.origin);
|
|
100
|
+
}
|
|
101
|
+
if (!app)
|
|
102
|
+
return { app: null, entries: [] };
|
|
103
|
+
// Touch last_seen_at so apps that are actively used bubble up.
|
|
104
|
+
db.prepare('UPDATE apps SET last_seen_at = ? WHERE id = ?').run(now(), app.id);
|
|
105
|
+
const pathname = input.url ? extractPathname(input.url) : null;
|
|
106
|
+
const rows = (pathname
|
|
107
|
+
? db
|
|
108
|
+
.prepare(`SELECT * FROM entries WHERE app_id = ? AND url_pattern = ? ORDER BY updated_at DESC`)
|
|
109
|
+
.all(app.id, pathname)
|
|
110
|
+
: db
|
|
111
|
+
.prepare(`SELECT * FROM entries WHERE app_id = ? ORDER BY url_pattern, updated_at DESC`)
|
|
112
|
+
.all(app.id));
|
|
113
|
+
return { app, entries: rows.map(hydrate) };
|
|
114
|
+
}
|
|
115
|
+
function extractPathname(url) {
|
|
116
|
+
try {
|
|
117
|
+
return new URL(url).pathname;
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return url;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Two prepared statements with no string interpolation. ok=true clears
|
|
124
|
+
// failed_at so a freshly verified entry is unambiguously healthy; ok=false
|
|
125
|
+
// only stamps failed_at and leaves verified_at as a historical fact so we
|
|
126
|
+
// can still tell whether the entry ever worked.
|
|
127
|
+
const RECORD_USE_OK_SQL = 'UPDATE entries SET verified_at = ?, failed_at = NULL, notes = COALESCE(?, notes), updated_at = ? WHERE id = ?';
|
|
128
|
+
const RECORD_USE_FAIL_SQL = 'UPDATE entries SET failed_at = ?, notes = COALESCE(?, notes), updated_at = ? WHERE id = ?';
|
|
129
|
+
export function recordUse(input) {
|
|
130
|
+
const db = getDb();
|
|
131
|
+
const ts = now();
|
|
132
|
+
const sql = input.ok ? RECORD_USE_OK_SQL : RECORD_USE_FAIL_SQL;
|
|
133
|
+
db.prepare(sql).run(ts, input.notes ?? null, ts, input.entry_id);
|
|
134
|
+
const row = db.prepare('SELECT * FROM entries WHERE id = ?').get(input.entry_id);
|
|
135
|
+
return row ? hydrate(row) : null;
|
|
136
|
+
}
|
|
137
|
+
export function forget(input) {
|
|
138
|
+
const db = getDb();
|
|
139
|
+
if (input.entry_id) {
|
|
140
|
+
const info = db.prepare('DELETE FROM entries WHERE id = ?').run(input.entry_id);
|
|
141
|
+
return { deleted_entries: info.changes, deleted_apps: 0 };
|
|
142
|
+
}
|
|
143
|
+
if (input.app_id) {
|
|
144
|
+
// ON DELETE CASCADE wipes entries.
|
|
145
|
+
const before = db
|
|
146
|
+
.prepare('SELECT COUNT(*) AS n FROM entries WHERE app_id = ?')
|
|
147
|
+
.get(input.app_id);
|
|
148
|
+
const info = db.prepare('DELETE FROM apps WHERE id = ?').run(input.app_id);
|
|
149
|
+
return { deleted_entries: before.n, deleted_apps: info.changes };
|
|
150
|
+
}
|
|
151
|
+
return { deleted_entries: 0, deleted_apps: 0 };
|
|
152
|
+
}
|
|
153
|
+
export function renameApp(app_id, new_app_key) {
|
|
154
|
+
const db = getDb();
|
|
155
|
+
db.prepare('UPDATE apps SET app_key = ?, last_seen_at = ? WHERE id = ?').run(slugify(new_app_key), now(), app_id);
|
|
156
|
+
const row = db.prepare('SELECT * FROM apps WHERE id = ?').get(app_id);
|
|
157
|
+
return row ?? null;
|
|
158
|
+
}
|
|
159
|
+
export function listApps() {
|
|
160
|
+
return getDb().prepare('SELECT * FROM apps ORDER BY last_seen_at DESC').all();
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=queries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/map/queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ToolDefinition {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
inputSchema: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export declare const MAP_TOOL_DEFINITIONS: ToolDefinition[];
|
|
7
|
+
export declare function isMapTool(name: string): boolean;
|
|
8
|
+
export declare function handleMapTool(name: string, args: unknown): unknown;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { forget, listApps, recall, recordUse, renameApp, saveEntry, } from './queries.js';
|
|
2
|
+
export const MAP_TOOL_DEFINITIONS = [
|
|
3
|
+
{
|
|
4
|
+
name: 'browser.map.recall',
|
|
5
|
+
description: 'Recall what is already known about a browser app/route from the local map DB. Call this first when you arrive at a tab so you can reuse known selectors, flows and gotchas instead of rediscovering them. Pass origin (scheme://host:port). Optionally pass app_key to disambiguate when multiple apps share an origin, and url to filter entries down to a specific pathname.',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
origin: { type: 'string', description: 'scheme://host:port of the tab.' },
|
|
10
|
+
app_key: {
|
|
11
|
+
type: 'string',
|
|
12
|
+
description: 'Optional. Slug identifying the app within the origin (e.g. "flight-managment"). If omitted, the most-recently-seen app for the origin is used.',
|
|
13
|
+
},
|
|
14
|
+
url: {
|
|
15
|
+
type: 'string',
|
|
16
|
+
description: 'Optional full URL; only its pathname is used to filter entries.',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
required: ['origin'],
|
|
20
|
+
additionalProperties: false,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'browser.map.save',
|
|
25
|
+
description: 'Persist something learned about a browser app. Three kinds are supported: "selector" (a CSS selector tied to a purpose), "flow" (an ordered list of steps to reach an outcome), and "gotcha" (a free-form note). Saving auto-creates the app row if needed (app_key is derived from title when not provided). Upsert on (app, url_pattern, kind, purpose). Marks verified_at = now and clears failed_at. Never save selectors or flows you have not just successfully executed.',
|
|
26
|
+
inputSchema: {
|
|
27
|
+
type: 'object',
|
|
28
|
+
properties: {
|
|
29
|
+
origin: { type: 'string' },
|
|
30
|
+
app_key: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: 'Optional slug. If omitted, derived from title or origin host.',
|
|
33
|
+
},
|
|
34
|
+
title: {
|
|
35
|
+
type: 'string',
|
|
36
|
+
description: 'Optional document.title; used to derive app_key on first save for this origin.',
|
|
37
|
+
},
|
|
38
|
+
url_pattern: {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: 'Pathname this entry applies to (e.g. "/home/flight-management/cga"). Use exact paths by default; only generalize when you have evidence of a parametric route.',
|
|
41
|
+
},
|
|
42
|
+
kind: { type: 'string', enum: ['selector', 'flow', 'gotcha'] },
|
|
43
|
+
purpose: {
|
|
44
|
+
type: 'string',
|
|
45
|
+
description: 'Human-readable label for what this entry achieves (e.g. "open task detail dialog").',
|
|
46
|
+
},
|
|
47
|
+
payload: {
|
|
48
|
+
description: 'Kind-specific payload. selector: { selector: string, evidence?: string }. flow: { steps: array<{action,...}>}. gotcha: { body: string }.',
|
|
49
|
+
},
|
|
50
|
+
notes: { type: 'string' },
|
|
51
|
+
},
|
|
52
|
+
required: ['origin', 'url_pattern', 'kind', 'purpose', 'payload'],
|
|
53
|
+
additionalProperties: false,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: 'browser.map.record_use',
|
|
58
|
+
description: 'Mark an entry as freshly verified or freshly failed after you used it. ok=true updates verified_at and clears failed_at; ok=false updates failed_at. Always call this after using an entry from recall so the map stays honest about what works today.',
|
|
59
|
+
inputSchema: {
|
|
60
|
+
type: 'object',
|
|
61
|
+
properties: {
|
|
62
|
+
entry_id: { type: 'number' },
|
|
63
|
+
ok: { type: 'boolean' },
|
|
64
|
+
notes: { type: 'string' },
|
|
65
|
+
},
|
|
66
|
+
required: ['entry_id', 'ok'],
|
|
67
|
+
additionalProperties: false,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'browser.map.forget',
|
|
72
|
+
description: 'Permanently delete an entry (entry_id) or a whole app and all its entries (app_id). Use when a refactor or app change makes the saved knowledge actively wrong.',
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: 'object',
|
|
75
|
+
properties: {
|
|
76
|
+
entry_id: { type: 'number' },
|
|
77
|
+
app_id: { type: 'number' },
|
|
78
|
+
reason: { type: 'string' },
|
|
79
|
+
},
|
|
80
|
+
additionalProperties: false,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'browser.map.rename_app',
|
|
85
|
+
description: 'Rename an app_key. Useful when the heuristic from the document title picked a poor name (e.g. typos like "FLIGHT MANAGMENT" → "flight-management").',
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: 'object',
|
|
88
|
+
properties: {
|
|
89
|
+
app_id: { type: 'number' },
|
|
90
|
+
new_app_key: { type: 'string' },
|
|
91
|
+
},
|
|
92
|
+
required: ['app_id', 'new_app_key'],
|
|
93
|
+
additionalProperties: false,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'browser.map.apps',
|
|
98
|
+
description: 'List apps currently tracked in the map, most recently used first. Use to discover known origins and their app_keys.',
|
|
99
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
export function isMapTool(name) {
|
|
103
|
+
return name.startsWith('browser.map.');
|
|
104
|
+
}
|
|
105
|
+
export function handleMapTool(name, args) {
|
|
106
|
+
switch (name) {
|
|
107
|
+
case 'browser.map.recall': {
|
|
108
|
+
const a = args;
|
|
109
|
+
return recall({ origin: a.origin, app_key: a.app_key ?? null, url: a.url ?? null });
|
|
110
|
+
}
|
|
111
|
+
case 'browser.map.save': {
|
|
112
|
+
const a = args;
|
|
113
|
+
return saveEntry({
|
|
114
|
+
origin: a.origin,
|
|
115
|
+
app_key: a.app_key ?? null,
|
|
116
|
+
title: a.title ?? null,
|
|
117
|
+
url_pattern: a.url_pattern,
|
|
118
|
+
kind: a.kind,
|
|
119
|
+
purpose: a.purpose,
|
|
120
|
+
payload: a.payload,
|
|
121
|
+
notes: a.notes ?? null,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
case 'browser.map.record_use': {
|
|
125
|
+
const a = args;
|
|
126
|
+
return recordUse({ entry_id: a.entry_id, ok: a.ok, notes: a.notes ?? null });
|
|
127
|
+
}
|
|
128
|
+
case 'browser.map.forget': {
|
|
129
|
+
const a = args;
|
|
130
|
+
return forget({ entry_id: a.entry_id, app_id: a.app_id, reason: a.reason });
|
|
131
|
+
}
|
|
132
|
+
case 'browser.map.rename_app': {
|
|
133
|
+
const a = args;
|
|
134
|
+
return renameApp(a.app_id, a.new_app_key);
|
|
135
|
+
}
|
|
136
|
+
case 'browser.map.apps': {
|
|
137
|
+
return listApps();
|
|
138
|
+
}
|
|
139
|
+
default:
|
|
140
|
+
throw new Error(`Unknown map tool: ${name}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/map/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire-protocol types between the MCP server and the Chrome extension.
|
|
3
|
+
*
|
|
4
|
+
* Kept in-tree (instead of the @browser-link/shared workspace package) so the
|
|
5
|
+
* server publishes to npm without an unresolvable workspace dependency.
|
|
6
|
+
* The extension still uses the workspace copy in packages/shared.
|
|
7
|
+
*/
|
|
8
|
+
export type TabId = string;
|
|
9
|
+
export interface TabRegisterPayload {
|
|
10
|
+
url: string;
|
|
11
|
+
title: string;
|
|
12
|
+
}
|
|
13
|
+
export interface TabRegisteredPayload {
|
|
14
|
+
tabId: TabId;
|
|
15
|
+
}
|
|
16
|
+
export interface TabRegisterMessage {
|
|
17
|
+
kind: 'tab.register';
|
|
18
|
+
payload: TabRegisterPayload;
|
|
19
|
+
}
|
|
20
|
+
export interface TabRegisteredMessage {
|
|
21
|
+
kind: 'tab.registered';
|
|
22
|
+
payload: TabRegisteredPayload;
|
|
23
|
+
}
|
|
24
|
+
export interface ToolRequestMessage {
|
|
25
|
+
kind: 'tool.request';
|
|
26
|
+
id: string;
|
|
27
|
+
tool: string;
|
|
28
|
+
params: unknown;
|
|
29
|
+
}
|
|
30
|
+
export type ToolResponseMessage = {
|
|
31
|
+
kind: 'tool.response';
|
|
32
|
+
id: string;
|
|
33
|
+
ok: true;
|
|
34
|
+
result: unknown;
|
|
35
|
+
} | {
|
|
36
|
+
kind: 'tool.response';
|
|
37
|
+
id: string;
|
|
38
|
+
ok: false;
|
|
39
|
+
error: string;
|
|
40
|
+
};
|
|
41
|
+
export type ExtensionToServer = TabRegisterMessage | ToolResponseMessage;
|
|
42
|
+
export type ServerToExtension = TabRegisteredMessage | ToolRequestMessage;
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire-protocol types between the MCP server and the Chrome extension.
|
|
3
|
+
*
|
|
4
|
+
* Kept in-tree (instead of the @browser-link/shared workspace package) so the
|
|
5
|
+
* server publishes to npm without an unresolvable workspace dependency.
|
|
6
|
+
* The extension still uses the workspace copy in packages/shared.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=messages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const WS_HOST = "127.0.0.1";
|
|
2
|
+
export declare const WS_PORT = 17529;
|
|
3
|
+
/** Start the MCP server (stdio transport) and the WebSocket bridge.
|
|
4
|
+
* Resolves only when both are ready. If the WebSocket bind fails the
|
|
5
|
+
* MCP transport is never exposed and the caller sees a clear error. */
|
|
6
|
+
export declare function runServer(): Promise<void>;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { WebSocketServer } from 'ws';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { MAP_TOOL_DEFINITIONS, handleMapTool, isMapTool } from './map/tools.js';
|
|
7
|
+
import { closeDb } from './map/db.js';
|
|
8
|
+
import { isAllowedBrowser } from './auth/allowlist.js';
|
|
9
|
+
import { lookupPeerProcess } from './auth/process-identity.js';
|
|
10
|
+
import { BROWSER_TOOL_DEFINITIONS } from './tools/browser-definitions.js';
|
|
11
|
+
import { handleBrowserTool, isBrowserTool, } from './tools/browser-dispatch.js';
|
|
12
|
+
import { toolError, toolResponse } from './tools/responses.js';
|
|
13
|
+
import { SERVER_INSTRUCTIONS } from './tools/server-instructions.js';
|
|
14
|
+
export const WS_HOST = '127.0.0.1';
|
|
15
|
+
export const WS_PORT = 17529;
|
|
16
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
17
|
+
function log(msg) {
|
|
18
|
+
console.error(`[browser-link] ${msg}`);
|
|
19
|
+
}
|
|
20
|
+
function safeParse(raw) {
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(raw);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function send(ws, msg) {
|
|
29
|
+
ws.send(JSON.stringify(msg));
|
|
30
|
+
}
|
|
31
|
+
/** Bring up the WebSocket bridge for the Chrome extension. Resolves only
|
|
32
|
+
* after the server is listening, so the caller can fail fast (and refuse
|
|
33
|
+
* to expose the MCP transport) when the port is taken or any other bind
|
|
34
|
+
* error happens. */
|
|
35
|
+
/**
|
|
36
|
+
* Loopback-only addresses can show up as ::ffff:127.0.0.1 (IPv4-mapped IPv6)
|
|
37
|
+
* or ::1 depending on how the kernel exposes the dual stack. Normalise to the
|
|
38
|
+
* IPv4 form lsof / netstat understand.
|
|
39
|
+
*/
|
|
40
|
+
function normaliseLoopback(addr) {
|
|
41
|
+
if (addr === '::1' || addr === '::ffff:127.0.0.1')
|
|
42
|
+
return '127.0.0.1';
|
|
43
|
+
if (addr.startsWith('::ffff:'))
|
|
44
|
+
return addr.slice('::ffff:'.length);
|
|
45
|
+
return addr;
|
|
46
|
+
}
|
|
47
|
+
function startWsBridge(tabs, pendingRequests) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const wss = new WebSocketServer({
|
|
50
|
+
host: WS_HOST,
|
|
51
|
+
port: WS_PORT,
|
|
52
|
+
// Refuse the upgrade unless the OS confirms the peer is a Chromium-based
|
|
53
|
+
// browser. The check happens before any application bytes are exchanged.
|
|
54
|
+
verifyClient: (info, cb) => {
|
|
55
|
+
const remoteAddress = normaliseLoopback(info.req.socket.remoteAddress ?? '');
|
|
56
|
+
const remotePort = info.req.socket.remotePort;
|
|
57
|
+
if (!remoteAddress || remotePort == null) {
|
|
58
|
+
log('Rejected WS handshake: peer address/port not exposed by socket.');
|
|
59
|
+
cb(false, 403, 'Cannot identify peer');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
lookupPeerProcess(remoteAddress, remotePort)
|
|
63
|
+
.then((peer) => {
|
|
64
|
+
if (!peer) {
|
|
65
|
+
log(`Rejected WS handshake from ${remoteAddress}:${remotePort}: could not identify owning process.`);
|
|
66
|
+
cb(false, 403, 'Peer process unknown');
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (!isAllowedBrowser(peer.binaryName)) {
|
|
70
|
+
log(`Rejected WS handshake from PID ${peer.pid} (${peer.binaryName}): not a Chromium-based browser.`);
|
|
71
|
+
cb(false, 403, 'Peer is not a Chromium-based browser');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
cb(true);
|
|
75
|
+
})
|
|
76
|
+
.catch((err) => {
|
|
77
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
78
|
+
log(`Rejected WS handshake: process lookup failed (${msg}).`);
|
|
79
|
+
cb(false, 500, 'Process lookup failed');
|
|
80
|
+
});
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
let settled = false;
|
|
84
|
+
wss.on('listening', () => {
|
|
85
|
+
settled = true;
|
|
86
|
+
log(`WebSocket listening on ws://${WS_HOST}:${WS_PORT}`);
|
|
87
|
+
resolve(wss);
|
|
88
|
+
});
|
|
89
|
+
wss.on('error', (err) => {
|
|
90
|
+
if (!settled) {
|
|
91
|
+
settled = true;
|
|
92
|
+
reject(translateBindError(err));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Post-listening errors: log but keep running; ws will emit per-connection
|
|
96
|
+
// errors separately.
|
|
97
|
+
log(`WebSocket server error: ${err.message}`);
|
|
98
|
+
});
|
|
99
|
+
wss.on('connection', (ws) => {
|
|
100
|
+
let assignedTabId = null;
|
|
101
|
+
ws.on('message', (raw) => {
|
|
102
|
+
const msg = safeParse(raw.toString());
|
|
103
|
+
if (!msg)
|
|
104
|
+
return;
|
|
105
|
+
if (msg.kind === 'tab.register' && !assignedTabId) {
|
|
106
|
+
assignedTabId = assignTabId();
|
|
107
|
+
tabs.set(assignedTabId, {
|
|
108
|
+
tabId: assignedTabId,
|
|
109
|
+
url: msg.payload.url,
|
|
110
|
+
title: msg.payload.title,
|
|
111
|
+
ws,
|
|
112
|
+
});
|
|
113
|
+
send(ws, { kind: 'tab.registered', payload: { tabId: assignedTabId } });
|
|
114
|
+
log(`Tab registered: ${assignedTabId} -> ${msg.payload.url}`);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (msg.kind === 'tool.response') {
|
|
118
|
+
const pending = pendingRequests.get(msg.id);
|
|
119
|
+
if (!pending)
|
|
120
|
+
return;
|
|
121
|
+
clearTimeout(pending.timeout);
|
|
122
|
+
pendingRequests.delete(msg.id);
|
|
123
|
+
if (msg.ok)
|
|
124
|
+
pending.resolve(msg.result);
|
|
125
|
+
else
|
|
126
|
+
pending.reject(new Error(msg.error));
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
ws.on('close', () => {
|
|
130
|
+
if (assignedTabId) {
|
|
131
|
+
tabs.delete(assignedTabId);
|
|
132
|
+
log(`Tab disconnected: ${assignedTabId}`);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
ws.on('error', (err) => {
|
|
136
|
+
log(`WS connection error: ${err.message}`);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
let tabIdCounter = 0;
|
|
142
|
+
function assignTabId() {
|
|
143
|
+
tabIdCounter += 1;
|
|
144
|
+
return `tab_${tabIdCounter}`;
|
|
145
|
+
}
|
|
146
|
+
function translateBindError(err) {
|
|
147
|
+
if (err.code === 'EADDRINUSE') {
|
|
148
|
+
return new Error(`browser-link: port ${WS_HOST}:${WS_PORT} is already in use. ` +
|
|
149
|
+
`Another browser-link server is likely running. Stop it (and any ` +
|
|
150
|
+
`\`npm run dev\` running this project) before launching this one.`);
|
|
151
|
+
}
|
|
152
|
+
return err;
|
|
153
|
+
}
|
|
154
|
+
function buildCallBrowserTool(tabs, pendingRequests) {
|
|
155
|
+
return (tabId, tool, params, timeoutMs = DEFAULT_TIMEOUT_MS) => {
|
|
156
|
+
const session = tabs.get(tabId);
|
|
157
|
+
if (!session)
|
|
158
|
+
return Promise.reject(new Error(`Tab not connected: ${tabId}`));
|
|
159
|
+
const id = randomUUID();
|
|
160
|
+
return new Promise((resolve, reject) => {
|
|
161
|
+
const timeout = setTimeout(() => {
|
|
162
|
+
pendingRequests.delete(id);
|
|
163
|
+
reject(new Error(`Tool '${tool}' timed out after ${timeoutMs}ms`));
|
|
164
|
+
}, timeoutMs);
|
|
165
|
+
pendingRequests.set(id, { resolve, reject, timeout });
|
|
166
|
+
send(session.ws, { kind: 'tool.request', id, tool, params });
|
|
167
|
+
});
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function buildListTabs(tabs) {
|
|
171
|
+
return () => Array.from(tabs.values()).map((t) => ({
|
|
172
|
+
tab_id: t.tabId,
|
|
173
|
+
url: t.url,
|
|
174
|
+
title: t.title,
|
|
175
|
+
}));
|
|
176
|
+
}
|
|
177
|
+
/** Start the MCP server (stdio transport) and the WebSocket bridge.
|
|
178
|
+
* Resolves only when both are ready. If the WebSocket bind fails the
|
|
179
|
+
* MCP transport is never exposed and the caller sees a clear error. */
|
|
180
|
+
export async function runServer() {
|
|
181
|
+
const tabs = new Map();
|
|
182
|
+
const pendingRequests = new Map();
|
|
183
|
+
// Bind the WS bridge first. If this throws, runServer() rejects and the
|
|
184
|
+
// MCP client receives a fail-fast exit instead of a half-started server.
|
|
185
|
+
await startWsBridge(tabs, pendingRequests);
|
|
186
|
+
const deps = {
|
|
187
|
+
listTabs: buildListTabs(tabs),
|
|
188
|
+
callBrowserTool: buildCallBrowserTool(tabs, pendingRequests),
|
|
189
|
+
};
|
|
190
|
+
const mcpServer = new Server({ name: 'browser-link', version: '0.0.1' }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
|
|
191
|
+
mcpServer.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
192
|
+
tools: [...BROWSER_TOOL_DEFINITIONS, ...MAP_TOOL_DEFINITIONS],
|
|
193
|
+
}));
|
|
194
|
+
mcpServer.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
195
|
+
const { name, arguments: args } = req.params;
|
|
196
|
+
try {
|
|
197
|
+
if (isMapTool(name))
|
|
198
|
+
return toolResponse(handleMapTool(name, args));
|
|
199
|
+
if (isBrowserTool(name))
|
|
200
|
+
return toolResponse(await handleBrowserTool(name, args, deps));
|
|
201
|
+
return toolError(`Unknown tool: ${name}`);
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
const transport = new StdioServerTransport();
|
|
208
|
+
await mcpServer.connect(transport);
|
|
209
|
+
log('MCP server ready on stdio');
|
|
210
|
+
for (const sig of ['SIGINT', 'SIGTERM']) {
|
|
211
|
+
process.once(sig, () => {
|
|
212
|
+
closeDb();
|
|
213
|
+
process.exit(0);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP tool definitions for the browser-bridge family. Kept separate from
|
|
3
|
+
* the runtime dispatcher so the JSON schemas stay reviewable in one place
|
|
4
|
+
* and the dispatch logic stays small.
|
|
5
|
+
*/
|
|
6
|
+
import type { ToolDefinition } from './types.js';
|
|
7
|
+
export declare const BROWSER_TOOL_DEFINITIONS: ToolDefinition[];
|