openmausbot 0.1.95 → 0.1.96

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 (140) hide show
  1. package/dist/assets/{DesktopViewer-BwWpc4RK.js → DesktopViewer-DsnA23KM.js} +1 -1
  2. package/dist/assets/{abnfDiagram-O67JEVCF-jsQkIqTn.js → abnfDiagram-O67JEVCF-Dkbd2hcj.js} +1 -1
  3. package/dist/assets/{arc-7kei4Hsu.js → arc-Duj5Coy2.js} +1 -1
  4. package/dist/assets/{architectureDiagram-NJMV4G6O-CRWDFDMq.js → architectureDiagram-NJMV4G6O-uYUsDawP.js} +1 -1
  5. package/dist/assets/{blockDiagram-BEXU5L5S-CTKW_IKs.js → blockDiagram-BEXU5L5S-CWDlTpXe.js} +1 -1
  6. package/dist/assets/{c4Diagram-YGBWAQC7-BBTW7-6M.js → c4Diagram-YGBWAQC7-B0t15PDc.js} +1 -1
  7. package/dist/assets/channel-BZxwC-Gw.js +1 -0
  8. package/dist/assets/{chunk-2Q5K7J3B-M_Ox-MkD.js → chunk-2Q5K7J3B-BJSCL-HV.js} +1 -1
  9. package/dist/assets/{chunk-3FUC2YCW-D2YiN-Ud.js → chunk-3FUC2YCW-D3_ILccd.js} +2 -2
  10. package/dist/assets/{chunk-5VM5RSS4-BmVYJ0f8.js → chunk-5VM5RSS4-D3dmwT_S.js} +1 -1
  11. package/dist/assets/{chunk-GTNCS2PH-BtiLVVnZ.js → chunk-GTNCS2PH-Br73HFPD.js} +1 -1
  12. package/dist/assets/{chunk-GWA4HPMP-DFYSb6J6.js → chunk-GWA4HPMP-uSsjxubC.js} +1 -1
  13. package/dist/assets/{chunk-JWPE2WC7-mknKBzgV.js → chunk-JWPE2WC7-C40VWFyr.js} +1 -1
  14. package/dist/assets/{chunk-NETBCI7D-DgSYGiOu.js → chunk-NETBCI7D-D6WNNYwU.js} +1 -1
  15. package/dist/assets/{chunk-WEXAMYUT-C7ZvuguH.js → chunk-WEXAMYUT-DOEhq64P.js} +1 -1
  16. package/dist/assets/{chunk-XXDRQBXY-CPqxINpA.js → chunk-XXDRQBXY-BqJEi6Pi.js} +1 -1
  17. package/dist/assets/{classDiagram-v2-NBCMYWYE-Cd6xfJaC.js → classDiagram-v2-NBCMYWYE-ByU_GnxT.js} +1 -1
  18. package/dist/assets/{cose-bilkent-JH36ORCC-BSXY5qRh.js → cose-bilkent-JH36ORCC-D-Uglxqq.js} +1 -1
  19. package/dist/assets/{cynefin-OW5HDTMX-D_lhEMj1.js → cynefin-OW5HDTMX-CZWO7aYj.js} +1 -1
  20. package/dist/assets/{cynefinDiagram-VND7K2PF-Da9FrFwk.js → cynefinDiagram-VND7K2PF-C70-w0la.js} +1 -1
  21. package/dist/assets/{dagre-6A5THRUB-T77jMOXe.js → dagre-6A5THRUB-CnhjhExB.js} +1 -1
  22. package/dist/assets/{diagram-22UHCM2B-Dkj96X5E.js → diagram-22UHCM2B-bnjWCNb4.js} +1 -1
  23. package/dist/assets/{diagram-3UASUU5V-CMi9zlD_.js → diagram-3UASUU5V-A4uTWoFV.js} +1 -1
  24. package/dist/assets/{diagram-ATOU4E4O-CXK6YUfS.js → diagram-ATOU4E4O-Zi6m3NUl.js} +1 -1
  25. package/dist/assets/{diagram-CDSNMT55-BE7B1u9Q.js → diagram-CDSNMT55-DtCcmd5k.js} +1 -1
  26. package/dist/assets/{diagram-MLGK6HIB-CCMQphKr.js → diagram-MLGK6HIB-DofuETS3.js} +1 -1
  27. package/dist/assets/{diagram-MPIPVDR6-iHJ_-tGH.js → diagram-MPIPVDR6-Dw2T9PuU.js} +1 -1
  28. package/dist/assets/{ebnfDiagram-ZINNZB2B-DONsCWQ7.js → ebnfDiagram-ZINNZB2B-DbrwPiem.js} +1 -1
  29. package/dist/assets/{elk-276RUBZZ-CU_WOaXk.js → elk-276RUBZZ-BvCt1dCb.js} +1 -1
  30. package/dist/assets/{erDiagram-OPXOYQCR-BeYwM04G.js → erDiagram-OPXOYQCR-Y-QKqPnU.js} +1 -1
  31. package/dist/assets/{flowDiagram-KWPJA3E3-Bdw9DqEl.js → flowDiagram-KWPJA3E3-CDkL1B5w.js} +1 -1
  32. package/dist/assets/{ganttDiagram-FUAMR5RP-C9iwq3qm.js → ganttDiagram-FUAMR5RP-CKV5D2F6.js} +1 -1
  33. package/dist/assets/{gitGraphDiagram-X574FWY7-Dx-VWzUg.js → gitGraphDiagram-X574FWY7-nL9iFTCv.js} +1 -1
  34. package/dist/assets/{index-KygHRE3E.js → index-DreDnjOu.js} +1 -1
  35. package/dist/assets/index-Du7o6Dsf.js +610 -0
  36. package/dist/assets/index-KxG4bWSr.css +1 -0
  37. package/dist/assets/{infoDiagram-VRGFBTTK-BG7uaEd4.js → infoDiagram-VRGFBTTK-C7aHjzsf.js} +1 -1
  38. package/dist/assets/{ishikawaDiagram-OU5B5YK6-D72WAXnM.js → ishikawaDiagram-OU5B5YK6-KUZsNBTh.js} +1 -1
  39. package/dist/assets/{journeyDiagram-ZHPQQLJL-DKH1gjYT.js → journeyDiagram-ZHPQQLJL-CGUuodFl.js} +1 -1
  40. package/dist/assets/{kanban-definition-PNTS6WVX-3upm9JUT.js → kanban-definition-PNTS6WVX-Cy6r868Z.js} +1 -1
  41. package/dist/assets/{linear-CcR4pc0-.js → linear-Bl669148.js} +1 -1
  42. package/dist/assets/{mermaid.core-C6yU5FSS.js → mermaid.core-86Xqz5Mr.js} +5 -5
  43. package/dist/assets/{mindmap-definition-NLK3R4M7-DOI2xEuv.js → mindmap-definition-NLK3R4M7-G4DzHLrd.js} +1 -1
  44. package/dist/assets/{pegDiagram-GJSIUBJH-BVWJSgLd.js → pegDiagram-GJSIUBJH-K4eruzY0.js} +1 -1
  45. package/dist/assets/{pieDiagram-5QR66LMP-jtbYezhq.js → pieDiagram-5QR66LMP-DYdR9PPq.js} +1 -1
  46. package/dist/assets/{quadrantDiagram-O4NWA36T-g0u8mtPX.js → quadrantDiagram-O4NWA36T-BCAh0nEy.js} +1 -1
  47. package/dist/assets/{railroadDiagram-XR7U4H2S-k8689Wny.js → railroadDiagram-XR7U4H2S-p0dGRc4g.js} +1 -1
  48. package/dist/assets/{requirementDiagram-PLB6GJNP-DsJ22PDt.js → requirementDiagram-PLB6GJNP-tLeBG0aL.js} +1 -1
  49. package/dist/assets/{sankeyDiagram-IPEJSGJF-CneWBRgG.js → sankeyDiagram-IPEJSGJF-QRuN16rV.js} +1 -1
  50. package/dist/assets/{sequenceDiagram-PO4LG4MO-DWsFCWap.js → sequenceDiagram-PO4LG4MO-ueT1nVoa.js} +1 -1
  51. package/dist/assets/{sizeCapture-INFHLROL-Bvf0YE3S.js → sizeCapture-INFHLROL-wRS2zWg2.js} +1 -1
  52. package/dist/assets/{stateDiagram-v2-GCMORJYK-Bxb3Iei8.js → stateDiagram-v2-GCMORJYK-CYzA_hE1.js} +1 -1
  53. package/dist/assets/{swimlanes-2SLR337P-DLkk7W4A.js → swimlanes-2SLR337P-kDnv6LMc.js} +1 -1
  54. package/dist/assets/swimlanesDiagram-TC7HE7FX-C7voMDle.js +8 -0
  55. package/dist/assets/{timeline-definition-EJHVYXUP-KR9bIHYC.js → timeline-definition-EJHVYXUP-D1y2UbbH.js} +1 -1
  56. package/dist/assets/{usecaseDiagram-POWQR4AR-DfsOrj8t.js → usecaseDiagram-POWQR4AR-IqB4v9HX.js} +1 -1
  57. package/dist/assets/{vennDiagram-UO4OBE2U-DRSTzG3h.js → vennDiagram-UO4OBE2U-BEi7KYVF.js} +1 -1
  58. package/dist/assets/{wardleyDiagram-VNRHLVJA-DtEdhPgT.js → wardleyDiagram-VNRHLVJA-Dkybo-Yf.js} +1 -1
  59. package/dist/assets/{xychartDiagram-PMCCYNJV-B-XhTxjG.js → xychartDiagram-PMCCYNJV-BAPFJLpg.js} +1 -1
  60. package/dist/index.html +2 -2
  61. package/dist-server/cloud-home-start.js +25 -12
  62. package/dist-server/companion/src/listener.js +39 -18
  63. package/dist-server/container-mcp.js +14 -27
  64. package/dist-server/drivers/agents-proxy.js +103 -44
  65. package/dist-server/harness-mcp-proxy.js +1 -2
  66. package/dist-server/index.js +2633 -3396
  67. package/dist-server/openmausbot.js +606 -463
  68. package/dist-server/pair-cli.js +606 -463
  69. package/dist-server/server/admin-activity.js +1 -4
  70. package/dist-server/server/auto-approve.js +19 -4
  71. package/dist-server/server/boat.js +4 -4
  72. package/dist-server/server/checkpoints.js +90 -148
  73. package/dist-server/server/chief-of-staff.js +7 -6
  74. package/dist-server/server/cli.js +33 -26
  75. package/dist-server/server/cloud-home-start.js +12 -15
  76. package/dist-server/server/cloud-home.js +0 -4
  77. package/dist-server/server/cloud-move-http.js +44 -30
  78. package/dist-server/server/cloud-move.js +20 -18
  79. package/dist-server/server/composio.js +10 -3
  80. package/dist-server/server/config.js +92 -64
  81. package/dist-server/server/container-computer.js +16 -5
  82. package/dist-server/server/contracts.js +0 -9
  83. package/dist-server/server/decider/jev.js +1 -4
  84. package/dist-server/server/decider/log.js +1 -3
  85. package/dist-server/server/decision-log.js +1 -4
  86. package/dist-server/server/delegations.js +3 -2
  87. package/dist-server/server/drivers/acp/core.js +4 -3
  88. package/dist-server/server/drivers/acp/opencode-go.js +17 -16
  89. package/dist-server/server/drivers/agents-call.js +46 -63
  90. package/dist-server/server/drivers/agents-catalog.js +66 -0
  91. package/dist-server/server/drivers/agents-proxy.js +2 -1
  92. package/dist-server/server/drivers/claude-login-auth.js +2 -11
  93. package/dist-server/server/drivers/codex-device-auth.js +3 -1
  94. package/dist-server/server/drivers/codex.js +5 -4
  95. package/dist-server/server/drivers/grok.js +1 -1
  96. package/dist-server/server/drivers/openai-chat-protocol.js +4 -2
  97. package/dist-server/server/drivers/openai-chat.js +15 -5
  98. package/dist-server/server/drivers/prompt-split.js +4 -4
  99. package/dist-server/server/harness/bus.js +49 -0
  100. package/dist-server/server/harness-mcp-proxy.js +1 -1
  101. package/dist-server/server/index.js +448 -762
  102. package/dist-server/server/mcp-registry.js +35 -0
  103. package/dist-server/server/message-file.js +4 -4
  104. package/dist-server/server/peer-delivery.js +4 -19
  105. package/dist-server/server/peer-roster.js +30 -4
  106. package/dist-server/server/profile-versions.js +0 -31
  107. package/dist-server/server/provider-key-check.js +2 -1
  108. package/dist-server/server/restart.js +40 -0
  109. package/dist-server/server/room-handoffs.js +12 -0
  110. package/dist-server/server/routes/bot-memory.js +0 -24
  111. package/dist-server/server/routine-requests.js +1 -4
  112. package/dist-server/server/routines.js +5 -4
  113. package/dist-server/server/server-launcher.js +53 -0
  114. package/dist-server/server/store.js +1 -1
  115. package/dist-server/server/surface.js +23 -27
  116. package/dist-server/server/system-prompt.js +13 -3
  117. package/dist-server/server/team-manifest.js +1 -6
  118. package/dist-server/server/tunnel.js +4 -1
  119. package/dist-server/server/turn-images.js +1 -21
  120. package/dist-server/server/turn-resources.js +19 -150
  121. package/dist-server/server/usage-ledger.js +3 -1
  122. package/dist-server/server/workspace.js +2 -3
  123. package/dist-server/server-launcher.js +72 -0
  124. package/dist-server/shared/ask-question.js +1 -1
  125. package/dist-server/shared/cloud-computer.js +12 -0
  126. package/dist-server/shared/failed-turn.js +25 -0
  127. package/dist-server/shared/live-approval.js +2 -2
  128. package/dist-server/shared/package-format.js +3 -3
  129. package/dist-server/shared/pairing-link.js +144 -0
  130. package/dist-server/vps-container-mcp.js +14 -27
  131. package/dist-server/workspace-backup.worker.js +14 -27
  132. package/package.json +1 -1
  133. package/dist/assets/channel-DS2NbT5x.js +0 -1
  134. package/dist/assets/index-NF7XCHAy.css +0 -1
  135. package/dist/assets/index-X_5ydXIE.js +0 -610
  136. package/dist/assets/swimlanesDiagram-TC7HE7FX-C6bZtBXk.js +0 -8
  137. package/dist-server/server/claim-idle.js +0 -33
  138. package/dist-server/server/cloud-overflow.js +0 -167
  139. package/dist-server/server/tightening-requests.js +0 -435
  140. package/dist-server/shared/tightening-request.js +0 -87
