@opentabs-dev/mcp-server 0.0.66 → 0.0.68

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 (123) hide show
  1. package/dist/browser-tools/analyze-site.d.ts.map +1 -1
  2. package/dist/browser-tools/analyze-site.js +3 -1
  3. package/dist/browser-tools/analyze-site.js.map +1 -1
  4. package/dist/browser-tools/extension-get-logs.d.ts +2 -2
  5. package/dist/browser-tools/get-console-logs.d.ts +2 -2
  6. package/dist/extension-handlers.d.ts +2 -1
  7. package/dist/extension-handlers.d.ts.map +1 -1
  8. package/dist/extension-handlers.js +22 -1
  9. package/dist/extension-handlers.js.map +1 -1
  10. package/dist/extension-protocol.d.ts.map +1 -1
  11. package/dist/extension-protocol.js +6 -1
  12. package/dist/extension-protocol.js.map +1 -1
  13. package/dist/mcp-setup.d.ts +1 -13
  14. package/dist/mcp-setup.d.ts.map +1 -1
  15. package/dist/mcp-setup.js +4 -96
  16. package/dist/mcp-setup.js.map +1 -1
  17. package/dist/reload.js +5 -5
  18. package/dist/reload.js.map +1 -1
  19. package/package.json +3 -1
  20. package/dist/browser-tool-names.d.ts +0 -14
  21. package/dist/browser-tool-names.d.ts.map +0 -1
  22. package/dist/browser-tool-names.js +0 -55
  23. package/dist/browser-tool-names.js.map +0 -1
  24. package/dist/discovery-legacy.d.ts +0 -32
  25. package/dist/discovery-legacy.d.ts.map +0 -1
  26. package/dist/discovery-legacy.js +0 -415
  27. package/dist/discovery-legacy.js.map +0 -1
  28. package/dist/manifest-schema.d.ts +0 -14
  29. package/dist/manifest-schema.d.ts.map +0 -1
  30. package/dist/manifest-schema.js +0 -51
  31. package/dist/manifest-schema.js.map +0 -1
  32. package/dist/mcp-prompts.d.ts +0 -71
  33. package/dist/mcp-prompts.d.ts.map +0 -1
  34. package/dist/mcp-prompts.js +0 -248
  35. package/dist/mcp-prompts.js.map +0 -1
  36. package/dist/mcp-resources.d.ts +0 -53
  37. package/dist/mcp-resources.d.ts.map +0 -1
  38. package/dist/mcp-resources.js +0 -139
  39. package/dist/mcp-resources.js.map +0 -1
  40. package/dist/permissions.d.ts +0 -59
  41. package/dist/permissions.d.ts.map +0 -1
  42. package/dist/permissions.js +0 -144
  43. package/dist/permissions.js.map +0 -1
  44. package/dist/prompts/audit-ai-docs.d.ts +0 -6
  45. package/dist/prompts/audit-ai-docs.d.ts.map +0 -1
  46. package/dist/prompts/audit-ai-docs.js +0 -155
  47. package/dist/prompts/audit-ai-docs.js.map +0 -1
  48. package/dist/prompts/build-plugin.d.ts +0 -3
  49. package/dist/prompts/build-plugin.d.ts.map +0 -1
  50. package/dist/prompts/build-plugin.js +0 -455
  51. package/dist/prompts/build-plugin.js.map +0 -1
  52. package/dist/prompts/contribute-learnings.d.ts +0 -12
  53. package/dist/prompts/contribute-learnings.d.ts.map +0 -1
  54. package/dist/prompts/contribute-learnings.js +0 -107
  55. package/dist/prompts/contribute-learnings.js.map +0 -1
  56. package/dist/prompts/plugin-icon.d.ts +0 -5
  57. package/dist/prompts/plugin-icon.d.ts.map +0 -1
  58. package/dist/prompts/plugin-icon.js +0 -147
  59. package/dist/prompts/plugin-icon.js.map +0 -1
  60. package/dist/prompts/setup-plugin.d.ts +0 -3
  61. package/dist/prompts/setup-plugin.d.ts.map +0 -1
  62. package/dist/prompts/setup-plugin.js +0 -197
  63. package/dist/prompts/setup-plugin.js.map +0 -1
  64. package/dist/prompts/troubleshoot.d.ts +0 -3
  65. package/dist/prompts/troubleshoot.d.ts.map +0 -1
  66. package/dist/prompts/troubleshoot.js +0 -191
  67. package/dist/prompts/troubleshoot.js.map +0 -1
  68. package/dist/resources/browser-tools.d.ts +0 -3
  69. package/dist/resources/browser-tools.d.ts.map +0 -1
  70. package/dist/resources/browser-tools.js +0 -100
  71. package/dist/resources/browser-tools.js.map +0 -1
  72. package/dist/resources/cli.d.ts +0 -3
  73. package/dist/resources/cli.d.ts.map +0 -1
  74. package/dist/resources/cli.js +0 -217
  75. package/dist/resources/cli.js.map +0 -1
  76. package/dist/resources/plugin-development.d.ts +0 -3
  77. package/dist/resources/plugin-development.d.ts.map +0 -1
  78. package/dist/resources/plugin-development.js +0 -596
  79. package/dist/resources/plugin-development.js.map +0 -1
  80. package/dist/resources/quick-start.d.ts +0 -3
  81. package/dist/resources/quick-start.d.ts.map +0 -1
  82. package/dist/resources/quick-start.js +0 -210
  83. package/dist/resources/quick-start.js.map +0 -1
  84. package/dist/resources/sdk-api.d.ts +0 -3
  85. package/dist/resources/sdk-api.d.ts.map +0 -1
  86. package/dist/resources/sdk-api.js +0 -199
  87. package/dist/resources/sdk-api.js.map +0 -1
  88. package/dist/resources/self-improvement.d.ts +0 -10
  89. package/dist/resources/self-improvement.d.ts.map +0 -1
  90. package/dist/resources/self-improvement.js +0 -91
  91. package/dist/resources/self-improvement.js.map +0 -1
  92. package/dist/resources/status.d.ts +0 -5
  93. package/dist/resources/status.d.ts.map +0 -1
  94. package/dist/resources/status.js +0 -27
  95. package/dist/resources/status.js.map +0 -1
  96. package/dist/resources/troubleshooting.d.ts +0 -3
  97. package/dist/resources/troubleshooting.d.ts.map +0 -1
  98. package/dist/resources/troubleshooting.js +0 -167
  99. package/dist/resources/troubleshooting.js.map +0 -1
  100. package/dist/sanitize-tool-output.d.ts +0 -20
  101. package/dist/sanitize-tool-output.d.ts.map +0 -1
  102. package/dist/sanitize-tool-output.js +0 -52
  103. package/dist/sanitize-tool-output.js.map +0 -1
  104. package/dist/skip-confirmation.d.ts +0 -15
  105. package/dist/skip-confirmation.d.ts.map +0 -1
  106. package/dist/skip-confirmation.js +0 -16
  107. package/dist/skip-confirmation.js.map +0 -1
  108. package/dist/skip-permissions.d.ts +0 -11
  109. package/dist/skip-permissions.d.ts.map +0 -1
  110. package/dist/skip-permissions.js +0 -12
  111. package/dist/skip-permissions.js.map +0 -1
  112. package/dist/skip-sanitization.d.ts +0 -17
  113. package/dist/skip-sanitization.d.ts.map +0 -1
  114. package/dist/skip-sanitization.js +0 -18
  115. package/dist/skip-sanitization.js.map +0 -1
  116. package/dist/skip-verification.d.ts +0 -11
  117. package/dist/skip-verification.d.ts.map +0 -1
  118. package/dist/skip-verification.js +0 -12
  119. package/dist/skip-verification.js.map +0 -1
  120. package/dist/verify-plugin.d.ts +0 -53
  121. package/dist/verify-plugin.d.ts.map +0 -1
  122. package/dist/verify-plugin.js +0 -123
  123. package/dist/verify-plugin.js.map +0 -1
