@yusufffararatt/dombridge-mcp 2.7.5

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.
Files changed (49) hide show
  1. package/README.md +559 -0
  2. package/bin/cli.js +88 -0
  3. package/package.json +54 -0
  4. package/src/bridge/http-server.js +290 -0
  5. package/src/bridge/middleware.js +56 -0
  6. package/src/bridge/routes.js +1003 -0
  7. package/src/bridge-daemon.js +172 -0
  8. package/src/cli/auto-config.js +120 -0
  9. package/src/constants.js +13 -0
  10. package/src/index.js +279 -0
  11. package/src/mcp-bridge.js +136 -0
  12. package/src/metrics/error-codes.js +44 -0
  13. package/src/metrics/index.js +3 -0
  14. package/src/metrics/metrics-db.js +269 -0
  15. package/src/metrics/metrics-recorder.js +240 -0
  16. package/src/metrics/metrics-report.js +146 -0
  17. package/src/profiles/profile-db.js +159 -0
  18. package/src/profiles/profile-enricher.js +333 -0
  19. package/src/profiles/profile-manager.js +563 -0
  20. package/src/profiles/profile-repo.js +183 -0
  21. package/src/state/bridge-client.js +272 -0
  22. package/src/state/bridge-persistence.js +205 -0
  23. package/src/state/cache.js +38 -0
  24. package/src/state/extension-state.js +321 -0
  25. package/src/tools/action_tools.js +218 -0
  26. package/src/tools/analyze-page.js +247 -0
  27. package/src/tools/debug-mcp-state.js +172 -0
  28. package/src/tools/discover-apis.js +186 -0
  29. package/src/tools/execute-js.js +284 -0
  30. package/src/tools/export-session.js +171 -0
  31. package/src/tools/extract-data.js +395 -0
  32. package/src/tools/get-element.js +281 -0
  33. package/src/tools/get-network-trace.js +471 -0
  34. package/src/tools/index.js +110 -0
  35. package/src/tools/manage-site-profile.js +153 -0
  36. package/src/tools/paginate.js +444 -0
  37. package/src/tools/quick-scan.js +418 -0
  38. package/src/tools/screenshot_tools.js +117 -0
  39. package/src/utils/circuit-breaker.js +112 -0
  40. package/src/utils/extract-density.js +21 -0
  41. package/src/utils/logger.js +31 -0
  42. package/src/utils/paginate-detector.js +24 -0
  43. package/src/utils/rate-limiter.js +244 -0
  44. package/src/utils/run-script.js +37 -0
  45. package/src/utils/selector-validator.js +95 -0
  46. package/src/utils/state-validator.js +354 -0
  47. package/src/utils/tab-resolver.js +70 -0
  48. package/src/utils/workflow-helper.js +292 -0
  49. package/src/utils/workflow-state.js +177 -0
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Workflow State
3
+ * Tracks per-tab history and per-domain profile usage.
4
+ */
5
+
6
+ import { loadProfile, getProfileFieldTimestamp } from '../profiles/profile-manager.js';
7
+
8
+ /**
9
+ * @typedef {object} TabState
10
+ * @property {string} url
11
+ * @property {string} domain
12
+ * @property {number|null} lastQuickScanAt
13
+ * @property {number|null} lastAnalyzeAt
14
+ * @property {number|null} lastDiscoverApisAt
15
+ * @property {number|null} lastProfileLoadAt
16
+ * @property {number|null} lastProfileCheckAt
17
+ * @property {number|null} lastSelectedElementAt
18
+ * @property {number|null} lastNavigationAt
19
+ */
20
+
21
+ /**
22
+ * @typedef {object} ProfileState
23
+ * @property {boolean} exists
24
+ * @property {number|null} lastLoadedAt
25
+ * @property {number|null} lastSavedAt
26
+ * @property {number|null} lastCheckedAt
27
+ * @property {number|null} freshUntil
28
+ * @property {Record<string, string|number>} fieldFreshness
29
+ */
30
+
31
+ const PROFILE_FRESHNESS_MS = 15 * 60 * 1000;
32
+
33
+ const STALENESS_THRESHOLDS = {
34
+ framework: 7 * 24 * 60 * 60 * 1000,
35
+ apiEndpoints: 24 * 60 * 60 * 1000,
36
+ dataSchema: 3 * 24 * 60 * 60 * 1000,
37
+ authInfo: 7 * 24 * 60 * 60 * 1000,
38
+ pageCharacteristics: 3 * 24 * 60 * 60 * 1000,
39
+ knownPaths: 3 * 24 * 60 * 60 * 1000,
40
+ default: 24 * 60 * 60 * 1000
41
+ };
42
+
43
+ const workflowState = {
44
+ tabs: {},
45
+ profiles: {}
46
+ };
47
+
48
+ function extractDomain(url) {
49
+ if (!url) return '';
50
+ try {
51
+ return new URL(url).hostname;
52
+ } catch {
53
+ return '';
54
+ }
55
+ }
56
+
57
+ function createEmptyTabState(url) {
58
+ return {
59
+ url,
60
+ domain: extractDomain(url),
61
+ lastQuickScanAt: null,
62
+ lastAnalyzeAt: null,
63
+ lastDiscoverApisAt: null,
64
+ lastProfileLoadAt: null,
65
+ lastProfileCheckAt: null,
66
+ lastSelectedElementAt: null,
67
+ lastNavigationAt: null
68
+ };
69
+ }
70
+
71
+ function getTabState(tabId, url) {
72
+ if (!workflowState.tabs[tabId]) {
73
+ workflowState.tabs[tabId] = createEmptyTabState(url || '');
74
+ }
75
+ return workflowState.tabs[tabId];
76
+ }
77
+
78
+ function invalidateTabState(tabId, newUrl) {
79
+ workflowState.tabs[tabId] = createEmptyTabState(newUrl);
80
+ workflowState.tabs[tabId].lastNavigationAt = Date.now();
81
+ }
82
+
83
+ function touchTabField(tabId, field, url) {
84
+ const state = getTabState(tabId, url);
85
+
86
+ if (url && url !== state.url) {
87
+ invalidateTabState(tabId, url);
88
+ workflowState.tabs[tabId][field] = Date.now();
89
+ return;
90
+ }
91
+
92
+ state[field] = Date.now();
93
+ }
94
+
95
+ function removeTabState(tabId) {
96
+ delete workflowState.tabs[tabId];
97
+ }
98
+
99
+ function createEmptyProfileState() {
100
+ return {
101
+ exists: false,
102
+ lastLoadedAt: null,
103
+ lastSavedAt: null,
104
+ lastCheckedAt: null,
105
+ freshUntil: null,
106
+ fieldFreshness: {}
107
+ };
108
+ }
109
+
110
+ function getProfileState(domain) {
111
+ if (!workflowState.profiles[domain]) {
112
+ workflowState.profiles[domain] = createEmptyProfileState();
113
+ }
114
+ return workflowState.profiles[domain];
115
+ }
116
+
117
+ function markProfileLoaded(domain, freshnessMs = PROFILE_FRESHNESS_MS) {
118
+ const state = getProfileState(domain);
119
+ const now = Date.now();
120
+ state.exists = true;
121
+ state.lastLoadedAt = now;
122
+ state.freshUntil = now + freshnessMs;
123
+ }
124
+
125
+ function markProfileSaved(domain) {
126
+ const state = getProfileState(domain);
127
+ state.exists = true;
128
+ state.lastSavedAt = Date.now();
129
+ }
130
+
131
+ function markProfileChecked(domain) {
132
+ const state = getProfileState(domain);
133
+ state.lastCheckedAt = Date.now();
134
+ }
135
+
136
+ function isProfileFresh(domain) {
137
+ const state = workflowState.profiles[domain];
138
+ if (!state?.freshUntil) return false;
139
+ return Date.now() < state.freshUntil;
140
+ }
141
+
142
+ function markFieldFresh(domain, field, timestamp = Date.now()) {
143
+ const state = getProfileState(domain);
144
+ state.fieldFreshness[field] = timestamp;
145
+ }
146
+
147
+ function isFieldFresh(domain, field, maxAgeMs) {
148
+ const threshold = maxAgeMs ?? STALENESS_THRESHOLDS[field] ?? STALENESS_THRESHOLDS.default;
149
+ const runtimeTimestamp = workflowState.profiles[domain]?.fieldFreshness?.[field] || null;
150
+ const persistedTimestamp = getProfileFieldTimestamp(loadProfile(domain), field);
151
+ const timestamp = runtimeTimestamp || persistedTimestamp;
152
+ if (!timestamp) return false;
153
+ return Date.now() - new Date(timestamp).getTime() < threshold;
154
+ }
155
+
156
+ function snapshot() {
157
+ return JSON.parse(JSON.stringify(workflowState));
158
+ }
159
+
160
+ export {
161
+ workflowState,
162
+ getTabState,
163
+ touchTabField,
164
+ invalidateTabState,
165
+ removeTabState,
166
+ getProfileState,
167
+ markProfileLoaded,
168
+ markProfileSaved,
169
+ markProfileChecked,
170
+ isProfileFresh,
171
+ markFieldFresh,
172
+ isFieldFresh,
173
+ extractDomain,
174
+ snapshot,
175
+ PROFILE_FRESHNESS_MS,
176
+ STALENESS_THRESHOLDS
177
+ };