@@ -7,7 +7,7 @@ import { ChatToolSessionError, mountChatTools } from "./chat-mcp-tools.js";
7
7
  import { assertImageTransport, chatImageBudget, chatToolImages, chatUserContent } from "./chat-images.js";
8
8
  import { promptHalves, volatileContextNote, withContextNote } from "./prompt-split.js";
9
9
  import { createChatToolApproval } from "./chat-tool-approval.js";
10
- import { ChatProtocolError, ChatReasoningDetails, ChatToolCalls, MAX_CHAT_TOOL_CALLS, object } from "./openai-chat-protocol.js";
10
+ import { ChatProtocolError, ChatReasoningDetails, ChatToolCalls, object } from "./openai-chat-protocol.js";
11
11
  import { appendNative } from "./native.js";
12
12
  import { classifyError, computeBackoff, interruptibleDelay, RETRY_MAX_ATTEMPTS } from "./retry.js";
13
13
  /** The message of a JSON error body a provider returned with HTTP 200.
@@ -31,6 +31,15 @@ const usageFrom = (usage) => usage
31
31
  const asError = (value) => value instanceof Error ? value : new Error(String(value));
32
32
  class UnsupportedChatToolsError extends Error {
33
33
  }
34
+ /** One turn's safety stops: model steps, and tool calls across all of them.
35
+ * Tool-heavy models (a memory server, a browser) take dozens of steps, and
36
+ * a stopped turn cannot simply be continued — the next turn is rebuilt from
37
+ * the text transcript, which holds none of these tool results. The calls
38
+ * that ran have taken effect, so the stop asks only for what is left: a
39
+ * retry of the whole task would repeat them. */
40
+ const MAX_CHAT_ROUNDS = 64;
41
+ const MAX_TURN_TOOL_CALLS = 200;
42
+ const stoppedAfter = (count) => `Stopped after ${count} without a final answer. The steps so far already ran, so ask only for what's left.`;
34
43
  const NUDGE_ANNOUNCED_ACTION = "You said what you would do next but called no tool. Do it now with your tools, or reply with your final answer if nothing is left to do.";
