@meetopenbot/stagehand 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +70 -9
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import { defineAgentPlugin } from "@meetopenbot/plugin-sdk";
3
3
 
4
4
  // src/agent.ts
5
5
  import { Stagehand } from "@browserbasehq/stagehand";
6
+ import { textReply as textReply2 } from "@meetopenbot/plugin-sdk";
6
7
 
7
8
  // src/config.ts
8
9
  import {
@@ -30,14 +31,70 @@ function resolveStagehandConfig(config) {
30
31
  };
31
32
  }
32
33
 
34
+ // src/stream.ts
35
+ import {
36
+ createTextReplyBuffer,
37
+ textReply
38
+ } from "@meetopenbot/plugin-sdk";
39
+ var classifyStagehandPart = (part) => {
40
+ if (part.type === "text-delta") {
41
+ const text = part.text ?? part.delta ?? "";
42
+ return text ? { type: "delta", text } : { type: "skip" };
43
+ }
44
+ if (part.type === "tool-call" && part.toolCallId) {
45
+ return {
46
+ type: "tool_call",
47
+ id: part.toolCallId,
48
+ name: part.toolName ?? "tool",
49
+ input: part.input
50
+ };
51
+ }
52
+ if ((part.type === "tool-result" || part.type === "tool-error") && part.toolCallId) {
53
+ return {
54
+ type: "tool_result",
55
+ id: part.toolCallId,
56
+ name: part.toolName,
57
+ input: part.input,
58
+ output: part.type === "tool-error" ? part.error : part.output,
59
+ error: part.type === "tool-error"
60
+ };
61
+ }
62
+ if (part.type === "step-finish" || part.type === "finish") {
63
+ return { type: "flush" };
64
+ }
65
+ return { type: "skip" };
66
+ };
67
+ async function* runStagehandStream(fullStream) {
68
+ const replies = createTextReplyBuffer({ groupId: "stagehand:tools" });
69
+ for await (const part of fullStream) {
70
+ yield* replies.apply(classifyStagehandPart(part));
71
+ }
72
+ yield* replies.end();
73
+ }
74
+ function finalStagehandReply(args) {
75
+ const items = [];
76
+ if (!args.yielded && args.message?.trim()) items.push(textReply(args.message.trim()));
77
+ if (args.output && typeof args.output === "object" && Object.keys(args.output).length > 0) {
78
+ items.push(textReply(JSON.stringify(args.output, null, 2)));
79
+ }
80
+ return items;
81
+ }
82
+
33
83
  // src/agent.ts
34
- async function runStagehandTurn({ prompt, context }) {
84
+ async function* runStagehandTurn({
85
+ prompt,
86
+ context
87
+ }) {
35
88
  const config = resolveStagehandConfig(context.config);
36
89
  if (config.requestedEnv === "BROWSERBASE" && (!config.browserbaseApiKey || !config.browserbaseProjectId)) {
37
- return "Stagehand Browserbase setup is incomplete. Set `BROWSERBASE_API_KEY` and `BROWSERBASE_PROJECT_ID` in workspace settings.";
90
+ yield textReply2(
91
+ "Stagehand Browserbase setup is incomplete. Set `BROWSERBASE_API_KEY` and `BROWSERBASE_PROJECT_ID` in workspace settings."
92
+ );
93
+ return;
38
94
  }
39
95
  if (config.requestedEnv === "LOCAL" && !config.apiKey) {
40
- return "Stagehand local setup is incomplete. Set `OPENAI_API_KEY` in workspace settings.";
96
+ yield textReply2("Stagehand local setup is incomplete. Set `OPENAI_API_KEY` in workspace settings.");
97
+ return;
41
98
  }
42
99
  let stagehand = null;
43
100
  try {
@@ -58,15 +115,19 @@ async function runStagehandTurn({ prompt, context }) {
58
115
  instruction: prompt,
59
116
  maxSteps: config.maxSteps
60
117
  });
61
- for await (const _part of streamResult.fullStream) {
118
+ let yielded = false;
119
+ for await (const item of runStagehandStream(streamResult.fullStream)) {
120
+ yielded = true;
121
+ yield item;
62
122
  }
63
123
  const result = await streamResult.result;
64
- const parts = [];
65
- if (result.message) parts.push(result.message);
66
- if (result.output && Object.keys(result.output).length > 0) {
67
- parts.push(JSON.stringify(result.output, null, 2));
124
+ for (const item of finalStagehandReply({
125
+ yielded,
126
+ message: result.message,
127
+ output: result.output
128
+ })) {
129
+ yield item;
68
130
  }
69
- return parts.join("\n\n");
70
131
  } finally {
71
132
  if (stagehand) await stagehand.close().catch(() => {
72
133
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meetopenbot/stagehand",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "type": "module",
5
5
  "description": "Stagehand AI browser automation plugin for OpenBot",
6
6
  "main": "./dist/index.js",
@@ -24,7 +24,7 @@
24
24
  "@browserbasehq/stagehand": "^3.3.0",
25
25
  "playwright": "^1.52.0",
26
26
  "zod": "^4.3.5",
27
- "@meetopenbot/plugin-sdk": "^0.3.0"
27
+ "@meetopenbot/plugin-sdk": "^0.5.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^20.10.1",