@poncho-ai/cli 0.28.1 → 0.28.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poncho-ai/cli",
3
- "version": "0.28.1",
3
+ "version": "0.28.2",
4
4
  "description": "CLI for building and deploying AI agents",
5
5
  "repository": {
6
6
  "type": "git",
package/src/index.ts CHANGED
@@ -3123,11 +3123,22 @@ export const createRequestHandler = async (options?: {
3123
3123
 
3124
3124
  const browserSession = harness.browserSession as BrowserSessionTyped | undefined;
3125
3125
 
3126
+ const resolveBrowserSession = (cid: string): BrowserSessionTyped | undefined => {
3127
+ if (browserSession?.isActiveFor(cid)) return browserSession;
3128
+ const subRun = activeSubagentRuns.get(cid);
3129
+ if (subRun) {
3130
+ const childSession = subRun.harness.browserSession as BrowserSessionTyped | undefined;
3131
+ if (childSession?.isActiveFor(cid)) return childSession;
3132
+ }
3133
+ return undefined;
3134
+ };
3135
+
3126
3136
  if (pathname === "/api/browser/status" && request.method === "GET") {
3127
3137
  const cid = requestUrl.searchParams.get("conversationId") ?? "";
3138
+ const session = cid ? resolveBrowserSession(cid) : undefined;
3128
3139
  writeJson(response, 200, {
3129
- active: cid && browserSession ? browserSession.isActiveFor(cid) : false,
3130
- url: cid && browserSession ? browserSession.getUrl(cid) ?? null : null,
3140
+ active: !!session,
3141
+ url: session ? session.getUrl(cid) ?? null : null,
3131
3142
  conversationId: cid || null,
3132
3143
  });
3133
3144
  return;
@@ -3135,7 +3146,8 @@ export const createRequestHandler = async (options?: {
3135
3146
 
3136
3147
  if (pathname === "/api/browser/stream" && request.method === "GET") {
3137
3148
  const cid = requestUrl.searchParams.get("conversationId");
3138
- if (!cid || !browserSession) {
3149
+ const streamSession = cid ? resolveBrowserSession(cid) : undefined;
3150
+ if (!cid || !streamSession) {
3139
3151
  writeJson(response, 404, { error: "No browser session available" });
3140
3152
  return;
3141
3153
  }
@@ -3180,28 +3192,28 @@ export const createRequestHandler = async (options?: {
3180
3192
  };
3181
3193
 
3182
3194
  sendSse("browser:status", {
3183
- active: browserSession.isActiveFor(cid),
3184
- url: browserSession.getUrl(cid),
3185
- interactionAllowed: browserSession.isActiveFor(cid),
3195
+ active: streamSession.isActiveFor(cid),
3196
+ url: streamSession.getUrl(cid),
3197
+ interactionAllowed: streamSession.isActiveFor(cid),
3186
3198
  });
3187
3199
 
3188
- const removeFrame = browserSession.onFrame(cid, (frame) => {
3200
+ const removeFrame = streamSession.onFrame(cid, (frame) => {
3189
3201
  frameCount++;
3190
3202
  if (frameCount <= 3 || frameCount % 50 === 0) {
3191
3203
  console.log(`[poncho][browser-sse] Frame ${frameCount}: ${frame.width}x${frame.height}, data bytes: ${frame.data?.length ?? 0}${droppedFrames > 0 ? `, dropped: ${droppedFrames}` : ""}`);
3192
3204
  }
3193
3205
  sendFrame(frame);
3194
3206
  });
3195
- const removeStatus = browserSession.onStatus(cid, (status) => {
3207
+ const removeStatus = streamSession.onStatus(cid, (status) => {
3196
3208
  sendSse("browser:status", status);
3197
3209
  });
3198
3210
 
3199
- if (browserSession.isActiveFor(cid)) {
3200
- browserSession.screenshot(cid).then((data) => {
3211
+ if (streamSession.isActiveFor(cid)) {
3212
+ streamSession.screenshot(cid).then((data) => {
3201
3213
  if (!response.destroyed) {
3202
3214
  sendFrame({ data, width: 1280, height: 720, timestamp: Date.now() });
3203
3215
  }
3204
- return browserSession.startScreencast(cid);
3216
+ return streamSession.startScreencast(cid);
3205
3217
  }).catch((err: unknown) => {
3206
3218
  console.error("[poncho][browser-sse] initial frame/screencast failed:", (err as Error)?.message ?? err);
3207
3219
  });
@@ -3220,19 +3232,20 @@ export const createRequestHandler = async (options?: {
3220
3232
  for await (const chunk of request) chunks.push(chunk as Buffer);
3221
3233
  const body = JSON.parse(Buffer.concat(chunks).toString());
3222
3234
  const cid = body.conversationId as string;
3223
- if (!cid || !browserSession || !browserSession.isActiveFor(cid)) {
3235
+ const inputSession = cid ? resolveBrowserSession(cid) : undefined;
3236
+ if (!cid || !inputSession) {
3224
3237
  writeJson(response, 404, { error: "No active browser session" });
3225
3238
  return;
3226
3239
  }
3227
3240
  try {
3228
3241
  if (body.kind === "mouse") {
3229
- await browserSession.injectMouse(cid, body.event);
3242
+ await inputSession.injectMouse(cid, body.event);
3230
3243
  } else if (body.kind === "keyboard") {
3231
- await browserSession.injectKeyboard(cid, body.event);
3244
+ await inputSession.injectKeyboard(cid, body.event);
3232
3245
  } else if (body.kind === "scroll") {
3233
- await browserSession.injectScroll(cid, body.event);
3246
+ await inputSession.injectScroll(cid, body.event);
3234
3247
  } else if (body.kind === "paste") {
3235
- await browserSession.injectPaste(cid, body.text ?? body.event?.text ?? "");
3248
+ await inputSession.injectPaste(cid, body.text ?? body.event?.text ?? "");
3236
3249
  } else {
3237
3250
  writeJson(response, 400, { error: "Unknown input kind" });
3238
3251
  return;
@@ -3249,12 +3262,13 @@ export const createRequestHandler = async (options?: {
3249
3262
  for await (const chunk of request) chunks.push(chunk as Buffer);
3250
3263
  const body = JSON.parse(Buffer.concat(chunks).toString());
3251
3264
  const cid = body.conversationId as string;
3252
- if (!cid || !browserSession || !browserSession.isActiveFor(cid)) {
3265
+ const navSession = cid ? resolveBrowserSession(cid) : undefined;
3266
+ if (!cid || !navSession) {
3253
3267
  writeJson(response, 400, { error: "No active browser session" });
3254
3268
  return;
3255
3269
  }
3256
3270
  try {
3257
- await browserSession.navigate(cid, body.action);
3271
+ await navSession.navigate(cid, body.action);
3258
3272
  writeJson(response, 200, { ok: true });
3259
3273
  } catch (err) {
3260
3274
  writeJson(response, 500, { error: (err as Error)?.message ?? "Navigation failed" });
@@ -17,6 +17,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
17
17
  activeStreamAbortController: null,
18
18
  activeStreamConversationId: null,
19
19
  activeStreamRunId: null,
20
+ _activeStreamMessages: null,
20
21
  isMessagesPinnedToBottom: true,
21
22
  confirmDeleteId: null,
22
23
  approvalRequestsInFlight: {},
@@ -1190,17 +1191,25 @@ export const getWebUiClientScript = (markedSource: string): string => `
1190
1191
 
1191
1192
  updateContextRing();
1192
1193
  var willStream = !!payload.hasActiveRun;
1193
- renderMessages(state.activeMessages, willStream, { forceScrollBottom: true });
1194
+ var hasSendMessageStream = state.activeStreamConversationId === conversationId && state._activeStreamMessages;
1195
+ if (hasSendMessageStream) {
1196
+ state.activeMessages = state._activeStreamMessages;
1197
+ renderMessages(state.activeMessages, true, { forceScrollBottom: true });
1198
+ } else {
1199
+ renderMessages(state.activeMessages, willStream, { forceScrollBottom: true });
1200
+ }
1194
1201
  if (!state.viewingSubagentId) {
1195
1202
  elements.prompt.focus();
1196
1203
  }
1197
- if (willStream) {
1204
+ if (willStream && !hasSendMessageStream) {
1198
1205
  setStreaming(true);
1199
- streamConversationEvents(conversationId, { liveOnly: true }).finally(() => {
1206
+ streamConversationEvents(conversationId, { liveOnly: false }).finally(() => {
1200
1207
  if (state.activeConversationId === conversationId) {
1201
1208
  pollUntilRunIdle(conversationId);
1202
1209
  }
1203
1210
  });
1211
+ } else if (willStream) {
1212
+ setStreaming(true);
1204
1213
  }
1205
1214
  };
1206
1215
 
@@ -2149,6 +2158,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
2149
2158
  };
2150
2159
  localMessages.push(assistantMessage);
2151
2160
  state.activeMessages = localMessages;
2161
+ state._activeStreamMessages = localMessages;
2152
2162
  renderMessages(localMessages, true, { forceScrollBottom: true });
2153
2163
  let conversationId = state.activeConversationId;
2154
2164
  let didCompact = false;
@@ -2564,6 +2574,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
2564
2574
  }
2565
2575
  if (state.activeStreamConversationId === conversationId) {
2566
2576
  state.activeStreamConversationId = null;
2577
+ state._activeStreamMessages = null;
2567
2578
  }
2568
2579
  state.activeStreamRunId = null;
2569
2580
  setStreaming(false);
@@ -3248,6 +3259,8 @@ export const getWebUiClientScript = (markedSource: string): string => `
3248
3259
  panelHiddenByUser = false;
3249
3260
  showPanel(false);
3250
3261
  frameImg.style.display = "none";
3262
+ frameImg.style.pointerEvents = "";
3263
+ frameImg.style.opacity = "";
3251
3264
  if (placeholder) {
3252
3265
  placeholder.textContent = "No active browser session";
3253
3266
  placeholder.style.display = "flex";
@@ -3369,6 +3382,8 @@ export const getWebUiClientScript = (markedSource: string): string => `
3369
3382
  if (abortController) abortController.abort();
3370
3383
  streamConversationId = cid;
3371
3384
  abortController = new AbortController();
3385
+ frameImg.style.pointerEvents = "";
3386
+ frameImg.style.opacity = "";
3372
3387
  var headers = {};
3373
3388
  if (state.csrfToken) headers["x-csrf-token"] = state.csrfToken;
3374
3389
  if (state.authToken) headers["authorization"] = "Bearer " + state.authToken;
@@ -3416,12 +3431,8 @@ export const getWebUiClientScript = (markedSource: string): string => `
3416
3431
  } else {
3417
3432
  if (abortController) { abortController.abort(); abortController = null; }
3418
3433
  streamConversationId = null;
3419
- frameImg.style.display = "none";
3420
- if (placeholder) {
3421
- placeholder.textContent = "Browser closed";
3422
- placeholder.style.display = "flex";
3423
- }
3424
- showPanel(false);
3434
+ frameImg.style.pointerEvents = "none";
3435
+ frameImg.style.opacity = "0.6";
3425
3436
  }
3426
3437
  }
3427
3438
  } catch(e) {}