@upbeat-works/fisgon 0.1.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.
Files changed (155) hide show
  1. package/LICENSE.md +10 -0
  2. package/README.md +150 -0
  3. package/dist/adapters/drizzle.d.ts +17 -0
  4. package/dist/adapters/drizzle.d.ts.map +1 -0
  5. package/dist/adapters/drizzle.js +83 -0
  6. package/dist/adapters/drizzle.js.map +1 -0
  7. package/dist/adapters/prisma.d.ts +16 -0
  8. package/dist/adapters/prisma.d.ts.map +1 -0
  9. package/dist/adapters/prisma.js +69 -0
  10. package/dist/adapters/prisma.js.map +1 -0
  11. package/dist/agent/ai.d.ts +3 -0
  12. package/dist/agent/ai.d.ts.map +1 -0
  13. package/dist/agent/ai.js +19 -0
  14. package/dist/agent/ai.js.map +1 -0
  15. package/dist/agent/browser-bridge.d.ts +42 -0
  16. package/dist/agent/browser-bridge.d.ts.map +1 -0
  17. package/dist/agent/browser-bridge.js +2 -0
  18. package/dist/agent/browser-bridge.js.map +1 -0
  19. package/dist/agent/index.d.ts +66 -0
  20. package/dist/agent/index.d.ts.map +1 -0
  21. package/dist/agent/index.js +572 -0
  22. package/dist/agent/index.js.map +1 -0
  23. package/dist/agent/llm-driver.d.ts +30 -0
  24. package/dist/agent/llm-driver.d.ts.map +1 -0
  25. package/dist/agent/llm-driver.js +239 -0
  26. package/dist/agent/llm-driver.js.map +1 -0
  27. package/dist/agent/session-state.d.ts +28 -0
  28. package/dist/agent/session-state.d.ts.map +1 -0
  29. package/dist/agent/session-state.js +6 -0
  30. package/dist/agent/session-state.js.map +1 -0
  31. package/dist/agent/worker.d.ts +6 -0
  32. package/dist/agent/worker.d.ts.map +1 -0
  33. package/dist/agent/worker.js +12 -0
  34. package/dist/agent/worker.js.map +1 -0
  35. package/dist/cli/browser-handler.d.ts +30 -0
  36. package/dist/cli/browser-handler.d.ts.map +1 -0
  37. package/dist/cli/browser-handler.js +89 -0
  38. package/dist/cli/browser-handler.js.map +1 -0
  39. package/dist/cli/browser-setup.d.ts +11 -0
  40. package/dist/cli/browser-setup.d.ts.map +1 -0
  41. package/dist/cli/browser-setup.js +25 -0
  42. package/dist/cli/browser-setup.js.map +1 -0
  43. package/dist/cli/commands/actions.d.ts +3 -0
  44. package/dist/cli/commands/actions.d.ts.map +1 -0
  45. package/dist/cli/commands/actions.js +28 -0
  46. package/dist/cli/commands/actions.js.map +1 -0
  47. package/dist/cli/commands/do.d.ts +3 -0
  48. package/dist/cli/commands/do.d.ts.map +1 -0
  49. package/dist/cli/commands/do.js +138 -0
  50. package/dist/cli/commands/do.js.map +1 -0
  51. package/dist/cli/commands/events.d.ts +3 -0
  52. package/dist/cli/commands/events.d.ts.map +1 -0
  53. package/dist/cli/commands/events.js +36 -0
  54. package/dist/cli/commands/events.js.map +1 -0
  55. package/dist/cli/commands/interact.d.ts +3 -0
  56. package/dist/cli/commands/interact.d.ts.map +1 -0
  57. package/dist/cli/commands/interact.js +54 -0
  58. package/dist/cli/commands/interact.js.map +1 -0
  59. package/dist/cli/commands/navigate.d.ts +3 -0
  60. package/dist/cli/commands/navigate.d.ts.map +1 -0
  61. package/dist/cli/commands/navigate.js +34 -0
  62. package/dist/cli/commands/navigate.js.map +1 -0
  63. package/dist/cli/commands/open.d.ts +3 -0
  64. package/dist/cli/commands/open.d.ts.map +1 -0
  65. package/dist/cli/commands/open.js +29 -0
  66. package/dist/cli/commands/open.js.map +1 -0
  67. package/dist/cli/commands/run.d.ts +3 -0
  68. package/dist/cli/commands/run.d.ts.map +1 -0
  69. package/dist/cli/commands/run.js +209 -0
  70. package/dist/cli/commands/run.js.map +1 -0
  71. package/dist/cli/commands/start.d.ts +3 -0
  72. package/dist/cli/commands/start.d.ts.map +1 -0
  73. package/dist/cli/commands/start.js +169 -0
  74. package/dist/cli/commands/start.js.map +1 -0
  75. package/dist/cli/commands/stop.d.ts +3 -0
  76. package/dist/cli/commands/stop.d.ts.map +1 -0
  77. package/dist/cli/commands/stop.js +37 -0
  78. package/dist/cli/commands/stop.js.map +1 -0
  79. package/dist/cli/commands/tick.d.ts +3 -0
  80. package/dist/cli/commands/tick.d.ts.map +1 -0
  81. package/dist/cli/commands/tick.js +34 -0
  82. package/dist/cli/commands/tick.js.map +1 -0
  83. package/dist/cli/config.d.ts +3 -0
  84. package/dist/cli/config.d.ts.map +1 -0
  85. package/dist/cli/config.js +20 -0
  86. package/dist/cli/config.js.map +1 -0
  87. package/dist/cli/connection.d.ts +18 -0
  88. package/dist/cli/connection.d.ts.map +1 -0
  89. package/dist/cli/connection.js +79 -0
  90. package/dist/cli/connection.js.map +1 -0
  91. package/dist/cli/index.d.ts +3 -0
  92. package/dist/cli/index.d.ts.map +1 -0
  93. package/dist/cli/index.js +29 -0
  94. package/dist/cli/index.js.map +1 -0
  95. package/dist/cli/session-file.d.ts +9 -0
  96. package/dist/cli/session-file.d.ts.map +1 -0
  97. package/dist/cli/session-file.js +23 -0
  98. package/dist/cli/session-file.js.map +1 -0
  99. package/dist/cli/task-runner.d.ts +20 -0
  100. package/dist/cli/task-runner.d.ts.map +1 -0
  101. package/dist/cli/task-runner.js +318 -0
  102. package/dist/cli/task-runner.js.map +1 -0
  103. package/dist/core/task-file.d.ts +32 -0
  104. package/dist/core/task-file.d.ts.map +1 -0
  105. package/dist/core/task-file.js +51 -0
  106. package/dist/core/task-file.js.map +1 -0
  107. package/dist/core/tick-detector.d.ts +24 -0
  108. package/dist/core/tick-detector.d.ts.map +1 -0
  109. package/dist/core/tick-detector.js +71 -0
  110. package/dist/core/tick-detector.js.map +1 -0
  111. package/dist/core/types.d.ts +74 -0
  112. package/dist/core/types.d.ts.map +1 -0
  113. package/dist/core/types.js +4 -0
  114. package/dist/core/types.js.map +1 -0
  115. package/dist/index.d.ts +4 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +4 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/probes/action-scanner.d.ts +2 -0
  120. package/dist/probes/action-scanner.d.ts.map +1 -0
  121. package/dist/probes/action-scanner.js +9 -0
  122. package/dist/probes/action-scanner.js.map +1 -0
  123. package/dist/probes/fetch-probe.d.ts +2 -0
  124. package/dist/probes/fetch-probe.d.ts.map +1 -0
  125. package/dist/probes/fetch-probe.js +9 -0
  126. package/dist/probes/fetch-probe.js.map +1 -0
  127. package/dist/probes/inject.d.ts +3 -0
  128. package/dist/probes/inject.d.ts.map +1 -0
  129. package/dist/probes/inject.js +24 -0
  130. package/dist/probes/inject.js.map +1 -0
  131. package/dist/probes/navigation-probe.d.ts +2 -0
  132. package/dist/probes/navigation-probe.d.ts.map +1 -0
  133. package/dist/probes/navigation-probe.js +9 -0
  134. package/dist/probes/navigation-probe.js.map +1 -0
  135. package/dist/probes/scripts/action-scanner.js +62 -0
  136. package/dist/probes/scripts/fetch.js +61 -0
  137. package/dist/probes/scripts/navigation.js +55 -0
  138. package/dist/probes/scripts/scripts/action-scanner.js +62 -0
  139. package/dist/probes/scripts/scripts/fetch.js +61 -0
  140. package/dist/probes/scripts/scripts/navigation.js +55 -0
  141. package/dist/probes/scripts/scripts/ws-bootstrap.js +35 -0
  142. package/dist/probes/scripts/ws-bootstrap.js +35 -0
  143. package/dist/server/create-probe.d.ts +8 -0
  144. package/dist/server/create-probe.d.ts.map +1 -0
  145. package/dist/server/create-probe.js +73 -0
  146. package/dist/server/create-probe.js.map +1 -0
  147. package/dist/server/sql-parser.d.ts +6 -0
  148. package/dist/server/sql-parser.d.ts.map +1 -0
  149. package/dist/server/sql-parser.js +40 -0
  150. package/dist/server/sql-parser.js.map +1 -0
  151. package/dist/server.d.ts +3 -0
  152. package/dist/server.d.ts.map +1 -0
  153. package/dist/server.js +2 -0
  154. package/dist/server.js.map +1 -0
  155. package/package.json +64 -0
