@astrasyncai/verification-gateway 1.1.0 → 2.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.
Files changed (113) hide show
  1. package/dist/adapter-interface/interface.d.mts +71 -0
  2. package/dist/adapter-interface/interface.d.ts +71 -0
  3. package/dist/adapter-interface/interface.js +36 -0
  4. package/dist/adapter-interface/interface.js.map +1 -0
  5. package/dist/adapter-interface/interface.mjs +10 -0
  6. package/dist/adapter-interface/interface.mjs.map +1 -0
  7. package/dist/adapter-interface/purpose-mapping.d.mts +28 -0
  8. package/dist/adapter-interface/purpose-mapping.d.ts +28 -0
  9. package/dist/adapter-interface/purpose-mapping.js +117 -0
  10. package/dist/adapter-interface/purpose-mapping.js.map +1 -0
  11. package/dist/adapter-interface/purpose-mapping.mjs +89 -0
  12. package/dist/adapter-interface/purpose-mapping.mjs.map +1 -0
  13. package/dist/adapters/express.d.mts +2 -2
  14. package/dist/adapters/express.d.ts +2 -2
  15. package/dist/adapters/express.js +123 -11
  16. package/dist/adapters/express.js.map +1 -1
  17. package/dist/adapters/express.mjs +123 -11
  18. package/dist/adapters/express.mjs.map +1 -1
  19. package/dist/adapters/nextjs.d.mts +2 -2
  20. package/dist/adapters/nextjs.d.ts +2 -2
  21. package/dist/adapters/nextjs.js +192 -14
  22. package/dist/adapters/nextjs.js.map +1 -1
  23. package/dist/adapters/nextjs.mjs +192 -14
  24. package/dist/adapters/nextjs.mjs.map +1 -1
  25. package/dist/adapters/sdk.d.mts +2 -2
  26. package/dist/adapters/sdk.d.ts +2 -2
  27. package/dist/adapters/sdk.js +7 -2
  28. package/dist/adapters/sdk.js.map +1 -1
  29. package/dist/adapters/sdk.mjs +7 -2
  30. package/dist/adapters/sdk.mjs.map +1 -1
  31. package/dist/agent/index.d.mts +2 -0
  32. package/dist/agent/index.d.ts +2 -0
  33. package/dist/agent/index.js +354 -0
  34. package/dist/agent/index.js.map +1 -0
  35. package/dist/agent/index.mjs +323 -0
  36. package/dist/agent/index.mjs.map +1 -0
  37. package/dist/browser/background.d.mts +2 -0
  38. package/dist/browser/background.d.ts +2 -0
  39. package/dist/browser/background.js +4090 -0
  40. package/dist/browser/background.js.map +1 -0
  41. package/dist/browser/background.mjs +4088 -0
  42. package/dist/browser/background.mjs.map +1 -0
  43. package/dist/browser/browser-adapter.d.mts +110 -0
  44. package/dist/browser/browser-adapter.d.ts +110 -0
  45. package/dist/browser/browser-adapter.js +297 -0
  46. package/dist/browser/browser-adapter.js.map +1 -0
  47. package/dist/browser/browser-adapter.mjs +269 -0
  48. package/dist/browser/browser-adapter.mjs.map +1 -0
  49. package/dist/cli/index.d.mts +241 -0
  50. package/dist/cli/index.d.ts +241 -0
  51. package/dist/cli/index.js +3734 -0
  52. package/dist/cli/index.js.map +1 -0
  53. package/dist/cli/index.mjs +3688 -0
  54. package/dist/cli/index.mjs.map +1 -0
  55. package/dist/cursor/cursor-adapter.d.mts +91 -0
  56. package/dist/cursor/cursor-adapter.d.ts +91 -0
  57. package/dist/cursor/cursor-adapter.js +273 -0
  58. package/dist/cursor/cursor-adapter.js.map +1 -0
  59. package/dist/cursor/cursor-adapter.mjs +246 -0
  60. package/dist/cursor/cursor-adapter.mjs.map +1 -0
  61. package/dist/cursor/extension.d.mts +27 -0
  62. package/dist/cursor/extension.d.ts +27 -0
  63. package/dist/cursor/extension.js +4057 -0
  64. package/dist/cursor/extension.js.map +1 -0
  65. package/dist/cursor/extension.mjs +4029 -0
  66. package/dist/cursor/extension.mjs.map +1 -0
  67. package/dist/{express-BGZiLINd.d.ts → express-Bcl-uBUE.d.ts} +1 -1
  68. package/dist/{express-BoayLpqq.d.mts → express-CtwDIZyF.d.mts} +1 -1
  69. package/dist/gateway/gateway.d.mts +70 -0
  70. package/dist/gateway/gateway.d.ts +70 -0
  71. package/dist/gateway/gateway.js +3726 -0
  72. package/dist/gateway/gateway.js.map +1 -0
  73. package/dist/gateway/gateway.mjs +3699 -0
  74. package/dist/gateway/gateway.mjs.map +1 -0
  75. package/dist/git-trigger/git-hooks.d.mts +69 -0
  76. package/dist/git-trigger/git-hooks.d.ts +69 -0
  77. package/dist/git-trigger/git-hooks.js +243 -0
  78. package/dist/git-trigger/git-hooks.js.map +1 -0
  79. package/dist/git-trigger/git-hooks.mjs +213 -0
  80. package/dist/git-trigger/git-hooks.mjs.map +1 -0
  81. package/dist/index-B1ThcGZl.d.mts +89 -0
  82. package/dist/index-BY8yQ8N8.d.mts +206 -0
  83. package/dist/index-CtYSYwn3.d.ts +206 -0
  84. package/dist/index-DnoXfdFd.d.ts +89 -0
  85. package/dist/index.d.mts +8 -295
  86. package/dist/index.d.ts +8 -295
  87. package/dist/index.js +215 -27
  88. package/dist/index.js.map +1 -1
  89. package/dist/index.mjs +215 -27
  90. package/dist/index.mjs.map +1 -1
  91. package/dist/local-evaluator/evaluator.d.mts +55 -0
  92. package/dist/local-evaluator/evaluator.d.ts +55 -0
  93. package/dist/local-evaluator/evaluator.js +272 -0
  94. package/dist/local-evaluator/evaluator.js.map +1 -0
  95. package/dist/local-evaluator/evaluator.mjs +244 -0
  96. package/dist/local-evaluator/evaluator.mjs.map +1 -0
  97. package/dist/{nextjs-BNbHm5Ui.d.mts → nextjs-BQyMCSx_.d.mts} +1 -1
  98. package/dist/{nextjs-DTCS5Sw8.d.ts → nextjs-CEldnIJ9.d.ts} +1 -1
  99. package/dist/{sdk-VAFRmdt7.d.mts → sdk-BhvuJSrH.d.mts} +3 -1
  100. package/dist/{sdk-9TKZzhxE.d.ts → sdk-BlyVSC_S.d.ts} +3 -1
  101. package/dist/transport/index.d.mts +2 -0
  102. package/dist/transport/index.d.ts +2 -0
  103. package/dist/transport/index.js +211 -0
  104. package/dist/transport/index.js.map +1 -0
  105. package/dist/transport/index.mjs +176 -0
  106. package/dist/transport/index.mjs.map +1 -0
  107. package/dist/types-79qS7aON.d.ts +153 -0
  108. package/dist/{types-cA_xfFU7.d.mts → types-CxQwJKbd.d.mts} +17 -2
  109. package/dist/{types-cA_xfFU7.d.ts → types-CxQwJKbd.d.ts} +17 -2
  110. package/dist/types-jJnPXStc.d.mts +153 -0
  111. package/dist/ui/index.d.mts +1 -1
  112. package/dist/ui/index.d.ts +1 -1
  113. package/package.json +48 -2
