@poolzin/pool-bot 2026.3.11 → 2026.3.14

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 (195) hide show
  1. package/CHANGELOG.md +121 -0
  2. package/dist/.buildstamp +1 -1
  3. package/dist/agents/checkpoint-manager.js +291 -0
  4. package/dist/agents/poolbot-tools.js +5 -0
  5. package/dist/agents/subagent-announce-reliability.js +160 -0
  6. package/dist/agents/tool-result-truncation.js +299 -0
  7. package/dist/agents/tools/nodes-file-tool.js +197 -0
  8. package/dist/build-info.json +3 -3
  9. package/dist/cli/config-cli.js +60 -0
  10. package/dist/cron/cron-improvements.js +195 -0
  11. package/dist/discord/discord-improvements.js +167 -0
  12. package/dist/gateway/auth-rate-limit.js +19 -0
  13. package/dist/gateway/auth.js +41 -0
  14. package/dist/gateway/gateway-improvements.js +294 -0
  15. package/dist/gateway/node-command-policy.js +7 -2
  16. package/dist/infra/net/ssrf.js +15 -2
  17. package/dist/infra/shell-security.js +201 -0
  18. package/dist/memory/memory-improvements.js +239 -0
  19. package/dist/node-host/runner.js +146 -79
  20. package/dist/security/prototype-pollution.js +141 -0
  21. package/dist/security/webhook-security.js +253 -0
  22. package/dist/shared/net/ip.js +52 -1
  23. package/dist/slack/slack-improvements.js +225 -0
  24. package/dist/telegram/telegram-improvements.js +220 -0
  25. package/dist/ui-plugins/ui-plugins-improvements.js +191 -0
  26. package/docs/ANALISE_OPENCLAW_PROFISSIONAL.md +520 -0
  27. package/docs/competitive-analysis.md +421 -0
  28. package/docs/implementation-analysis.md +393 -0
  29. package/docs/plans/2026-03-11-file-operations-security-hardening.md +307 -0
  30. package/docs/plans/2026-03-11-integracao-projetos-poolbot.md +666 -0
  31. package/docs/refactor/plugin-development-guide.md +281 -0
  32. package/extensions/agency-agents/README.md +301 -0
  33. package/extensions/agency-agents/agents/CONTRIBUTING.md +353 -0
  34. package/extensions/agency-agents/agents/README.md +602 -0
  35. package/extensions/agency-agents/agents/design/design-brand-guardian.md +320 -0
  36. package/extensions/agency-agents/agents/design/design-image-prompt-engineer.md +234 -0
  37. package/extensions/agency-agents/agents/design/design-ui-designer.md +381 -0
  38. package/extensions/agency-agents/agents/design/design-ux-architect.md +467 -0
  39. package/extensions/agency-agents/agents/design/design-ux-researcher.md +327 -0
  40. package/extensions/agency-agents/agents/design/design-visual-storyteller.md +147 -0
  41. package/extensions/agency-agents/agents/design/design-whimsy-injector.md +436 -0
  42. package/extensions/agency-agents/agents/engineering/engineering-ai-engineer.md +144 -0
  43. package/extensions/agency-agents/agents/engineering/engineering-backend-architect.md +233 -0
  44. package/extensions/agency-agents/agents/engineering/engineering-devops-automator.md +374 -0
  45. package/extensions/agency-agents/agents/engineering/engineering-frontend-developer.md +223 -0
  46. package/extensions/agency-agents/agents/engineering/engineering-mobile-app-builder.md +491 -0
  47. package/extensions/agency-agents/agents/engineering/engineering-rapid-prototyper.md +460 -0
  48. package/extensions/agency-agents/agents/engineering/engineering-security-engineer.md +275 -0
  49. package/extensions/agency-agents/agents/engineering/engineering-senior-developer.md +174 -0
  50. package/extensions/agency-agents/agents/examples/README.md +48 -0
  51. package/extensions/agency-agents/agents/examples/nexus-spatial-discovery.md +852 -0
  52. package/extensions/agency-agents/agents/examples/workflow-landing-page.md +119 -0
  53. package/extensions/agency-agents/agents/examples/workflow-startup-mvp.md +155 -0
  54. package/extensions/agency-agents/agents/integrations/README.md +117 -0
  55. package/extensions/agency-agents/agents/integrations/aider/README.md +38 -0
  56. package/extensions/agency-agents/agents/integrations/antigravity/README.md +49 -0
  57. package/extensions/agency-agents/agents/integrations/claude-code/README.md +31 -0
  58. package/extensions/agency-agents/agents/integrations/cursor/README.md +38 -0
  59. package/extensions/agency-agents/agents/integrations/gemini-cli/README.md +36 -0
  60. package/extensions/agency-agents/agents/integrations/opencode/README.md +58 -0
  61. package/extensions/agency-agents/agents/integrations/windsurf/README.md +26 -0
  62. package/extensions/agency-agents/agents/marketing/marketing-app-store-optimizer.md +319 -0
  63. package/extensions/agency-agents/agents/marketing/marketing-content-creator.md +52 -0
  64. package/extensions/agency-agents/agents/marketing/marketing-growth-hacker.md +52 -0
  65. package/extensions/agency-agents/agents/marketing/marketing-instagram-curator.md +111 -0
  66. package/extensions/agency-agents/agents/marketing/marketing-reddit-community-builder.md +121 -0
  67. package/extensions/agency-agents/agents/marketing/marketing-social-media-strategist.md +123 -0
  68. package/extensions/agency-agents/agents/marketing/marketing-tiktok-strategist.md +123 -0
  69. package/extensions/agency-agents/agents/marketing/marketing-twitter-engager.md +124 -0
  70. package/extensions/agency-agents/agents/marketing/marketing-wechat-official-account.md +143 -0
  71. package/extensions/agency-agents/agents/marketing/marketing-xiaohongshu-specialist.md +136 -0
  72. package/extensions/agency-agents/agents/marketing/marketing-zhihu-strategist.md +160 -0
  73. package/extensions/agency-agents/agents/product/product-feedback-synthesizer.md +117 -0
  74. package/extensions/agency-agents/agents/product/product-sprint-prioritizer.md +152 -0
  75. package/extensions/agency-agents/agents/product/product-trend-researcher.md +157 -0
  76. package/extensions/agency-agents/agents/project-management/project-management-experiment-tracker.md +196 -0
  77. package/extensions/agency-agents/agents/project-management/project-management-project-shepherd.md +192 -0
  78. package/extensions/agency-agents/agents/project-management/project-management-studio-operations.md +198 -0
  79. package/extensions/agency-agents/agents/project-management/project-management-studio-producer.md +201 -0
  80. package/extensions/agency-agents/agents/project-management/project-manager-senior.md +133 -0
  81. package/extensions/agency-agents/agents/scripts/convert.sh +362 -0
  82. package/extensions/agency-agents/agents/scripts/install.sh +465 -0
  83. package/extensions/agency-agents/agents/scripts/lint-agents.sh +115 -0
  84. package/extensions/agency-agents/agents/spatial-computing/macos-spatial-metal-engineer.md +335 -0
  85. package/extensions/agency-agents/agents/spatial-computing/terminal-integration-specialist.md +68 -0
  86. package/extensions/agency-agents/agents/spatial-computing/visionos-spatial-engineer.md +52 -0
  87. package/extensions/agency-agents/agents/spatial-computing/xr-cockpit-interaction-specialist.md +30 -0
  88. package/extensions/agency-agents/agents/spatial-computing/xr-immersive-developer.md +30 -0
  89. package/extensions/agency-agents/agents/spatial-computing/xr-interface-architect.md +30 -0
  90. package/extensions/agency-agents/agents/specialized/agentic-identity-trust.md +367 -0
  91. package/extensions/agency-agents/agents/specialized/agents-orchestrator.md +365 -0
  92. package/extensions/agency-agents/agents/specialized/data-analytics-reporter.md +52 -0
  93. package/extensions/agency-agents/agents/specialized/data-consolidation-agent.md +58 -0
  94. package/extensions/agency-agents/agents/specialized/lsp-index-engineer.md +312 -0
  95. package/extensions/agency-agents/agents/specialized/report-distribution-agent.md +63 -0
  96. package/extensions/agency-agents/agents/specialized/sales-data-extraction-agent.md +65 -0
  97. package/extensions/agency-agents/agents/strategy/EXECUTIVE-BRIEF.md +95 -0
  98. package/extensions/agency-agents/agents/strategy/QUICKSTART.md +194 -0
  99. package/extensions/agency-agents/agents/strategy/coordination/agent-activation-prompts.md +401 -0
  100. package/extensions/agency-agents/agents/strategy/coordination/handoff-templates.md +357 -0
  101. package/extensions/agency-agents/agents/strategy/nexus-strategy.md +1110 -0
  102. package/extensions/agency-agents/agents/strategy/playbooks/phase-0-discovery.md +178 -0
  103. package/extensions/agency-agents/agents/strategy/playbooks/phase-1-strategy.md +238 -0
  104. package/extensions/agency-agents/agents/strategy/playbooks/phase-2-foundation.md +278 -0
  105. package/extensions/agency-agents/agents/strategy/playbooks/phase-3-build.md +286 -0
  106. package/extensions/agency-agents/agents/strategy/playbooks/phase-4-hardening.md +332 -0
  107. package/extensions/agency-agents/agents/strategy/playbooks/phase-5-launch.md +277 -0
  108. package/extensions/agency-agents/agents/strategy/playbooks/phase-6-operate.md +318 -0
  109. package/extensions/agency-agents/agents/strategy/runbooks/scenario-enterprise-feature.md +157 -0
  110. package/extensions/agency-agents/agents/strategy/runbooks/scenario-incident-response.md +217 -0
  111. package/extensions/agency-agents/agents/strategy/runbooks/scenario-marketing-campaign.md +187 -0
  112. package/extensions/agency-agents/agents/strategy/runbooks/scenario-startup-mvp.md +154 -0
  113. package/extensions/agency-agents/agents/support/support-analytics-reporter.md +363 -0
  114. package/extensions/agency-agents/agents/support/support-executive-summary-generator.md +210 -0
  115. package/extensions/agency-agents/agents/support/support-finance-tracker.md +440 -0
  116. package/extensions/agency-agents/agents/support/support-infrastructure-maintainer.md +616 -0
  117. package/extensions/agency-agents/agents/support/support-legal-compliance-checker.md +586 -0
  118. package/extensions/agency-agents/agents/support/support-support-responder.md +583 -0
  119. package/extensions/agency-agents/agents/testing/testing-accessibility-auditor.md +313 -0
  120. package/extensions/agency-agents/agents/testing/testing-api-tester.md +304 -0
  121. package/extensions/agency-agents/agents/testing/testing-evidence-collector.md +208 -0
  122. package/extensions/agency-agents/agents/testing/testing-performance-benchmarker.md +266 -0
  123. package/extensions/agency-agents/agents/testing/testing-reality-checker.md +236 -0
  124. package/extensions/agency-agents/agents/testing/testing-test-results-analyzer.md +303 -0
  125. package/extensions/agency-agents/agents/testing/testing-tool-evaluator.md +392 -0
  126. package/extensions/agency-agents/agents/testing/testing-workflow-optimizer.md +448 -0
  127. package/extensions/agency-agents/index.ts +733 -0
  128. package/extensions/agency-agents/node_modules/.bin/jiti +21 -0
  129. package/extensions/agency-agents/node_modules/.bin/tsc +21 -0
  130. package/extensions/agency-agents/node_modules/.bin/tsserver +21 -0
  131. package/extensions/agency-agents/node_modules/.bin/tsx +21 -0
  132. package/extensions/agency-agents/node_modules/.bin/vite +21 -0
  133. package/extensions/agency-agents/node_modules/.bin/vitest +21 -0
  134. package/extensions/agency-agents/node_modules/.bin/yaml +21 -0
  135. package/extensions/agency-agents/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  136. package/extensions/agency-agents/package.json +25 -0
  137. package/extensions/agency-agents/src/AgencyAgentsService.test.ts +443 -0
  138. package/extensions/agency-agents/src/AgencyAgentsService.ts +288 -0
  139. package/extensions/agency-agents/src/types.ts +147 -0
  140. package/extensions/agency-agents/vitest.config.ts +8 -0
  141. package/extensions/hexstrike-ai/README.md +98 -0
  142. package/extensions/hexstrike-ai/node_modules/.bin/tsc +21 -0
  143. package/extensions/hexstrike-ai/node_modules/.bin/tsserver +21 -0
  144. package/extensions/hexstrike-ai/package.json +29 -0
  145. package/extensions/hexstrike-ai/poolbot.plugin.json +31 -0
  146. package/extensions/hexstrike-ai/src/client.ts +91 -0
  147. package/extensions/hexstrike-ai/src/index.ts +170 -0
  148. package/extensions/hexstrike-ai/src/server/hexstrike_mcp.py +5470 -0
  149. package/extensions/hexstrike-ai/src/server/hexstrike_server.py +17289 -0
  150. package/extensions/hexstrike-ai/src/server/requirements.txt +84 -0
  151. package/extensions/hexstrike-ai/src/server-manager.ts +83 -0
  152. package/extensions/hexstrike-ai/tsconfig.json +20 -0
  153. package/extensions/hexstrike-bridge/package.json +1 -1
  154. package/extensions/hexstrike-bridge/poolbot.plugin.json +23 -0
  155. package/extensions/mcp-server/poolbot.plugin.json +10 -0
  156. package/extensions/page-agent/README.md +159 -0
  157. package/extensions/page-agent/index.ts +595 -0
  158. package/extensions/page-agent/node_modules/.bin/jiti +21 -0
  159. package/extensions/page-agent/node_modules/.bin/playwright +21 -0
  160. package/extensions/page-agent/node_modules/.bin/tsc +21 -0
  161. package/extensions/page-agent/node_modules/.bin/tsserver +21 -0
  162. package/extensions/page-agent/node_modules/.bin/tsx +21 -0
  163. package/extensions/page-agent/node_modules/.bin/vitest +21 -0
  164. package/extensions/page-agent/node_modules/.bin/yaml +21 -0
  165. package/extensions/page-agent/package.json +43 -0
  166. package/extensions/page-agent/src/PageAgentService.test.ts +517 -0
  167. package/extensions/page-agent/src/PageAgentService.ts +636 -0
  168. package/extensions/page-agent/src/PoolBotPageController.test.ts +358 -0
  169. package/extensions/page-agent/src/PoolBotPageController.ts +245 -0
  170. package/extensions/page-agent/src/index.ts +20 -0
  171. package/extensions/page-agent/src/tools.test.ts +231 -0
  172. package/extensions/page-agent/src/tools.ts +167 -0
  173. package/extensions/page-agent/src/types.ts +198 -0
  174. package/extensions/template/README.md +101 -0
  175. package/extensions/template/index.ts +38 -0
  176. package/extensions/template/package.json +15 -0
  177. package/extensions/template/poolbot.plugin.json +10 -0
  178. package/extensions/xyops/README.md +227 -0
  179. package/extensions/xyops/index.ts +342 -0
  180. package/extensions/xyops/node_modules/.bin/jiti +21 -0
  181. package/extensions/xyops/node_modules/.bin/tsc +21 -0
  182. package/extensions/xyops/node_modules/.bin/tsserver +21 -0
  183. package/extensions/xyops/node_modules/.bin/tsx +21 -0
  184. package/extensions/xyops/node_modules/.bin/vitest +21 -0
  185. package/extensions/xyops/node_modules/.bin/yaml +21 -0
  186. package/extensions/xyops/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  187. package/extensions/xyops/package.json +39 -0
  188. package/extensions/xyops/src/client.test.ts +467 -0
  189. package/extensions/xyops/src/client.ts +157 -0
  190. package/extensions/xyops/src/types.ts +147 -0
  191. package/extensions/xyops/vitest.config.ts +8 -0
  192. package/package.json +1 -1
  193. package/extensions/mavalie/README.md +0 -97
  194. package/extensions/mavalie/package.json +0 -15
  195. package/extensions/mavalie/src/index.ts +0 -62