35
44
  /** A short reply that only announces a next step, with nothing to answer. */
36
45
  export function announcesAction(text) {
@@ -413,7 +422,7 @@ export function createOpenAIChatRuntime(options) {
413
422
  if (questionAllowed && !tools.definitions.some((definition) => definition.function.name === ASK_USER_TOOL)) {
414
423
  tools.definitions.push(ASK_USER_TOOL_DEFINITION);
415
424
  }
416
- for (let round = 0; round < 16; round++) {
425
+ for (let round = 0; round < MAX_CHAT_ROUNDS; round++) {
417
426
  abort.signal.throwIfAborted();
418
427
  // Drain parked mid-turn input here, before the next completion
419
428
  // request: the previous round's tool results are complete, so a
@@ -531,8 +540,9 @@ export function createOpenAIChatRuntime(options) {
531
540
  throw new ChatProtocolError("provider reused a tool-call ID; refusing to repeat an operation");
532
541
  seenCalls.add(call.id);
533
542
  }
534
- if (seenCalls.size > MAX_CHAT_TOOL_CALLS)
535
- throw new ChatProtocolError("tool-call limit reached");
543
+ // The whole batch is refused before any of it runs.
544
+ if (seenCalls.size > MAX_TURN_TOOL_CALLS)
545
+ throw new ChatProtocolError(stoppedAfter(`${MAX_TURN_TOOL_CALLS} tool calls`));
536
546
  messages.push({ role: "assistant", content: completion.text || null, tool_calls: completion.toolCalls,
537
547
  ...(completion.protocolReasoning && !reasoningReplayRejected.has(model) ? { [options.reasoningReplayField ?? "reasoning_content"]: completion.protocolReasoning } : {}),
538
548
  ...(completion.protocolReasoningDetails.length ? { reasoning_details: completion.protocolReasoningDetails } : {}),
@@ -645,7 +655,7 @@ export function createOpenAIChatRuntime(options) {
645
655
  messages.push({ role: "user", content: screenshotParts });
646
656
  }
647
657
  if (!ok)
648
- throw new ChatProtocolError("model-call limit reached before a final response");
658
+ throw new ChatProtocolError(stoppedAfter(`${MAX_CHAT_ROUNDS} steps`));
649
659
  }
650
660
  catch (value) {
651
661
  stopReason = abort.signal.aborted ? "interrupted" : stopReason ?? "error";
@@ -1,9 +1,9 @@
1
1
  // The stable/volatile prompt split, shared by the drivers that deliver it.
2
2
  // The stable half is everything that must stay byte-identical for a
3
3
  // provider's cached prefix (or a spawned CLI's session contract) to
4
- // survive; the volatile half (memory, mentions, outstanding teammate
5
- // work, recent work) legitimately changes mid-conversation and reaches
6
- // the model inside the turn that changed it, after the cacheable prefix.
4
+ // survive; the volatile half (the sections in VOLATILE_SECTIONS,
5
+ // system-prompt.ts) legitimately changes mid-conversation and reaches the
6
+ // model inside the turn that changed it, after the cacheable prefix.
7
7
  import { createHash } from "node:crypto";
8
8
  import { mkdirSync, readFileSync, rmSync } from "node:fs";
9
9
  import { join } from "node:path";
@@ -20,7 +20,7 @@ export function promptHalves(turn) {
20
20
  return { stable: systemStable, volatile: systemVolatile };
21
21
  }
22
22
  export const VOLATILE_CONTEXT_NOTE_PREFIX = "Context from OpenMausBot updated since this conversation started; it replaces any earlier copy:";
23
- export const VOLATILE_CONTEXT_CLEARED_NOTE = "The OpenMausBot context notes from earlier in this conversation (memory, mentions, outstanding teammate work) have been cleared; the standing instructions still apply.";
23
+ export const VOLATILE_CONTEXT_CLEARED_NOTE = "The OpenMausBot context notes from earlier in this conversation have been cleared; the standing instructions still apply.";
24
24
  /** The labelled block that carries a changed volatile half inside a user
25
25
  * turn. A half that is empty and always was needs no note; one that was
26
26
  * cleared announces the removal so the model stops relying on it. */
@@ -4,6 +4,13 @@
4
4
  // a per-thread canonical NDJSON log (the debugging trick both upstream and
5
5
  // agentcal lean on), and delivered to subscribers (the SSE endpoint and
6
6
  // the server-side message folder).
7
+ //
8
+ // Streamed text is merged here, once, for every engine on every kind of
9
+ // install: a provider sends a reply as hundreds of small text deltas, and
10
+ // each would otherwise be its own log line, listener call and SSE frame. The
11
+ // bus holds a thread's text for at most DELTA_MERGE_MS and publishes it as
12
+ // one delta, sooner when anything else happens on that thread, so the order
13
+ // of events never changes.
7
14
  import { appendFileSync } from "node:fs";
8
15
  import { join } from "node:path";
9
16
  import { EVENTS_DIR } from "../config.js";
@@ -11,10 +18,19 @@ import { redactSecrets } from "../redact.js";
11
18
  import { capThreadLog, currentThreadLogCap } from "../thread-log-rotation.js";
12
19
  import { newId } from "../contracts.js";
13
20
  const INCOMPLETE_LOG_MESSAGE = "Canonical event history is incomplete: OpenMausBot could not write one or more events to disk. Live updates will continue.";
21
+ /** How long a thread's streamed text waits to be merged with what follows. */
22
+ const DELTA_MERGE_MS = 50;
23
+ /** Two deltas are one stream when only their text, id and time differ. */
24
+ function sameStream(a, b) {
25
+ return a.provider === b.provider && a.providerInstanceId === b.providerInstanceId && a.turnId === b.turnId &&
26
+ a.itemId === b.itemId && a.streamKind === b.streamKind && a.synthetic === b.synthetic;
27
+ }
14
28
  export class EventBus {
15
29
  listeners = new Set();
16
30
  unsubscribes = new Map();
17
31
  pendingLogWarnings = new Map();
32
+ /** Per thread: the streamed text not yet published, and when it goes. */
33
+ pendingText = new Map();
18
34
  appendLog;
19
35
  constructor(appendLog = appendFileSync) {
20
36
  this.appendLog = appendLog;
@@ -35,6 +51,38 @@ export class EventBus {
35
51
  }
36
52
  }
37
53
  publish(event) {
54
+ const pending = this.pendingText.get(event.threadId);
55
+ if (event.type === "content.delta") {
56
+ if (pending && sameStream(pending.event, event)) {
57
+ pending.event = { ...pending.event, delta: pending.event.delta + event.delta };
58
+ return;
59
+ }
60
+ if (pending)
61
+ this.flushThread(event.threadId);
62
+ const timer = setTimeout(() => this.flushThread(event.threadId), DELTA_MERGE_MS);
63
+ timer.unref?.();
64
+ this.pendingText.set(event.threadId, { event, timer });
65
+ return;
66
+ }
67
+ if (pending)
68
+ this.flushThread(event.threadId);
69
+ this.write(event);
70
+ }
71
+ /** Publish every thread's waiting text now: on detach, and as the server exits. */
72
+ flush() {
73
+ for (const threadId of Array.from(this.pendingText.keys()))
74
+ this.flushThread(threadId);
75
+ }
76
+ flushThread(threadId) {
77
+ const pending = this.pendingText.get(threadId);
78
+ if (!pending)
79
+ return;
80
+ // gone from the map before delivery: a listener may publish on this thread
81
+ this.pendingText.delete(threadId);
82
+ clearTimeout(pending.timer);
83
+ this.write(pending.event);
84
+ }
85
+ write(event) {
38
86
  const pendingWarning = this.pendingLogWarnings.get(event.threadId);
39
87
  const persistedEvents = pendingWarning ? [pendingWarning, redactSecrets(event)] : [redactSecrets(event)];
40
88
  try {
@@ -91,5 +139,6 @@ export class EventBus {
91
139
  detach(instanceId) {
92
140
  this.unsubscribes.get(instanceId)?.();
93
141
  this.unsubscribes.delete(instanceId);
142
+ this.flush();
94
143
  }
95
144
  }
@@ -13,7 +13,7 @@ const RECOVERY = {
13
13
  browser: " This failure does not establish that all browsers are unavailable. Inspect available connections with select_computer if that tool is present. Keep the requested computer and account; do not bypass a permission refusal or human takeover, and do not repeat an uncertain action without checking its result.",
14
14
  computer: " Keep working on the assigned cloud computer only; do not bypass a person's control of it, and take a fresh screenshot before repeating an action whose result is uncertain.",
15
15
  };
16
- export function parseHarnessMcpKind(value) {
16
+ function parseHarnessMcpKind(value) {
17
17
  return value === "browser" || value === "computer" ? value : null;
18
18
  }
19
19
  function failure(id, method, message, code = -32603) {