@@ -1,167 +0,0 @@
1
- /** Troubleshooting Guide resource content. */
2
- export const TROUBLESHOOTING_CONTENT = `# Troubleshooting Guide
3
-
4
- Common errors when using OpenTabs, their causes, and resolution steps.
5
-
6
- ## Quick Diagnosis
7
-
8
- Before diving into specific errors, run these diagnostic commands:
9
-
10
- \`\`\`bash
11
- opentabs status # Server, extension, and plugin state
12
- opentabs doctor # Comprehensive setup diagnostics
13
- \`\`\`
14
-
15
- From your AI client:
16
- - Call \`extension_get_state\` — extension health and WebSocket status
17
- - Call \`plugin_list_tabs\` — per-plugin tab readiness
18
- - Fetch \`opentabs://status\` — full server state snapshot
19
-
20
- ## Error Reference
21
-
22
- ### Extension Not Connected
23
-
24
- **Error:** \`Extension not connected. Please ensure the OpenTabs Chrome extension is running.\`
25
-
26
- **Cause:** The Chrome extension WebSocket connection to the MCP server is not active.
27
-
28
- **Resolution:**
29
- 1. Verify server is running: \`opentabs status\`
30
- 2. Check extension is loaded: open \`chrome://extensions\`, verify OpenTabs is enabled
31
- 3. Reload extension: click the refresh icon on the OpenTabs card in \`chrome://extensions\`
32
- 4. Close and reopen the side panel
33
- 5. If still failing, run \`opentabs doctor\` for full diagnostics
34
- 6. Check for stale auth secret: \`opentabs config rotate-secret --confirm\`, then reload extension
35
-
36
- ### Tab Closed
37
-
38
- **Error:** \`Tab closed: <message>\`
39
-
40
- **Cause:** No browser tab matches the plugin's URL patterns, or the matching tab was closed during dispatch.
41
-
42
- **Resolution:**
43
- 1. Open the target web application in Chrome
44
- 2. Verify the URL matches the plugin's \`urlPatterns\` (\`opentabs status\` shows patterns)
45
- 3. Call \`plugin_list_tabs\` to verify the tab is detected
46
- 4. Retry the tool call
47
-
48
- ### Tab Unavailable
49
-
50
- **Error:** \`Tab unavailable: <message>\`
51
-
52
- **Cause:** A tab matches the plugin's URL patterns but \`isReady()\` returns false. The user is likely not logged in.
53
-
54
- **Resolution:**
55
- 1. Log into the web application in the matching browser tab
56
- 2. Refresh the tab (Ctrl+R / Cmd+R)
57
- 3. Wait 5 seconds for the readiness probe to complete
58
- 4. Call \`plugin_list_tabs\` to check the \`ready\` field
59
- 5. Retry the tool call
60
-
61
- ### Plugin Not Reviewed
62
-
63
- **Error:** \`Plugin "<name>" (v<version>) has not been reviewed yet.\`
64
-
65
- **Cause:** New plugins start with permission \`'off'\` and require a security review before use.
66
-
67
- **Resolution (AI client flow):**
68
- 1. Call \`plugin_inspect({"plugin": "<name>"})\` — retrieves adapter source code + review token
69
- 2. Review the code for security concerns (data exfiltration, credential access, suspicious network requests)
70
- 3. Share findings with the user
71
- 4. If approved, call \`plugin_mark_reviewed({"plugin": "<name>", "version": "<ver>", "reviewToken": "<token>", "permission": "auto"})\`
72
-
73
- **Resolution (side panel):** Open the side panel, click the shield icon on the plugin card, and confirm.
74
-
75
- ### Plugin Updated — Re-Review Required
76
-
77
- **Error:** \`Plugin "<name>" has been updated from v<old> to v<new> and needs re-review.\`
78
-
79
- **Cause:** Plugin version changed since last review. Permission resets to \`'off'\` on version change.
80
-
81
- **Resolution:** Same as "Plugin Not Reviewed" above — call \`plugin_inspect\` and re-review.
82
-
83
- ### Tool Disabled
84
-
85
- **Error:** \`Tool "<name>" is currently disabled. Ask the user to enable it in the OpenTabs side panel.\`
86
-
87
- **Cause:** The tool's permission is set to \`'off'\`.
88
-
89
- **Resolution:**
90
- - User enables in side panel, OR
91
- - \`opentabs config set tool-permission.<plugin>.<tool> ask\`
92
- - \`opentabs config set plugin-permission.<plugin> ask\`
93
-
94
- ### Permission Denied by User
95
-
96
- **Error:** \`Tool "<name>" was denied by the user.\`
97
-
98
- **Cause:** Tool permission is \`'ask'\` and the user clicked "Deny" in the approval dialog.
99
-
100
- **Resolution:** Do NOT retry immediately. Ask the user if they want to approve the action. To skip future prompts: \`opentabs config set tool-permission.<plugin>.<tool> auto\`
101
-
102
- ### Too Many Concurrent Dispatches
103
-
104
- **Error:** \`Too many concurrent dispatches for plugin "<name>" (limit: 5). Wait for in-flight requests to complete.\`
105
-
106
- **Cause:** More than 5 simultaneous tool calls to the same plugin.
107
-
108
- **Resolution:** Wait 100-500ms for in-flight dispatches to complete, then retry.
109
-
110
- ### Dispatch Timeout
111
-
112
- **Error:** \`Dispatch <label> timed out after <ms>ms\`
113
-
114
- **Cause:** Tool handler did not respond within 30 seconds (or 5 minutes with progress reporting).
115
-
116
- **Resolution:**
117
- 1. Check if the tab is responsive (take a screenshot, check console logs)
118
- 2. Refresh the target tab if unresponsive
119
- 3. For legitimately long operations, the plugin should use \`context.reportProgress()\` to extend the timeout
120
- 4. Break long operations into multiple tool calls
121
-
122
- **Timeout rules:**
123
- - Default: 30s per dispatch
124
- - Progress resets the timer: each \`reportProgress()\` call extends by 30s
125
- - Absolute ceiling: 5 minutes regardless of progress
126
-
127
- ### Schema Validation Error
128
-
129
- **Error:** \`Invalid arguments for tool "<name>": - <field>: <issue>\`
130
-
131
- **Cause:** Tool arguments don't match the JSON Schema defined by the plugin.
132
-
133
- **Resolution:** Check the tool's input schema via \`tools/list\` and ensure all required fields are provided with correct types.
134
-
135
- ### Tool Not Found
136
-
137
- **Error:** \`Tool <name> not found\`
138
-
139
- **Cause:** The prefixed tool name doesn't exist in the registry. Plugin may not be installed.
140
-
141
- **Resolution:**
142
- 1. Run \`opentabs status\` to verify the plugin is installed
143
- 2. Check the tool name (format: \`<plugin>_<tool>\`, e.g., \`slack_send_message\`)
144
- 3. Reinstall: \`opentabs plugin install <name>\`
145
-
146
- ### Rate Limited
147
-
148
- **Error:** Tool response includes \`retryable: true\` and \`retryAfterMs\`.
149
-
150
- **Cause:** The target web application's API returned HTTP 429.
151
-
152
- **Resolution:** Wait the specified \`retryAfterMs\` before retrying. The \`ToolError.rateLimited\` metadata includes the exact delay.
153
-
154
- ## Diagnostic Tools Reference
155
-
156
- | Tool | What it checks |
157
- |------|---------------|
158
- | \`extension_get_state\` | WebSocket status, registered plugins, active captures |
159
- | \`extension_get_logs\` | Extension background script logs, injection warnings |
160
- | \`extension_check_adapter({"plugin": "<name>"})\` | Adapter injection status, hash match, isReady() result |
161
- | \`plugin_list_tabs\` | Per-plugin tab matching and readiness |
162
- | \`browser_get_console_logs\` | Browser console errors (requires network capture) |
163
- | \`opentabs status\` | Server uptime, extension connection, plugin states |
164
- | \`opentabs doctor\` | Full setup diagnostics with fix suggestions |
165
- | \`opentabs logs --plugin <name>\` | Server-side plugin-specific logs |
166
- `;
167
- //# sourceMappingURL=troubleshooting.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"troubleshooting.js","sourceRoot":"","sources":["../../src/resources/troubleshooting.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAE9C,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoKtC,CAAC"}
@@ -1,20 +0,0 @@
1
- /**
2
- * Sanitize successful tool output before returning to MCP clients.
3
- *
4
- * Applies the same path, URL, localhost, and IP replacement patterns
5
- * as sanitizeErrorMessage (from sanitize-error.ts) but operates
6
- * recursively on all string values within an object tree. Numbers,
7
- * booleans, nulls, and object keys are left untouched.
8
- *
9
- * This prevents internal system details (filesystem paths, local IP
10
- * addresses) from leaking to AI agents in tool output. Error messages
11
- * are sanitized separately by sanitizeErrorMessage and are not affected
12
- * by the skipSanitization flag.
13
- */
14
- /**
15
- * Recursively sanitize all string values within an object.
16
- * Leaves numbers, booleans, nulls, and object keys unchanged.
17
- */
18
- declare const sanitizeToolOutput: (obj: unknown, depth?: number) => unknown;
19
- export { sanitizeToolOutput };
20
- //# sourceMappingURL=sanitize-tool-output.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sanitize-tool-output.d.ts","sourceRoot":"","sources":["../src/sanitize-tool-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAsBH;;;GAGG;AACH,QAAA,MAAM,kBAAkB,GAAI,KAAK,OAAO,EAAE,cAAS,KAAG,OAerD,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1,52 +0,0 @@
1
- /**
2
- * Sanitize successful tool output before returning to MCP clients.
3
- *
4
- * Applies the same path, URL, localhost, and IP replacement patterns
5
- * as sanitizeErrorMessage (from sanitize-error.ts) but operates
6
- * recursively on all string values within an object tree. Numbers,
7
- * booleans, nulls, and object keys are left untouched.
8
- *
9
- * This prevents internal system details (filesystem paths, local IP
10
- * addresses) from leaking to AI agents in tool output. Error messages
11
- * are sanitized separately by sanitizeErrorMessage and are not affected
12
- * by the skipSanitization flag.
13
- */
14
- const MAX_DEPTH = 50;
15
- /**
16
- * Sanitize a single string value using the same patterns as sanitizeErrorMessage.
17
- * Does NOT truncate — tool output can be arbitrarily long (truncation is only
18
- * for error messages where brevity matters).
19
- */
20
- const sanitizeString = (value) => value
21
- // Windows absolute paths: C:\path\to\file or C:/path/to/file
22
- .replace(/[a-z]:[/\\][^\s,;)}\]]+/gi, '[PATH]')
23
- // Unix absolute paths: /path/to/file (at least 2 segments to avoid false positives like "/")
24
- .replace(/\/[a-z0-9._-]+(?:\/[a-z0-9._-]+)+/gi, '[PATH]')
25
- // Full URLs with protocol
26
- .replace(/https?:\/\/[^\s,;)}\]]+/gi, '[URL]')
27
- // localhost with port
28
- .replace(/localhost:\d+/gi, '[LOCALHOST]')
29
- // IPv4 addresses
30
- .replace(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/g, '[IP]');
31
- /**
32
- * Recursively sanitize all string values within an object.
33
- * Leaves numbers, booleans, nulls, and object keys unchanged.
34
- */
35
- const sanitizeToolOutput = (obj, depth = 0) => {
36
- if (depth > MAX_DEPTH)
37
- return obj;
38
- if (typeof obj === 'string')
39
- return sanitizeString(obj);
40
- if (obj === null || obj === undefined || typeof obj !== 'object')
41
- return obj;
42
- if (Array.isArray(obj)) {
43
- return obj.map(item => sanitizeToolOutput(item, depth + 1));
44
- }
45
- const result = {};
46
- for (const [key, value] of Object.entries(obj)) {
47
- result[key] = sanitizeToolOutput(value, depth + 1);
48
- }
49
- return result;
50
- };
51
- export { sanitizeToolOutput };
52
- //# sourceMappingURL=sanitize-tool-output.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sanitize-tool-output.js","sourceRoot":"","sources":["../src/sanitize-tool-output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,SAAS,GAAG,EAAE,CAAC;AAErB;;;;GAIG;AACH,MAAM,cAAc,GAAG,CAAC,KAAa,EAAU,EAAE,CAC/C,KAAK;IACH,6DAA6D;KAC5D,OAAO,CAAC,2BAA2B,EAAE,QAAQ,CAAC;IAC/C,6FAA6F;KAC5F,OAAO,CAAC,qCAAqC,EAAE,QAAQ,CAAC;IACzD,0BAA0B;KACzB,OAAO,CAAC,2BAA2B,EAAE,OAAO,CAAC;IAC9C,sBAAsB;KACrB,OAAO,CAAC,iBAAiB,EAAE,aAAa,CAAC;IAC1C,iBAAiB;KAChB,OAAO,CAAC,qCAAqC,EAAE,MAAM,CAAC,CAAC;AAE5D;;;GAGG;AACH,MAAM,kBAAkB,GAAG,CAAC,GAAY,EAAE,KAAK,GAAG,CAAC,EAAW,EAAE;IAC9D,IAAI,KAAK,GAAG,SAAS;QAAE,OAAO,GAAG,CAAC;IAElC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,GAAG,CAAC;IAE7E,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAA8B,CAAC,EAAE,CAAC;QAC1E,MAAM,CAAC,GAAG,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1,15 +0,0 @@
1
- /**
2
- * Confirmation bypass detection — determined once at startup.
3
- *
4
- * The --dangerously-skip-confirmation flag (or OPENTABS_SKIP_CONFIRMATION=1
5
- * env var) bypasses all browser tool confirmation prompts. This is a
6
- * dangerous option that disables human-in-the-loop safety for sensitive
7
- * browser operations. It exists for CI/testing environments where no human
8
- * is available to approve tool calls.
9
- *
10
- * The config.json `skipConfirmation` field is checked separately at reload
11
- * time and combined with this flag in state.skipConfirmation.
12
- */
13
- /** Whether the CLI flag or env var requests confirmation bypass */
14
- export declare const isCliSkipConfirmation: () => boolean;
15
- //# sourceMappingURL=skip-confirmation.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skip-confirmation.d.ts","sourceRoot":"","sources":["../src/skip-confirmation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,mEAAmE;AACnE,eAAO,MAAM,qBAAqB,QAAO,OAA8B,CAAC"}
@@ -1,16 +0,0 @@
1
- /**
2
- * Confirmation bypass detection — determined once at startup.
3
- *
4
- * The --dangerously-skip-confirmation flag (or OPENTABS_SKIP_CONFIRMATION=1
5
- * env var) bypasses all browser tool confirmation prompts. This is a
6
- * dangerous option that disables human-in-the-loop safety for sensitive
7
- * browser operations. It exists for CI/testing environments where no human
8
- * is available to approve tool calls.
9
- *
10
- * The config.json `skipConfirmation` field is checked separately at reload
11
- * time and combined with this flag in state.skipConfirmation.
12
- */
13
- const cliSkipConfirmation = process.argv.includes('--dangerously-skip-confirmation') || process.env['OPENTABS_SKIP_CONFIRMATION'] === '1';
14
- /** Whether the CLI flag or env var requests confirmation bypass */
15
- export const isCliSkipConfirmation = () => cliSkipConfirmation;
16
- //# sourceMappingURL=skip-confirmation.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skip-confirmation.js","sourceRoot":"","sources":["../src/skip-confirmation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,mBAAmB,GACvB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,iCAAiC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,KAAK,GAAG,CAAC;AAEhH,mEAAmE;AACnE,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAY,EAAE,CAAC,mBAAmB,CAAC"}
@@ -1,11 +0,0 @@
1
- /**
2
- * Permission bypass detection — determined once at startup.
3
- *
4
- * Set OPENTABS_DANGEROUSLY_SKIP_PERMISSIONS=1 to bypass approval prompts
5
- * for tools in 'ask' mode (converts them to 'auto'). Tools set to 'off'
6
- * remain disabled. Intended for CI/testing environments where no human is
7
- * available to approve tool calls.
8
- */
9
- /** Whether the env var requests permission bypass */
10
- export declare const isCliSkipPermissions: () => boolean;
11
- //# sourceMappingURL=skip-permissions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skip-permissions.d.ts","sourceRoot":"","sources":["../src/skip-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,qDAAqD;AACrD,eAAO,MAAM,oBAAoB,QAAO,OAA0B,CAAC"}
@@ -1,12 +0,0 @@
1
- /**
2
- * Permission bypass detection — determined once at startup.
3
- *
4
- * Set OPENTABS_DANGEROUSLY_SKIP_PERMISSIONS=1 to bypass approval prompts
5
- * for tools in 'ask' mode (converts them to 'auto'). Tools set to 'off'
6
- * remain disabled. Intended for CI/testing environments where no human is
7
- * available to approve tool calls.
8
- */
9
- const skipPermissions = process.env.OPENTABS_DANGEROUSLY_SKIP_PERMISSIONS === '1';
10
- /** Whether the env var requests permission bypass */
11
- export const isCliSkipPermissions = () => skipPermissions;
12
- //# sourceMappingURL=skip-permissions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skip-permissions.js","sourceRoot":"","sources":["../src/skip-permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,qCAAqC,KAAK,GAAG,CAAC;AAElF,qDAAqD;AACrD,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAY,EAAE,CAAC,eAAe,CAAC"}
@@ -1,17 +0,0 @@
1
- /**
2
- * Output sanitization bypass detection — determined once at startup.
3
- *
4
- * The --dangerously-skip-sanitization flag (or OPENTABS_SKIP_SANITIZATION=1
5
- * env var) disables path/IP sanitization of successful tool output. This is
6
- * useful when raw output is needed for debugging or when the AI agent needs
7
- * actual filesystem paths.
8
- *
9
- * Error message sanitization (via sanitizeErrorMessage) is never affected
10
- * by this flag — errors are always sanitized regardless.
11
- *
12
- * The config.json `skipSanitization` field is checked separately at reload
13
- * time and combined with this flag in state.skipSanitization.
14
- */
15
- /** Whether the CLI flag or env var requests output sanitization bypass */
16
- export declare const isCliSkipSanitization: () => boolean;
17
- //# sourceMappingURL=skip-sanitization.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skip-sanitization.d.ts","sourceRoot":"","sources":["../src/skip-sanitization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,0EAA0E;AAC1E,eAAO,MAAM,qBAAqB,QAAO,OAA8B,CAAC"}
@@ -1,18 +0,0 @@
1
- /**
2
- * Output sanitization bypass detection — determined once at startup.
3
- *
4
- * The --dangerously-skip-sanitization flag (or OPENTABS_SKIP_SANITIZATION=1
5
- * env var) disables path/IP sanitization of successful tool output. This is
6
- * useful when raw output is needed for debugging or when the AI agent needs
7
- * actual filesystem paths.
8
- *
9
- * Error message sanitization (via sanitizeErrorMessage) is never affected
10
- * by this flag — errors are always sanitized regardless.
11
- *
12
- * The config.json `skipSanitization` field is checked separately at reload
13
- * time and combined with this flag in state.skipSanitization.
14
- */
15
- const cliSkipSanitization = Bun.argv.includes('--dangerously-skip-sanitization') || Bun.env.OPENTABS_SKIP_SANITIZATION === '1';
16
- /** Whether the CLI flag or env var requests output sanitization bypass */
17
- export const isCliSkipSanitization = () => cliSkipSanitization;
18
- //# sourceMappingURL=skip-sanitization.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skip-sanitization.js","sourceRoot":"","sources":["../src/skip-sanitization.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,mBAAmB,GACvB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,iCAAiC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,0BAA0B,KAAK,GAAG,CAAC;AAErG,0EAA0E;AAC1E,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAY,EAAE,CAAC,mBAAmB,CAAC"}
@@ -1,11 +0,0 @@
1
- /**
2
- * Plugin verification bypass detection — determined once at startup.
3
- *
4
- * The --skip-plugin-verification flag (or OPENTABS_SKIP_PLUGIN_VERIFICATION=1
5
- * env var) disables npm registry signature verification for official plugins.
6
- * This is intended for air-gapped environments where the npm registry is
7
- * unreachable.
8
- */
9
- /** Whether the CLI flag or env var requests plugin verification bypass */
10
- export declare const isSkipPluginVerification: () => boolean;
11
- //# sourceMappingURL=skip-verification.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skip-verification.d.ts","sourceRoot":"","sources":["../src/skip-verification.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,0EAA0E;AAC1E,eAAO,MAAM,wBAAwB,QAAO,OAA8B,CAAC"}
@@ -1,12 +0,0 @@
1
- /**
2
- * Plugin verification bypass detection — determined once at startup.
3
- *
4
- * The --skip-plugin-verification flag (or OPENTABS_SKIP_PLUGIN_VERIFICATION=1
5
- * env var) disables npm registry signature verification for official plugins.
6
- * This is intended for air-gapped environments where the npm registry is
7
- * unreachable.
8
- */
9
- const cliSkipVerification = Bun.argv.includes('--skip-plugin-verification') || Bun.env.OPENTABS_SKIP_PLUGIN_VERIFICATION === '1';
10
- /** Whether the CLI flag or env var requests plugin verification bypass */
11
- export const isSkipPluginVerification = () => cliSkipVerification;
12
- //# sourceMappingURL=skip-verification.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skip-verification.js","sourceRoot":"","sources":["../src/skip-verification.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,mBAAmB,GACvB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,4BAA4B,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,iCAAiC,KAAK,GAAG,CAAC;AAEvG,0EAA0E;AAC1E,MAAM,CAAC,MAAM,wBAAwB,GAAG,GAAY,EAAE,CAAC,mBAAmB,CAAC"}
@@ -1,53 +0,0 @@
1
- /**
2
- * Official plugin verification module.
3
- *
4
- * Verifies that plugins in the @opentabs-dev/ scope match what is published
5
- * on the npm registry by comparing the installed package's integrity hash
6
- * against the registry's published integrity value.
7
- *
8
- * This is a best-effort check that catches the common case of npm package
9
- * hijacking. It does NOT provide full supply chain security (that would
10
- * require signing keys).
11
- */
12
- interface VerificationResult {
13
- /** Whether the plugin passed verification */
14
- verified: boolean;
15
- /** Human-readable reason when verification fails or is skipped */
16
- reason?: string;
17
- }
18
- /**
19
- * Read the installed package's integrity hash from its package.json.
20
- *
21
- * npm and bun both write _integrity (subresource integrity format, e.g.,
22
- * "sha512-...") into the installed package.json. Falls back to _shasum
23
- * (hex SHA-1) if _integrity is not present.
24
- */
25
- declare const readInstalledIntegrity: (packagePath: string) => Promise<{
26
- integrity?: string;
27
- shasum?: string;
28
- version?: string;
29
- }>;
30
- /**
31
- * Fetch the registry metadata for a specific package version.
32
- *
33
- * Uses the abbreviated registry endpoint to minimize data transfer.
34
- * Returns the dist object containing integrity and shasum fields.
35
- */
36
- declare const fetchRegistryDist: (npmPackageName: string, version: string) => Promise<{
37
- integrity?: string;
38
- shasum?: string;
39
- } | null>;
40
- /**
41
- * Verify that an official plugin's installed files match what is published
42
- * on the npm registry.
43
- *
44
- * Compares the _integrity or _shasum field from the installed package.json
45
- * against the npm registry's published dist metadata for the same version.
46
- *
47
- * @param packagePath - Absolute path to the installed plugin directory
48
- * @param npmPackageName - The npm package name (e.g., "@opentabs-dev/opentabs-plugin-slack")
49
- */
50
- declare const verifyOfficialPlugin: (packagePath: string, npmPackageName: string) => Promise<VerificationResult>;
51
- export { verifyOfficialPlugin, readInstalledIntegrity, fetchRegistryDist };
52
- export type { VerificationResult };
53
- //# sourceMappingURL=verify-plugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-plugin.d.ts","sourceRoot":"","sources":["../src/verify-plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,UAAU,kBAAkB;IAC1B,6CAA6C;IAC7C,QAAQ,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,QAAA,MAAM,sBAAsB,GAC1B,aAAa,MAAM,KAClB,OAAO,CAAC;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAanE,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,iBAAiB,GACrB,gBAAgB,MAAM,EACtB,SAAS,MAAM,KACd,OAAO,CAAC;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAiCxD,CAAC;AAEF;;;;;;;;;GASG;AACH,QAAA,MAAM,oBAAoB,GAAU,aAAa,MAAM,EAAE,gBAAgB,MAAM,KAAG,OAAO,CAAC,kBAAkB,CAgD3G,CAAC;AAEF,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,CAAC;AAC3E,YAAY,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1,123 +0,0 @@
1
- /**
2
- * Official plugin verification module.
3
- *
4
- * Verifies that plugins in the @opentabs-dev/ scope match what is published
5
- * on the npm registry by comparing the installed package's integrity hash
6
- * against the registry's published integrity value.
7
- *
8
- * This is a best-effort check that catches the common case of npm package
9
- * hijacking. It does NOT provide full supply chain security (that would
10
- * require signing keys).
11
- */
12
- import { log } from './logger.js';
13
- import { join } from 'node:path';
14
- /**
15
- * Read the installed package's integrity hash from its package.json.
16
- *
17
- * npm and bun both write _integrity (subresource integrity format, e.g.,
18
- * "sha512-...") into the installed package.json. Falls back to _shasum
19
- * (hex SHA-1) if _integrity is not present.
20
- */
21
- const readInstalledIntegrity = async (packagePath) => {
22
- try {
23
- const pkgJson = await Bun.file(join(packagePath, 'package.json')).json();
24
- if (pkgJson === null || typeof pkgJson !== 'object')
25
- return {};
26
- const pkg = pkgJson;
27
- return {
28
- integrity: typeof pkg._integrity === 'string' ? pkg._integrity : undefined,
29
- shasum: typeof pkg._shasum === 'string' ? pkg._shasum : undefined,
30
- version: typeof pkg.version === 'string' ? pkg.version : undefined,
31
- };
32
- }
33
- catch {
34
- return {};
35
- }
36
- };
37
- /**
38
- * Fetch the registry metadata for a specific package version.
39
- *
40
- * Uses the abbreviated registry endpoint to minimize data transfer.
41
- * Returns the dist object containing integrity and shasum fields.
42
- */
43
- const fetchRegistryDist = async (npmPackageName, version) => {
44
- const registryUrl = `https://registry.npmjs.org/${encodeURIComponent(npmPackageName).replace('%40', '@')}/${version}`;
45
- try {
46
- const controller = new AbortController();
47
- const timeoutId = setTimeout(() => controller.abort(), 10_000);
48
- const response = await fetch(registryUrl, {
49
- signal: controller.signal,
50
- headers: { Accept: 'application/json' },
51
- });
52
- clearTimeout(timeoutId);
53
- if (!response.ok) {
54
- return null;
55
- }
56
- const data = await response.json();
57
- if (data === null || typeof data !== 'object')
58
- return null;
59
- const record = data;
60
- const dist = record.dist;
61
- if (dist === null || typeof dist !== 'object')
62
- return null;
63
- const distRecord = dist;
64
- return {
65
- integrity: typeof distRecord.integrity === 'string' ? distRecord.integrity : undefined,
66
- shasum: typeof distRecord.shasum === 'string' ? distRecord.shasum : undefined,
67
- };
68
- }
69
- catch {
70
- return null;
71
- }
72
- };
73
- /**
74
- * Verify that an official plugin's installed files match what is published
75
- * on the npm registry.
76
- *
77
- * Compares the _integrity or _shasum field from the installed package.json
78
- * against the npm registry's published dist metadata for the same version.
79
- *
80
- * @param packagePath - Absolute path to the installed plugin directory
81
- * @param npmPackageName - The npm package name (e.g., "@opentabs-dev/opentabs-plugin-slack")
82
- */
83
- const verifyOfficialPlugin = async (packagePath, npmPackageName) => {
84
- const installed = await readInstalledIntegrity(packagePath);
85
- if (!installed.version) {
86
- return { verified: false, reason: 'Could not read version from installed package.json' };
87
- }
88
- if (!installed.integrity && !installed.shasum) {
89
- return {
90
- verified: false,
91
- reason: 'No _integrity or _shasum found in installed package.json — package may not have been installed via npm/bun',
92
- };
93
- }
94
- const registryDist = await fetchRegistryDist(npmPackageName, installed.version);
95
- if (registryDist === null) {
96
- log.warn(`Could not reach npm registry to verify ${npmPackageName}@${installed.version} — loading at original tier`);
97
- return { verified: true, reason: 'Registry unreachable — verification skipped' };
98
- }
99
- // Prefer integrity (SRI hash, usually sha512) over shasum (SHA-1)
100
- if (installed.integrity && registryDist.integrity) {
101
- if (installed.integrity === registryDist.integrity) {
102
- return { verified: true };
103
- }
104
- return {
105
- verified: false,
106
- reason: `Integrity mismatch: installed=${installed.integrity}, registry=${registryDist.integrity}`,
107
- };
108
- }
109
- // Fall back to shasum comparison
110
- if (installed.shasum && registryDist.shasum) {
111
- if (installed.shasum === registryDist.shasum) {
112
- return { verified: true };
113
- }
114
- return {
115
- verified: false,
116
- reason: `Shasum mismatch: installed=${installed.shasum}, registry=${registryDist.shasum}`,
117
- };
118
- }
119
- // One side has integrity, the other has shasum — can't compare directly
120
- return { verified: true, reason: 'Hash format mismatch between installed and registry — verification skipped' };
121
- };
122
- export { verifyOfficialPlugin, readInstalledIntegrity, fetchRegistryDist };
123
- //# sourceMappingURL=verify-plugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"verify-plugin.js","sourceRoot":"","sources":["../src/verify-plugin.ts"],"names":[],"mappings":"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"}