@symbo.ls/connect 3.4.9 → 3.5.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/dist/manifest.json +1 -1
- package/dist/panel.css +275 -0
- package/dist/panel.html +117 -4
- package/dist/panel.js +485 -20
- package/dist/service_worker.js +57 -1
- package/dist/service_worker.js.map +2 -2
- package/package.json +2 -2
- package/src/service_worker.js +57 -1
- package/static/panel.css +275 -0
- package/static/panel.html +117 -4
- package/static/panel.js +485 -20
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/settings/settings_utils.js", "../src/service_worker.js"],
|
|
4
|
-
"sourcesContent": ["/**\n * @typedef {Object} Settings\n * @property {boolean} useComputed\n * @property {boolean} useStylesheets\n */\n\nconst storageKey = 'settings'\n\n/**\n * @typedef {Object} SettingDefinition\n * @property {string} type\n * @property {String} name\n * @property {string} [key]\n * @property {any} [default]\n * @property {value} [any]\n */\n\n/**\n * @type {SettingDefinition[]}\n */\nexport const settingsDefinitions = [\n {\n key: 'useStylesheets',\n name: 'Use Stylesheets',\n type: 'checkbox',\n default: true\n },\n {\n key: 'useComputed',\n name: 'Use Computed',\n type: 'checkbox',\n default: false\n }\n]\n\n/**\n * @returns {Promise<Settings>}\n */\nexport const getSettings = async () =>\n (await chrome.storage.local.get(storageKey)).settings\n\n/**\n * @param {Partial<Settings>} updates\n */\nexport async function updateSettings(updates) {\n const cur = await getSettings()\n chrome.storage.local\n .set({ [storageKey]: { ...cur, ...updates } })\n .catch((reason) => console.error(`failed to update settings : ${reason}`))\n}\n\nexport async function initSettings() {\n const curSettings = (await getSettings()) ?? {}\n\n // construct default settings from definitions\n const defaultSettings = {}\n settingsDefinitions.forEach(({ key, default: defValue }) => {\n defaultSettings[key] = defValue\n })\n\n // override defaults with any existing settings\n Object.keys(curSettings).forEach((key) => {\n // only include settings within the current defined set\n if (key in defaultSettings) {\n defaultSettings[key] = curSettings[key]\n }\n })\n\n updateSettings(defaultSettings)\n}\n", "import { initSettings } from './settings/settings_utils'\n\n// ============================================================\n// Tab state helpers (for grabber toggle)\n// ============================================================\nconst getTabState = (tabId) =>\n chrome.storage.session\n .get(String(tabId))\n .then((data) => parseInt(data[tabId] || 0, 10))\n\nconst setTabState = (tabId, state) =>\n chrome.storage.session.set({ [tabId]: state })\n\nconst getActiveTabs = () =>\n chrome.tabs.query({ active: true, currentWindow: true })\n\nconst messageActiveTabs = async (message, { condition, modifyMsg } = {}) => {\n let tabs = await getActiveTabs()\n tabs = tabs.filter(\n (tab) => /^https?:/u.test(tab.url) && (!condition || condition(tab))\n )\n\n return Promise.all(\n tabs.map((tab, index) => {\n const msg = modifyMsg ? modifyMsg(tab, message, index) : message\n return chrome.tabs\n .sendMessage(tab.id, msg)\n .then((response) => response)\n .catch((reason) => {\n console.log(`Failed to send msg to tab ${tab.id}`, { reason })\n })\n })\n )\n}\n\nconst toggleActiveTabsState = async () => {\n const tabs = await getActiveTabs()\n let states = await Promise.all(tabs.map((tab) => getTabState(tab.id)))\n states = states.map((s) => (s ? 0 : 1))\n\n return messageActiveTabs(\n { type: 'toggle' },\n {\n modifyMsg: (tab, msg, index) => {\n const state = states[index]\n setTabState(tab.id, state)\n return { ...msg, state }\n }\n }\n )\n}\n\n// ============================================================\n// Install / update\n// ============================================================\nchrome.runtime.onInstalled.addListener(({ previousVersion, reason }) => {\n const { name } = chrome.runtime.getManifest()\n chrome.action.setBadgeBackgroundColor({ color: '#099058ff' })\n console.log(`${name} ${reason}`, { id: chrome.runtime.id, previousVersion })\n\n if (['install', 'update'].includes(reason)) {\n initSettings()\n\n // Override Origin header on API requests to avoid CORS rejection\n chrome.declarativeNetRequest.updateDynamicRules({\n removeRuleIds: [1, 2, 3],\n addRules: [\n {\n id: 1,\n priority: 1,\n action: {\n type: 'modifyHeaders',\n requestHeaders: [\n { header: 'Origin', operation: 'set', value: 'https://symbols.app' }\n ]\n },\n condition: {\n urlFilter: 'https://api.symbols.app/*',\n resourceTypes: ['xmlhttprequest', 'other']\n }\n },\n {\n id: 2,\n priority: 1,\n action: {\n type: 'modifyHeaders',\n requestHeaders: [\n { header: 'Origin', operation: 'remove' }\n ]\n },\n condition: {\n urlFilter: 'https://api.anthropic.com/*',\n resourceTypes: ['xmlhttprequest', 'other']\n }\n }\n ]\n })\n }\n})\n\n// ============================================================\n// Badge state\n// ============================================================\nchrome.storage.onChanged.addListener((changes, areas) => {\n if (\n areas === 'session' &&\n Object.values(changes).some((change) => parseInt(change.newValue, 10))\n ) {\n chrome.action.setBadgeText({ text: 'ON' })\n } else {\n chrome.action.setBadgeText({ text: null })\n }\n})\n\nchrome.tabs.onActivated.addListener(({ tabId }) => {\n chrome.action.setBadgeText({ text: null })\n setTabState(tabId, 0)\n})\n\n// ============================================================\n// Keyboard shortcut (Ctrl+E / Cmd+E)\n// ============================================================\nchrome.commands.onCommand.addListener(async (command) => {\n if (command === 'toggleGrabber') {\n await toggleActiveTabsState()\n }\n})\n\n// ============================================================\n// Toolbar icon click -> toggle grabber\n// ============================================================\nchrome.action.onClicked.addListener(async () => {\n await toggleActiveTabsState()\n})\n\n// ============================================================\n// Internal messaging (from devtools panel)\n// ============================================================\nlet pickerTabId = null\n\nchrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {\n if (msg.type === 'open-picker') {\n const pickerUrl = chrome.runtime.getURL('picker.html')\n chrome.tabs.create({ url: pickerUrl, active: true }, (tab) => {\n pickerTabId = tab.id\n })\n sendResponse({ ok: true })\n return true\n }\n\n // Forward file operations to the picker tab\n if (msg.type === 'read-file' || msg.type === 'write-file' || msg.type === 'rescan-project') {\n const forwardToPickerTab = (tabId) => {\n chrome.tabs.sendMessage(tabId, msg, (response) => {\n if (chrome.runtime.lastError) {\n sendResponse({ error: 'Picker tab error: ' + chrome.runtime.lastError.message })\n } else {\n sendResponse(response)\n }\n })\n }\n\n const openNewPickerTab = () => {\n const pickerUrl = chrome.runtime.getURL('picker.html?bg')\n chrome.tabs.create({ url: pickerUrl, active: false }, (tab) => {\n pickerTabId = tab.id\n // Wait for the page to load before forwarding\n setTimeout(() => forwardToPickerTab(tab.id), 800)\n })\n }\n\n if (pickerTabId) {\n // Verify the tab still exists\n chrome.tabs.get(pickerTabId, (tab) => {\n if (chrome.runtime.lastError || !tab) {\n pickerTabId = null\n openNewPickerTab()\n } else {\n forwardToPickerTab(pickerTabId)\n }\n })\n } else {\n openNewPickerTab()\n }\n return true\n }\n\n // Proxy API requests \u2014 strip Origin to avoid CORS rejection on server\n if (msg.type === 'api-fetch') {\n const headers = new Headers(msg.headers || {})\n headers.delete('Origin')\n const fetchOpts = {\n method: msg.method || 'GET',\n headers\n }\n if (msg.body && msg.method && msg.method !== 'GET') {\n fetchOpts.body = msg.body\n }\n fetch(msg.url, fetchOpts)\n .then((res) => res.text().then((text) => ({ ok: res.ok, status: res.status, text })))\n .then(({ ok, status, text }) => {\n let json = null\n try { json = JSON.parse(text) } catch (e) {}\n sendResponse({ ok, status, data: json, text })\n })\n .catch((e) => {\n sendResponse({ ok: false, status: 0, error: e.message || String(e) })\n })\n return true\n }\n\n // Forward folder-picked to all extension pages\n if (msg.type === 'folder-picked') {\n // Already handled by chrome.runtime.onMessage in panel\n }\n\n return true\n})\n\n// ============================================================\n// External messaging (from symbols.app / platform.symbo.ls)\n// ============================================================\nchrome.runtime.onMessageExternal.addListener(async (msg, sender, respond) => {\n switch (msg.type) {\n case 'toggle_platform_mode': {\n const responses = await toggleActiveTabsState()\n if (responses.some((res) => res && res.success)) {\n const domql = responses.find((res) => res && res.domql)?.domql || null\n setTabState(sender.tab.id, 0)\n respond({ success: true, domql })\n }\n break\n }\n case 'request_domql': {\n const data = await chrome.storage.local.get('domqlStr')\n const domql = JSON.parse(data.domqlStr)\n respond(domql)\n break\n }\n default: {\n console.error('Invalid message received', { msg, sender })\n }\n }\n\n return true\n})\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["/**\n * @typedef {Object} Settings\n * @property {boolean} useComputed\n * @property {boolean} useStylesheets\n */\n\nconst storageKey = 'settings'\n\n/**\n * @typedef {Object} SettingDefinition\n * @property {string} type\n * @property {String} name\n * @property {string} [key]\n * @property {any} [default]\n * @property {value} [any]\n */\n\n/**\n * @type {SettingDefinition[]}\n */\nexport const settingsDefinitions = [\n {\n key: 'useStylesheets',\n name: 'Use Stylesheets',\n type: 'checkbox',\n default: true\n },\n {\n key: 'useComputed',\n name: 'Use Computed',\n type: 'checkbox',\n default: false\n }\n]\n\n/**\n * @returns {Promise<Settings>}\n */\nexport const getSettings = async () =>\n (await chrome.storage.local.get(storageKey)).settings\n\n/**\n * @param {Partial<Settings>} updates\n */\nexport async function updateSettings(updates) {\n const cur = await getSettings()\n chrome.storage.local\n .set({ [storageKey]: { ...cur, ...updates } })\n .catch((reason) => console.error(`failed to update settings : ${reason}`))\n}\n\nexport async function initSettings() {\n const curSettings = (await getSettings()) ?? {}\n\n // construct default settings from definitions\n const defaultSettings = {}\n settingsDefinitions.forEach(({ key, default: defValue }) => {\n defaultSettings[key] = defValue\n })\n\n // override defaults with any existing settings\n Object.keys(curSettings).forEach((key) => {\n // only include settings within the current defined set\n if (key in defaultSettings) {\n defaultSettings[key] = curSettings[key]\n }\n })\n\n updateSettings(defaultSettings)\n}\n", "import { initSettings } from './settings/settings_utils'\n\n// ============================================================\n// Tab state helpers (for grabber toggle)\n// ============================================================\nconst getTabState = (tabId) =>\n chrome.storage.session\n .get(String(tabId))\n .then((data) => parseInt(data[tabId] || 0, 10))\n\nconst setTabState = (tabId, state) =>\n chrome.storage.session.set({ [tabId]: state })\n\nconst getActiveTabs = () =>\n chrome.tabs.query({ active: true, currentWindow: true })\n\nconst messageActiveTabs = async (message, { condition, modifyMsg } = {}) => {\n let tabs = await getActiveTabs()\n tabs = tabs.filter(\n (tab) => /^https?:/u.test(tab.url) && (!condition || condition(tab))\n )\n\n return Promise.all(\n tabs.map((tab, index) => {\n const msg = modifyMsg ? modifyMsg(tab, message, index) : message\n return chrome.tabs\n .sendMessage(tab.id, msg)\n .then((response) => response)\n .catch((reason) => {\n console.log(`Failed to send msg to tab ${tab.id}`, { reason })\n })\n })\n )\n}\n\nconst toggleActiveTabsState = async () => {\n const tabs = await getActiveTabs()\n let states = await Promise.all(tabs.map((tab) => getTabState(tab.id)))\n states = states.map((s) => (s ? 0 : 1))\n\n return messageActiveTabs(\n { type: 'toggle' },\n {\n modifyMsg: (tab, msg, index) => {\n const state = states[index]\n setTabState(tab.id, state)\n return { ...msg, state }\n }\n }\n )\n}\n\n// ============================================================\n// Install / update\n// ============================================================\nchrome.runtime.onInstalled.addListener(({ previousVersion, reason }) => {\n const { name } = chrome.runtime.getManifest()\n chrome.action.setBadgeBackgroundColor({ color: '#099058ff' })\n console.log(`${name} ${reason}`, { id: chrome.runtime.id, previousVersion })\n\n if (['install', 'update'].includes(reason)) {\n initSettings()\n\n // Override Origin header on API requests to avoid CORS rejection\n chrome.declarativeNetRequest.updateDynamicRules({\n removeRuleIds: [1, 2, 3, 4, 5, 6, 7],\n addRules: [\n {\n id: 1,\n priority: 1,\n action: {\n type: 'modifyHeaders',\n requestHeaders: [\n { header: 'Origin', operation: 'set', value: 'https://symbols.app' }\n ]\n },\n condition: {\n urlFilter: 'https://api.symbols.app/*',\n resourceTypes: ['xmlhttprequest', 'other']\n }\n },\n {\n id: 2,\n priority: 1,\n action: {\n type: 'modifyHeaders',\n requestHeaders: [\n { header: 'Origin', operation: 'remove' }\n ]\n },\n condition: {\n urlFilter: 'https://api.anthropic.com/*',\n resourceTypes: ['xmlhttprequest', 'other']\n }\n },\n {\n id: 3,\n priority: 1,\n action: {\n type: 'modifyHeaders',\n requestHeaders: [\n { header: 'Origin', operation: 'remove' }\n ]\n },\n condition: {\n urlFilter: 'https://api.openai.com/*',\n resourceTypes: ['xmlhttprequest', 'other']\n }\n },\n {\n id: 4,\n priority: 1,\n action: {\n type: 'modifyHeaders',\n requestHeaders: [\n { header: 'Origin', operation: 'remove' }\n ]\n },\n condition: {\n urlFilter: 'https://generativelanguage.googleapis.com/*',\n resourceTypes: ['xmlhttprequest', 'other']\n }\n },\n {\n id: 5,\n priority: 1,\n action: {\n type: 'modifyHeaders',\n requestHeaders: [\n { header: 'Origin', operation: 'remove' }\n ]\n },\n condition: {\n urlFilter: 'https://api.deepseek.com/*',\n resourceTypes: ['xmlhttprequest', 'other']\n }\n },\n {\n id: 6,\n priority: 1,\n action: {\n type: 'modifyHeaders',\n requestHeaders: [\n { header: 'Origin', operation: 'remove' }\n ]\n },\n condition: {\n urlFilter: 'https://api.groq.com/*',\n resourceTypes: ['xmlhttprequest', 'other']\n }\n }\n ]\n })\n }\n})\n\n// ============================================================\n// Badge state\n// ============================================================\nchrome.storage.onChanged.addListener((changes, areas) => {\n if (\n areas === 'session' &&\n Object.values(changes).some((change) => parseInt(change.newValue, 10))\n ) {\n chrome.action.setBadgeText({ text: 'ON' })\n } else {\n chrome.action.setBadgeText({ text: null })\n }\n})\n\nchrome.tabs.onActivated.addListener(({ tabId }) => {\n chrome.action.setBadgeText({ text: null })\n setTabState(tabId, 0)\n})\n\n// ============================================================\n// Keyboard shortcut (Ctrl+E / Cmd+E)\n// ============================================================\nchrome.commands.onCommand.addListener(async (command) => {\n if (command === 'toggleGrabber') {\n await toggleActiveTabsState()\n }\n})\n\n// ============================================================\n// Toolbar icon click -> toggle grabber\n// ============================================================\nchrome.action.onClicked.addListener(async () => {\n await toggleActiveTabsState()\n})\n\n// ============================================================\n// Internal messaging (from devtools panel)\n// ============================================================\nlet pickerTabId = null\n\nchrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {\n if (msg.type === 'open-picker') {\n const pickerUrl = chrome.runtime.getURL('picker.html')\n chrome.tabs.create({ url: pickerUrl, active: true }, (tab) => {\n pickerTabId = tab.id\n })\n sendResponse({ ok: true })\n return true\n }\n\n // Forward file operations to the picker tab\n if (msg.type === 'read-file' || msg.type === 'write-file' || msg.type === 'rescan-project') {\n const forwardToPickerTab = (tabId) => {\n chrome.tabs.sendMessage(tabId, msg, (response) => {\n if (chrome.runtime.lastError) {\n sendResponse({ error: 'Picker tab error: ' + chrome.runtime.lastError.message })\n } else {\n sendResponse(response)\n }\n })\n }\n\n const openNewPickerTab = () => {\n const pickerUrl = chrome.runtime.getURL('picker.html?bg')\n chrome.tabs.create({ url: pickerUrl, active: false }, (tab) => {\n pickerTabId = tab.id\n // Wait for the page to load before forwarding\n setTimeout(() => forwardToPickerTab(tab.id), 800)\n })\n }\n\n if (pickerTabId) {\n // Verify the tab still exists\n chrome.tabs.get(pickerTabId, (tab) => {\n if (chrome.runtime.lastError || !tab) {\n pickerTabId = null\n openNewPickerTab()\n } else {\n forwardToPickerTab(pickerTabId)\n }\n })\n } else {\n openNewPickerTab()\n }\n return true\n }\n\n // Proxy API requests \u2014 strip Origin to avoid CORS rejection on server\n if (msg.type === 'api-fetch') {\n const headers = new Headers(msg.headers || {})\n headers.delete('Origin')\n const fetchOpts = {\n method: msg.method || 'GET',\n headers\n }\n if (msg.body && msg.method && msg.method !== 'GET') {\n fetchOpts.body = msg.body\n }\n fetch(msg.url, fetchOpts)\n .then((res) => res.text().then((text) => ({ ok: res.ok, status: res.status, text })))\n .then(({ ok, status, text }) => {\n let json = null\n try { json = JSON.parse(text) } catch (e) {}\n sendResponse({ ok, status, data: json, text })\n })\n .catch((e) => {\n sendResponse({ ok: false, status: 0, error: e.message || String(e) })\n })\n return true\n }\n\n // Forward folder-picked to all extension pages\n if (msg.type === 'folder-picked') {\n // Already handled by chrome.runtime.onMessage in panel\n }\n\n return true\n})\n\n// ============================================================\n// External messaging (from symbols.app / platform.symbo.ls)\n// ============================================================\nchrome.runtime.onMessageExternal.addListener(async (msg, sender, respond) => {\n switch (msg.type) {\n case 'toggle_platform_mode': {\n const responses = await toggleActiveTabsState()\n if (responses.some((res) => res && res.success)) {\n const domql = responses.find((res) => res && res.domql)?.domql || null\n setTabState(sender.tab.id, 0)\n respond({ success: true, domql })\n }\n break\n }\n case 'request_domql': {\n const data = await chrome.storage.local.get('domqlStr')\n const domql = JSON.parse(data.domqlStr)\n respond(domql)\n break\n }\n default: {\n console.error('Invalid message received', { msg, sender })\n }\n }\n\n return true\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbo.ls/connect",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "Symbols Connect — Chrome extension for DOMQL inspection and element grabbing",
|
|
5
5
|
"main": "dist/content.js",
|
|
6
6
|
"scripts": {
|
|
@@ -15,6 +15,6 @@
|
|
|
15
15
|
"chokidar": "^3.5.3"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@domql/utils": "^3.
|
|
18
|
+
"@domql/utils": "^3.5.0"
|
|
19
19
|
}
|
|
20
20
|
}
|
package/src/service_worker.js
CHANGED
|
@@ -63,7 +63,7 @@ chrome.runtime.onInstalled.addListener(({ previousVersion, reason }) => {
|
|
|
63
63
|
|
|
64
64
|
// Override Origin header on API requests to avoid CORS rejection
|
|
65
65
|
chrome.declarativeNetRequest.updateDynamicRules({
|
|
66
|
-
removeRuleIds: [1, 2, 3],
|
|
66
|
+
removeRuleIds: [1, 2, 3, 4, 5, 6, 7],
|
|
67
67
|
addRules: [
|
|
68
68
|
{
|
|
69
69
|
id: 1,
|
|
@@ -92,6 +92,62 @@ chrome.runtime.onInstalled.addListener(({ previousVersion, reason }) => {
|
|
|
92
92
|
urlFilter: 'https://api.anthropic.com/*',
|
|
93
93
|
resourceTypes: ['xmlhttprequest', 'other']
|
|
94
94
|
}
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
id: 3,
|
|
98
|
+
priority: 1,
|
|
99
|
+
action: {
|
|
100
|
+
type: 'modifyHeaders',
|
|
101
|
+
requestHeaders: [
|
|
102
|
+
{ header: 'Origin', operation: 'remove' }
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
condition: {
|
|
106
|
+
urlFilter: 'https://api.openai.com/*',
|
|
107
|
+
resourceTypes: ['xmlhttprequest', 'other']
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: 4,
|
|
112
|
+
priority: 1,
|
|
113
|
+
action: {
|
|
114
|
+
type: 'modifyHeaders',
|
|
115
|
+
requestHeaders: [
|
|
116
|
+
{ header: 'Origin', operation: 'remove' }
|
|
117
|
+
]
|
|
118
|
+
},
|
|
119
|
+
condition: {
|
|
120
|
+
urlFilter: 'https://generativelanguage.googleapis.com/*',
|
|
121
|
+
resourceTypes: ['xmlhttprequest', 'other']
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
id: 5,
|
|
126
|
+
priority: 1,
|
|
127
|
+
action: {
|
|
128
|
+
type: 'modifyHeaders',
|
|
129
|
+
requestHeaders: [
|
|
130
|
+
{ header: 'Origin', operation: 'remove' }
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
condition: {
|
|
134
|
+
urlFilter: 'https://api.deepseek.com/*',
|
|
135
|
+
resourceTypes: ['xmlhttprequest', 'other']
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: 6,
|
|
140
|
+
priority: 1,
|
|
141
|
+
action: {
|
|
142
|
+
type: 'modifyHeaders',
|
|
143
|
+
requestHeaders: [
|
|
144
|
+
{ header: 'Origin', operation: 'remove' }
|
|
145
|
+
]
|
|
146
|
+
},
|
|
147
|
+
condition: {
|
|
148
|
+
urlFilter: 'https://api.groq.com/*',
|
|
149
|
+
resourceTypes: ['xmlhttprequest', 'other']
|
|
150
|
+
}
|
|
95
151
|
}
|
|
96
152
|
]
|
|
97
153
|
})
|
package/static/panel.css
CHANGED
|
@@ -2803,3 +2803,278 @@ body {
|
|
|
2803
2803
|
padding-top: 8px;
|
|
2804
2804
|
border-top: 1px solid var(--border);
|
|
2805
2805
|
}
|
|
2806
|
+
|
|
2807
|
+
/* ============================================================
|
|
2808
|
+
Network mode
|
|
2809
|
+
============================================================ */
|
|
2810
|
+
#mode-network {
|
|
2811
|
+
flex-direction: column;
|
|
2812
|
+
overflow-y: auto;
|
|
2813
|
+
}
|
|
2814
|
+
.network-panel {
|
|
2815
|
+
padding: 12px 16px;
|
|
2816
|
+
display: flex;
|
|
2817
|
+
flex-direction: column;
|
|
2818
|
+
gap: 16px;
|
|
2819
|
+
}
|
|
2820
|
+
.network-section {
|
|
2821
|
+
border: 1px solid var(--border);
|
|
2822
|
+
border-radius: var(--radius);
|
|
2823
|
+
padding: 12px;
|
|
2824
|
+
background: var(--bg-alt);
|
|
2825
|
+
}
|
|
2826
|
+
.network-section .section-header {
|
|
2827
|
+
margin-bottom: 10px;
|
|
2828
|
+
}
|
|
2829
|
+
.network-status {
|
|
2830
|
+
display: flex;
|
|
2831
|
+
align-items: center;
|
|
2832
|
+
gap: 8px;
|
|
2833
|
+
padding: 8px 10px;
|
|
2834
|
+
border-radius: var(--radius-sm);
|
|
2835
|
+
background: var(--bg-input);
|
|
2836
|
+
font-size: 12px;
|
|
2837
|
+
margin-bottom: 10px;
|
|
2838
|
+
}
|
|
2839
|
+
.network-status-dot {
|
|
2840
|
+
width: 8px;
|
|
2841
|
+
height: 8px;
|
|
2842
|
+
border-radius: 50%;
|
|
2843
|
+
background: var(--text-dim);
|
|
2844
|
+
flex-shrink: 0;
|
|
2845
|
+
}
|
|
2846
|
+
.network-status.connected .network-status-dot { background: #4caf50; }
|
|
2847
|
+
.network-status.error .network-status-dot { background: var(--error-color); }
|
|
2848
|
+
.network-fields {
|
|
2849
|
+
display: flex;
|
|
2850
|
+
flex-direction: column;
|
|
2851
|
+
gap: 8px;
|
|
2852
|
+
}
|
|
2853
|
+
.network-field label {
|
|
2854
|
+
display: block;
|
|
2855
|
+
font-size: 11px;
|
|
2856
|
+
color: var(--text-dim);
|
|
2857
|
+
margin-bottom: 3px;
|
|
2858
|
+
}
|
|
2859
|
+
.network-field-row {
|
|
2860
|
+
display: flex;
|
|
2861
|
+
gap: 6px;
|
|
2862
|
+
}
|
|
2863
|
+
.network-input {
|
|
2864
|
+
flex: 1;
|
|
2865
|
+
background: var(--bg-input);
|
|
2866
|
+
border: 1px solid var(--border);
|
|
2867
|
+
color: var(--text-bright);
|
|
2868
|
+
font-family: inherit;
|
|
2869
|
+
font-size: 12px;
|
|
2870
|
+
padding: 6px 10px;
|
|
2871
|
+
border-radius: var(--radius-sm);
|
|
2872
|
+
outline: none;
|
|
2873
|
+
}
|
|
2874
|
+
.network-input:focus { border-color: var(--accent); }
|
|
2875
|
+
.network-btn-sm {
|
|
2876
|
+
background: var(--bg-input);
|
|
2877
|
+
border: 1px solid var(--border);
|
|
2878
|
+
color: var(--text);
|
|
2879
|
+
font-size: 11px;
|
|
2880
|
+
padding: 4px 10px;
|
|
2881
|
+
border-radius: var(--radius-sm);
|
|
2882
|
+
cursor: pointer;
|
|
2883
|
+
white-space: nowrap;
|
|
2884
|
+
}
|
|
2885
|
+
.network-btn-sm:hover { border-color: var(--accent); color: var(--text-bright); }
|
|
2886
|
+
.network-actions {
|
|
2887
|
+
display: flex;
|
|
2888
|
+
gap: 8px;
|
|
2889
|
+
margin-top: 10px;
|
|
2890
|
+
}
|
|
2891
|
+
.network-btn {
|
|
2892
|
+
background: var(--accent);
|
|
2893
|
+
border: none;
|
|
2894
|
+
color: #fff;
|
|
2895
|
+
font-size: 12px;
|
|
2896
|
+
font-family: inherit;
|
|
2897
|
+
padding: 6px 14px;
|
|
2898
|
+
border-radius: var(--radius-sm);
|
|
2899
|
+
cursor: pointer;
|
|
2900
|
+
}
|
|
2901
|
+
.network-btn:hover { opacity: 0.9; }
|
|
2902
|
+
.network-btn-secondary {
|
|
2903
|
+
background: transparent;
|
|
2904
|
+
border: 1px solid var(--border);
|
|
2905
|
+
color: var(--text-dim);
|
|
2906
|
+
}
|
|
2907
|
+
.network-btn-secondary:hover { border-color: var(--text-dim); color: var(--text); }
|
|
2908
|
+
.network-info {
|
|
2909
|
+
display: flex;
|
|
2910
|
+
flex-direction: column;
|
|
2911
|
+
gap: 4px;
|
|
2912
|
+
}
|
|
2913
|
+
.network-info-row {
|
|
2914
|
+
display: flex;
|
|
2915
|
+
justify-content: space-between;
|
|
2916
|
+
padding: 4px 0;
|
|
2917
|
+
font-size: 12px;
|
|
2918
|
+
border-bottom: 1px solid var(--border);
|
|
2919
|
+
}
|
|
2920
|
+
.network-info-row:last-child { border-bottom: none; }
|
|
2921
|
+
.network-info-label {
|
|
2922
|
+
color: var(--text-dim);
|
|
2923
|
+
}
|
|
2924
|
+
.network-info-value {
|
|
2925
|
+
color: var(--text-bright);
|
|
2926
|
+
font-family: 'SF Mono', 'Menlo', 'Consolas', monospace;
|
|
2927
|
+
font-size: 11px;
|
|
2928
|
+
}
|
|
2929
|
+
|
|
2930
|
+
/* ============================================================
|
|
2931
|
+
Integrations mode
|
|
2932
|
+
============================================================ */
|
|
2933
|
+
#mode-integrations {
|
|
2934
|
+
flex-direction: column;
|
|
2935
|
+
overflow-y: auto;
|
|
2936
|
+
}
|
|
2937
|
+
.integrations-panel {
|
|
2938
|
+
padding: 12px 16px;
|
|
2939
|
+
display: flex;
|
|
2940
|
+
flex-direction: column;
|
|
2941
|
+
gap: 16px;
|
|
2942
|
+
}
|
|
2943
|
+
.integrations-section {
|
|
2944
|
+
display: flex;
|
|
2945
|
+
flex-direction: column;
|
|
2946
|
+
gap: 8px;
|
|
2947
|
+
}
|
|
2948
|
+
.integrations-search-row {
|
|
2949
|
+
margin-bottom: 4px;
|
|
2950
|
+
}
|
|
2951
|
+
.integrations-search {
|
|
2952
|
+
width: 100%;
|
|
2953
|
+
background: var(--bg-input);
|
|
2954
|
+
border: 1px solid var(--border);
|
|
2955
|
+
color: var(--text);
|
|
2956
|
+
font-size: 12px;
|
|
2957
|
+
font-family: inherit;
|
|
2958
|
+
padding: 6px 10px;
|
|
2959
|
+
border-radius: var(--radius-sm);
|
|
2960
|
+
outline: none;
|
|
2961
|
+
}
|
|
2962
|
+
.integrations-search:focus { border-color: var(--accent); }
|
|
2963
|
+
.integrations-list {
|
|
2964
|
+
display: flex;
|
|
2965
|
+
flex-direction: column;
|
|
2966
|
+
gap: 6px;
|
|
2967
|
+
}
|
|
2968
|
+
.integration-item {
|
|
2969
|
+
display: flex;
|
|
2970
|
+
align-items: center;
|
|
2971
|
+
gap: 10px;
|
|
2972
|
+
padding: 10px 12px;
|
|
2973
|
+
border: 1px solid var(--border);
|
|
2974
|
+
border-radius: var(--radius);
|
|
2975
|
+
background: var(--bg-alt);
|
|
2976
|
+
}
|
|
2977
|
+
.integration-icon {
|
|
2978
|
+
width: 32px;
|
|
2979
|
+
height: 32px;
|
|
2980
|
+
border-radius: var(--radius-sm);
|
|
2981
|
+
background: var(--bg-input);
|
|
2982
|
+
display: flex;
|
|
2983
|
+
align-items: center;
|
|
2984
|
+
justify-content: center;
|
|
2985
|
+
font-size: 16px;
|
|
2986
|
+
flex-shrink: 0;
|
|
2987
|
+
}
|
|
2988
|
+
.integration-info {
|
|
2989
|
+
flex: 1;
|
|
2990
|
+
min-width: 0;
|
|
2991
|
+
}
|
|
2992
|
+
.integration-name {
|
|
2993
|
+
font-size: 12px;
|
|
2994
|
+
font-weight: 500;
|
|
2995
|
+
color: var(--text-bright);
|
|
2996
|
+
}
|
|
2997
|
+
.integration-desc {
|
|
2998
|
+
font-size: 10px;
|
|
2999
|
+
color: var(--text-dim);
|
|
3000
|
+
margin-top: 2px;
|
|
3001
|
+
overflow: hidden;
|
|
3002
|
+
text-overflow: ellipsis;
|
|
3003
|
+
white-space: nowrap;
|
|
3004
|
+
}
|
|
3005
|
+
.integration-actions {
|
|
3006
|
+
flex-shrink: 0;
|
|
3007
|
+
display: flex;
|
|
3008
|
+
gap: 4px;
|
|
3009
|
+
}
|
|
3010
|
+
.integration-btn {
|
|
3011
|
+
background: var(--bg-input);
|
|
3012
|
+
border: 1px solid var(--border);
|
|
3013
|
+
color: var(--text);
|
|
3014
|
+
font-size: 10px;
|
|
3015
|
+
padding: 3px 8px;
|
|
3016
|
+
border-radius: var(--radius-sm);
|
|
3017
|
+
cursor: pointer;
|
|
3018
|
+
font-family: inherit;
|
|
3019
|
+
}
|
|
3020
|
+
.integration-btn:hover { border-color: var(--accent); color: var(--text-bright); }
|
|
3021
|
+
.integration-btn-primary {
|
|
3022
|
+
background: var(--accent);
|
|
3023
|
+
border-color: var(--accent);
|
|
3024
|
+
color: #fff;
|
|
3025
|
+
}
|
|
3026
|
+
.integration-btn-primary:hover { opacity: 0.9; }
|
|
3027
|
+
.integration-btn-danger {
|
|
3028
|
+
color: var(--error-color);
|
|
3029
|
+
}
|
|
3030
|
+
.integration-btn-danger:hover { border-color: var(--error-color); }
|
|
3031
|
+
.integrations-grid {
|
|
3032
|
+
display: grid;
|
|
3033
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
3034
|
+
gap: 8px;
|
|
3035
|
+
}
|
|
3036
|
+
.integration-card {
|
|
3037
|
+
padding: 12px;
|
|
3038
|
+
border: 1px solid var(--border);
|
|
3039
|
+
border-radius: var(--radius);
|
|
3040
|
+
background: var(--bg-alt);
|
|
3041
|
+
cursor: pointer;
|
|
3042
|
+
transition: border-color 0.15s;
|
|
3043
|
+
}
|
|
3044
|
+
.integration-card:hover { border-color: var(--accent); }
|
|
3045
|
+
.integration-card-header {
|
|
3046
|
+
display: flex;
|
|
3047
|
+
align-items: center;
|
|
3048
|
+
gap: 8px;
|
|
3049
|
+
margin-bottom: 6px;
|
|
3050
|
+
}
|
|
3051
|
+
.integration-card-icon {
|
|
3052
|
+
width: 24px;
|
|
3053
|
+
height: 24px;
|
|
3054
|
+
border-radius: 4px;
|
|
3055
|
+
background: var(--bg-input);
|
|
3056
|
+
display: flex;
|
|
3057
|
+
align-items: center;
|
|
3058
|
+
justify-content: center;
|
|
3059
|
+
font-size: 14px;
|
|
3060
|
+
flex-shrink: 0;
|
|
3061
|
+
}
|
|
3062
|
+
.integration-card-name {
|
|
3063
|
+
font-size: 12px;
|
|
3064
|
+
font-weight: 500;
|
|
3065
|
+
color: var(--text-bright);
|
|
3066
|
+
}
|
|
3067
|
+
.integration-card-desc {
|
|
3068
|
+
font-size: 10px;
|
|
3069
|
+
color: var(--text-dim);
|
|
3070
|
+
line-height: 1.4;
|
|
3071
|
+
}
|
|
3072
|
+
.integration-card-tag {
|
|
3073
|
+
display: inline-block;
|
|
3074
|
+
font-size: 9px;
|
|
3075
|
+
color: var(--text-dim);
|
|
3076
|
+
background: var(--bg-input);
|
|
3077
|
+
padding: 1px 5px;
|
|
3078
|
+
border-radius: 8px;
|
|
3079
|
+
margin-top: 6px;
|
|
3080
|
+
}
|
package/static/panel.html
CHANGED
|
@@ -72,6 +72,8 @@
|
|
|
72
72
|
<button class="mode-tab" data-mode="chat">Chat</button>
|
|
73
73
|
<button class="mode-tab" data-mode="gallery">Gallery</button>
|
|
74
74
|
<button class="mode-tab" data-mode="content">Content</button>
|
|
75
|
+
<button class="mode-tab" data-mode="network">Network</button>
|
|
76
|
+
<button class="mode-tab" data-mode="integrations">Integrations</button>
|
|
75
77
|
<span class="mode-tab-spacer"></span>
|
|
76
78
|
<span id="app-connection-badge"></span>
|
|
77
79
|
<button id="btn-app-disconnect" title="Disconnect">✕</button>
|
|
@@ -167,6 +169,10 @@
|
|
|
167
169
|
<select id="ai-model" class="ai-model-select" title="Select AI model">
|
|
168
170
|
<option value="Starter">Starter (free)</option>
|
|
169
171
|
<option value="claude">Claude</option>
|
|
172
|
+
<option value="openai">GPT-4o</option>
|
|
173
|
+
<option value="gemini">Gemini</option>
|
|
174
|
+
<option value="deepseek">DeepSeek</option>
|
|
175
|
+
<option value="groq">Groq</option>
|
|
170
176
|
<option value="chrome">Chrome AI (local)</option>
|
|
171
177
|
</select>
|
|
172
178
|
<button class="ai-settings-btn" title="AI settings" data-settings="ai">⚙</button>
|
|
@@ -205,6 +211,10 @@
|
|
|
205
211
|
<select id="chat-model" class="ai-model-select" title="Select AI model">
|
|
206
212
|
<option value="Starter">Starter (free)</option>
|
|
207
213
|
<option value="claude">Claude</option>
|
|
214
|
+
<option value="openai">GPT-4o</option>
|
|
215
|
+
<option value="gemini">Gemini</option>
|
|
216
|
+
<option value="deepseek">DeepSeek</option>
|
|
217
|
+
<option value="groq">Groq</option>
|
|
208
218
|
<option value="chrome">Chrome AI (local)</option>
|
|
209
219
|
</select>
|
|
210
220
|
<button class="ai-settings-btn" title="AI settings" data-settings="ai">⚙</button>
|
|
@@ -239,6 +249,79 @@
|
|
|
239
249
|
</div>
|
|
240
250
|
</div>
|
|
241
251
|
|
|
252
|
+
<!-- ============================================================
|
|
253
|
+
NETWORK MODE
|
|
254
|
+
============================================================ -->
|
|
255
|
+
<div id="mode-network" class="mode-panel">
|
|
256
|
+
<div class="network-panel">
|
|
257
|
+
<div class="network-section">
|
|
258
|
+
<div class="section-header">Backend Connection</div>
|
|
259
|
+
<div id="network-status" class="network-status">
|
|
260
|
+
<span class="network-status-dot"></span>
|
|
261
|
+
<span id="network-status-text">Not connected</span>
|
|
262
|
+
</div>
|
|
263
|
+
<div class="network-fields">
|
|
264
|
+
<div class="network-field">
|
|
265
|
+
<label>Server URL</label>
|
|
266
|
+
<div class="network-field-row">
|
|
267
|
+
<input id="network-url" type="text" placeholder="https://api.example.com" class="network-input" />
|
|
268
|
+
<button id="network-test" class="network-btn-sm">Test</button>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
<div class="network-field">
|
|
272
|
+
<label>API Key / Token</label>
|
|
273
|
+
<input id="network-token" type="password" placeholder="Bearer token or API key" class="network-input" />
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
<div class="network-actions">
|
|
277
|
+
<button id="network-save" class="network-btn">Save Connection</button>
|
|
278
|
+
<button id="network-disconnect" class="network-btn network-btn-secondary">Disconnect</button>
|
|
279
|
+
</div>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
<div class="network-section">
|
|
283
|
+
<div class="section-header">Server Info</div>
|
|
284
|
+
<div id="network-info" class="network-info">
|
|
285
|
+
<div class="network-info-row"><span class="network-info-label">Host</span><span id="network-info-host" class="network-info-value">—</span></div>
|
|
286
|
+
<div class="network-info-row"><span class="network-info-label">IP</span><span id="network-info-ip" class="network-info-value">—</span></div>
|
|
287
|
+
<div class="network-info-row"><span class="network-info-label">Status</span><span id="network-info-status" class="network-info-value">—</span></div>
|
|
288
|
+
<div class="network-info-row"><span class="network-info-label">Latency</span><span id="network-info-latency" class="network-info-value">—</span></div>
|
|
289
|
+
<div class="network-info-row"><span class="network-info-label">Platform</span><span id="network-info-platform" class="network-info-value">—</span></div>
|
|
290
|
+
<div class="network-info-row"><span class="network-info-label">Region</span><span id="network-info-region" class="network-info-value">—</span></div>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
|
|
294
|
+
<div class="network-section">
|
|
295
|
+
<div class="section-header">Deployment</div>
|
|
296
|
+
<div id="network-deployment" class="network-info">
|
|
297
|
+
<div class="empty-message">Connect to view deployment configuration</div>
|
|
298
|
+
</div>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
|
|
303
|
+
<!-- ============================================================
|
|
304
|
+
INTEGRATIONS MODE
|
|
305
|
+
============================================================ -->
|
|
306
|
+
<div id="mode-integrations" class="mode-panel">
|
|
307
|
+
<div class="integrations-panel">
|
|
308
|
+
<div class="integrations-section">
|
|
309
|
+
<div class="section-header">Active Integrations</div>
|
|
310
|
+
<div id="integrations-active" class="integrations-list">
|
|
311
|
+
<div class="empty-message">No integrations enabled</div>
|
|
312
|
+
</div>
|
|
313
|
+
</div>
|
|
314
|
+
|
|
315
|
+
<div class="integrations-section">
|
|
316
|
+
<div class="section-header">Marketplace</div>
|
|
317
|
+
<div class="integrations-search-row">
|
|
318
|
+
<input id="integrations-search" type="text" placeholder="Search integrations..." class="integrations-search" />
|
|
319
|
+
</div>
|
|
320
|
+
<div id="integrations-marketplace" class="integrations-grid"></div>
|
|
321
|
+
</div>
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
|
|
242
325
|
</div>
|
|
243
326
|
|
|
244
327
|
<!-- AI Settings Dialog -->
|
|
@@ -249,15 +332,45 @@
|
|
|
249
332
|
<button id="ai-dialog-close">×</button>
|
|
250
333
|
</div>
|
|
251
334
|
<div class="ai-dialog-body">
|
|
335
|
+
<div id="ai-dialog-auth-status" class="ai-dialog-auth-status"></div>
|
|
336
|
+
|
|
252
337
|
<div class="ai-dialog-section">
|
|
253
|
-
<div class="ai-dialog-label">Claude API</div>
|
|
254
|
-
<p class="ai-dialog-hint">Sign in to symbols.app to use Claude via the platform, or enter your own Anthropic API key.</p>
|
|
255
|
-
<div id="ai-dialog-auth-status" class="ai-dialog-auth-status"></div>
|
|
256
338
|
<div class="ai-dialog-field">
|
|
257
|
-
<label>Anthropic
|
|
339
|
+
<label>Anthropic (Claude)</label>
|
|
258
340
|
<input id="ai-key-anthropic" type="password" placeholder="sk-ant-..." class="ai-dialog-input" />
|
|
259
341
|
</div>
|
|
260
342
|
</div>
|
|
343
|
+
|
|
344
|
+
<div class="ai-dialog-section">
|
|
345
|
+
<div class="ai-dialog-field">
|
|
346
|
+
<label>OpenAI (GPT-4o)</label>
|
|
347
|
+
<input id="ai-key-openai" type="password" placeholder="sk-..." class="ai-dialog-input" />
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
<div class="ai-dialog-section">
|
|
352
|
+
<div class="ai-dialog-field">
|
|
353
|
+
<label>Google AI (Gemini)</label>
|
|
354
|
+
<input id="ai-key-gemini" type="password" placeholder="AIza..." class="ai-dialog-input" />
|
|
355
|
+
</div>
|
|
356
|
+
</div>
|
|
357
|
+
|
|
358
|
+
<div class="ai-dialog-section">
|
|
359
|
+
<div class="ai-dialog-field">
|
|
360
|
+
<label>DeepSeek</label>
|
|
361
|
+
<input id="ai-key-deepseek" type="password" placeholder="sk-..." class="ai-dialog-input" />
|
|
362
|
+
</div>
|
|
363
|
+
</div>
|
|
364
|
+
|
|
365
|
+
<div class="ai-dialog-section">
|
|
366
|
+
<div class="ai-dialog-field">
|
|
367
|
+
<label>Groq</label>
|
|
368
|
+
<input id="ai-key-groq" type="password" placeholder="gsk_..." class="ai-dialog-input" />
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
371
|
+
|
|
372
|
+
<p class="ai-dialog-hint">Sign in to symbols.app for free Claude access, or enter API keys above.</p>
|
|
373
|
+
|
|
261
374
|
<div class="ai-dialog-actions">
|
|
262
375
|
<button id="ai-dialog-save" class="ai-dialog-save">Save</button>
|
|
263
376
|
</div>
|