@@ -0,0 +1,636 @@
1
+ /**
2
+ * PageAgentService - ReAct Agent Loop for PoolBot
3
+ *
4
+ * Implements the core agent loop:
5
+ * - observe (gather information about current environment)
6
+ * - think (LLM calling with reflection and action planning)
7
+ * - act (execute the action via tools)
8
+ *
9
+ * This is a native PoolBot service that uses the browser client
10
+ * and LLM infrastructure already available in PoolBot.
11
+ */
12
+
13
+ import type { PoolBotPageController } from './PoolBotPageController.js'
14
+ import type {
15
+ PageAgentConfig,
16
+ PageAgentExecutionResult,
17
+ AgentActivity,
18
+ AgentHistoryEvent,
19
+ PageAgentTool,
20
+ } from './types.js'
21
+ import { createPageAgentTools } from './tools.js'
22
+
23
+ // System prompt for the agent
24
+ const SYSTEM_PROMPT = `You are an AI agent that can control a web browser to complete tasks.
25
+
26
+ Your job is to:
27
+ 1. Analyze the current browser state
28
+ 2. Reflect on previous actions and their results
29
+ 3. Plan the next action to progress toward the goal
30
+ 4. Execute the action using available tools
31
+
32
+ Available tools:
33
+ - navigate: Navigate to a URL
34
+ - click: Click on an element
35
+ - type: Type text into an input field
36
+ - scroll: Scroll the page
37
+ - wait: Wait for a specified time
38
+ - screenshot: Take a screenshot
39
+ - get_text: Get text content from the page
40
+ - done: Complete the task with success/failure
41
+
42
+ Rules:
43
+ - Always evaluate your previous action before planning the next one
44
+ - Keep track of important information in your memory
45
+ - Be concise but thorough in your reasoning
46
+ - If stuck, try a different approach
47
+ - Call 'done' when the task is complete or if you cannot proceed
48
+
49
+ Default working language: **English**`
50
+
51
+ // Tool output type
52
+ interface ToolOutput {
53
+ success: boolean
54
+ data?: unknown
55
+ error?: string
56
+ }
57
+
58
+ // LLM message type
59
+ interface LLMMessage {
60
+ role: 'system' | 'user' | 'assistant'
61
+ content: string
62
+ }
63
+
64
+ // Agent status type
65
+ type AgentStatus = 'idle' | 'running' | 'completed' | 'error'
66
+
67
+ // Historical event types
68
+ interface AgentStepEvent {
69
+ type: 'step'
70
+ stepIndex: number
71
+ reflection: {
72
+ evaluation_previous_goal?: string
73
+ memory?: string
74
+ next_goal?: string
75
+ }
76
+ action: {
77
+ name: string
78
+ input: unknown
79
+ output: unknown
80
+ }
81
+ }
82
+
83
+ interface ObservationEvent {
84
+ type: 'observation'
85
+ content: string
86
+ }
87
+
88
+ interface ErrorEvent {
89
+ type: 'error'
90
+ message: string
91
+ rawResponse?: unknown
92
+ }
93
+
94
+ type HistoricalEvent = AgentStepEvent | ObservationEvent | ErrorEvent
95
+
96
+ // Macro tool types
97
+ interface MacroToolInput {
98
+ evaluation_previous_goal?: string
99
+ memory?: string
100
+ next_goal?: string
101
+ action: Record<string, unknown>
102
+ }
103
+
104
+ export class PageAgentService extends EventTarget {
105
+ readonly id: string
106
+ readonly config: PageAgentConfig
107
+ private readonly controller: PoolBotPageController
108
+ private readonly tools: PageAgentTool[]
109
+
110
+ task = ''
111
+ taskId = ''
112
+ history: HistoricalEvent[] = []
113
+ status: AgentStatus = 'idle'
114
+ disposed = false
115
+
116
+ private abortController = new AbortController()
117
+ private observations: string[] = []
118
+ private currentStep = 0
119
+ private maxSteps: number
120
+
121
+ // Internal state tracking
122
+ private states = {
123
+ totalWaitTime: 0,
124
+ lastURL: '',
125
+ }
126
+
127
+ constructor(config: PageAgentConfig, controller: PoolBotPageController) {
128
+ super()
129
+
130
+ this.id = this.generateId()
131
+ this.config = config
132
+ this.controller = controller
133
+ this.maxSteps = config.maxSteps ?? 40
134
+
135
+ // Initialize tools
136
+ this.tools = createPageAgentTools()
137
+
138
+ // Apply custom tools
139
+ if (this.config.customTools) {
140
+ for (const [name, tool] of Object.entries(this.config.customTools)) {
141
+ if (tool === null) {
142
+ const idx = this.tools.findIndex((t) => t.name === name)
143
+ if (idx >= 0) this.tools.splice(idx, 1)
144
+ } else {
145
+ const idx = this.tools.findIndex((t) => t.name === name)
146
+ if (idx >= 0) {
147
+ this.tools[idx] = tool as PageAgentTool
148
+ } else {
149
+ this.tools.push(tool as PageAgentTool)
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Execute a task using the ReAct loop
158
+ */
159
+ async execute(task: string): Promise<PageAgentExecutionResult> {
160
+ if (this.disposed) {
161
+ throw new Error('PageAgentService has been disposed. Create a new instance.')
162
+ }
163
+ if (!task) {
164
+ throw new Error('Task is required')
165
+ }
166
+
167
+ this.task = task
168
+ this.taskId = this.generateId()
169
+ this.currentStep = 0
170
+
171
+ await this.config.onBeforeTask?.(this)
172
+
173
+ // Reset state
174
+ this.abortController = new AbortController()
175
+ this.history = []
176
+ this.observations = []
177
+ this.states = { totalWaitTime: 0, lastURL: '' }
178
+
179
+ this.setStatus('running')
180
+ this.emitHistoryChange()
181
+
182
+ const startTime = Date.now()
183
+
184
+ try {
185
+ while (true) {
186
+ console.group(`Step: ${this.currentStep}`)
187
+
188
+ await this.config.onBeforeStep?.(this, this.currentStep)
189
+
190
+ // OBSERVE: Gather information about current state
191
+ console.log('👀 Observing...')
192
+ await this.observe()
193
+
194
+ // THINK: Call LLM to decide next action
195
+ console.log('🧠 Thinking...')
196
+ this.emitActivity({ type: 'thinking' })
197
+
198
+ const messages = await this.buildMessages()
199
+ const tools = this.buildMacroTool()
200
+
201
+ const llmResult = await this.callLLM(messages, tools)
202
+
203
+ // Parse the result
204
+ const parsed = this.parseLLMResponse(llmResult)
205
+ if (!parsed) {
206
+ throw new Error('Failed to parse LLM response')
207
+ }
208
+
209
+ // Extract reflection and action
210
+ const reflection = {
211
+ evaluation_previous_goal: parsed.evaluation_previous_goal,
212
+ memory: parsed.memory,
213
+ next_goal: parsed.next_goal,
214
+ }
215
+
216
+ const actionName = Object.keys(parsed.action)[0]
217
+ const actionInput = parsed.action[actionName]
218
+
219
+ // ACT: Execute the tool
220
+ console.log(`🎬 Executing: ${actionName}`)
221
+ this.emitActivity({ type: 'executing', tool: actionName, input: actionInput })
222
+
223
+ const stepStartTime = Date.now()
224
+ const toolResult = await this.executeTool(actionName, actionInput)
225
+ const duration = Date.now() - stepStartTime
226
+
227
+ console.log(`✅ Tool (${actionName}) executed in ${duration}ms`, toolResult)
228
+ this.emitActivity({
229
+ type: 'executed',
230
+ tool: actionName,
231
+ input: actionInput,
232
+ output: toolResult.data,
233
+ duration,
234
+ })
235
+
236
+ // Track wait time
237
+ if (actionName === 'wait') {
238
+ this.states.totalWaitTime += ((actionInput as { seconds?: number })?.seconds) || 0
239
+ } else {
240
+ this.states.totalWaitTime = 0
241
+ }
242
+
243
+ // Record step in history
244
+ const stepEvent: AgentStepEvent = {
245
+ type: 'step',
246
+ stepIndex: this.currentStep,
247
+ reflection,
248
+ action: {
249
+ name: actionName,
250
+ input: actionInput,
251
+ output: toolResult.data,
252
+ },
253
+ }
254
+ this.history.push(stepEvent)
255
+ this.emitHistoryChange()
256
+
257
+ await this.config.onAfterStep?.(this, this.history)
258
+
259
+ console.groupEnd()
260
+
261
+ // Check if done
262
+ if (actionName === 'done') {
263
+ const input = actionInput as { success?: boolean; answer?: string }
264
+ const success = input?.success ?? false
265
+ const text = input?.answer || 'Task completed'
266
+ console.log('Task completed:', success, text)
267
+
268
+ this.setStatus(success ? 'completed' : 'error')
269
+ const result: PageAgentExecutionResult = {
270
+ success,
271
+ data: text,
272
+ history: this.history as AgentHistoryEvent[],
273
+ totalSteps: this.currentStep + 1,
274
+ duration: Date.now() - startTime,
275
+ }
276
+ await this.config.onAfterTask?.(this, result)
277
+ return result
278
+ }
279
+
280
+ // Increment step
281
+ this.currentStep++
282
+
283
+ // Check max steps
284
+ if (this.currentStep >= this.maxSteps) {
285
+ const errorMessage = 'Step count exceeded maximum limit'
286
+ this.history.push({ type: 'error', message: errorMessage })
287
+ this.emitHistoryChange()
288
+ this.setStatus('error')
289
+ const result: PageAgentExecutionResult = {
290
+ success: false,
291
+ data: errorMessage,
292
+ history: this.history as AgentHistoryEvent[],
293
+ totalSteps: this.currentStep,
294
+ duration: Date.now() - startTime,
295
+ error: errorMessage,
296
+ }
297
+ await this.config.onAfterTask?.(this, result)
298
+ return result
299
+ }
300
+
301
+ // Small delay between steps
302
+ await this.wait(400)
303
+ }
304
+ } catch (error: unknown) {
305
+ console.groupEnd()
306
+ const errorMessage = error instanceof Error ? error.message : String(error)
307
+ console.error('Task failed:', errorMessage)
308
+
309
+ this.emitActivity({ type: 'error', message: errorMessage })
310
+ this.history.push({ type: 'error', message: errorMessage })
311
+ this.emitHistoryChange()
312
+ this.setStatus('error')
313
+
314
+ const result: PageAgentExecutionResult = {
315
+ success: false,
316
+ data: errorMessage,
317
+ history: this.history as AgentHistoryEvent[],
318
+ totalSteps: this.currentStep,
319
+ duration: Date.now() - startTime,
320
+ error: errorMessage,
321
+ }
322
+ await this.config.onAfterTask?.(this, result)
323
+ return result
324
+ }
325
+ }
326
+
327
+ /**
328
+ * Observe the current browser state and gather information
329
+ */
330
+ private async observe(): Promise<void> {
331
+ // Get current browser state
332
+ const browserState = await this.controller.getBrowserState()
333
+
334
+ // Check accumulated wait time
335
+ if (this.states.totalWaitTime >= 3) {
336
+ this.pushObservation(
337
+ `You have waited ${this.states.totalWaitTime} seconds accumulatively. DO NOT wait any longer unless you have a good reason.`
338
+ )
339
+ }
340
+
341
+ // Detect URL change
342
+ if (browserState.url !== this.states.lastURL) {
343
+ this.pushObservation(`Page navigated to → ${browserState.url}`)
344
+ this.states.lastURL = browserState.url
345
+ await this.wait(500) // Wait for page to stabilize
346
+ }
347
+
348
+ // Remaining steps warning
349
+ const remaining = this.maxSteps - this.currentStep
350
+ if (remaining === 5) {
351
+ this.pushObservation(
352
+ `⚠️ Only ${remaining} steps remaining. Consider wrapping up or calling done with partial results.`
353
+ )
354
+ } else if (remaining === 2) {
355
+ this.pushObservation(
356
+ `⚠️ Critical: Only ${remaining} steps left! You must finish the task or call done immediately.`
357
+ )
358
+ }
359
+
360
+ // Push observations to history
361
+ if (this.observations.length > 0) {
362
+ for (const content of this.observations) {
363
+ this.history.push({ type: 'observation', content })
364
+ console.log('Observation:', content)
365
+ }
366
+ this.observations = []
367
+ this.emitHistoryChange()
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Push an observation to be included in the next step
373
+ */
374
+ pushObservation(content: string): void {
375
+ this.observations.push(content)
376
+ }
377
+
378
+ /**
379
+ * Build the messages for the LLM
380
+ */
381
+ private async buildMessages(): Promise<LLMMessage[]> {
382
+ const systemPrompt = this.config.customSystemPrompt || SYSTEM_PROMPT
383
+ const userPrompt = await this.buildUserPrompt()
384
+
385
+ return [
386
+ { role: 'system', content: systemPrompt },
387
+ { role: 'user', content: userPrompt },
388
+ ]
389
+ }
390
+
391
+ /**
392
+ * Build the user prompt with current state and history
393
+ */
394
+ private async buildUserPrompt(): Promise<string> {
395
+ const browserState = await this.controller.getBrowserState()
396
+ let prompt = ''
397
+
398
+ // Agent state
399
+ const stepCount = this.history.filter((e) => e.type === 'step').length
400
+
401
+ prompt += '<agent_state>\n'
402
+ prompt += '<user_request>\n'
403
+ prompt += `${this.task}\n`
404
+ prompt += '</user_request>\n'
405
+ prompt += '<step_info>\n'
406
+ prompt += `Step ${stepCount + 1} of ${this.maxSteps} max possible steps\n`
407
+ prompt += `Current time: ${new Date().toLocaleString()}\n`
408
+ prompt += '</step_info>\n'
409
+ prompt += '</agent_state>\n\n'
410
+
411
+ // History
412
+ prompt += '<agent_history>\n'
413
+
414
+ let stepIndex = 0
415
+ for (const event of this.history) {
416
+ if (event.type === 'step') {
417
+ stepIndex++
418
+ prompt += `<step_${stepIndex}>\n`
419
+ prompt += `Evaluation of Previous Step: ${event.reflection.evaluation_previous_goal}\n`
420
+ prompt += `Memory: ${event.reflection.memory}\n`
421
+ prompt += `Next Goal: ${event.reflection.next_goal}\n`
422
+ prompt += `Action Results: ${JSON.stringify(event.action.output)}\n`
423
+ prompt += `</step_${stepIndex}>\n`
424
+ } else if (event.type === 'observation') {
425
+ prompt += `<sys>${event.content}</sys>\n`
426
+ }
427
+ }
428
+
429
+ prompt += '</agent_history>\n\n'
430
+
431
+ // Browser state
432
+ prompt += '<browser_state>\n'
433
+ prompt += `URL: ${browserState.url}\n`
434
+ prompt += `Title: ${browserState.title}\n`
435
+ prompt += `Content:\n${browserState.content}\n`
436
+ prompt += '</browser_state>\n\n'
437
+
438
+ return prompt
439
+ }
440
+
441
+ /**
442
+ * Build the macro tool schema for the LLM
443
+ */
444
+ private buildMacroTool(): Record<string, unknown> {
445
+ // Build action schema from available tools
446
+ const actionProperties: Record<string, unknown> = {}
447
+
448
+ for (const tool of this.tools) {
449
+ actionProperties[tool.name] = {
450
+ type: 'object',
451
+ properties: (tool.inputSchema as { properties?: Record<string, unknown> }).properties || {},
452
+ required: (tool.inputSchema as { required?: string[] }).required || [],
453
+ description: tool.description,
454
+ }
455
+ }
456
+
457
+ // OneOf for action selection
458
+ const actionAnyOf = Object.entries(actionProperties).map(([toolName, schema]) => ({
459
+ type: 'object',
460
+ properties: {
461
+ [toolName]: schema,
462
+ },
463
+ required: [toolName],
464
+ }))
465
+
466
+ return {
467
+ AgentOutput: {
468
+ type: 'object',
469
+ properties: {
470
+ evaluation_previous_goal: {
471
+ type: 'string',
472
+ description: 'Evaluate if the previous step achieved its goal',
473
+ },
474
+ memory: {
475
+ type: 'string',
476
+ description: 'Important information to remember for future steps',
477
+ },
478
+ next_goal: {
479
+ type: 'string',
480
+ description: 'What you aim to accomplish in the next step',
481
+ },
482
+ action: {
483
+ anyOf: actionAnyOf,
484
+ description: 'The action to take - must select one tool',
485
+ },
486
+ },
487
+ required: ['action'],
488
+ },
489
+ }
490
+ }
491
+
492
+ /**
493
+ * Call the LLM with messages and tools
494
+ */
495
+ private async callLLM(
496
+ messages: LLMMessage[],
497
+ tools: Record<string, unknown>
498
+ ): Promise<string> {
499
+ const { llm } = this.config
500
+
501
+ const response = await fetch(`${llm.baseURL}/chat/completions`, {
502
+ method: 'POST',
503
+ headers: {
504
+ 'Content-Type': 'application/json',
505
+ Authorization: `Bearer ${llm.apiKey}`,
506
+ },
507
+ body: JSON.stringify({
508
+ model: llm.model,
509
+ messages,
510
+ tools: [
511
+ {
512
+ type: 'function',
513
+ function: {
514
+ name: 'AgentOutput',
515
+ description: 'You MUST call this tool every step!',
516
+ parameters: tools.AgentOutput,
517
+ },
518
+ },
519
+ ],
520
+ tool_choice: { type: 'function', function: { name: 'AgentOutput' } },
521
+ temperature: llm.temperature ?? 0.7,
522
+ }),
523
+ signal: this.abortController.signal,
524
+ })
525
+
526
+ if (!response.ok) {
527
+ throw new Error(`LLM API error: ${response.status} ${response.statusText}`)
528
+ }
529
+
530
+ const data = (await response.json()) as {
531
+ choices: Array<{
532
+ message: {
533
+ tool_calls?: Array<{
534
+ function: {
535
+ name: string
536
+ arguments: string
537
+ }
538
+ }>
539
+ }
540
+ }>
541
+ }
542
+
543
+ const toolCall = data.choices[0]?.message?.tool_calls?.[0]
544
+ if (!toolCall) {
545
+ throw new Error('No tool call in LLM response')
546
+ }
547
+
548
+ return toolCall.function.arguments
549
+ }
550
+
551
+ /**
552
+ * Parse the LLM response
553
+ */
554
+ private parseLLMResponse(response: string): MacroToolInput | null {
555
+ try {
556
+ return JSON.parse(response) as MacroToolInput
557
+ } catch {
558
+ return null
559
+ }
560
+ }
561
+
562
+ /**
563
+ * Execute a tool by name
564
+ */
565
+ private async executeTool(name: string, input: unknown): Promise<ToolOutput> {
566
+ const tool = this.tools.find((t) => t.name === name)
567
+ if (!tool) {
568
+ return { success: false, error: `Tool ${name} not found` }
569
+ }
570
+
571
+ try {
572
+ // Execute the tool with controller
573
+ const result = await tool.execute(this.controller, input)
574
+ return { success: true, data: result }
575
+ } catch (error: unknown) {
576
+ const errorMessage = error instanceof Error ? error.message : String(error)
577
+ return { success: false, error: errorMessage }
578
+ }
579
+ }
580
+
581
+ /**
582
+ * Stop the current task
583
+ */
584
+ stop(): void {
585
+ this.abortController.abort()
586
+ }
587
+
588
+ /**
589
+ * Dispose the agent
590
+ */
591
+ dispose(): void {
592
+ console.log('Disposing PageAgentService...')
593
+ this.disposed = true
594
+ this.stop()
595
+ this.config.onDispose?.(this)
596
+ this.dispatchEvent(new Event('dispose'))
597
+ }
598
+
599
+ /**
600
+ * Set status and emit event
601
+ */
602
+ private setStatus(status: AgentStatus): void {
603
+ if (this.status !== status) {
604
+ this.status = status
605
+ this.dispatchEvent(new Event('statuschange'))
606
+ }
607
+ }
608
+
609
+ /**
610
+ * Emit history change event
611
+ */
612
+ private emitHistoryChange(): void {
613
+ this.dispatchEvent(new Event('historychange'))
614
+ }
615
+
616
+ /**
617
+ * Emit activity event
618
+ */
619
+ private emitActivity(activity: AgentActivity): void {
620
+ this.dispatchEvent(new CustomEvent('activity', { detail: activity }))
621
+ }
622
+
623
+ /**
624
+ * Generate a unique ID
625
+ */
626
+ private generateId(): string {
627
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`
628
+ }
629
+
630
+ /**
631
+ * Wait for a specified time
632
+ */
633
+ private wait(ms: number): Promise<void> {
634
+ return new Promise((resolve) => setTimeout(resolve, ms))
635
+ }
636
+ }