@pasko70/pibo 1.9.13 → 1.10.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.
- package/README.md +183 -183
- package/context/codex-base-prompt.md +148 -148
- package/context/compute-worker.md +23 -23
- package/context/pibo-compaction-prompt.md +100 -100
- package/context/pibo-native-tooling.md +18 -18
- package/context/pibo-system-prompt.md +77 -77
- package/dist/apps/chat/agent-profiles.js +2 -2
- package/dist/apps/chat/agent-store.js +263 -250
- package/dist/apps/chat/chat-request-normalizers.js +17 -0
- package/dist/apps/chat/data/chat-data-mappers.js +2 -0
- package/dist/apps/chat/data/project-service.js +168 -168
- package/dist/apps/chat/data/read-state-service.js +18 -18
- package/dist/apps/chat/data/session-query-service.js +25 -25
- package/dist/apps/chat/data/timeline-query-service.js +19 -19
- package/dist/apps/chat/loop-api.js +181 -0
- package/dist/apps/chat/static-assets.js +854 -854
- package/dist/apps/chat/web-app.js +36 -16
- package/dist/apps/chat/workflow-manual-trigger-runtime.js +149 -46
- package/dist/apps/chat/workflow-persistence.js +255 -255
- package/dist/apps/chat-ui/assets/{dist-BZ2eTC4f.js → dist-3Sts0Afa.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BHa-kcGl.js → dist-4NlLjLs7.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-yCYNNb5d.js → dist-BA6mhAec.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-D811wJeV.js → dist-BPl-fzRB.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-Dq4GxJi3.js → dist-BPnn9e2B.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CzE6k3F3.js → dist-BpfBSMzK.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-CnVsqwSG.js → dist-Cvx5M97R.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-WyXdYl-w.js → dist-DnXWNQRm.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BNMu92bb.js → dist-hU-2oAb6.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-BCB6zezO.js → dist-r31x5Fcc.js} +1 -1
- package/dist/apps/chat-ui/assets/{dist-HqTN67dc.js → dist-uF6UXzI7.js} +1 -1
- package/dist/apps/chat-ui/assets/index-CaTGYBOS.js +173 -0
- package/dist/apps/chat-ui/assets/{index-C0x9nEcf.css → index-al8DeEjA.css} +1 -1
- package/dist/apps/chat-ui/index.html +18 -18
- package/dist/apps/chat-ui/manifest.webmanifest +25 -25
- package/dist/apps/chat-ui/sw.js +47 -47
- package/dist/apps/chat-vscode-web/assets/index-CK4SMZuu.js +41 -0
- package/dist/apps/chat-vscode-web/index.html +13 -13
- package/dist/apps/cli-ui/cliSessionsCommand.js +23 -23
- package/dist/apps/context-files-ui/index.html +11 -11
- package/dist/cli-session/localSessionSource.js +34 -12
- package/dist/cli.js +61 -44
- package/dist/compute/cli.js +54 -54
- package/dist/compute/resource-health.js +35 -2
- package/dist/core/events.js +6 -1
- package/dist/core/routed-session.js +97 -5
- package/dist/core/runtime.js +6 -1
- package/dist/core/session-router.js +27 -8
- package/dist/cron/cli.js +15 -15
- package/dist/cron/store.js +49 -49
- package/dist/data/cli.js +23 -23
- package/dist/data/event-log.js +23 -23
- package/dist/data/ingest-service.js +3 -1
- package/dist/data/message-store.js +27 -27
- package/dist/data/navigation-store.js +9 -9
- package/dist/data/observation-store.js +4 -4
- package/dist/data/payload-store.js +17 -17
- package/dist/data/schema.js +433 -433
- package/dist/data/session-store.js +4 -4
- package/dist/data/telemetry-queries.js +54 -54
- package/dist/data/telemetry.js +197 -197
- package/dist/debug/events.js +12 -12
- package/dist/debug/failures.js +6 -6
- package/dist/debug/index.js +231 -227
- package/dist/debug/messages.js +6 -6
- package/dist/debug/pty.js +124 -124
- package/dist/debug/session.js +29 -29
- package/dist/debug/tools.js +5 -5
- package/dist/debug/trace.js +42 -7
- package/dist/debug/web-snapshot-browser-scripts.js +294 -294
- package/dist/debug/web-streaming-browser-library.js +925 -925
- package/dist/debug/web-streaming-browser-scripts.js +232 -232
- package/dist/debug/web-streaming-provider-telemetry.js +4 -4
- package/dist/debug/web.js +93 -93
- package/dist/gateway/cli.js +19 -19
- package/dist/gateway/server.js +4 -2
- package/dist/gateway/web.js +2 -2
- package/dist/index.js +1 -0
- package/dist/loops/accounting.js +19 -0
- package/dist/loops/channel.js +8 -0
- package/dist/loops/cli.js +224 -0
- package/dist/loops/plugin.js +16 -0
- package/dist/loops/prompts.js +86 -0
- package/dist/loops/service.js +446 -0
- package/dist/loops/stopping.js +170 -0
- package/dist/loops/store.js +642 -0
- package/dist/loops/templates.js +232 -0
- package/dist/loops/tools.js +184 -0
- package/dist/loops/types.js +1 -0
- package/dist/mcp/config-command.js +53 -53
- package/dist/mcp/index.js +21 -21
- package/dist/mcp/registry.js +11 -11
- package/dist/pi-packages/cli.js +11 -11
- package/dist/plugins/builtin.js +8 -0
- package/dist/plugins/context-files-store.js +110 -110
- package/dist/plugins/context-files.js +4 -4
- package/dist/plugins/registry.js +23 -12
- package/dist/ralph/cli.js +18 -18
- package/dist/ralph/templates.js +140 -140
- package/dist/reliability/store.js +256 -229
- package/dist/runs/lifecycle.js +59 -0
- package/dist/runs/registry.js +47 -1
- package/dist/runs/tools.js +31 -13
- package/dist/session-ui/terminalRows.js +66 -2
- package/dist/sessions/pibo-data-store.js +16 -16
- package/dist/sessions/sqlite-store.js +53 -53
- package/dist/setup/cli.js +58 -58
- package/dist/shared/trace-async-agent-runs.js +4 -4
- package/dist/shared/trace-event-projection.js +59 -19
- package/dist/shared/trace-nodes.js +5 -0
- package/dist/shared/trace-page-merge.js +15 -0
- package/dist/shared/trace-run-notifications.js +3 -1
- package/dist/signals/projector.js +6 -2
- package/dist/tools/agent-browser-wrapper.js +80 -80
- package/dist/tools/browser-pool.js +50 -0
- package/dist/tools/browser-use-cdp.js +12 -12
- package/dist/tools/browser-use-leases.js +12 -8
- package/dist/tools/browser-use-wrapper.js +762 -762
- package/dist/tools/guides.js +596 -538
- package/dist/tools/index.js +123 -99
- package/dist/tools/registry.js +21 -3
- package/dist/tools/runtime/node-worker-source.js +205 -205
- package/dist/tools/runtime/python-worker-source.js +177 -177
- package/dist/vscode/cli.js +9 -9
- package/dist/web-annotations/cdp.js +900 -900
- package/dist/web-annotations/store.js +96 -96
- package/docs/README.md +23 -23
- package/docs/ops/install-developer-host.md +112 -112
- package/docs/ops/install-user-host.md +96 -96
- package/docs/ops/upgrade-user-to-developer-host.md +69 -69
- package/docs/ops/vscode-extension-release.md +160 -160
- package/package.json +99 -95
- package/skills/builtin/graphify/SKILL.md +52 -52
- package/skills/builtin/loop/SKILL.md +78 -0
- package/skills/builtin/pi-agent-harness/SKILL.md +319 -319
- package/skills/builtin/pi-agent-harness/agents/openai.yaml +4 -4
- package/skills/builtin/pibo-docker-system/SKILL.md +170 -170
- package/skills/builtin/pibo-spec-writing/SKILL.md +330 -330
- package/skills/builtin/prd/SKILL.md +143 -143
- package/skills/builtin/ralph-loop/SKILL.md +361 -359
- package/skills/builtin/ralph-prd-json/SKILL.md +123 -123
- package/skills/builtin/skill-creator/LICENSE.txt +201 -201
- package/skills/builtin/skill-creator/SKILL.md +513 -513
- package/skills/builtin/skill-creator/agents/analyzer.md +274 -274
- package/skills/builtin/skill-creator/agents/comparator.md +202 -202
- package/skills/builtin/skill-creator/agents/grader.md +223 -223
- package/skills/builtin/skill-creator/assets/eval_review.html +146 -146
- package/skills/builtin/skill-creator/eval-viewer/generate_review.py +471 -471
- package/skills/builtin/skill-creator/eval-viewer/viewer.html +1325 -1325
- package/skills/builtin/skill-creator/references/schemas.md +430 -430
- package/skills/builtin/skill-creator/scripts/aggregate_benchmark.py +401 -401
- package/skills/builtin/skill-creator/scripts/generate_report.py +326 -326
- package/skills/builtin/skill-creator/scripts/improve_description.py +247 -247
- package/skills/builtin/skill-creator/scripts/package_skill.py +136 -136
- package/skills/builtin/skill-creator/scripts/quick_validate.py +102 -102
- package/skills/builtin/skill-creator/scripts/run_eval.py +310 -310
- package/skills/builtin/skill-creator/scripts/run_loop.py +328 -328
- package/skills/builtin/skill-creator/scripts/utils.py +47 -47
- package/skills/builtin/web-annotations/SKILL.md +93 -93
- package/src/mcp/LICENSE.mcp-cli +21 -21
- package/dist/apps/chat-ui/assets/index-DwHJfmiF.js +0 -173
- package/dist/apps/chat-vscode-web/assets/index-BAMxIaI_.js +0 -41
- package/dist/apps/vscode-artifacts/latest.vsix +0 -0
- package/dist/apps/vscode-artifacts/pibo-vscode-ext-1.9.13.vsix +0 -0
|
@@ -34,12 +34,12 @@ export function reconcileAsyncAgentRunStatuses(nodes) {
|
|
|
34
34
|
if (!latest)
|
|
35
35
|
continue;
|
|
36
36
|
const status = stringValue(latest.snapshot.status);
|
|
37
|
-
if (status !== "completed" && status !== "cancelled" && status !== "failed")
|
|
37
|
+
if (status !== "completed" && status !== "cancelled" && status !== "failed" && status !== "timed_out")
|
|
38
38
|
continue;
|
|
39
|
-
node.status = status === "failed" ? "error" : "done";
|
|
39
|
+
node.status = status === "failed" || status === "timed_out" ? "error" : "done";
|
|
40
40
|
node.completedAt = latest.completedAt ?? node.completedAt;
|
|
41
41
|
node.output = latest.snapshot;
|
|
42
|
-
if (status === "failed")
|
|
42
|
+
if (status === "failed" || status === "timed_out")
|
|
43
43
|
node.error = stringValue(latest.snapshot.summary) ?? node.error;
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -67,7 +67,7 @@ function createAsyncAgentRunNode(parent, piboSessionId, startedAt, delegation) {
|
|
|
67
67
|
title: subagentName,
|
|
68
68
|
status: asyncAgentStatus(parent, runStatus),
|
|
69
69
|
startedAt: delegation?.startedAt ?? startedAt ?? parent.startedAt,
|
|
70
|
-
completedAt: runStatus === "completed" || runStatus === "cancelled" ? parent.completedAt : undefined,
|
|
70
|
+
completedAt: runStatus === "completed" || runStatus === "cancelled" || runStatus === "failed" || runStatus === "timed_out" ? parent.completedAt : undefined,
|
|
71
71
|
summary: `Started by ${parent.title}`,
|
|
72
72
|
input: {
|
|
73
73
|
startedBy: parent.title,
|
|
@@ -5,6 +5,13 @@ import { createRunNotificationNode, parseRunNotificationText } from "./trace-run
|
|
|
5
5
|
import { findLikelyTraceChildSession, isSubagentToolName, } from "./trace-subagent-links.js";
|
|
6
6
|
export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent, childByParent, linkedChildByToolCallId, hasPersistedTranscript, openTranscriptEventIds, sessionStatus) {
|
|
7
7
|
const payload = storedEvent.payload;
|
|
8
|
+
const confirmedUserMessage = hasPersistedTranscript ? confirmedUserMessageEchoNode(nodes, storedEvent) : undefined;
|
|
9
|
+
if (confirmedUserMessage) {
|
|
10
|
+
if (payload.type === "message_steered" && payload.activeEventId) {
|
|
11
|
+
confirmedUserMessage.parentId = messageTurnNodeId(payload.activeEventId);
|
|
12
|
+
}
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
8
15
|
if (hasPersistedTranscript &&
|
|
9
16
|
isTranscriptEchoEvent(payload) &&
|
|
10
17
|
!shouldKeepTranscriptEchoEvent(payload, openTranscriptEventIds)) {
|
|
@@ -84,8 +91,14 @@ export function applySingleEventToNodes(nodes, byId, piboSessionId, storedEvent,
|
|
|
84
91
|
return;
|
|
85
92
|
}
|
|
86
93
|
}
|
|
87
|
-
if (node.eventId
|
|
88
|
-
|
|
94
|
+
if (node.eventId) {
|
|
95
|
+
const existing = byId.get(node.id);
|
|
96
|
+
if (existing) {
|
|
97
|
+
if (node.type === "user.message" && node.parentId)
|
|
98
|
+
existing.parentId = node.parentId;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
89
102
|
attachExecutionCommandToOpenTurn(node, byId);
|
|
90
103
|
attachAsyncAgentRunNode(node, piboSessionId, storedEvent.createdAt);
|
|
91
104
|
nodes.push(node);
|
|
@@ -174,7 +187,7 @@ export function reconcileTranscriptUserMessageTimestamps(nodes, events) {
|
|
|
174
187
|
let userCursor = 0;
|
|
175
188
|
for (const storedEvent of events) {
|
|
176
189
|
const event = storedEvent.payload;
|
|
177
|
-
if (event.type !== "message_queued" || event.source !== "user")
|
|
190
|
+
if ((event.type !== "message_queued" && event.type !== "message_steered") || event.source !== "user")
|
|
178
191
|
continue;
|
|
179
192
|
const eventId = typeof event.eventId === "string" ? event.eventId : storedEvent.eventId;
|
|
180
193
|
const text = typeof event.text === "string" ? event.text : undefined;
|
|
@@ -192,12 +205,15 @@ export function reconcileTranscriptUserMessageTimestamps(nodes, events) {
|
|
|
192
205
|
}
|
|
193
206
|
}
|
|
194
207
|
export function isConfirmedUserMessageEcho(nodes, event) {
|
|
208
|
+
return Boolean(confirmedUserMessageEchoNode(nodes, event));
|
|
209
|
+
}
|
|
210
|
+
function confirmedUserMessageEchoNode(nodes, event) {
|
|
195
211
|
const payload = event.payload;
|
|
196
|
-
if (payload.type !== "message_queued" || payload.source !== "user")
|
|
197
|
-
return
|
|
212
|
+
if ((payload.type !== "message_queued" && payload.type !== "message_steered") || payload.source !== "user")
|
|
213
|
+
return undefined;
|
|
198
214
|
const eventId = typeof payload.eventId === "string" ? payload.eventId : event.eventId;
|
|
199
215
|
const text = typeof payload.text === "string" ? payload.text : undefined;
|
|
200
|
-
return nodes.
|
|
216
|
+
return flattenTraceNodes([...nodes]).find((node) => {
|
|
201
217
|
if (node.type !== "user.message" || node.source !== "transcript")
|
|
202
218
|
return false;
|
|
203
219
|
if (eventId && (node.entryId === eventId || node.stableKey === `entry:${eventId}`))
|
|
@@ -261,7 +277,8 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
261
277
|
children: [],
|
|
262
278
|
};
|
|
263
279
|
switch (event.type) {
|
|
264
|
-
case "message_queued":
|
|
280
|
+
case "message_queued":
|
|
281
|
+
case "message_steered": {
|
|
265
282
|
const notification = parseRunNotificationText(event.text);
|
|
266
283
|
if (event.source === "service" && notification) {
|
|
267
284
|
return createRunNotificationNode({
|
|
@@ -277,6 +294,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
277
294
|
}
|
|
278
295
|
return {
|
|
279
296
|
...base,
|
|
297
|
+
...(event.type === "message_steered" && event.activeEventId ? { parentId: messageTurnNodeId(event.activeEventId) } : {}),
|
|
280
298
|
type: "user.message",
|
|
281
299
|
title: "User Message",
|
|
282
300
|
status: "done",
|
|
@@ -368,10 +386,12 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
368
386
|
children: [],
|
|
369
387
|
};
|
|
370
388
|
}
|
|
371
|
-
case "subagent_session":
|
|
389
|
+
case "subagent_session": {
|
|
390
|
+
const childPiboSessionId = nonEmptyString(event.childPiboSessionId);
|
|
391
|
+
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event);
|
|
372
392
|
return {
|
|
373
393
|
...base,
|
|
374
|
-
id: event.toolCallId ? `tool:${event.toolCallId}` :
|
|
394
|
+
id: event.toolCallId ? `tool:${event.toolCallId}` : `event:subagent_session:${eventInstanceKey}`,
|
|
375
395
|
eventId,
|
|
376
396
|
toolCallId: event.toolCallId,
|
|
377
397
|
type: "agent.delegation",
|
|
@@ -379,10 +399,13 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
379
399
|
status: sessionStatus === "running" ? "running" : "done",
|
|
380
400
|
summary: event.subagentName,
|
|
381
401
|
input: { subagentName: event.subagentName, threadKey: event.threadKey },
|
|
382
|
-
linkedPiboSessionId:
|
|
383
|
-
stableKey: event.toolCallId
|
|
402
|
+
linkedPiboSessionId: childPiboSessionId,
|
|
403
|
+
stableKey: event.toolCallId
|
|
404
|
+
? `tool:${event.toolCallId}`
|
|
405
|
+
: childPiboSessionId ? `subagent:${childPiboSessionId}` : `subagent:event:${eventInstanceKey}`,
|
|
384
406
|
children: [],
|
|
385
407
|
};
|
|
408
|
+
}
|
|
386
409
|
case "execution_result":
|
|
387
410
|
if (isInternalSessionOperation(event.action))
|
|
388
411
|
return undefined;
|
|
@@ -394,21 +417,24 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
394
417
|
input: { action: event.action },
|
|
395
418
|
output: event.result,
|
|
396
419
|
};
|
|
397
|
-
case "compaction_start":
|
|
420
|
+
case "compaction_start": {
|
|
421
|
+
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event);
|
|
398
422
|
return {
|
|
399
423
|
...base,
|
|
400
|
-
id: `event:compaction:${
|
|
424
|
+
id: `event:compaction:${eventInstanceKey}`,
|
|
401
425
|
type: "execution.compaction",
|
|
402
426
|
title: "compact",
|
|
403
427
|
status: "running",
|
|
404
428
|
summary: "Compacting",
|
|
405
429
|
input: { reason: event.reason },
|
|
406
|
-
stableKey:
|
|
430
|
+
stableKey: `compaction:${eventInstanceKey}`,
|
|
407
431
|
};
|
|
408
|
-
|
|
432
|
+
}
|
|
433
|
+
case "compaction_end": {
|
|
434
|
+
const eventInstanceKey = traceEventInstanceKey(eventSequence, streamId, event);
|
|
409
435
|
return {
|
|
410
436
|
...base,
|
|
411
|
-
id: `event:compaction:end:${
|
|
437
|
+
id: `event:compaction:end:${eventInstanceKey}`,
|
|
412
438
|
type: "execution.compaction",
|
|
413
439
|
title: "compact",
|
|
414
440
|
status: event.errorMessage ? "error" : "done",
|
|
@@ -417,8 +443,9 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
417
443
|
input: { reason: event.reason },
|
|
418
444
|
output: event.result,
|
|
419
445
|
error: event.errorMessage,
|
|
420
|
-
stableKey:
|
|
446
|
+
stableKey: `compaction:${eventInstanceKey}`,
|
|
421
447
|
};
|
|
448
|
+
}
|
|
422
449
|
case "session_error":
|
|
423
450
|
return {
|
|
424
451
|
...base,
|
|
@@ -435,7 +462,7 @@ function traceNodeFromEvent(piboSessionId, event, childByParent, linkedChildByTo
|
|
|
435
462
|
}
|
|
436
463
|
}
|
|
437
464
|
function mergeAssistantDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex) {
|
|
438
|
-
if (event.text.length === 0)
|
|
465
|
+
if (typeof event.text !== "string" || event.text.length === 0)
|
|
439
466
|
return;
|
|
440
467
|
const assistantId = assistantEventNodeId(event);
|
|
441
468
|
const id = assistantId ? assistantMessageNodeId(assistantId) : `event:assistant_delta:${cryptoSafeId(event)}`;
|
|
@@ -474,7 +501,7 @@ function mergeAssistantMessageEvent(target, update) {
|
|
|
474
501
|
target.completedAt = update.completedAt ?? target.completedAt;
|
|
475
502
|
}
|
|
476
503
|
function mergeThinkingDeltaEvent(nodes, byId, event, sessionStatus, createdAt, eventSequence, streamId, streamFrameIndex) {
|
|
477
|
-
if (event.text.length === 0)
|
|
504
|
+
if (typeof event.text !== "string" || event.text.length === 0)
|
|
478
505
|
return;
|
|
479
506
|
const thinkingId = thinkingEventNodeId(event);
|
|
480
507
|
const id = thinkingId ? thinkingNodeId(thinkingId) : `event:thinking_delta:${cryptoSafeId(event)}`;
|
|
@@ -642,6 +669,7 @@ function eventTraceNodeOrder(eventSequence, type, streamId, streamFrameIndex) {
|
|
|
642
669
|
function eventNodeKind(type) {
|
|
643
670
|
switch (type) {
|
|
644
671
|
case "message_queued":
|
|
672
|
+
case "message_steered":
|
|
645
673
|
return "user.message";
|
|
646
674
|
case "message_started":
|
|
647
675
|
case "message_finished":
|
|
@@ -792,6 +820,18 @@ function parseTimestamp(value) {
|
|
|
792
820
|
const timestamp = new Date(value).getTime();
|
|
793
821
|
return Number.isFinite(timestamp) ? timestamp : undefined;
|
|
794
822
|
}
|
|
823
|
+
function traceEventInstanceKey(eventSequence, streamId, event) {
|
|
824
|
+
if (eventSequence !== undefined)
|
|
825
|
+
return `sequence:${eventSequence}`;
|
|
826
|
+
if (streamId !== undefined)
|
|
827
|
+
return `stream:${streamId}`;
|
|
828
|
+
return cryptoSafeId(event);
|
|
829
|
+
}
|
|
830
|
+
function nonEmptyString(value) {
|
|
831
|
+
if (typeof value !== "string")
|
|
832
|
+
return undefined;
|
|
833
|
+
return value.trim() || undefined;
|
|
834
|
+
}
|
|
795
835
|
function cryptoSafeId(value) {
|
|
796
836
|
return base64UrlEncode(new TextEncoder().encode(JSON.stringify(value))).slice(0, 48);
|
|
797
837
|
}
|
|
@@ -22,6 +22,11 @@ export function compareTraceNodes(left, right) {
|
|
|
22
22
|
const bySameTurnPhase = compareSameTurnPhase(left, right);
|
|
23
23
|
if (bySameTurnPhase !== 0)
|
|
24
24
|
return bySameTurnPhase;
|
|
25
|
+
if (left.orderKey?.sourceRank === right.orderKey?.sourceRank) {
|
|
26
|
+
const bySameSourceOrder = compareTraceOrder(left.orderKey, right.orderKey);
|
|
27
|
+
if (bySameSourceOrder !== 0)
|
|
28
|
+
return bySameSourceOrder;
|
|
29
|
+
}
|
|
25
30
|
const byStartTime = compareOptionalIsoTime(left.startedAt, right.startedAt);
|
|
26
31
|
if (byStartTime !== 0)
|
|
27
32
|
return byStartTime;
|
|
@@ -23,6 +23,21 @@ export function mergeOlderTracePage(current, older) {
|
|
|
23
23
|
eventLimit: (current.eventLimit ?? 0) + (older.eventLimit ?? older.pageSize ?? 0),
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
export function mergeRefreshedTracePage(current, refreshed) {
|
|
27
|
+
if (current.piboSessionId !== refreshed.piboSessionId)
|
|
28
|
+
return refreshed;
|
|
29
|
+
return {
|
|
30
|
+
...refreshed,
|
|
31
|
+
nodes: mergeTraceNodes(current.nodes, refreshed.nodes),
|
|
32
|
+
rawEvents: current.rawEvents.length ? current.rawEvents : refreshed.rawEvents,
|
|
33
|
+
beforeCursor: current.beforeCursor,
|
|
34
|
+
firstEventSequence: current.firstEventSequence ?? refreshed.firstEventSequence,
|
|
35
|
+
nextBeforeSequence: current.nextBeforeSequence,
|
|
36
|
+
nextBeforeCursor: current.nextBeforeCursor,
|
|
37
|
+
hasOlderEvents: current.hasOlderEvents,
|
|
38
|
+
eventLimit: current.eventLimit ?? refreshed.eventLimit,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
26
41
|
function mergeTraceNodes(olderNodes, currentNodes) {
|
|
27
42
|
const byId = new Map();
|
|
28
43
|
for (const node of flattenTraceNodes([...olderNodes])) {
|
|
@@ -19,7 +19,7 @@ export function parseRunNotificationText(text) {
|
|
|
19
19
|
export function createRunNotificationNode(input) {
|
|
20
20
|
const runs = runNotificationRuns(input.notification);
|
|
21
21
|
const singleRun = runs.length === 1 ? runs[0] : undefined;
|
|
22
|
-
const failedCount = countRunGroup(input.notification.failed);
|
|
22
|
+
const failedCount = countRunGroup(input.notification.failed) + countRunGroup(input.notification.timedOut);
|
|
23
23
|
const runningCount = countRunGroup(input.notification.running);
|
|
24
24
|
return {
|
|
25
25
|
id: input.id,
|
|
@@ -43,6 +43,7 @@ function runNotificationRuns(notification) {
|
|
|
43
43
|
return [
|
|
44
44
|
...runGroup(notification.completed),
|
|
45
45
|
...runGroup(notification.failed),
|
|
46
|
+
...runGroup(notification.timedOut),
|
|
46
47
|
...runGroup(notification.cancelled),
|
|
47
48
|
...runGroup(notification.running),
|
|
48
49
|
];
|
|
@@ -57,6 +58,7 @@ function runNotificationSummary(notification) {
|
|
|
57
58
|
const parts = [
|
|
58
59
|
[countRunGroup(notification.completed), "completed"],
|
|
59
60
|
[countRunGroup(notification.failed), "failed"],
|
|
61
|
+
[countRunGroup(notification.timedOut), "timed out"],
|
|
60
62
|
[countRunGroup(notification.cancelled), "cancelled"],
|
|
61
63
|
[countRunGroup(notification.running), "running"],
|
|
62
64
|
]
|
|
@@ -12,7 +12,7 @@ function node(input, context) {
|
|
|
12
12
|
function runStatus(status) {
|
|
13
13
|
if (status === "completed")
|
|
14
14
|
return "done";
|
|
15
|
-
if (status === "failed")
|
|
15
|
+
if (status === "failed" || status === "timed_out")
|
|
16
16
|
return "error";
|
|
17
17
|
return status;
|
|
18
18
|
}
|
|
@@ -133,6 +133,10 @@ export const outputSignalProducer = {
|
|
|
133
133
|
mutations.push({ type: "set_session_queue", piboSessionId, queuedMessages: event.queuedMessages });
|
|
134
134
|
mutations.push({ type: "upsert_node", node: node({ id: `message:${piboSessionId}:${event.eventId ?? context.now()}`, kind: "message", status: "queued", piboSessionId, metadata: { source: event.source } }, context) });
|
|
135
135
|
}
|
|
136
|
+
if (event.type === "message_steered") {
|
|
137
|
+
mutations.push({ type: "patch_node", nodeId: `session:${piboSessionId}`, patch: { status: "running" } });
|
|
138
|
+
mutations.push({ type: "upsert_node", node: node({ id: `message:${piboSessionId}:${event.eventId ?? context.now()}`, kind: "message", status: "done", piboSessionId, parentNodeId: event.activeEventId ? `turn:${piboSessionId}:${event.activeEventId}` : undefined, completedAt: context.now(), metadata: { source: event.source, delivery: "steer" } }, context) });
|
|
139
|
+
}
|
|
136
140
|
if (event.type === "message_started") {
|
|
137
141
|
mutations.push({ type: "patch_node", nodeId: `session:${piboSessionId}`, patch: { status: "running" } });
|
|
138
142
|
if (event.eventId) {
|
|
@@ -200,7 +204,7 @@ export const runSignalProducer = {
|
|
|
200
204
|
if (data.type !== "run_changed")
|
|
201
205
|
return [];
|
|
202
206
|
const run = data.run;
|
|
203
|
-
return [{ type: "upsert_node", node: node({ id: `run:${run.runId}`, kind: "yielded_run", status: runStatus(run.status), piboSessionId: run.controllerPiboSessionId, startedAt: run.createdAt, completedAt: run.completedAt, error: run.status === "failed" ? { message: run.summary ?? "Run failed.", source: "run" } : undefined, metadata: { runId: run.runId, toolName: run.toolName, completionPolicy: run.completionPolicy, consumed: run.consumed, summary: run.summary, previousStatus: data.previousStatus, reason: data.reason } }, context) }];
|
|
207
|
+
return [{ type: "upsert_node", node: node({ id: `run:${run.runId}`, kind: "yielded_run", status: runStatus(run.status), piboSessionId: run.controllerPiboSessionId, startedAt: run.createdAt, completedAt: run.completedAt, error: run.status === "failed" || run.status === "timed_out" ? { message: run.summary ?? "Run failed.", source: "run" } : undefined, metadata: { runId: run.runId, toolName: run.toolName, completionPolicy: run.completionPolicy, consumed: run.consumed, summary: run.summary, timeoutMs: run.timeoutMs, timeoutAt: run.timeoutAt, timeoutPhase: run.timeoutPhase, serviceWarning: run.serviceWarning, previousStatus: data.previousStatus, reason: data.reason } }, context) }];
|
|
204
208
|
},
|
|
205
209
|
};
|
|
206
210
|
export function createDefaultSignalProducers() {
|
|
@@ -6,86 +6,86 @@ function shellQuote(value) {
|
|
|
6
6
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
7
7
|
}
|
|
8
8
|
function createAgentBrowserWrapper(realExecutablePath, defaultHomeDir) {
|
|
9
|
-
return `#!/usr/bin/env bash
|
|
10
|
-
set -euo pipefail
|
|
11
|
-
|
|
12
|
-
real_agent_browser=${shellQuote(realExecutablePath)}
|
|
13
|
-
default_home=${shellQuote(defaultHomeDir)}
|
|
14
|
-
fresh_flag=${shellQuote(AGENT_BROWSER_FRESH_PROFILE_FLAG)}
|
|
15
|
-
|
|
16
|
-
if [ -z "\${AGENT_BROWSER_HOME:-}" ]; then
|
|
17
|
-
export AGENT_BROWSER_HOME="$default_home"
|
|
18
|
-
fi
|
|
19
|
-
mkdir -p "$AGENT_BROWSER_HOME" "$AGENT_BROWSER_HOME/profiles"
|
|
20
|
-
|
|
21
|
-
# agent-browser@0.27.0 uses HOME for ~/.agent-browser state. Redirect it by
|
|
22
|
-
# default so doctor, config, sockets, and auth vault files stay inside Pibo's
|
|
23
|
-
# tool home. Operators can opt out for upstream debugging.
|
|
24
|
-
if [ "\${PIBO_AGENT_BROWSER_PRESERVE_HOME:-0}" != "1" ]; then
|
|
25
|
-
export HOME="$AGENT_BROWSER_HOME"
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
explicit_runtime=0
|
|
29
|
-
fresh_profile=0
|
|
30
|
-
show_help=0
|
|
31
|
-
starts_browser=0
|
|
32
|
-
args=()
|
|
33
|
-
|
|
34
|
-
print_wrapper_help() {
|
|
35
|
-
cat <<'HELP'
|
|
36
|
-
Pibo agent-browser wrapper
|
|
37
|
-
- keeps Agent Browser state under AGENT_BROWSER_HOME by default
|
|
38
|
-
- prepends a persistent Pibo profile for browser-launching commands
|
|
39
|
-
- pass --fresh-profile to disable Pibo profile injection
|
|
40
|
-
- explicit --profile, --state, --cdp, --auto-connect, --provider, --engine,
|
|
41
|
-
--executable-path, or --config flags override Pibo defaults
|
|
42
|
-
HELP
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
while [ "$#" -gt 0 ]; do
|
|
46
|
-
case "$1" in
|
|
47
|
-
--help|-h)
|
|
48
|
-
show_help=1
|
|
49
|
-
args+=("$1")
|
|
50
|
-
;;
|
|
51
|
-
--fresh-profile)
|
|
52
|
-
fresh_profile=1
|
|
53
|
-
;;
|
|
54
|
-
--profile|--state|--cdp|--auto-connect|--provider|--engine|--executable-path|--config)
|
|
55
|
-
explicit_runtime=1
|
|
56
|
-
args+=("$1")
|
|
57
|
-
if [ "$#" -gt 1 ]; then
|
|
58
|
-
shift
|
|
59
|
-
args+=("$1")
|
|
60
|
-
fi
|
|
61
|
-
;;
|
|
62
|
-
--profile=*|--state=*|--cdp=*|--auto-connect=*|--provider=*|--engine=*|--executable-path=*|--config=*)
|
|
63
|
-
explicit_runtime=1
|
|
64
|
-
args+=("$1")
|
|
65
|
-
;;
|
|
66
|
-
open|launch|new|goto)
|
|
67
|
-
starts_browser=1
|
|
68
|
-
args+=("$1")
|
|
69
|
-
;;
|
|
70
|
-
*)
|
|
71
|
-
args+=("$1")
|
|
72
|
-
;;
|
|
73
|
-
esac
|
|
74
|
-
shift
|
|
75
|
-
done
|
|
76
|
-
|
|
77
|
-
if [ "$show_help" -eq 1 ]; then
|
|
78
|
-
print_wrapper_help
|
|
79
|
-
exec "$real_agent_browser" "\${args[@]}"
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
if [ "$starts_browser" -eq 1 ] && [ "$fresh_profile" -eq 0 ] && [ "$explicit_runtime" -eq 0 ]; then
|
|
83
|
-
profile_dir=\${AGENT_BROWSER_PROFILE:-$AGENT_BROWSER_HOME/profiles/${AGENT_BROWSER_DEFAULT_PROFILE}}
|
|
84
|
-
mkdir -p "$profile_dir"
|
|
85
|
-
exec "$real_agent_browser" --profile "$profile_dir" "\${args[@]}"
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
exec "$real_agent_browser" "\${args[@]}"
|
|
9
|
+
return `#!/usr/bin/env bash
|
|
10
|
+
set -euo pipefail
|
|
11
|
+
|
|
12
|
+
real_agent_browser=${shellQuote(realExecutablePath)}
|
|
13
|
+
default_home=${shellQuote(defaultHomeDir)}
|
|
14
|
+
fresh_flag=${shellQuote(AGENT_BROWSER_FRESH_PROFILE_FLAG)}
|
|
15
|
+
|
|
16
|
+
if [ -z "\${AGENT_BROWSER_HOME:-}" ]; then
|
|
17
|
+
export AGENT_BROWSER_HOME="$default_home"
|
|
18
|
+
fi
|
|
19
|
+
mkdir -p "$AGENT_BROWSER_HOME" "$AGENT_BROWSER_HOME/profiles"
|
|
20
|
+
|
|
21
|
+
# agent-browser@0.27.0 uses HOME for ~/.agent-browser state. Redirect it by
|
|
22
|
+
# default so doctor, config, sockets, and auth vault files stay inside Pibo's
|
|
23
|
+
# tool home. Operators can opt out for upstream debugging.
|
|
24
|
+
if [ "\${PIBO_AGENT_BROWSER_PRESERVE_HOME:-0}" != "1" ]; then
|
|
25
|
+
export HOME="$AGENT_BROWSER_HOME"
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
explicit_runtime=0
|
|
29
|
+
fresh_profile=0
|
|
30
|
+
show_help=0
|
|
31
|
+
starts_browser=0
|
|
32
|
+
args=()
|
|
33
|
+
|
|
34
|
+
print_wrapper_help() {
|
|
35
|
+
cat <<'HELP'
|
|
36
|
+
Pibo agent-browser wrapper
|
|
37
|
+
- keeps Agent Browser state under AGENT_BROWSER_HOME by default
|
|
38
|
+
- prepends a persistent Pibo profile for browser-launching commands
|
|
39
|
+
- pass --fresh-profile to disable Pibo profile injection
|
|
40
|
+
- explicit --profile, --state, --cdp, --auto-connect, --provider, --engine,
|
|
41
|
+
--executable-path, or --config flags override Pibo defaults
|
|
42
|
+
HELP
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
while [ "$#" -gt 0 ]; do
|
|
46
|
+
case "$1" in
|
|
47
|
+
--help|-h)
|
|
48
|
+
show_help=1
|
|
49
|
+
args+=("$1")
|
|
50
|
+
;;
|
|
51
|
+
--fresh-profile)
|
|
52
|
+
fresh_profile=1
|
|
53
|
+
;;
|
|
54
|
+
--profile|--state|--cdp|--auto-connect|--provider|--engine|--executable-path|--config)
|
|
55
|
+
explicit_runtime=1
|
|
56
|
+
args+=("$1")
|
|
57
|
+
if [ "$#" -gt 1 ]; then
|
|
58
|
+
shift
|
|
59
|
+
args+=("$1")
|
|
60
|
+
fi
|
|
61
|
+
;;
|
|
62
|
+
--profile=*|--state=*|--cdp=*|--auto-connect=*|--provider=*|--engine=*|--executable-path=*|--config=*)
|
|
63
|
+
explicit_runtime=1
|
|
64
|
+
args+=("$1")
|
|
65
|
+
;;
|
|
66
|
+
open|launch|new|goto)
|
|
67
|
+
starts_browser=1
|
|
68
|
+
args+=("$1")
|
|
69
|
+
;;
|
|
70
|
+
*)
|
|
71
|
+
args+=("$1")
|
|
72
|
+
;;
|
|
73
|
+
esac
|
|
74
|
+
shift
|
|
75
|
+
done
|
|
76
|
+
|
|
77
|
+
if [ "$show_help" -eq 1 ]; then
|
|
78
|
+
print_wrapper_help
|
|
79
|
+
exec "$real_agent_browser" "\${args[@]}"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
if [ "$starts_browser" -eq 1 ] && [ "$fresh_profile" -eq 0 ] && [ "$explicit_runtime" -eq 0 ]; then
|
|
83
|
+
profile_dir=\${AGENT_BROWSER_PROFILE:-$AGENT_BROWSER_HOME/profiles/${AGENT_BROWSER_DEFAULT_PROFILE}}
|
|
84
|
+
mkdir -p "$profile_dir"
|
|
85
|
+
exec "$real_agent_browser" --profile "$profile_dir" "\${args[@]}"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
exec "$real_agent_browser" "\${args[@]}"
|
|
89
89
|
`;
|
|
90
90
|
}
|
|
91
91
|
export function ensureAgentBrowserWrapper(status) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { access, mkdir, open, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
4
5
|
const DEFAULT_MAX_BROWSER_PROCESSES = 1;
|
|
5
6
|
const DEFAULT_LOCK_TIMEOUT_MS = 5_000;
|
|
6
7
|
const DEFAULT_LOCK_POLL_INTERVAL_MS = 50;
|
|
@@ -239,6 +240,55 @@ export async function acquireBrowserPoolLease(paths, identity, options = {}) {
|
|
|
239
240
|
}
|
|
240
241
|
}, options.lockOptions);
|
|
241
242
|
}
|
|
243
|
+
export async function restartRecordedBrowserPoolChrome(state) {
|
|
244
|
+
if (!state.userDataDir)
|
|
245
|
+
throw new Error("Browser pool has no persisted user-data directory for reacquisition");
|
|
246
|
+
if (!state.cdpPort)
|
|
247
|
+
throw new Error("Browser pool has no persisted CDP port for reacquisition");
|
|
248
|
+
const candidates = [process.env.PIBO_CHROME_BIN, "/usr/bin/google-chrome", "/usr/bin/chromium", "/usr/bin/chromium-browser", "/opt/google/chrome/chrome"].filter((value) => !!value);
|
|
249
|
+
let executable;
|
|
250
|
+
for (const candidate of candidates) {
|
|
251
|
+
try {
|
|
252
|
+
await access(candidate);
|
|
253
|
+
executable = candidate;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
catch { /* try next */ }
|
|
257
|
+
}
|
|
258
|
+
if (!executable)
|
|
259
|
+
throw new Error("No supported Chrome/Chromium executable is available to reacquire the persisted browser profile");
|
|
260
|
+
await removeDefaultStaleBrowserFiles(state);
|
|
261
|
+
const cdpUrl = `http://127.0.0.1:${state.cdpPort}`;
|
|
262
|
+
const child = spawn(executable, [
|
|
263
|
+
`--remote-debugging-port=${state.cdpPort}`,
|
|
264
|
+
"--remote-debugging-address=127.0.0.1",
|
|
265
|
+
`--user-data-dir=${state.userDataDir}`,
|
|
266
|
+
`--profile-directory=${process.env.PIBO_BROWSER_USE_DEFAULT_PROFILE || "PIBo"}`,
|
|
267
|
+
"--headless=new",
|
|
268
|
+
"--no-sandbox",
|
|
269
|
+
"--disable-gpu",
|
|
270
|
+
"--disable-dev-shm-usage",
|
|
271
|
+
"about:blank",
|
|
272
|
+
], { detached: true, stdio: "ignore" });
|
|
273
|
+
await new Promise((resolve, reject) => {
|
|
274
|
+
child.once("spawn", resolve);
|
|
275
|
+
child.once("error", reject);
|
|
276
|
+
});
|
|
277
|
+
child.unref();
|
|
278
|
+
if (!child.pid)
|
|
279
|
+
throw new Error("Chrome reacquisition did not return a process id");
|
|
280
|
+
for (let attempt = 0; attempt < 100; attempt += 1) {
|
|
281
|
+
const health = await checkBrowserPoolCdpHealth(cdpUrl, { timeoutMs: 250 });
|
|
282
|
+
if (health.ok)
|
|
283
|
+
return { pid: child.pid, processGroupId: child.pid, cdpPort: state.cdpPort, cdpUrl, userDataDir: state.userDataDir };
|
|
284
|
+
await delay(100);
|
|
285
|
+
}
|
|
286
|
+
try {
|
|
287
|
+
process.kill(-child.pid, "SIGKILL");
|
|
288
|
+
}
|
|
289
|
+
catch { /* already exited */ }
|
|
290
|
+
throw new Error(`Reacquired Chrome did not expose CDP at ${cdpUrl}`);
|
|
291
|
+
}
|
|
242
292
|
export async function releaseBrowserPoolLease(paths, identity, options = {}) {
|
|
243
293
|
const now = options.now ?? (() => new Date());
|
|
244
294
|
const isPidAlive = options.isPidAlive ?? defaultIsPidAlive;
|
|
@@ -47,18 +47,18 @@ async function discoverCdpUrl() {
|
|
|
47
47
|
}
|
|
48
48
|
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
49
49
|
import { join } from 'node:path';
|
|
50
|
-
const CHAT_TARGET_PROBE = `(() => {
|
|
51
|
-
const text = String(document.body?.innerText || "");
|
|
52
|
-
const textareas = [...document.querySelectorAll("textarea")].map((textarea) => ({
|
|
53
|
-
placeholder: textarea.placeholder || "",
|
|
54
|
-
disabled: Boolean(textarea.disabled),
|
|
55
|
-
value: textarea.value || "",
|
|
56
|
-
}));
|
|
57
|
-
return {
|
|
58
|
-
title: document.title || "",
|
|
59
|
-
text: text.slice(0, 3000),
|
|
60
|
-
textareas,
|
|
61
|
-
};
|
|
50
|
+
const CHAT_TARGET_PROBE = `(() => {
|
|
51
|
+
const text = String(document.body?.innerText || "");
|
|
52
|
+
const textareas = [...document.querySelectorAll("textarea")].map((textarea) => ({
|
|
53
|
+
placeholder: textarea.placeholder || "",
|
|
54
|
+
disabled: Boolean(textarea.disabled),
|
|
55
|
+
value: textarea.value || "",
|
|
56
|
+
}));
|
|
57
|
+
return {
|
|
58
|
+
title: document.title || "",
|
|
59
|
+
text: text.slice(0, 3000),
|
|
60
|
+
textareas,
|
|
61
|
+
};
|
|
62
62
|
})()`;
|
|
63
63
|
export async function listBrowserUseCdpTargets(options = {}) {
|
|
64
64
|
const cdpUrl = await normalizeCdpUrl(options.cdpUrl);
|
|
@@ -365,21 +365,19 @@ export async function acquireBrowserUseLease(context, options = {}) {
|
|
|
365
365
|
}
|
|
366
366
|
await writeRegistry(context.status, registry);
|
|
367
367
|
if (reapedCount > 0 && !options.json) {
|
|
368
|
-
console.
|
|
368
|
+
console.error(`Reaped ${reapedCount} stale lease${reapedCount === 1 ? '' : 's'}`);
|
|
369
369
|
}
|
|
370
370
|
if (options.json)
|
|
371
371
|
printLeaseJson(context.status, lease);
|
|
372
372
|
else
|
|
373
373
|
printLeaseEnv(context.status, lease);
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
console.log(`Warning: Browser warm-up failed: ${warmup.error}`);
|
|
378
|
-
}
|
|
374
|
+
const warmup = await warmupBrowserUseLease(context, lease, 15000, options.headed);
|
|
375
|
+
if (!warmup.success && !options.json) {
|
|
376
|
+
console.error(`Warning: Browser warm-up failed: ${warmup.error?.trim() || 'unknown error'}`);
|
|
379
377
|
}
|
|
380
378
|
});
|
|
381
379
|
}
|
|
382
|
-
async function warmupBrowserUseLease(context, lease, timeoutMs = 15000) {
|
|
380
|
+
async function warmupBrowserUseLease(context, lease, timeoutMs = 15000, headed = false) {
|
|
383
381
|
const wrapperPath = join(context.status.homeDir, 'bin', 'browser-use');
|
|
384
382
|
if (!existsSync(wrapperPath)) {
|
|
385
383
|
return { success: false, error: 'browser-use wrapper not found' };
|
|
@@ -393,7 +391,13 @@ async function warmupBrowserUseLease(context, lease, timeoutMs = 15000) {
|
|
|
393
391
|
...(lease.browserPoolLeaseId ? { PIBO_BROWSER_POOL_LEASE_ID: lease.browserPoolLeaseId } : {}),
|
|
394
392
|
};
|
|
395
393
|
return new Promise((resolve) => {
|
|
396
|
-
const
|
|
394
|
+
const args = [
|
|
395
|
+
...(headed ? ['--headed'] : []),
|
|
396
|
+
'--session',
|
|
397
|
+
lease.sessionName,
|
|
398
|
+
'--pibo-ensure-chrome',
|
|
399
|
+
];
|
|
400
|
+
const child = spawn(wrapperPath, args, {
|
|
397
401
|
env,
|
|
398
402
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
399
403
|
});
|