@@ -0,0 +1,269 @@
1
+ // src/adapter-interface/interface.ts
2
+ var ADAPTER_INTERFACE_VERSION = 1;
3
+
4
+ // src/adapter-interface/purpose-mapping.ts
5
+ var TOOL_PURPOSE_MAP = {
6
+ // Shell
7
+ shell_exec: "shell.exec",
8
+ run_command: "shell.exec",
9
+ execute: "shell.exec",
10
+ terminal_exec: "shell.exec",
11
+ run_terminal_command: "shell.exec",
12
+ // File read
13
+ file_read: "file.read",
14
+ read_file: "file.read",
15
+ // File write
16
+ file_write: "file.write",
17
+ write_file: "file.write",
18
+ create_file: "file.write",
19
+ edit_file: "file.write",
20
+ // File delete
21
+ file_delete: "file.delete",
22
+ delete_file: "file.delete",
23
+ // Network
24
+ http_request: "network.request",
25
+ fetch: "network.request",
26
+ web_request: "network.request",
27
+ // Email
28
+ send_email: "email.send",
29
+ read_email: "email.read",
30
+ // Calendar
31
+ create_event: "calendar.create",
32
+ // Database
33
+ query_database: "database.query",
34
+ write_database: "database.write",
35
+ // Payment
36
+ payment_execute: "payment.execute"
37
+ };
38
+ function mapToolToPurpose(toolName) {
39
+ return TOOL_PURPOSE_MAP[toolName] || `tool.${toolName}`;
40
+ }
41
+ function extractTarget(toolName, args) {
42
+ const purpose = mapToolToPurpose(toolName);
43
+ if (purpose.startsWith("shell.")) {
44
+ return String(args.command || args.cmd || args.script || "");
45
+ }
46
+ if (purpose.startsWith("file.")) {
47
+ return String(args.path || args.file || args.filename || args.file_path || "");
48
+ }
49
+ if (purpose.startsWith("network.")) {
50
+ return String(args.url || args.endpoint || args.uri || "");
51
+ }
52
+ if (purpose.startsWith("email.")) {
53
+ return String(args.to || args.recipient || args.address || "");
54
+ }
55
+ if (purpose.startsWith("database.")) {
56
+ return String(args.query || args.table || "");
57
+ }
58
+ if (purpose.startsWith("payment.")) {
59
+ return String(args.description || args.merchant || args.amount || "");
60
+ }
61
+ if (args.command) return String(args.command);
62
+ if (args.path) return String(args.path);
63
+ if (args.url) return String(args.url);
64
+ for (const val of Object.values(args)) {
65
+ if (typeof val === "string" && val.length > 0) return val;
66
+ }
67
+ return toolName;
68
+ }
69
+ function extractNetworkDomains(target) {
70
+ try {
71
+ if (target.startsWith("http://") || target.startsWith("https://")) {
72
+ const url = new URL(target);
73
+ return [url.hostname];
74
+ }
75
+ } catch {
76
+ }
77
+ return void 0;
78
+ }
79
+
80
+ // src/browser/browser-adapter.ts
81
+ function mapBrowserActionToPurpose(details) {
82
+ const url = details.url;
83
+ if (details.method === "POST") {
84
+ if (/mail|email|smtp/i.test(url)) {
85
+ return { toolName: "send_email", args: { url, to: url } };
86
+ }
87
+ if (/pay|checkout|stripe|payment/i.test(url)) {
88
+ return { toolName: "payment_execute", args: { url, description: url } };
89
+ }
90
+ return { toolName: "http_request", args: { url } };
91
+ }
92
+ if (details.type === "main_frame") {
93
+ return { toolName: "http_request", args: { url } };
94
+ }
95
+ return { toolName: "http_request", args: { url } };
96
+ }
97
+ var OpenClawBrowserAdapter = class {
98
+ constructor(options) {
99
+ this.interfaceVersion = ADAPTER_INTERFACE_VERSION;
100
+ this.requestListener = null;
101
+ this.navigationListener = null;
102
+ this.messageListener = null;
103
+ this._isRunning = false;
104
+ this.options = {
105
+ urlPatterns: options?.urlPatterns ?? ["<all_urls>"],
106
+ requestTypes: options?.requestTypes ?? ["main_frame", "xmlhttprequest", "sub_frame"],
107
+ onApprovalRequired: options?.onApprovalRequired ?? (async () => false),
108
+ browserAPI: options?.browserAPI
109
+ };
110
+ }
111
+ get isRunning() {
112
+ return this._isRunning;
113
+ }
114
+ async initialize(config) {
115
+ this.gateway = config.gateway;
116
+ if (config.adapterOptions.browserAPI) {
117
+ this.browserAPI = config.adapterOptions.browserAPI;
118
+ } else if (this.options.browserAPI) {
119
+ this.browserAPI = this.options.browserAPI;
120
+ }
121
+ if (!this.browserAPI) {
122
+ throw new Error("OpenClawBrowserAdapter requires browser extension API \u2014 pass via adapterOptions.browserAPI");
123
+ }
124
+ this.requestListener = (details) => {
125
+ return this.handleWebRequest(details);
126
+ };
127
+ this.browserAPI.webRequest.onBeforeRequest.addListener(
128
+ this.requestListener,
129
+ {
130
+ urls: this.options.urlPatterns,
131
+ types: this.options.requestTypes
132
+ },
133
+ ["blocking"]
134
+ );
135
+ this.navigationListener = (details) => {
136
+ this.handleNavigation(details);
137
+ };
138
+ this.browserAPI.webNavigation.onBeforeNavigate.addListener(this.navigationListener);
139
+ this.messageListener = (message, _sender, sendResponse) => {
140
+ const msg = message;
141
+ if (msg?.type === "astrasync-evaluate") {
142
+ this.handleContentScriptAction(msg.action).then(sendResponse);
143
+ return true;
144
+ }
145
+ };
146
+ this.browserAPI.runtime.onMessage.addListener(this.messageListener);
147
+ this._isRunning = true;
148
+ }
149
+ async shutdown() {
150
+ if (this.requestListener) {
151
+ this.browserAPI.webRequest.onBeforeRequest.removeListener(this.requestListener);
152
+ this.requestListener = null;
153
+ }
154
+ if (this.navigationListener) {
155
+ this.browserAPI.webNavigation.onBeforeNavigate.removeListener(this.navigationListener);
156
+ this.navigationListener = null;
157
+ }
158
+ if (this.messageListener) {
159
+ this.browserAPI.runtime.onMessage.removeListener(this.messageListener);
160
+ this.messageListener = null;
161
+ }
162
+ this._isRunning = false;
163
+ }
164
+ async interceptAction(action) {
165
+ const raw = action.raw;
166
+ if (!raw) {
167
+ return { intercepted: false, skipReason: "No action data" };
168
+ }
169
+ const context = this.extractContext(action);
170
+ return { intercepted: true, context };
171
+ }
172
+ extractContext(action) {
173
+ const raw = action.raw;
174
+ const { toolName, args } = mapBrowserActionToPurpose(raw);
175
+ const purpose = mapToolToPurpose(toolName);
176
+ const target = extractTarget(toolName, args);
177
+ const networkAccess = extractNetworkDomains(target);
178
+ return {
179
+ purpose,
180
+ action: toolName,
181
+ target,
182
+ ...networkAccess && { networkAccess }
183
+ };
184
+ }
185
+ async enforceDecision(decision) {
186
+ if (decision.recommendation === "DENY" && this.browserAPI.notifications) {
187
+ this.browserAPI.notifications.create(`astrasync-${Date.now()}`, {
188
+ type: "basic",
189
+ title: "AstraSync Local Guard",
190
+ message: `Blocked: ${decision.reason}`
191
+ });
192
+ }
193
+ }
194
+ // =====================================================================
195
+ // Internal handlers
196
+ // =====================================================================
197
+ handleWebRequest(details) {
198
+ const action = {
199
+ raw: details,
200
+ platform: "browser",
201
+ timestamp: /* @__PURE__ */ new Date()
202
+ };
203
+ const context = this.extractContext(action);
204
+ const decision = this.evaluateSync(context);
205
+ if (decision.recommendation === "DENY") {
206
+ this.enforceDecision(decision);
207
+ return { cancel: true };
208
+ }
209
+ if (decision.recommendation === "MANUAL_REVIEW") {
210
+ this.enforceDecision({
211
+ ...decision,
212
+ recommendation: "DENY",
213
+ reason: `Requires approval (auto-blocked in browser): ${decision.reason}`
214
+ });
215
+ return { cancel: true };
216
+ }
217
+ return void 0;
218
+ }
219
+ handleNavigation(details) {
220
+ const action = {
221
+ raw: {
222
+ requestId: `nav-${details.tabId}-${details.frameId}`,
223
+ url: details.url,
224
+ method: "GET",
225
+ type: "main_frame",
226
+ tabId: details.tabId
227
+ },
228
+ platform: "browser",
229
+ timestamp: /* @__PURE__ */ new Date()
230
+ };
231
+ this.interceptAction(action).then(async (result) => {
232
+ if (result.intercepted && result.context) {
233
+ await this.gateway.evaluate(result.context);
234
+ }
235
+ });
236
+ }
237
+ async handleContentScriptAction(action) {
238
+ const interception = await this.interceptAction(action);
239
+ if (!interception.intercepted || !interception.context) {
240
+ return { recommendation: "ALLOW", reason: "Not intercepted" };
241
+ }
242
+ return this.gateway.evaluate(interception.context);
243
+ }
244
+ /**
245
+ * Synchronous evaluation using the gateway's local evaluator.
246
+ * Falls back to ALLOW if async-only (online mode).
247
+ */
248
+ evaluateSync(context) {
249
+ const gw = this.gateway;
250
+ if (gw.evaluator) {
251
+ let decision = gw.evaluator.evaluate(context);
252
+ if (gw.posture === "passive" && decision.recommendation !== "ALLOW") {
253
+ decision = {
254
+ ...decision,
255
+ recommendation: "ALLOW",
256
+ reason: `[PASSIVE] Would have been ${decision.recommendation}: ${decision.reason}`
257
+ };
258
+ }
259
+ return decision;
260
+ }
261
+ return { recommendation: "ALLOW", reason: "Async-only mode \u2014 allowed by default" };
262
+ }
263
+ };
264
+ var BrowserAdapter = OpenClawBrowserAdapter;
265
+ export {
266
+ BrowserAdapter,
267
+ OpenClawBrowserAdapter
268
+ };
269
+ //# sourceMappingURL=browser-adapter.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapter-interface/interface.ts","../../src/adapter-interface/purpose-mapping.ts","../../src/browser/browser-adapter.ts"],"sourcesContent":["/**\n * PlatformAdapter Interface\n *\n * The contract that Layer 4 platform adapters implement.\n * Agent-side interception: governs what agents are allowed to do before they do it.\n *\n * Each adapter is 200-500 lines of platform-specific code.\n * All verification logic lives in the gateway — adapters just translate\n * between the platform's world and AstraSync's world.\n */\n\nimport type { AstraSyncGateway } from '../gateway/gateway';\nimport type { PDLSSContext, VerificationDecision, AgentAction, InterceptResult } from '../gateway/types';\n\nexport interface AdapterConfig {\n /** The AstraSyncGateway instance (handles mode routing) */\n gateway: AstraSyncGateway;\n /** Platform-specific configuration */\n adapterOptions: Record<string, unknown>;\n}\n\nexport interface PlatformAdapter {\n /**\n * Interface version for compatibility checking.\n * Current version: 1.\n */\n readonly interfaceVersion: number;\n\n /**\n * Platform-specific initialization.\n * Load config, register hooks, establish connections.\n */\n initialize(config: AdapterConfig): Promise<void>;\n\n /**\n * Graceful shutdown.\n * Drain in-flight verifications, deregister hooks, close connections.\n */\n shutdown(): Promise<void>;\n\n /**\n * Intercept an agent action before execution.\n *\n * How this works depends on the platform:\n * - CLI adapter: proxy server captures outbound request\n * - Browser adapter: content script intercepts DOM interaction\n * - Express: middleware captures inbound request\n */\n interceptAction(action: AgentAction): Promise<InterceptResult>;\n\n /**\n * Extract PDLSS-compatible context from a platform-specific action.\n * Maps platform-native action format to the universal PDLSSContext.\n */\n extractContext(action: AgentAction): PDLSSContext;\n\n /**\n * Enforce the verification decision in a platform-specific way.\n *\n * How this works depends on the platform:\n * - CLI: block command / allow command / prompt for approval\n * - Browser: block navigation / show confirmation dialog\n * - Express: return 403 / pass through / inject headers\n */\n enforceDecision(decision: VerificationDecision): Promise<void>;\n}\n\n/**\n * Current adapter interface version.\n */\nexport const ADAPTER_INTERFACE_VERSION = 1;\n\n/**\n * Check if an adapter is compatible with the current interface version.\n */\nexport function isCompatibleAdapter(adapter: PlatformAdapter): boolean {\n return adapter.interfaceVersion === ADAPTER_INTERFACE_VERSION;\n}\n","/**\n * Shared purpose mapping utilities for Layer 4 platform adapters.\n *\n * Maps platform-native action names to PDLSS purpose categories.\n * Used by OpenClaw CLI, Cursor, browser, and future adapters.\n */\n\n// -----------------------------------------------------------------------\n// Tool → Purpose mapping\n// -----------------------------------------------------------------------\n\n/** Standard tool name → PDLSS purpose mapping used by all adapters */\nconst TOOL_PURPOSE_MAP: Record<string, string> = {\n // Shell\n shell_exec: 'shell.exec',\n run_command: 'shell.exec',\n execute: 'shell.exec',\n terminal_exec: 'shell.exec',\n run_terminal_command: 'shell.exec',\n\n // File read\n file_read: 'file.read',\n read_file: 'file.read',\n\n // File write\n file_write: 'file.write',\n write_file: 'file.write',\n create_file: 'file.write',\n edit_file: 'file.write',\n\n // File delete\n file_delete: 'file.delete',\n delete_file: 'file.delete',\n\n // Network\n http_request: 'network.request',\n fetch: 'network.request',\n web_request: 'network.request',\n\n // Email\n send_email: 'email.send',\n read_email: 'email.read',\n\n // Calendar\n create_event: 'calendar.create',\n\n // Database\n query_database: 'database.query',\n write_database: 'database.write',\n\n // Payment\n payment_execute: 'payment.execute',\n};\n\n/**\n * Map a tool/action name to a PDLSS purpose category.\n * Returns `tool.<name>` for unmapped tools (denied by default).\n */\nexport function mapToolToPurpose(toolName: string): string {\n return TOOL_PURPOSE_MAP[toolName] || `tool.${toolName}`;\n}\n\n/**\n * Register additional tool → purpose mappings (e.g. from a platform adapter).\n * Does not overwrite existing mappings.\n */\nexport function registerToolMappings(mappings: Record<string, string>): void {\n for (const [tool, purpose] of Object.entries(mappings)) {\n if (!(tool in TOOL_PURPOSE_MAP)) {\n TOOL_PURPOSE_MAP[tool] = purpose;\n }\n }\n}\n\n// -----------------------------------------------------------------------\n// Target extraction\n// -----------------------------------------------------------------------\n\n/**\n * Extract the meaningful target string from tool arguments.\n * Uses the purpose category to determine which argument field is relevant.\n */\nexport function extractTarget(toolName: string, args: Record<string, unknown>): string {\n const purpose = mapToolToPurpose(toolName);\n\n if (purpose.startsWith('shell.')) {\n return String(args.command || args.cmd || args.script || '');\n }\n\n if (purpose.startsWith('file.')) {\n return String(args.path || args.file || args.filename || args.file_path || '');\n }\n\n if (purpose.startsWith('network.')) {\n return String(args.url || args.endpoint || args.uri || '');\n }\n\n if (purpose.startsWith('email.')) {\n return String(args.to || args.recipient || args.address || '');\n }\n\n if (purpose.startsWith('database.')) {\n return String(args.query || args.table || '');\n }\n\n if (purpose.startsWith('payment.')) {\n return String(args.description || args.merchant || args.amount || '');\n }\n\n // Fallback: try common field names\n if (args.command) return String(args.command);\n if (args.path) return String(args.path);\n if (args.url) return String(args.url);\n\n // Default: use first non-empty string argument or tool name\n for (const val of Object.values(args)) {\n if (typeof val === 'string' && val.length > 0) return val;\n }\n return toolName;\n}\n\n// -----------------------------------------------------------------------\n// Network domain extraction\n// -----------------------------------------------------------------------\n\n/**\n * Extract network domains from a URL target.\n * Returns undefined if the target is not a URL.\n */\nexport function extractNetworkDomains(target: string): string[] | undefined {\n try {\n if (target.startsWith('http://') || target.startsWith('https://')) {\n const url = new URL(target);\n return [url.hostname];\n }\n } catch {\n // Not a URL\n }\n return undefined;\n}\n","/**\n * @astrasyncai/adapter-openclaw-browser\n *\n * Layer 4 adapter for browser-based AI agents (e.g. OpenClaw browser extension).\n * Intercepts page navigation, form submissions, and network requests\n * made by the agent in the browser DOM.\n *\n * The adapter does NOT depend on chrome types. The browser extension\n * passes the chrome/browser API via a minimal interface at initialize() time.\n *\n * ~300 lines — thin, disposable, platform-specific.\n */\n\nimport type { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface';\nimport type { PDLSSContext, VerificationDecision, AgentAction, InterceptResult } from '../gateway/types';\nimport type { AstraSyncGateway } from '../gateway/gateway';\nimport { ADAPTER_INTERFACE_VERSION } from '../adapter-interface/interface';\nimport { mapToolToPurpose, extractTarget, extractNetworkDomains } from '../adapter-interface/purpose-mapping';\n\n// -----------------------------------------------------------------------\n// Minimal browser extension type stubs (injected at runtime)\n// -----------------------------------------------------------------------\n\nexport interface WebRequestDetails {\n requestId: string;\n url: string;\n method: string;\n type: string; // 'main_frame' | 'sub_frame' | 'xmlhttprequest' | 'script' etc.\n tabId: number;\n initiator?: string;\n documentUrl?: string;\n}\n\nexport interface BlockingResponse {\n cancel?: boolean;\n redirectUrl?: string;\n}\n\nexport interface RequestFilter {\n urls: string[];\n types?: string[];\n}\n\nexport interface BrowserExtensionAPI {\n webRequest: {\n onBeforeRequest: {\n addListener(\n callback: (details: WebRequestDetails) => BlockingResponse | void,\n filter: RequestFilter,\n extraInfoSpec?: string[],\n ): void;\n removeListener(callback: (details: WebRequestDetails) => BlockingResponse | void): void;\n };\n };\n webNavigation: {\n onBeforeNavigate: {\n addListener(callback: (details: NavigationDetails) => void): void;\n removeListener(callback: (details: NavigationDetails) => void): void;\n };\n };\n runtime: {\n sendMessage(message: unknown): Promise<unknown>;\n onMessage: {\n addListener(\n callback: (message: unknown, sender: unknown, sendResponse: (response: unknown) => void) => boolean | void,\n ): void;\n removeListener(callback: (...args: unknown[]) => void): void;\n };\n };\n notifications?: {\n create(id: string, options: { type: string; title: string; message: string; iconUrl?: string }): void;\n };\n}\n\nexport interface NavigationDetails {\n tabId: number;\n url: string;\n frameId: number;\n}\n\n// -----------------------------------------------------------------------\n// Configuration\n// -----------------------------------------------------------------------\n\nexport interface OpenClawBrowserAdapterOptions {\n /** The browser extension API object (chrome or browser) */\n browserAPI: BrowserExtensionAPI;\n /** URL patterns to intercept (default: ['<all_urls>']) */\n urlPatterns?: string[];\n /** Request types to intercept (default: main_frame, xmlhttprequest, sub_frame) */\n requestTypes?: string[];\n /** Callback for MANUAL_REVIEW decisions */\n onApprovalRequired?: (context: PDLSSContext, decision: VerificationDecision) => Promise<boolean>;\n}\n\n// -----------------------------------------------------------------------\n// Purpose mapping for browser actions\n// -----------------------------------------------------------------------\n\nfunction mapBrowserActionToPurpose(details: WebRequestDetails): { toolName: string; args: Record<string, unknown> } {\n const url = details.url;\n\n // Form submissions\n if (details.method === 'POST') {\n // Check for email-related URLs\n if (/mail|email|smtp/i.test(url)) {\n return { toolName: 'send_email', args: { url, to: url } };\n }\n // Check for payment-related URLs\n if (/pay|checkout|stripe|payment/i.test(url)) {\n return { toolName: 'payment_execute', args: { url, description: url } };\n }\n // Generic form submission\n return { toolName: 'http_request', args: { url } };\n }\n\n // Navigation\n if (details.type === 'main_frame') {\n return { toolName: 'http_request', args: { url } };\n }\n\n // XHR / fetch requests\n return { toolName: 'http_request', args: { url } };\n}\n\n// -----------------------------------------------------------------------\n// Adapter implementation\n// -----------------------------------------------------------------------\n\nexport class OpenClawBrowserAdapter implements PlatformAdapter {\n readonly interfaceVersion = ADAPTER_INTERFACE_VERSION;\n\n private gateway!: AstraSyncGateway;\n private browserAPI!: BrowserExtensionAPI;\n private options: Required<Omit<OpenClawBrowserAdapterOptions, 'browserAPI'>> & { browserAPI?: BrowserExtensionAPI };\n private requestListener: ((details: WebRequestDetails) => BlockingResponse | void) | null = null;\n private navigationListener: ((details: NavigationDetails) => void) | null = null;\n private messageListener: ((message: unknown, sender: unknown, sendResponse: (response: unknown) => void) => boolean | void) | null = null;\n private _isRunning = false;\n\n constructor(options?: Partial<OpenClawBrowserAdapterOptions>) {\n this.options = {\n urlPatterns: options?.urlPatterns ?? ['<all_urls>'],\n requestTypes: options?.requestTypes ?? ['main_frame', 'xmlhttprequest', 'sub_frame'],\n onApprovalRequired: options?.onApprovalRequired ?? (async () => false),\n browserAPI: options?.browserAPI,\n };\n }\n\n get isRunning(): boolean {\n return this._isRunning;\n }\n\n async initialize(config: AdapterConfig): Promise<void> {\n this.gateway = config.gateway as AstraSyncGateway;\n\n if (config.adapterOptions.browserAPI) {\n this.browserAPI = config.adapterOptions.browserAPI as BrowserExtensionAPI;\n } else if (this.options.browserAPI) {\n this.browserAPI = this.options.browserAPI;\n }\n\n if (!this.browserAPI) {\n throw new Error('OpenClawBrowserAdapter requires browser extension API — pass via adapterOptions.browserAPI');\n }\n\n // Register web request interceptor\n this.requestListener = (details: WebRequestDetails): BlockingResponse | void => {\n return this.handleWebRequest(details);\n };\n\n this.browserAPI.webRequest.onBeforeRequest.addListener(\n this.requestListener,\n {\n urls: this.options.urlPatterns,\n types: this.options.requestTypes,\n },\n ['blocking'],\n );\n\n // Register navigation interceptor\n this.navigationListener = (details: NavigationDetails): void => {\n this.handleNavigation(details);\n };\n\n this.browserAPI.webNavigation.onBeforeNavigate.addListener(this.navigationListener);\n\n // Listen for messages from content scripts\n this.messageListener = (message: unknown, _sender: unknown, sendResponse: (response: unknown) => void): boolean | void => {\n const msg = message as { type?: string; action?: AgentAction };\n if (msg?.type === 'astrasync-evaluate') {\n this.handleContentScriptAction(msg.action!).then(sendResponse);\n return true; // async response\n }\n };\n\n this.browserAPI.runtime.onMessage.addListener(this.messageListener as (message: unknown, sender: unknown, sendResponse: (response: unknown) => void) => void);\n\n this._isRunning = true;\n }\n\n async shutdown(): Promise<void> {\n if (this.requestListener) {\n this.browserAPI.webRequest.onBeforeRequest.removeListener(this.requestListener);\n this.requestListener = null;\n }\n if (this.navigationListener) {\n this.browserAPI.webNavigation.onBeforeNavigate.removeListener(this.navigationListener);\n this.navigationListener = null;\n }\n if (this.messageListener) {\n this.browserAPI.runtime.onMessage.removeListener(this.messageListener as (...args: unknown[]) => void);\n this.messageListener = null;\n }\n this._isRunning = false;\n }\n\n async interceptAction(action: AgentAction): Promise<InterceptResult> {\n const raw = action.raw as WebRequestDetails | { type: string };\n\n if (!raw) {\n return { intercepted: false, skipReason: 'No action data' };\n }\n\n const context = this.extractContext(action);\n return { intercepted: true, context };\n }\n\n extractContext(action: AgentAction): PDLSSContext {\n const raw = action.raw as WebRequestDetails;\n\n const { toolName, args } = mapBrowserActionToPurpose(raw);\n const purpose = mapToolToPurpose(toolName);\n const target = extractTarget(toolName, args);\n const networkAccess = extractNetworkDomains(target);\n\n return {\n purpose,\n action: toolName,\n target,\n ...(networkAccess && { networkAccess }),\n };\n }\n\n async enforceDecision(decision: VerificationDecision): Promise<void> {\n if (decision.recommendation === 'DENY' && this.browserAPI.notifications) {\n this.browserAPI.notifications.create(`astrasync-${Date.now()}`, {\n type: 'basic',\n title: 'AstraSync Local Guard',\n message: `Blocked: ${decision.reason}`,\n });\n }\n }\n\n // =====================================================================\n // Internal handlers\n // =====================================================================\n\n private handleWebRequest(details: WebRequestDetails): BlockingResponse | void {\n const action: AgentAction = {\n raw: details,\n platform: 'browser',\n timestamp: new Date(),\n };\n\n const context = this.extractContext(action);\n\n // Synchronous evaluation — browser webRequest requires sync return.\n // We use a cached/pre-computed decision if available, otherwise allow.\n // The gateway's evaluate() is async, so for blocking we need the\n // synchronous local evaluator path.\n const decision = this.evaluateSync(context);\n\n if (decision.recommendation === 'DENY') {\n this.enforceDecision(decision);\n return { cancel: true };\n }\n\n if (decision.recommendation === 'MANUAL_REVIEW') {\n // Can't show async prompt in synchronous handler — block by default\n this.enforceDecision({\n ...decision,\n recommendation: 'DENY',\n reason: `Requires approval (auto-blocked in browser): ${decision.reason}`,\n });\n return { cancel: true };\n }\n\n // ALLOW — don't cancel\n return undefined;\n }\n\n private handleNavigation(details: NavigationDetails): void {\n // Navigation events are informational — evaluate async\n const action: AgentAction = {\n raw: {\n requestId: `nav-${details.tabId}-${details.frameId}`,\n url: details.url,\n method: 'GET',\n type: 'main_frame',\n tabId: details.tabId,\n } as WebRequestDetails,\n platform: 'browser',\n timestamp: new Date(),\n };\n\n // Fire-and-forget async evaluation for logging/traces\n this.interceptAction(action).then(async (result) => {\n if (result.intercepted && result.context) {\n await this.gateway.evaluate(result.context);\n }\n });\n }\n\n private async handleContentScriptAction(action: AgentAction): Promise<VerificationDecision> {\n const interception = await this.interceptAction(action);\n if (!interception.intercepted || !interception.context) {\n return { recommendation: 'ALLOW', reason: 'Not intercepted' };\n }\n\n return this.gateway.evaluate(interception.context);\n }\n\n /**\n * Synchronous evaluation using the gateway's local evaluator.\n * Falls back to ALLOW if async-only (online mode).\n */\n private evaluateSync(context: PDLSSContext): VerificationDecision {\n // The gateway.evaluate() is async, but the local evaluator is synchronous.\n // We access the evaluator directly for browser webRequest handlers.\n // This only works in local/hybrid mode — online mode falls through to ALLOW.\n const gw = this.gateway as unknown as {\n evaluator?: { evaluate(ctx: PDLSSContext): VerificationDecision };\n posture?: 'active' | 'passive';\n };\n if (gw.evaluator) {\n let decision = gw.evaluator.evaluate(context);\n\n // Respect passive posture — same logic as gateway.evaluate()\n if (gw.posture === 'passive' && decision.recommendation !== 'ALLOW') {\n decision = {\n ...decision,\n recommendation: 'ALLOW',\n reason: `[PASSIVE] Would have been ${decision.recommendation}: ${decision.reason}`,\n };\n }\n\n return decision;\n }\n\n return { recommendation: 'ALLOW', reason: 'Async-only mode — allowed by default' };\n }\n}\n\n/** @deprecated Use OpenClawBrowserAdapter */\nexport const BrowserAdapter = OpenClawBrowserAdapter;\n/** @deprecated Use OpenClawBrowserAdapterOptions */\nexport type BrowserAdapterOptions = OpenClawBrowserAdapterOptions;\n"],"mappings":"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","names":[]}
@@ -0,0 +1,241 @@
1
+ import { a as LocalPurposeRule, c as LocalScope, d as LocalRiskThresholds, L as LocalPolicy, P as PDLSSContext, V as VerificationDecision, A as AgentAction, I as InterceptResult } from '../types-jJnPXStc.mjs';
2
+ import { PlatformAdapter, AdapterConfig } from '../adapter-interface/interface.mjs';
3
+ import '../types-CxQwJKbd.mjs';
4
+ import '../gateway/gateway.mjs';
5
+
6
+ /**
7
+ * Interactive Setup Wizard
8
+ *
9
+ * Generates a PDLSS-compliant local policy YAML file through
10
+ * plain-language questions with explainers for non-technical users.
11
+ *
12
+ * Usage:
13
+ * const wizard = new SetupWizard(readline);
14
+ * const policy = await wizard.run();
15
+ * // policy is a LocalPolicy ready to serialize to YAML
16
+ */
17
+
18
+ interface PromptInterface {
19
+ question(prompt: string): Promise<string>;
20
+ close(): void;
21
+ }
22
+ interface PurposeCategory {
23
+ id: string;
24
+ label: string;
25
+ explainer: string;
26
+ readId?: string;
27
+ writeId?: string;
28
+ deleteId?: string;
29
+ createId?: string;
30
+ modifyId?: string;
31
+ subActions?: {
32
+ id: string;
33
+ label: string;
34
+ explainer: string;
35
+ recommended: string;
36
+ }[];
37
+ recommendedDefault: string;
38
+ }
39
+ declare const PURPOSE_CATEGORIES: PurposeCategory[];
40
+ interface BlockedCommand {
41
+ pattern: string;
42
+ label: string;
43
+ recommended: boolean;
44
+ }
45
+ declare const DEFAULT_BLOCKED_COMMANDS: BlockedCommand[];
46
+ interface BlockedPath {
47
+ pattern: string;
48
+ label: string;
49
+ recommended: boolean;
50
+ }
51
+ declare const DEFAULT_BLOCKED_PATHS: BlockedPath[];
52
+ interface RiskPreset {
53
+ name: string;
54
+ label: string;
55
+ thresholds: LocalRiskThresholds;
56
+ }
57
+ declare const RISK_PRESETS: RiskPreset[];
58
+ declare class SetupWizard {
59
+ private prompt;
60
+ constructor(prompt: PromptInterface);
61
+ /**
62
+ * Run the full interactive wizard and return a validated LocalPolicy.
63
+ */
64
+ run(): Promise<LocalPolicy>;
65
+ /**
66
+ * Run the wizard and write the result to a YAML file.
67
+ */
68
+ runAndSave(outputPath: string): Promise<LocalPolicy>;
69
+ private askPurposeQuestion;
70
+ private askBlockedCommands;
71
+ private askBlockedPaths;
72
+ private askRiskPreset;
73
+ private askCommaSeparated;
74
+ private parseYesNoApproval;
75
+ private parseYesNo;
76
+ private ask;
77
+ private print;
78
+ }
79
+ interface ImportResult {
80
+ purposes: LocalPurposeRule[];
81
+ scope?: LocalScope;
82
+ source: string;
83
+ rulesImported: number;
84
+ }
85
+ /**
86
+ * Parse a .cursorrules file and extract PDLSS-compatible rules.
87
+ * Returns partial policy rules that can be merged with wizard output.
88
+ */
89
+ declare function importFromCursorRules(content: string): ImportResult;
90
+ /**
91
+ * Parse a .gitignore file to infer sensitive file patterns.
92
+ * These become blockedPatterns for file.read purposes.
93
+ */
94
+ declare function inferFromGitignore(content: string): string[];
95
+
96
+ /**
97
+ * AstraSync Guard Upgrade CLI
98
+ *
99
+ * Handles the free -> Developer tier upgrade flow:
100
+ * 1. Validate existing setup and check for prior upgrade
101
+ * 2. Open browser for KYD registration
102
+ * 3. Validate API key before proceeding
103
+ * 4. Upload local policy to cloud (YAML -> cloud PDLSS, 1:1 mapping)
104
+ * 5. Register agent and receive ASTRA-ID
105
+ * 6. Choose mode (online or hybrid) and switch gateway
106
+ *
107
+ * Also supports event-triggered upgrade prompts when counterparties
108
+ * reject unverified agents.
109
+ */
110
+
111
+ interface UpgradeConfig {
112
+ /** Path to local policy YAML file */
113
+ policyPath: string;
114
+ /** Loaded policy object */
115
+ policy: LocalPolicy;
116
+ /** AstraSync platform base URL */
117
+ platformUrl?: string;
118
+ /** Config directory for storing credentials (default: .astrasync/) */
119
+ configDir?: string;
120
+ }
121
+ interface UpgradeResult {
122
+ success: boolean;
123
+ kydId?: string;
124
+ agentId?: string;
125
+ apiKey?: string;
126
+ mode?: 'online' | 'hybrid';
127
+ error?: string;
128
+ }
129
+ interface UpgradeCallbacks {
130
+ /** Open a URL in the user's browser */
131
+ openBrowser: (url: string) => Promise<void>;
132
+ /** Prompt user for text input */
133
+ prompt: (message: string) => Promise<string>;
134
+ /** Display message to user */
135
+ print: (message: string) => void;
136
+ /** Write config file */
137
+ writeConfig: (path: string, content: string) => Promise<void>;
138
+ /** Read config file */
139
+ readConfig: (path: string) => Promise<string | null>;
140
+ }
141
+ /**
142
+ * Trigger context — why the upgrade was initiated.
143
+ * Used for event-triggered upgrade prompts.
144
+ */
145
+ interface UpgradeTrigger {
146
+ /** What triggered the upgrade prompt */
147
+ reason: 'cli' | 'counterparty-rejection' | 'deployment' | 'git-push';
148
+ /** Details from the triggering event */
149
+ details?: {
150
+ /** Counterparty that rejected the agent */
151
+ counterpartyUrl?: string;
152
+ /** Rejection message from counterparty */
153
+ rejectionMessage?: string;
154
+ /** Guidance URL from counterparty */
155
+ guidanceUrl?: string;
156
+ };
157
+ }
158
+ declare class UpgradeFlow {
159
+ private config;
160
+ private callbacks;
161
+ private platformUrl;
162
+ private configDir;
163
+ private trigger;
164
+ constructor(config: UpgradeConfig, callbacks: UpgradeCallbacks, trigger?: UpgradeTrigger);
165
+ /**
166
+ * Run the full upgrade flow.
167
+ */
168
+ run(): Promise<UpgradeResult>;
169
+ /**
170
+ * Continue the upgrade flow after API key validation.
171
+ */
172
+ private continueUpgrade;
173
+ /**
174
+ * Print the intro message based on what triggered the upgrade.
175
+ */
176
+ private printIntro;
177
+ /**
178
+ * Validate the API key by calling the platform.
179
+ */
180
+ private validateApiKey;
181
+ /**
182
+ * Upload local policy to the AstraSync cloud.
183
+ * YAML -> cloud PDLSS boundary, 1:1 mapping, no lossy transformation.
184
+ */
185
+ private uploadPolicy;
186
+ /**
187
+ * Write the config file for the chosen mode.
188
+ */
189
+ private writeLocalConfig;
190
+ }
191
+ /**
192
+ * Check if the project has already been upgraded.
193
+ */
194
+ declare function isUpgraded(configDir: string, readFile: (path: string) => Promise<string | null>): Promise<boolean>;
195
+
196
+ /**
197
+ * @astrasyncai/adapter-openclaw-cli
198
+ *
199
+ * Reference Layer 4 adapter for the OpenClaw CLI.
200
+ * Implements PlatformAdapter interface — proxy server that intercepts
201
+ * tool use requests before they reach the agent runtime.
202
+ *
203
+ * Configurable ports (defaults to OpenClaw conventions):
204
+ * proxyPort: 18790 (this adapter listens)
205
+ * targetPort: 18789 (OpenClaw CLI gateway)
206
+ */
207
+
208
+ interface OpenClawAdapterOptions {
209
+ /** Port this adapter listens on (default: 18790) */
210
+ proxyPort?: number;
211
+ /** Port the OpenClaw CLI gateway runs on (default: 18789) */
212
+ targetPort?: number;
213
+ /** Target host (default: 127.0.0.1) */
214
+ targetHost?: string;
215
+ /** Show approval prompts in terminal for MANUAL_REVIEW (default: true) */
216
+ interactiveApproval?: boolean;
217
+ /** Callback for MANUAL_REVIEW decisions (if not interactive) */
218
+ onApprovalRequired?: (context: PDLSSContext, decision: VerificationDecision) => Promise<boolean>;
219
+ }
220
+ declare class OpenClawCliAdapter implements PlatformAdapter {
221
+ readonly interfaceVersion = 1;
222
+ private gateway;
223
+ private options;
224
+ private server;
225
+ private _isRunning;
226
+ constructor(options?: OpenClawAdapterOptions);
227
+ get isRunning(): boolean;
228
+ get proxyPort(): number;
229
+ get targetPort(): number;
230
+ initialize(config: AdapterConfig): Promise<void>;
231
+ shutdown(): Promise<void>;
232
+ interceptAction(action: AgentAction): Promise<InterceptResult>;
233
+ extractContext(action: AgentAction): PDLSSContext;
234
+ enforceDecision(decision: VerificationDecision): Promise<void>;
235
+ private startProxy;
236
+ private handleProxyRequest;
237
+ private forwardRequest;
238
+ private handleApproval;
239
+ }
240
+
241
+ export { type BlockedCommand, type BlockedPath, DEFAULT_BLOCKED_COMMANDS, DEFAULT_BLOCKED_PATHS, type ImportResult, type OpenClawAdapterOptions, OpenClawCliAdapter, PURPOSE_CATEGORIES, type PromptInterface, type PurposeCategory, RISK_PRESETS, type RiskPreset, SetupWizard, type UpgradeCallbacks, type UpgradeConfig, UpgradeFlow, type UpgradeResult, importFromCursorRules, inferFromGitignore, isUpgraded };