chrome-ai-bridge 2.3.9 → 2.4.0
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/build/extension/README.md +181 -0
- package/build/extension/background.mjs +1318 -0
- package/build/extension/debug-logger.mjs +148 -0
- package/build/extension/icons/icon-128.png +0 -0
- package/build/extension/icons/icon-16.png +0 -0
- package/build/extension/icons/icon-32.png +0 -0
- package/build/extension/icons/icon-48.png +0 -0
- package/build/extension/icons/icon.svg +19 -0
- package/build/extension/manifest.json +28 -0
- package/build/extension/relay-server.ts +539 -0
- package/build/extension/ui/connect.html +429 -0
- package/build/extension/ui/connect.js +491 -0
- package/build/src/extension/relay-server.js +27 -5
- package/build/src/fast-cdp/extension-raw.js +4 -1
- package/build/src/fast-cdp/fast-chat.js +13 -6
- package/build/src/fast-cdp/network-interceptor.js +96 -26
- package/package.json +2 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DebugLogger - Chrome拡張機能デバッグ用ログ管理クラス
|
|
3
|
+
*
|
|
4
|
+
* カテゴリ:
|
|
5
|
+
* - ws: WebSocket接続関連
|
|
6
|
+
* - cdp: Chrome DevTools Protocol関連
|
|
7
|
+
* - tab: タブ操作関連
|
|
8
|
+
* - relay: リレーサーバー関連
|
|
9
|
+
* - error: エラー
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
class DebugLogger {
|
|
13
|
+
constructor() {
|
|
14
|
+
this.logs = [];
|
|
15
|
+
this.maxLogs = 500;
|
|
16
|
+
this.enabled = true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* ログエントリを追加
|
|
21
|
+
* @param {string} category - ログカテゴリ ('ws', 'cdp', 'tab', 'relay', 'error')
|
|
22
|
+
* @param {string} message - ログメッセージ
|
|
23
|
+
* @param {any} data - 追加データ(オプション)
|
|
24
|
+
*/
|
|
25
|
+
log(category, message, data = null) {
|
|
26
|
+
if (!this.enabled) return;
|
|
27
|
+
|
|
28
|
+
const entry = {
|
|
29
|
+
ts: new Date().toISOString(),
|
|
30
|
+
category,
|
|
31
|
+
message,
|
|
32
|
+
data: data !== null ? this._safeStringify(data) : null
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
this.logs.push(entry);
|
|
36
|
+
|
|
37
|
+
// 最大件数を超えたら古いログを削除
|
|
38
|
+
if (this.logs.length > this.maxLogs) {
|
|
39
|
+
this.logs.shift();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// コンソールにも出力
|
|
43
|
+
const prefix = `[${category.toUpperCase()}]`;
|
|
44
|
+
if (data !== null) {
|
|
45
|
+
console.log(prefix, message, data);
|
|
46
|
+
} else {
|
|
47
|
+
console.log(prefix, message);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* エラーログを追加(ショートカット)
|
|
53
|
+
* @param {string} message - エラーメッセージ
|
|
54
|
+
* @param {any} error - エラーオブジェクト
|
|
55
|
+
*/
|
|
56
|
+
error(message, error = null) {
|
|
57
|
+
const errorData = error instanceof Error
|
|
58
|
+
? { name: error.name, message: error.message, stack: error.stack }
|
|
59
|
+
: error;
|
|
60
|
+
this.log('error', message, errorData);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* ログを取得
|
|
65
|
+
* @param {string|null} filter - カテゴリでフィルタ(nullで全件)
|
|
66
|
+
* @param {number} limit - 取得件数(デフォルト: 100)
|
|
67
|
+
* @returns {Array} ログエントリの配列
|
|
68
|
+
*/
|
|
69
|
+
getLogs(filter = null, limit = 100) {
|
|
70
|
+
let result = filter
|
|
71
|
+
? this.logs.filter(l => l.category === filter)
|
|
72
|
+
: this.logs;
|
|
73
|
+
|
|
74
|
+
// 最新のログから返す
|
|
75
|
+
return result.slice(-limit);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* ログをクリア
|
|
80
|
+
*/
|
|
81
|
+
clear() {
|
|
82
|
+
this.logs = [];
|
|
83
|
+
console.log('[DEBUG] Logs cleared');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* ログを有効/無効にする
|
|
88
|
+
* @param {boolean} enabled
|
|
89
|
+
*/
|
|
90
|
+
setEnabled(enabled) {
|
|
91
|
+
this.enabled = enabled;
|
|
92
|
+
console.log('[DEBUG] Logger', enabled ? 'enabled' : 'disabled');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 安全なJSON変換(循環参照対策)
|
|
97
|
+
* @param {any} obj
|
|
98
|
+
* @returns {any}
|
|
99
|
+
*/
|
|
100
|
+
_safeStringify(obj) {
|
|
101
|
+
if (obj === null || obj === undefined) return obj;
|
|
102
|
+
if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean') {
|
|
103
|
+
return obj;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
const seen = new WeakSet();
|
|
108
|
+
return JSON.parse(JSON.stringify(obj, (key, value) => {
|
|
109
|
+
if (typeof value === 'object' && value !== null) {
|
|
110
|
+
if (seen.has(value)) {
|
|
111
|
+
return '[Circular]';
|
|
112
|
+
}
|
|
113
|
+
seen.add(value);
|
|
114
|
+
}
|
|
115
|
+
// WebSocketなど大きなオブジェクトは省略
|
|
116
|
+
if (value instanceof WebSocket) {
|
|
117
|
+
return `[WebSocket: ${value.readyState}]`;
|
|
118
|
+
}
|
|
119
|
+
return value;
|
|
120
|
+
}));
|
|
121
|
+
} catch (e) {
|
|
122
|
+
return String(obj);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 統計情報を取得
|
|
128
|
+
* @returns {Object}
|
|
129
|
+
*/
|
|
130
|
+
getStats() {
|
|
131
|
+
const stats = {
|
|
132
|
+
total: this.logs.length,
|
|
133
|
+
byCategory: {}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
for (const log of this.logs) {
|
|
137
|
+
stats.byCategory[log.category] = (stats.byCategory[log.category] || 0) + 1;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return stats;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// シングルトンインスタンスをエクスポート
|
|
145
|
+
export const debugLogger = new DebugLogger();
|
|
146
|
+
|
|
147
|
+
// デフォルトエクスポート
|
|
148
|
+
export default debugLogger;
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
4
|
+
<stop offset="0%" style="stop-color:#4285F4"/>
|
|
5
|
+
<stop offset="100%" style="stop-color:#7C3AED"/>
|
|
6
|
+
</linearGradient>
|
|
7
|
+
</defs>
|
|
8
|
+
<!-- Background circle -->
|
|
9
|
+
<circle cx="64" cy="64" r="60" fill="url(#grad)"/>
|
|
10
|
+
<!-- Bridge shape - two nodes connected -->
|
|
11
|
+
<circle cx="36" cy="64" r="16" fill="white" opacity="0.95"/>
|
|
12
|
+
<circle cx="92" cy="64" r="16" fill="white" opacity="0.95"/>
|
|
13
|
+
<!-- Connection line -->
|
|
14
|
+
<rect x="36" y="58" width="56" height="12" fill="white" opacity="0.95" rx="6"/>
|
|
15
|
+
<!-- AI sparkle on left -->
|
|
16
|
+
<path d="M36 52 L38 56 L42 56 L39 59 L40 64 L36 61 L32 64 L33 59 L30 56 L34 56 Z" fill="#4285F4"/>
|
|
17
|
+
<!-- Chrome dot on right -->
|
|
18
|
+
<circle cx="92" cy="64" r="6" fill="#7C3AED"/>
|
|
19
|
+
</svg>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 3,
|
|
3
|
+
"name": "chrome-ai-bridge Extension",
|
|
4
|
+
"version": "2.0.28",
|
|
5
|
+
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqDLiSB+b/gbnQ4zWRP65jnd27KmzpjJyR1JAQIjCD/dNORzTgk6+G0TjYEDZLIDceKHzGJudqnwq4q9g3T1eJ0SECZNXnaoE00WkgXfAUSQn6cmmXR3aQGFky/zbCmxnkRa0vYupxszlhw0yrlSZrIJd/weWF75Byh0zJfZ84kqDDhaj7TlB5laHICnoSLmPTif4mQcUW9oOKmAJPriPw4CWATKZsrQ4X46djxefSmfbqYfb9rttAqJVst40gO0Gsl6GOGxMHMds5Cl9GELc0dI3Gpobw07hQldZb8TeyilI/SnOaeS3HPtrp+KyEgRu8SgRdlrvuq6DeEZsP+kK7wIDAQAB",
|
|
6
|
+
"description": "Bridge between Chrome tabs and chrome-ai-bridge MCP server",
|
|
7
|
+
"permissions": ["debugger", "activeTab", "tabs", "storage", "alarms"],
|
|
8
|
+
"host_permissions": ["<all_urls>"],
|
|
9
|
+
"background": {
|
|
10
|
+
"service_worker": "background.mjs",
|
|
11
|
+
"type": "module"
|
|
12
|
+
},
|
|
13
|
+
"icons": {
|
|
14
|
+
"16": "icons/icon-16.png",
|
|
15
|
+
"32": "icons/icon-32.png",
|
|
16
|
+
"48": "icons/icon-48.png",
|
|
17
|
+
"128": "icons/icon-128.png"
|
|
18
|
+
},
|
|
19
|
+
"action": {
|
|
20
|
+
"default_title": "chrome-ai-bridge",
|
|
21
|
+
"default_icon": {
|
|
22
|
+
"16": "icons/icon-16.png",
|
|
23
|
+
"32": "icons/icon-32.png",
|
|
24
|
+
"48": "icons/icon-48.png"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"options_page": "ui/connect.html"
|
|
28
|
+
}
|