package/LICENSE.md ADDED
@@ -0,0 +1,10 @@
1
+ # O'Saasy License Agreement
2
+
3
+ Copyright © 2026, Upbeat SL.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ 1. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+ 2. No licensee or downstream recipient may use the Software (including any modified or derivative versions) to directly compete with the original Licensor by offering it to third parties as a hosted, managed, or Software-as-a-Service (SaaS) product or cloud service where the primary value of the service is the functionality of the Software itself.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,150 @@
1
+ # fisgon
2
+
3
+ *__Fisgón__ (fee-SGOHN) is Spanish for "nosy person" — the kind who can't help but peek through the window to see what's going on.*
4
+
5
+ <p align="center">
6
+ <img src=".github/sickos.png" width="100" alt="Yes... ha ha ha... YES!" />
7
+ </p>
8
+
9
+ *That's exactly what this tool does. It watches every fetch request, every SQL query, every navigation event, every email your app sends — and it loves every second of it. Your app has no secrets from el fisgón.*
10
+
11
+ *100% of the code was written by Claude Opus. A human just pointed and said "make it snoop on everything." The fisgón obliged.*
12
+
13
+ ---
14
+
15
+ Low-level primitives for LLM-driven application testing.
16
+
17
+ Fisgon lets an LLM agent control a real browser while observing both client-side **and** server-side events. It captures every fetch request, navigation, SQL query, and custom event into **ticks** — groups of events collected during silence — giving the agent a complete picture of what happened after each action.
18
+
19
+ ## How it works
20
+
21
+ <p align="center">
22
+ <a href="https://x.com/i/status/2020660017272365349">
23
+ <img src=".github/demo.png" height="250" alt="Watch demo" />
24
+ </a>
25
+ <br />
26
+ <a href="https://x.com/i/status/2020660017272365349">Watch demo</a>
27
+ </p>
28
+
29
+ 1. **Start a session** — Fisgon launches a browser and connects probes
30
+ 2. **Give an instruction** — An LLM agent navigates the app like a real user, discovering links, filling forms, and clicking buttons
31
+ 3. **Observe everything** — Browser probes capture fetch traffic and navigation; server probes capture SQL queries and custom events (e.g. email content, background jobs)
32
+ 4. **Save and replay** — The agent's trace is distilled into a deterministic YAML task file that can be replayed without an LLM
33
+
34
+ ```
35
+ fisgon start # launch browser + session
36
+ fisgon do "Sign up and verify email" --save-task signup # LLM does it, saves task
37
+ fisgon run signup # replay without LLM
38
+ ```
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ npm install fisgon
44
+ ```
45
+
46
+ ## CLI
47
+
48
+ ```bash
49
+ fisgon start [options] # Start a session with browser
50
+ fisgon do <instruction> [options] # LLM agent performs a task
51
+ fisgon run <task-name> [options] # Replay a saved task
52
+ fisgon navigate <url> [options] # Navigate to a URL
53
+ fisgon actions # List interactive elements on page
54
+ fisgon interact <selector> [options] # Interact with an element
55
+ fisgon tick [options] # Wait for next tick
56
+ fisgon events # View all session events
57
+ fisgon open <actionId> # Inspect an action's HTML
58
+ fisgon stop # Stop the session
59
+ ```
60
+
61
+ ## Configuration
62
+
63
+ Create a `fisgon.config.ts` (or `.js` / `.mjs`) in your project root:
64
+
65
+ ```typescript
66
+ import { defineConfig } from 'fisgon'
67
+
68
+ export default defineConfig({
69
+ url: 'http://localhost:3000',
70
+ loginUrl: '/login',
71
+ identity: {
72
+ admin: { email: 'admin@example.com', password: 'secret' },
73
+ },
74
+ probes: {
75
+ fetch: { match: ['/api/**'] },
76
+ navigation: true,
77
+ },
78
+ tick: {
79
+ silenceMs: 500, // wait 500ms of silence to close a tick
80
+ maxMs: 30000, // max tick duration
81
+ },
82
+ })
83
+ ```
84
+
85
+ ## Server-side probes
86
+
87
+ Fisgon can observe your server too. Add a probe to capture SQL queries and custom events:
88
+
89
+ ```typescript
90
+ import { createProbe } from 'fisgon/server'
91
+
92
+ const probe = createProbe({ url: 'http://localhost:9876' })
93
+
94
+ // In your request handler:
95
+ const scoped = probe.fromRequest(request)
96
+ scoped.fromSQL('INSERT INTO users ...')
97
+ scoped.emit({ source: 'email', type: 'sent', timestamp: Date.now(), data: { to, subject, text } })
98
+ ```
99
+
100
+ ## Task files
101
+
102
+ Tasks live in `.fisgon/tasks/` as YAML:
103
+
104
+ ```yaml
105
+ name: login
106
+ description: Log in with email and password
107
+ params:
108
+ email: admin@example.com
109
+ password: secret
110
+ steps:
111
+ - tool: navigate
112
+ args:
113
+ url: "{{loginUrl}}"
114
+ - tool: interact
115
+ args:
116
+ action: type
117
+ selector: input[name="email"]
118
+ value: "{{email}}"
119
+ - tool: interact
120
+ args:
121
+ action: type
122
+ selector: input[name="password"]
123
+ value: "{{password}}"
124
+ - tool: interact
125
+ args:
126
+ action: click
127
+ selector: button[type="submit"]
128
+ validate:
129
+ url_contains: /dashboard
130
+ ```
131
+
132
+ Tasks support `{{param}}` placeholders and `extract` to capture dynamic values (like magic link URLs from email events) for use in later steps.
133
+
134
+ ## Architecture
135
+
136
+ ```
137
+ CLI ──────────────┐
138
+ │ WebSocket
139
+ Browser probes ───┤──────────── Agent (Cloudflare Durable Object)
140
+ │ ├── Event ingestion
141
+ │ ├── Tick detection
142
+ Server probes ────┘ HTTP POST ├── SQLite session store
143
+ └── LLM task execution
144
+ ```
145
+
146
+ The agent runs locally via `wrangler dev` or remotely on Cloudflare Workers. The CLI and browser probes connect over WebSocket; server probes send events via HTTP POST. The browser gets instrumented with injected scripts that track fetch requests, navigation, and interactive elements.
147
+
148
+ ## License
149
+
150
+ [O'Saasy License](LICENSE.md) — free to use, modify, and distribute; cannot be offered as a competing SaaS product.
@@ -0,0 +1,17 @@
1
+ import { type ScopedProbe } from '../core/types.js';
2
+ type DrizzleDb = {
3
+ insert(table: unknown): {
4
+ values(...args: unknown[]): unknown;
5
+ };
6
+ update(table: unknown): {
7
+ set(...args: unknown[]): unknown;
8
+ };
9
+ delete(table: unknown): {
10
+ where(...args: unknown[]): unknown;
11
+ };
12
+ select(...args: unknown[]): unknown;
13
+ [key: string]: unknown;
14
+ };
15
+ export declare function drizzleAdapter<T extends DrizzleDb>(db: T, scoped: ScopedProbe): T;
16
+ export {};
17
+ //# sourceMappingURL=drizzle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle.d.ts","sourceRoot":"","sources":["../../src/adapters/drizzle.ts"],"names":[],"mappings":"AAAA,OAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEpD,KAAK,SAAS,GAAG;IACf,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;KAAE,CAAA;IAC/D,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;KAAE,CAAA;IAC5D,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;KAAE,CAAA;IAC9D,MAAM,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,CAAA;IACnC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB,CAAA;AAkBD,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,CAAC,CAyCjF"}
@@ -0,0 +1,83 @@
1
+ // Extracts a table name from a Drizzle table object.
2
+ // Drizzle tables have a Symbol-keyed property or a `_.name` property.
3
+ function getTableName(table) {
4
+ if (table && typeof table === 'object') {
5
+ const t = table;
6
+ // Drizzle v0.30+ uses _.name
7
+ if (t._ && typeof t._ === 'object' && 'name' in t._) {
8
+ return String(t._.name);
9
+ }
10
+ // Fallback: try Symbol.for('drizzle:Name')
11
+ const sym = Symbol.for('drizzle:Name');
12
+ if (sym in t)
13
+ return String(t[sym]);
14
+ }
15
+ return 'unknown';
16
+ }
17
+ export function drizzleAdapter(db, scoped) {
18
+ if (!scoped.active)
19
+ return db;
20
+ return new Proxy(db, {
21
+ get(target, prop, receiver) {
22
+ const value = Reflect.get(target, prop, receiver);
23
+ if (prop === 'insert' && typeof value === 'function') {
24
+ return (table) => {
25
+ const tableName = getTableName(table);
26
+ const result = value.call(target, table);
27
+ return wrapChain(result, 'insert', tableName, scoped);
28
+ };
29
+ }
30
+ if (prop === 'update' && typeof value === 'function') {
31
+ return (table) => {
32
+ const tableName = getTableName(table);
33
+ const result = value.call(target, table);
34
+ return wrapChain(result, 'update', tableName, scoped);
35
+ };
36
+ }
37
+ if (prop === 'delete' && typeof value === 'function') {
38
+ return (table) => {
39
+ const tableName = getTableName(table);
40
+ const result = value.call(target, table);
41
+ return wrapChain(result, 'delete', tableName, scoped);
42
+ };
43
+ }
44
+ if (prop === 'select' && typeof value === 'function') {
45
+ return (...args) => {
46
+ const result = value.apply(target, args);
47
+ return wrapChain(result, 'select', 'query', scoped);
48
+ };
49
+ }
50
+ return value;
51
+ },
52
+ });
53
+ }
54
+ function wrapChain(obj, operation, tableName, scoped) {
55
+ if (!obj || typeof obj !== 'object')
56
+ return obj;
57
+ return new Proxy(obj, {
58
+ get(target, prop, receiver) {
59
+ const value = Reflect.get(target, prop, receiver);
60
+ if (typeof value === 'function') {
61
+ return (...args) => {
62
+ const result = value.apply(target, args);
63
+ // If the result is a thenable (query execution), emit the event
64
+ if (result && typeof result === 'object' && 'then' in result) {
65
+ scoped.emit({
66
+ source: 'sql',
67
+ type: operation,
68
+ timestamp: Date.now(),
69
+ data: { table: tableName },
70
+ });
71
+ }
72
+ // Continue wrapping for chaining
73
+ if (result && typeof result === 'object') {
74
+ return wrapChain(result, operation, tableName, scoped);
75
+ }
76
+ return result;
77
+ };
78
+ }
79
+ return value;
80
+ },
81
+ });
82
+ }
83
+ //# sourceMappingURL=drizzle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drizzle.js","sourceRoot":"","sources":["../../src/adapters/drizzle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type ScopedProbe } from '../core/types.js';
2
+ type PrismaClient = {
3
+ $use?(middleware: (params: PrismaMiddlewareParams, next: (params: PrismaMiddlewareParams) => Promise<unknown>) => Promise<unknown>): void;
4
+ $extends?(extension: unknown): unknown;
5
+ [key: string]: unknown;
6
+ };
7
+ type PrismaMiddlewareParams = {
8
+ model?: string;
9
+ action: string;
10
+ args: unknown;
11
+ dataPath: string[];
12
+ runInTransaction: boolean;
13
+ };
14
+ export declare function prismaAdapter<T extends PrismaClient>(client: T, scoped: ScopedProbe): T;
15
+ export {};
16
+ //# sourceMappingURL=prisma.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/adapters/prisma.ts"],"names":[],"mappings":"AAAA,OAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAEpD,KAAK,YAAY,GAAG;IAClB,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,sBAAsB,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,OAAO,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;IACzI,QAAQ,CAAC,CAAC,SAAS,EAAE,OAAO,GAAG,OAAO,CAAA;IACtC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB,CAAA;AAED,KAAK,sBAAsB,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,gBAAgB,EAAE,OAAO,CAAA;CAC1B,CAAA;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,YAAY,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,CAAC,CAqDvF"}
@@ -0,0 +1,69 @@
1
+ export function prismaAdapter(client, scoped) {
2
+ if (!scoped.active)
3
+ return client;
4
+ // Use Prisma middleware ($use) if available
5
+ if (typeof client.$use === 'function') {
6
+ client.$use(async (params, next) => {
7
+ const timestamp = Date.now();
8
+ scoped.emit({
9
+ source: 'sql',
10
+ type: mapPrismaAction(params.action),
11
+ timestamp,
12
+ data: {
13
+ table: params.model ?? 'unknown',
14
+ action: params.action,
15
+ },
16
+ });
17
+ return next(params);
18
+ });
19
+ return client;
20
+ }
21
+ // Fallback: use $extends (Prisma 5+)
22
+ if (typeof client.$extends === 'function') {
23
+ return client.$extends({
24
+ query: {
25
+ $allModels: {
26
+ async $allOperations({ model, operation, args, query }) {
27
+ scoped.emit({
28
+ source: 'sql',
29
+ type: mapPrismaAction(operation),
30
+ timestamp: Date.now(),
31
+ data: {
32
+ table: model,
33
+ action: operation,
34
+ },
35
+ });
36
+ return query(args);
37
+ },
38
+ },
39
+ },
40
+ });
41
+ }
42
+ return client;
43
+ }
44
+ function mapPrismaAction(action) {
45
+ switch (action) {
46
+ case 'create':
47
+ case 'createMany':
48
+ return 'insert';
49
+ case 'update':
50
+ case 'updateMany':
51
+ case 'upsert':
52
+ return 'update';
53
+ case 'delete':
54
+ case 'deleteMany':
55
+ return 'delete';
56
+ case 'findFirst':
57
+ case 'findMany':
58
+ case 'findUnique':
59
+ case 'findFirstOrThrow':
60
+ case 'findUniqueOrThrow':
61
+ case 'count':
62
+ case 'aggregate':
63
+ case 'groupBy':
64
+ return 'select';
65
+ default:
66
+ return action;
67
+ }
68
+ }
69
+ //# sourceMappingURL=prisma.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prisma.js","sourceRoot":"","sources":["../../src/adapters/prisma.ts"],"names":[],"mappings":"AAgBA,MAAM,UAAU,aAAa,CAAyB,MAAS,EAAE,MAAmB;IAClF,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,MAAM,CAAA;IAEjC,4CAA4C;IAC5C,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;YACjC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YAE5B,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC;gBACpC,SAAS;gBACT,IAAI,EAAE;oBACJ,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,SAAS;oBAChC,MAAM,EAAE,MAAM,CAAC,MAAM;iBACtB;aACF,CAAC,CAAA;YAEF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAA;QACrB,CAAC,CAAC,CAAA;QAEF,OAAO,MAAM,CAAA;IACf,CAAC;IAED,qCAAqC;IACrC,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC,QAAQ,CAAC;YACrB,KAAK,EAAE;gBACL,UAAU,EAAE;oBACV,KAAK,CAAC,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAKnD;wBACC,MAAM,CAAC,IAAI,CAAC;4BACV,MAAM,EAAE,KAAK;4BACb,IAAI,EAAE,eAAe,CAAC,SAAS,CAAC;4BAChC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;4BACrB,IAAI,EAAE;gCACJ,KAAK,EAAE,KAAK;gCACZ,MAAM,EAAE,SAAS;6BAClB;yBACF,CAAC,CAAA;wBAEF,OAAO,KAAK,CAAC,IAAI,CAAC,CAAA;oBACpB,CAAC;iBACF;aACF;SACF,CAAM,CAAA;IACT,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,eAAe,CAAC,MAAc;IACrC,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,QAAQ,CAAC;QACd,KAAK,YAAY;YACf,OAAO,QAAQ,CAAA;QACjB,KAAK,QAAQ,CAAC;QACd,KAAK,YAAY,CAAC;QAClB,KAAK,QAAQ;YACX,OAAO,QAAQ,CAAA;QACjB,KAAK,QAAQ,CAAC;QACd,KAAK,YAAY;YACf,OAAO,QAAQ,CAAA;QACjB,KAAK,WAAW,CAAC;QACjB,KAAK,UAAU,CAAC;QAChB,KAAK,YAAY,CAAC;QAClB,KAAK,kBAAkB,CAAC;QACxB,KAAK,mBAAmB,CAAC;QACzB,KAAK,OAAO,CAAC;QACb,KAAK,WAAW,CAAC;QACjB,KAAK,SAAS;YACZ,OAAO,QAAQ,CAAA;QACjB;YACE,OAAO,MAAM,CAAA;IACjB,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare const model: import("@ai-sdk/provider").LanguageModelV3;
2
+ export declare const structuredModel: import("@ai-sdk/provider").LanguageModelV3;
3
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/agent/ai.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,KAAK,4CAA2D,CAAA;AAS7E,eAAO,MAAM,eAAe,4CAAkD,CAAA"}
@@ -0,0 +1,19 @@
1
+ import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
2
+ import { createAiGateway } from 'ai-gateway-provider';
3
+ import { createOpenAI } from 'ai-gateway-provider/providers/openai';
4
+ import { env } from 'cloudflare:workers';
5
+ const gateway = createOpenAICompatible({
6
+ name: 'cf-ai-gateway',
7
+ baseURL: `https://gateway.ai.cloudflare.com/v1/${env.ACCOUNT_ID}/${env.AI_GATEWAY}/compat`,
8
+ apiKey: env.AI_GATEWAY_TOKEN,
9
+ });
10
+ export const model = gateway.chatModel('anthropic/claude-haiku-4-5-20251001');
11
+ // OpenAI model via AI Gateway for structured output (json_schema)
12
+ const aiGateway = createAiGateway({
13
+ accountId: env.ACCOUNT_ID,
14
+ gateway: env.AI_GATEWAY,
15
+ apiKey: env.AI_GATEWAY_TOKEN,
16
+ });
17
+ const openai = createOpenAI();
18
+ export const structuredModel = aiGateway(openai.chat('gpt-5-nano-2025-08-07'));
19
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/agent/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAA;AACnE,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAExC,MAAM,OAAO,GAAG,sBAAsB,CAAC;IACtC,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,wCAAwC,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,SAAS;IAC1F,MAAM,EAAE,GAAG,CAAC,gBAAgB;CAC5B,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAA;AAE7E,kEAAkE;AAClE,MAAM,SAAS,GAAG,eAAe,CAAC;IACjC,SAAS,EAAE,GAAG,CAAC,UAAU;IACzB,OAAO,EAAE,GAAG,CAAC,UAAU;IACvB,MAAM,EAAE,GAAG,CAAC,gBAAgB;CAC5B,CAAC,CAAA;AACF,MAAM,MAAM,GAAG,YAAY,EAAE,CAAA;AAC7B,MAAM,CAAC,MAAM,eAAe,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAA"}
@@ -0,0 +1,42 @@
1
+ import { type Action, type InteractCommand } from '../core/types.js';
2
+ export type BrowserBridge = {
3
+ navigate(url: string): Promise<void>;
4
+ evaluateScript(script: string): Promise<unknown>;
5
+ getActions(): Promise<Action[]>;
6
+ getInnerHTML(actionId: string): Promise<string>;
7
+ interact(command: InteractCommand): Promise<void>;
8
+ setCookie(name: string, value: string, domain: string): Promise<void>;
9
+ close(): Promise<void>;
10
+ };
11
+ export type BrowserCommand = {
12
+ type: 'browser-navigate';
13
+ url: string;
14
+ } | {
15
+ type: 'browser-evaluate';
16
+ script: string;
17
+ } | {
18
+ type: 'browser-actions';
19
+ } | {
20
+ type: 'browser-open';
21
+ actionId: string;
22
+ } | {
23
+ type: 'browser-interact';
24
+ command: InteractCommand;
25
+ } | {
26
+ type: 'browser-set-cookie';
27
+ name: string;
28
+ value: string;
29
+ domain: string;
30
+ } | {
31
+ type: 'browser-close';
32
+ };
33
+ export type BrowserResult = {
34
+ type: 'browser-result';
35
+ success: true;
36
+ data?: unknown;
37
+ } | {
38
+ type: 'browser-result';
39
+ success: false;
40
+ error: string;
41
+ };
42
+ //# sourceMappingURL=browser-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-bridge.d.ts","sourceRoot":"","sources":["../../src/agent/browser-bridge.ts"],"names":[],"mappings":"AAAA,OAAQ,EAAE,KAAK,MAAM,EAAE,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAA;AAMrE,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAChD,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IAC/B,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/C,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACjD,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB,CAAA;AAMD,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,iBAAiB,CAAA;CAAE,GAC3B;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,eAAe,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,oBAAoB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,IAAI,EAAE,eAAe,CAAA;CAAE,CAAA;AAE7B,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=browser-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-bridge.js","sourceRoot":"","sources":["../../src/agent/browser-bridge.ts"],"names":[],"mappings":""}
@@ -0,0 +1,66 @@
1
+ import { Agent, type Connection, type WSMessage } from 'agents';
2
+ import { type TaskFile } from '../core/task-file.js';
3
+ import { type ProbeEvent, type Tick, type FisgonConfig, type IdentityConfig, type Action, type InteractCommand, type BrowserMode } from '../core/types.js';
4
+ import { type StepLog } from './llm-driver.js';
5
+ import { type AgentState } from './session-state.js';
6
+ export declare class FisgonAgent extends Agent<Cloudflare.Env, AgentState> {
7
+ initialState: AgentState;
8
+ private sessions;
9
+ private dbInitialized;
10
+ private initDb;
11
+ onConnect(connection: Connection): Promise<void>;
12
+ onClose(connection: Connection): Promise<void>;
13
+ onRequest(request: Request): Promise<Response>;
14
+ onMessage(connection: Connection, message: WSMessage): Promise<void>;
15
+ startSession(config: FisgonConfig, browserMode: BrowserMode, identity?: IdentityConfig): {
16
+ sessionId: string;
17
+ };
18
+ stopSession(sessionId: string): Promise<void>;
19
+ navigate(sessionId: string, url: string, asIdentity?: string): Promise<{
20
+ tick: Tick;
21
+ }>;
22
+ performTask(sessionId: string, instruction: string): Promise<{
23
+ result: string;
24
+ }>;
25
+ distillTask(sessionId: string, stepLogs: StepLog[], instruction: string, finalUrl: string): Promise<{
26
+ task: TaskFile;
27
+ }>;
28
+ matchTasks(instruction: string, tasks: Array<{
29
+ name: string;
30
+ description: string;
31
+ }>): Promise<{
32
+ tasks: string[] | null;
33
+ remaining: string | null;
34
+ }>;
35
+ getActions(sessionId: string): Promise<{
36
+ actions: Action[];
37
+ }>;
38
+ openAction(sessionId: string, actionId: string): Promise<{
39
+ html: string;
40
+ }>;
41
+ interact(sessionId: string, command: InteractCommand): Promise<void>;
42
+ waitForNextTick(sessionId: string, timeout?: number): Promise<{
43
+ tick: Tick;
44
+ }>;
45
+ getEvents(sessionId: string): {
46
+ events: ProbeEvent[];
47
+ };
48
+ listSessions(): {
49
+ sessions: Array<{
50
+ id: string;
51
+ status: string;
52
+ browserMode: string;
53
+ createdAt: number;
54
+ }>;
55
+ };
56
+ emitEvent(event: ProbeEvent): void;
57
+ private ingestEvent;
58
+ private handleTickComplete;
59
+ private handleBrowserResult;
60
+ private sendBrowserCommand;
61
+ private waitForTick;
62
+ private createTaskContext;
63
+ private requireRuntime;
64
+ private broadcastState;
65
+ }
66
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent/index.ts"],"names":[],"mappings":"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"}