@robota-sdk/agent-transport 3.0.0-beta.82 → 3.0.0-beta.84

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 (62) hide show
  1. package/CHANGELOG.md +795 -0
  2. package/README.md +80 -118
  3. package/dist/browser/client.d.ts +2 -2
  4. package/dist/browser/client.js +1 -1
  5. package/dist/browser/index.d.ts +87 -13
  6. package/dist/browser/index.d.ts.map +1 -1
  7. package/dist/browser/index.js +1 -1
  8. package/dist/browser/index.js.map +1 -1
  9. package/dist/browser/observer-messages-CEeisRaF.js +2 -0
  10. package/dist/browser/observer-messages-CEeisRaF.js.map +1 -0
  11. package/dist/browser/observer-messages-Dnff2Tdb.d.ts +471 -0
  12. package/dist/browser/observer-messages-Dnff2Tdb.d.ts.map +1 -0
  13. package/dist/node/index.cjs +1 -1
  14. package/dist/node/index.d.cts +308 -16
  15. package/dist/node/index.d.cts.map +1 -1
  16. package/dist/node/index.d.ts +308 -16
  17. package/dist/node/index.d.ts.map +1 -1
  18. package/dist/node/index.js +1 -1
  19. package/dist/node/index.js.map +1 -1
  20. package/dist/node/node.cjs +1 -1
  21. package/dist/node/node.d.cts +69 -1
  22. package/dist/node/node.d.cts.map +1 -1
  23. package/dist/node/node.d.ts +70 -2
  24. package/dist/node/node.d.ts.map +1 -1
  25. package/dist/node/node.js +1 -1
  26. package/dist/node/node.js.map +1 -1
  27. package/package.json +17 -14
  28. package/src/__tests__/bearer-resource-gate.test.ts +120 -0
  29. package/src/__tests__/history-attached-budget.test.ts +216 -0
  30. package/src/__tests__/message-decoders.test.ts +496 -6
  31. package/src/__tests__/project-read-messages.test.ts +118 -0
  32. package/src/__tests__/session-detail-loop-status.test.ts +169 -0
  33. package/src/__tests__/session-directory-messages.test.ts +322 -0
  34. package/src/__tests__/session-error-classification.test.ts +113 -0
  35. package/src/__tests__/session-history-wire.test.ts +342 -0
  36. package/src/__tests__/session-message-handler-observe.test.ts +217 -0
  37. package/src/__tests__/session-message-handler.test.ts +139 -4
  38. package/src/__tests__/settings-messages.test.ts +193 -0
  39. package/src/__tests__/ws-broadcast-events.test.ts +10 -0
  40. package/src/client.ts +9 -1
  41. package/src/index.ts +18 -2
  42. package/src/loop-control-messages.ts +34 -0
  43. package/src/message-decoders.ts +238 -6
  44. package/src/node/bearer-resource-gate.ts +291 -0
  45. package/src/node/index.ts +13 -0
  46. package/src/observer-messages.ts +47 -0
  47. package/src/open-prompts.ts +76 -0
  48. package/src/outbound-delivery.ts +11 -2
  49. package/src/project-read-messages.ts +74 -0
  50. package/src/protocol-session.ts +23 -1
  51. package/src/session-directory-messages.ts +162 -0
  52. package/src/session-error-classification.ts +91 -0
  53. package/src/session-events.ts +100 -19
  54. package/src/session-message-handler.ts +110 -15
  55. package/src/session-query-messages.ts +123 -5
  56. package/src/session-resume-bridge.ts +8 -0
  57. package/src/settings-messages.ts +103 -0
  58. package/src/wire-messages.ts +238 -11
  59. package/dist/browser/message-decoders-BB8n-H2X.d.ts +0 -252
  60. package/dist/browser/message-decoders-BB8n-H2X.d.ts.map +0 -1
  61. package/dist/browser/message-decoders-CDmDoZPR.js +0 -2
  62. package/dist/browser/message-decoders-CDmDoZPR.js.map +0 -1
package/README.md CHANGED
@@ -1,42 +1,11 @@
1
- # Agent Transport
1
+ # @robota-sdk/agent-transport
2
2
 
3
- Browser-safe transport protocol and delivery substrate for the Robota SDK. The root exports shared
4
- wire messages, session bridging, channel codecs, and delivery helpers. Browser decoders are also
5
- available from `./client`; Node-only admission and handoff integrity helpers are available from
6
- `./node`.
7
-
8
- ## Handoff offer migration
9
-
10
- `@robota-sdk/agent-transport/node` no longer exports `buildHandoffManifest`,
11
- `IBuildManifestInput`, `ISourceRuntimeState`, or `TManifestResult`. Handoff readiness and inventory
12
- classification belong to `@robota-sdk/agent-interface-session-mobility`. A host composing a handoff
13
- should check readiness before serializing, then pass the integrity of those exact bytes to the
14
- mobility offer policy:
15
-
16
- ```typescript
17
- import {
18
- assessHandoffReadiness,
19
- prepareHandoffOffer,
20
- type IPrepareHandoffOfferInput,
21
- } from '@robota-sdk/agent-interface-session-mobility';
22
- import { sealHandoffRecord } from '@robota-sdk/agent-transport/node';
23
-
24
- function buildOffer(request: Omit<IPrepareHandoffOfferInput, 'integrity'>) {
25
- const readiness = assessHandoffReadiness(request.runtime);
26
- if (!readiness.ready) return readiness;
27
-
28
- const { serialized, integrity } = sealHandoffRecord(request.record);
29
- const offer = prepareHandoffOffer({ ...request, integrity });
30
- if (!offer.built) return offer;
31
-
32
- // Send serialized unchanged: offer.manifest.integrity describes these exact bytes.
33
- return { manifest: offer.manifest, serialized };
34
- }
35
- ```
36
-
37
- For types, use `ISourceRuntimeState`, `IPrepareHandoffOfferInput`, and `THandoffOfferResult` from
38
- session mobility. `IPrepareHandoffOfferInput` includes the integrity metadata produced by
39
- `sealHandoffRecord`; the serialized payload remains a separate transport value.
3
+ The shared protocol layer under every Robota transport. It defines the transport-neutral wire messages
4
+ (`TClientMessage` / `TServerMessage`), the session bridge that turns those messages into calls on a live
5
+ session, and the delivery helpers a carrier needs (backpressure, resumable delivery, channel framing,
6
+ handoff payload chunking). The WebSocket and WebRTC transports carry its wire protocol, and the HTTP and
7
+ MCP transports use its admission and token-verification helpers. It opens no socket or listener of its
8
+ own.
40
9
 
41
10
  ## Installation
42
11
 
@@ -44,115 +13,108 @@ session mobility. `IPrepareHandoffOfferInput` includes the integrity metadata pr
44
13
  npm install @robota-sdk/agent-transport
45
14
  ```
46
15
 
47
- ## Available Transports
16
+ Requires Node.js 22.12 or later. The root and `./client` entry points also run in the browser.
48
17
 
49
- Headless execution belongs to `agent-framework`. HTTP, WebSocket, MCP, and WebRTC ship as standalone
50
- transport packages.
18
+ ## Entry points
51
19
 
52
- | Transport | Package / Sub-path | Description |
53
- | --------- | ------------------------------------ | ------------------------------------------------------- |
54
- | Headless | `@robota-sdk/agent-framework` | Non-interactive text / JSON / stream-JSON output |
55
- | HTTP | `@robota-sdk/agent-transport-http` | Hono-based REST adapter (Node.js / CF Workers / Lambda) |
56
- | WebSocket | `@robota-sdk/agent-transport-ws` | Framework-agnostic real-time bidirectional adapter |
57
- | MCP | `@robota-sdk/agent-transport-mcp` | Model Context Protocol server adapter |
58
- | WebRTC | `@robota-sdk/agent-transport-webrtc` | Peer-to-peer data-channel adapter |
20
+ | Import path | Environment | What it contains |
21
+ | ------------------------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
22
+ | `@robota-sdk/agent-transport` | browser and Node | Wire message types, runtime decoders, `createSessionMessageHandler`, `createOutboundDelivery`, `SessionResumeBridge`, channel frame codec, peer-message ledger, handoff chunking |
23
+ | `@robota-sdk/agent-transport/client` | browser and Node | Only the wire message types and the runtime decoders (`decodeServerMessage`, `decodeClientMessage`, `decodeFrame`) |
24
+ | `@robota-sdk/agent-transport/node` | Node only | Transport admission (`resolveAdmission`, `mintTransportToken`, `credentialMatches`), OAuth access-token verification (`createAccessTokenVerifier`), the bearer resource-server gate, file transfer, handoff integrity (`sealHandoffRecord`, `verifyHandoffPayload`) |
59
25
 
60
- Scripted-provider test fixtures live in `@robota-sdk/agent-core/testing` (the former `./testing`
61
- pass-through was removed, issue #2052).
26
+ Anything that needs `node:crypto` or the network lives under `./node`, so a browser bundle that imports
27
+ the root or `./client` never pulls in a Node built-in.
62
28
 
63
- All session-owning entry points treat `cwd` as provenance, not project trust. Pass a host-issued
64
- `TWorkspaceProjectAccess` decision through `projectAccess`; omitting it creates a Restricted session
65
- that does not load project contributions.
29
+ ## Usage: bridging a connection to a session
66
30
 
67
- ## Quick Start
68
-
69
- ### Headless
31
+ A carrier (your socket, data channel, or stream) turns each connection into three things: an outbound
32
+ sink, a failure policy, and a feed of inbound text frames. The package does the rest.
70
33
 
71
34
  ```typescript
72
- import { createHeadlessTransport } from '@robota-sdk/agent-framework';
35
+ import { createOutboundDelivery, createSessionMessageHandler } from '@robota-sdk/agent-transport';
36
+ import type { IProtocolSession, TServerMessage } from '@robota-sdk/agent-transport';
73
37
 
74
- const transport = createHeadlessTransport({ outputFormat: 'text', prompt: 'Hello!' });
75
- ```
38
+ declare const session: IProtocolSession; // e.g. an InteractiveSession from @robota-sdk/agent-framework
39
+ declare const socket: { send(text: string): void; close(): void }; // one client connection
76
40
 
77
- ### WebSocket
41
+ // Outbound: every frame to this connection goes through one delivery boundary. A failed send, or a
42
+ // peer that stops reading, calls the error handler once; the carrier then closes the connection.
43
+ const deliver = createOutboundDelivery(
44
+ (message: TServerMessage) => socket.send(JSON.stringify(message)),
45
+ () => socket.close(),
46
+ );
78
47
 
79
- ```typescript
80
- import { WsTransport } from '@robota-sdk/agent-transport-ws';
48
+ const handler = createSessionMessageHandler({ session, deliver });
81
49
 
82
- const transport = new WsTransport({ port: 3001 });
50
+ // Inbound: pass each raw text frame from the client; call cleanup when the connection closes.
51
+ handler.onMessage(JSON.stringify({ type: 'submit', prompt: 'Hello' }));
52
+ handler.cleanup();
83
53
  ```
84
54
 
85
- ### HTTP
55
+ `onMessage` decodes and validates the frame itself; malformed input is answered with a protocol error,
56
+ not thrown. Pass `role: 'observe'` for a read-only connection: it can read the session's conversation
57
+ and state but cannot submit, answer prompts or control the session.
86
58
 
87
- ```typescript
88
- import { createHttpTransport } from '@robota-sdk/agent-transport-http';
89
-
90
- const transport = createHttpTransport({ basePath: '/agent' }); // mount on your own server
91
- ```
59
+ ## Composing a handoff offer
92
60
 
93
- ### MCP
61
+ Moving a session to another device is split between two packages. Readiness and the offer policy
62
+ belong to `@robota-sdk/agent-interface-session-mobility`; this package seals the serialized record so
63
+ the receiver can verify it arrived intact. Check readiness first, then pass the integrity of those
64
+ exact bytes to the offer:
94
65
 
95
66
  ```typescript
96
- import { createMcpTransport } from '@robota-sdk/agent-transport-mcp';
97
-
98
- const transport = createMcpTransport({ name: 'my-agent', version: '1.0.0' });
99
- ```
67
+ import {
68
+ assessHandoffReadiness,
69
+ prepareHandoffOffer,
70
+ type IPrepareHandoffOfferInput,
71
+ } from '@robota-sdk/agent-interface-session-mobility';
72
+ import { sealHandoffRecord } from '@robota-sdk/agent-transport/node';
100
73
 
101
- ### TUI presentation (Ink/React)
74
+ function buildOffer(request: Omit<IPrepareHandoffOfferInput, 'integrity'>) {
75
+ const readiness = assessHandoffReadiness(request.runtime);
76
+ if (!readiness.ready) return readiness;
102
77
 
103
- ```typescript
104
- import { renderApp } from '@robota-sdk/agent-ui-terminal';
105
- import type { IRenderOptions } from '@robota-sdk/agent-ui-terminal';
78
+ const { serialized, integrity } = sealHandoffRecord(request.record);
79
+ const offer = prepareHandoffOffer({ ...request, integrity });
80
+ if (!offer.built) return offer;
106
81
 
107
- declare const options: IRenderOptions;
108
- await renderApp(options);
82
+ // Send serialized unchanged: offer.manifest.integrity describes these exact bytes.
83
+ return { manifest: offer.manifest, serialized };
84
+ }
109
85
  ```
110
86
 
111
- > React and Ink dependencies are confined to the standalone
112
- > `@robota-sdk/agent-ui-terminal` package. This core package stays React-free.
87
+ The receiver checks the bytes against `offer.manifest.integrity` with `verifyHandoffPayload` before
88
+ parsing them. A payload too large for one frame can be split with `chunkHandoffPayload` and reassembled
89
+ with `HandoffChunkAssembler`.
113
90
 
114
- ## Sub-path Imports
91
+ ## Transport packages
115
92
 
116
- Import only what you need to keep bundles small:
93
+ Each carrier is its own package, so an application installs only the protocol dependencies it uses.
117
94
 
118
- ```typescript
119
- import { createHeadlessTransport } from '@robota-sdk/agent-framework';
120
- import { WsTransport } from '@robota-sdk/agent-transport-ws';
121
- import type { TServerMessage } from '@robota-sdk/agent-transport';
122
- import { createHttpTransport } from '@robota-sdk/agent-transport-http';
123
- import { createMcpTransport } from '@robota-sdk/agent-transport-mcp';
124
- import { renderApp } from '@robota-sdk/agent-ui-terminal';
125
- ```
126
-
127
- The framework root owns headless and programmatic surfaces plus `TransportRegistry`. The transport
128
- root owns transport-neutral wire messages, session bridging, channel codecs, and delivery helpers;
129
- browser decoders are also available from `@robota-sdk/agent-transport/client`, while Node-only
130
- admission and handoff integrity helpers live under `@robota-sdk/agent-transport/node`.
131
-
132
- ```typescript
133
- import { createHeadlessTransport } from '@robota-sdk/agent-framework';
134
- ```
95
+ | Transport | Package | What it does |
96
+ | --------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
97
+ | WebSocket | [`@robota-sdk/agent-transport-ws`](../agent-transport-ws/README.md) | Serves a session on a loopback WebSocket server (token-authenticated by default) |
98
+ | HTTP | [`@robota-sdk/agent-transport-http`](../agent-transport-http/README.md) | Hono routes for submitting prompts and reading session state over HTTP + SSE |
99
+ | MCP | [`@robota-sdk/agent-transport-mcp`](../agent-transport-mcp/README.md) | Exposes a session as an MCP server over stdio or Streamable HTTP |
100
+ | WebRTC | [`@robota-sdk/agent-transport-webrtc`](../agent-transport-webrtc/README.md) | Carries a session peer-to-peer over a pairing-gated data channel (Node host side) |
135
101
 
136
- `TransportRegistry` accepts the discriminated base service/runner adapter union. It rejects active
137
- restart before mutation, rolls partial startup back in reverse order, reports real runner failure
138
- immediately, and returns a complete ordered aggregate whose pending runners become registry-owned
139
- `abandoned` records on stop or rollback.
102
+ The headless (non-interactive text / JSON / stream-JSON) transport and `TransportRegistry`, which
103
+ starts and stops a set of transports together, live in `@robota-sdk/agent-framework`. The terminal UI is
104
+ `@robota-sdk/agent-ui-terminal`; this package has no React or Ink dependency.
140
105
 
141
106
  ## Dependencies
142
107
 
143
- - `@robota-sdk/agent-interface-analytics`
144
- - `@robota-sdk/agent-interface-command`
145
- - `@robota-sdk/agent-interface-execution`
146
- - `@robota-sdk/agent-interface-session`
147
- - `@robota-sdk/agent-interface-session-mobility`
148
- - `@robota-sdk/agent-interface-transport`
108
+ - `@robota-sdk/agent-core`
109
+ - `@robota-sdk/agent-interface-analytics`, `-command`, `-execution`, `-session`, `-session-mobility`,
110
+ `-transport` (contract packages)
111
+ - `jose` (access-token signature verification under `./node`)
149
112
 
150
- The heavier protocol dependencies (`ws`, `hono`, `@modelcontextprotocol/sdk`,
151
- `react`, `ink`, and friends) now live in the split transport packages
152
- (`@robota-sdk/agent-transport-{http,ws,mcp}`) and presentation packages
153
- (`@robota-sdk/agent-ui-{terminal,web}`).
113
+ The protocol libraries (`ws`, `hono`, `@modelcontextprotocol/sdk`, `node-datachannel`) are
114
+ dependencies of the individual transport packages, not of this one.
154
115
 
155
- ## Links
116
+ ## Documentation
156
117
 
157
- - [npm](https://www.npmjs.com/package/@robota-sdk/agent-transport)
158
- - [GitHub](https://github.com/woojubb/robota)
118
+ - [docs/SPEC.md](./docs/SPEC.md) — package contract and boundaries
119
+ - [npm](https://www.npmjs.com/package/@robota-sdk/agent-transport) ·
120
+ [GitHub](https://github.com/woojubb/robota)
@@ -1,2 +1,2 @@
1
- import { a as decodeServerMessage, c as TServerMessage, i as decodeFrame, n as TMessageDecodeResult, o as TClientMessage, r as decodeClientMessage, s as TSeqServerMessage, t as MAX_INBOUND_FRAME_BYTES } from "./message-decoders-BB8n-H2X.js";
2
- export { MAX_INBOUND_FRAME_BYTES, type TClientMessage, type TMessageDecodeResult, type TSeqServerMessage, type TServerMessage, decodeClientMessage, decodeFrame, decodeServerMessage };
1
+ import { a as decodeFrame, c as IWireHistoryEntry, d as TServerMessage, f as TWireExecutionResult, i as decodeClientMessage, l as TClientMessage, n as MAX_INBOUND_FRAME_BYTES, o as decodeServerMessage, r as TMessageDecodeResult, t as isObserverMessageType, u as TSeqServerMessage } from "./observer-messages-Dnff2Tdb.js";
2
+ export { type IWireHistoryEntry, MAX_INBOUND_FRAME_BYTES, type TClientMessage, type TMessageDecodeResult, type TSeqServerMessage, type TServerMessage, type TWireExecutionResult, decodeClientMessage, decodeFrame, decodeServerMessage, isObserverMessageType };
@@ -1 +1 @@
1
- import{i as e,n as t,r as n,t as r}from"./message-decoders-CDmDoZPR.js";export{r as MAX_INBOUND_FRAME_BYTES,t as decodeClientMessage,n as decodeFrame,e as decodeServerMessage};
1
+ import{a as e,i as t,n,r,t as i}from"./observer-messages-CEeisRaF.js";export{n as MAX_INBOUND_FRAME_BYTES,r as decodeClientMessage,t as decodeFrame,e as decodeServerMessage,i as isObserverMessageType};
@@ -1,6 +1,7 @@
1
- import { a as decodeServerMessage, c as TServerMessage, i as decodeFrame, n as TMessageDecodeResult, o as TClientMessage, r as decodeClientMessage, s as TSeqServerMessage, t as MAX_INBOUND_FRAME_BYTES } from "./message-decoders-BB8n-H2X.js";
1
+ import { a as decodeFrame, c as IWireHistoryEntry, d as TServerMessage, f as TWireExecutionResult, i as decodeClientMessage, l as TClientMessage, n as MAX_INBOUND_FRAME_BYTES, o as decodeServerMessage, r as TMessageDecodeResult, s as IWireAgentDefinitionSummary, t as isObserverMessageType, u as TSeqServerMessage } from "./observer-messages-Dnff2Tdb.js";
2
+ import { ISessionAgentJobs, ISessionBackgroundGroups, ISessionBackgroundTasks, ISessionCommands, ISessionConversationRead, ISessionDirectory, ISessionDriverAttribution, ISessionEvents, ISessionExecutionDetail, ISessionExecutionState, ISessionExecutionWorkspace, ISessionProjectRead, ISessionPromptResolution, ISessionSelfPacedLoopControl, ISessionStatusRead, ISessionTurnControl, ISessionTurnSubmission, ISettingsSnapshot, TDriverId, TSettingsPatch } from "@robota-sdk/agent-interface-session";
2
3
  import { IPersonalUsageReport, IPersonalUsageRequest, IUsageBySourceReport, TUsageSurface } from "@robota-sdk/agent-interface-analytics";
3
- import { ISessionBackgroundGroups, ISessionBackgroundTasks, ISessionCommands, ISessionConversationRead, ISessionDriverAttribution, ISessionEvents, ISessionExecutionState, ISessionExecutionWorkspace, ISessionPromptResolution, ISessionTurnControl, ISessionTurnSubmission, TDriverId } from "@robota-sdk/agent-interface-session";
4
+ import { TCommandSurfaceLocality } from "@robota-sdk/agent-interface-command";
4
5
  import { IBinaryFrame, IChannelEventFrame, TChannelReceiveResult } from "@robota-sdk/agent-interface-transport";
5
6
  import { IHandoffIntegrity, IPeerMessage, IPeerMessageAck, TPeerDeliveryState } from "@robota-sdk/agent-interface-session-mobility";
6
7
  //#region src/outbound-delivery.d.ts
@@ -33,14 +34,22 @@ type TOutboundDeliver = ((message: TServerMessage) => void) & {
33
34
  };
34
35
  /**
35
36
  * Observe THIS connection's first outbound delivery failure. `event` is the `type` of the frame that
36
- * could not be delivered — a session event's own name for the fan-out (they are identical), and the
37
- * reply's type for a reply (`command_result`, `protocol_error`, …).
37
+ * could not be delivered — for the fan-out, the frame a session event was forwarded as (usually, not
38
+ * always, the event's own name), and the reply's type for a reply (`command_result`, `protocol_error`, …).
38
39
  *
39
40
  * Required, never optional: a carrier that could opt out of observing its own delivery failures is the
40
41
  * silent-failure shape this boundary exists to remove.
41
42
  */
42
43
  type TDeliveryErrorHandler = (error: Error, event: TServerMessage['type']) => void;
43
44
  declare const DEFAULT_MAX_PENDING_BYTES: number;
45
+ /**
46
+ * Backpressure budget for a terminal attached to a session on the same host, in either role.
47
+ *
48
+ * 1 MiB, tighter than the default: an attached terminal reads a local socket, so a backlog this large
49
+ * means it stopped reading rather than that a network is slow. Exceeding it closes that connection
50
+ * only; the session never waits for a reader, so other surfaces keep streaming.
51
+ */
52
+ declare const ATTACHED_SURFACE_MAX_PENDING_BYTES: number;
44
53
  /**
45
54
  * Is this carrier holding more than the budget allows?
46
55
  *
@@ -86,7 +95,48 @@ declare function createOutboundDelivery(send: (message: TServerMessage) => void,
86
95
  //#endregion
87
96
  //#region src/protocol-session.d.ts
88
97
  /** Session roles required by the shared WebSocket/WebRTC protocol. */
89
- interface IProtocolSession extends ISessionTurnSubmission, ISessionTurnControl, ISessionCommands, ISessionEvents, ISessionPromptResolution, ISessionConversationRead, ISessionExecutionState, ISessionDriverAttribution, ISessionBackgroundTasks, ISessionBackgroundGroups, ISessionExecutionWorkspace {}
98
+ interface IProtocolSession extends ISessionTurnSubmission, ISessionTurnControl, ISessionCommands, ISessionStatusRead, ISessionEvents, ISessionPromptResolution, ISessionConversationRead, ISessionExecutionState, ISessionDriverAttribution, ISessionBackgroundTasks, ISessionBackgroundGroups, ISessionExecutionWorkspace, ISessionExecutionDetail, ISessionSelfPacedLoopControl, ISessionAgentJobs {}
99
+ /**
100
+ * #3282 §4c: a protocol session that ALSO answers the Project panel's reads. `Partial` (not a fourth
101
+ * mandatory role on {@link IProtocolSession} itself) deliberately: every existing test double and
102
+ * every other host that builds an `IProtocolSession` keeps type-checking unchanged, and the panel's
103
+ * three methods are runtime-probed (`typeof session.readProjectStatus === 'function'`) rather than
104
+ * assumed — `InteractiveSession` (the one production implementation) provides all three, satisfying
105
+ * this type with no further wiring.
106
+ */
107
+ type TProjectReadCapableSession = IProtocolSession & Partial<ISessionProjectRead>;
108
+ //#endregion
109
+ //#region src/settings-messages.d.ts
110
+ type TSettingsMessage = Extract<TClientMessage, {
111
+ type: 'get-settings' | 'update-settings';
112
+ }>;
113
+ declare function isSettingsMessage(msg: TClientMessage): msg is TSettingsMessage;
114
+ /** What applying a patch did: the fresh snapshot, or why nothing was written. */
115
+ type TSettingsUpdateOutcome = {
116
+ readonly ok: true;
117
+ readonly settings: ISettingsSnapshot;
118
+ } | {
119
+ readonly ok: false;
120
+ readonly code: 'not_available' | 'invalid' | 'refused' | 'update_failed';
121
+ readonly message: string;
122
+ };
123
+ /**
124
+ * #3282 §4a: host-owned read/write for the Settings screen, supplied by the composition root the
125
+ * same way `IUsageQueryReporters` supplies usage reads — this package only correlates the request
126
+ * and carries the result. `updateSettings` applies through the SAME function the matching slash
127
+ * command uses (issue #3282 §4: "one code path, so the behavior matches the TUI"), so whatever a
128
+ * command would refuse on this surface is refused here too.
129
+ */
130
+ interface ISettingsReporter {
131
+ getSettings(session: IProtocolSession, locality?: TCommandSurfaceLocality): ISettingsSnapshot | Promise<ISettingsSnapshot>;
132
+ /**
133
+ * Applies through the SAME function the matching slash command uses. `locality` (#3282 §4 part
134
+ * b-2) is forwarded to that command exactly as the transport received it, so a command that
135
+ * refuses a remote surface (installing a plugin) refuses identically here.
136
+ */
137
+ updateSettings(session: IProtocolSession, patch: TSettingsPatch, locality?: TCommandSurfaceLocality): TSettingsUpdateOutcome | Promise<TSettingsUpdateOutcome>;
138
+ }
139
+ declare function handleSettingsMessage(session: IProtocolSession, deliver: TOutboundDeliver, msg: TSettingsMessage, reporter: ISettingsReporter | undefined, locality?: TCommandSurfaceLocality): void;
90
140
  //#endregion
91
141
  //#region src/usage-messages.d.ts
92
142
  interface IUsageQueryReporters {
@@ -105,17 +155,17 @@ declare const PROTOCOL_SESSION_EVENT_CLASSIFICATION: {
105
155
  readonly thinking: "forwarded";
106
156
  readonly complete: "forwarded";
107
157
  readonly error: "forwarded";
108
- readonly context_update: "non-surface";
109
- readonly compact: "non-surface";
158
+ readonly context_update: "forwarded";
159
+ readonly compact: "forwarded";
110
160
  readonly interrupted: "forwarded";
111
- readonly skill_activation: "non-surface";
161
+ readonly skill_activation: "forwarded";
112
162
  readonly background_task_event: "forwarded";
113
163
  readonly background_job_group_event: "forwarded";
114
164
  readonly execution_workspace_event: "forwarded";
115
165
  readonly user_message: "forwarded";
116
- readonly turn_source: "non-surface";
166
+ readonly turn_source: "forwarded";
117
167
  readonly context_file_refreshed: "forwarded";
118
- readonly memory_event: "non-surface";
168
+ readonly memory_event: "forwarded";
119
169
  readonly goal_event: "non-surface";
120
170
  readonly plan_event: "forwarded";
121
171
  readonly branch_event: "forwarded";
@@ -125,12 +175,20 @@ declare const PROTOCOL_SESSION_EVENT_CLASSIFICATION: {
125
175
  readonly ui_intent: "requester-routed";
126
176
  readonly session_renamed: "forwarded";
127
177
  readonly history_cleared: "forwarded";
178
+ readonly session_switched: "forwarded";
179
+ readonly status_changed: "forwarded";
128
180
  };
129
181
  //#endregion
130
182
  //#region src/session-message-handler.d.ts
183
+ /**
184
+ * What a connected surface may do. `drive` sends prompts, answers questions and controls the session.
185
+ * `observe` is read-only: it follows this session's conversation and state, but never submits, answers,
186
+ * controls, or reads another session's records, and it never counts as a surface that can answer.
187
+ */
188
+ type TSessionSurfaceRole = 'drive' | 'observe';
131
189
  interface ISessionMessageHandlerOptions {
132
- /** IProtocolSession to expose. */
133
- session: IProtocolSession;
190
+ /** IProtocolSession to expose — `Partial<ISessionProjectRead>` is probed, not assumed (#3282 §4c). */
191
+ session: TProjectReadCapableSession;
134
192
  /**
135
193
  * ARCH-030: the CARRIER's connection-scoped outbound delivery boundary — not a raw `send`, and not a
136
194
  * `send` plus an error callback for this handler to assemble into one. The carrier owns both the sink
@@ -147,12 +205,25 @@ interface ISessionMessageHandlerOptions {
147
205
  driverId?: TDriverId;
148
206
  /** Trusted carrier-owned product surface, kept separate from driver identity. */
149
207
  surface?: TUsageSurface;
208
+ /** Carrier-decided role of this connection; defaults to `drive`. The client never chooses it here. */
209
+ role?: TSessionSurfaceRole;
150
210
  /** Host-owned cross-session read model. The protocol only correlates and carries its result. */
151
211
  personalUsageReporter?: NonNullable<IUsageQueryReporters['personalUsageReporter']>;
152
212
  /** Host-owned current-session trace/cost producer for the pre-existing message family. */
153
213
  usageReporter?: NonNullable<IUsageQueryReporters['usageReporter']>;
154
214
  /** Host-owned stored-session producer used by cross-session drill-down. */
155
215
  storedSessionUsageReporter?: NonNullable<IUsageQueryReporters['storedSessionUsageReporter']>;
216
+ /** Host-owned session directory (#3189): list, start and switch the host's sessions. */
217
+ sessionDirectory?: ISessionDirectory;
218
+ /** #3282 §4a: host-owned read/write for the GUI Settings screen. */
219
+ settingsReporter?: ISettingsReporter;
220
+ /**
221
+ * #3282 §4 part b-2: carrier-decided, like `role` — whether THIS carrier's connections are
222
+ * provably on this machine. The loopback WS carrier is `'local'`; the device-mesh/WebRTC carrier
223
+ * sets `'remote'`. Absent → `'local'`, forwarded to `executeCommand` and the settings reporter so a
224
+ * command that runs code from outside the session (installing a plugin) can refuse a remote device.
225
+ */
226
+ commandSurfaceLocality?: TCommandSurfaceLocality;
156
227
  }
157
228
  /**
158
229
  * Create a carrier-neutral message handler for an IProtocolSession.
@@ -282,6 +353,8 @@ interface ISessionResumeBridgeOptions {
282
353
  readonly personalUsageReporter?: IUsageQueryReporters['personalUsageReporter'];
283
354
  readonly usageReporter?: IUsageQueryReporters['usageReporter'];
284
355
  readonly storedSessionUsageReporter?: IUsageQueryReporters['storedSessionUsageReporter'];
356
+ /** #3282 §4 part b-2: this bridge is the reconnectable WebRTC path, so it is always `'remote'`. */
357
+ readonly commandSurfaceLocality?: TCommandSurfaceLocality;
285
358
  }
286
359
  declare class SessionResumeBridge {
287
360
  private readonly session;
@@ -289,6 +362,7 @@ declare class SessionResumeBridge {
289
362
  private driverId?;
290
363
  private readonly reporters;
291
364
  private readonly surface?;
365
+ private readonly commandSurfaceLocality?;
292
366
  private readonly unsubscribe;
293
367
  private onDeliveryError?;
294
368
  /**
@@ -516,5 +590,5 @@ declare class HandoffChunkAssembler {
516
590
  */
517
591
  declare function chunkCountFor(integrity: IHandoffIntegrity, maxChunkBytes?: number): number;
518
592
  //#endregion
519
- export { CHANNEL_FRAME_MAGIC, CHANNEL_FRAME_VERSION, DEFAULT_MAX_CHUNK_BYTES, DEFAULT_MAX_PENDING_BYTES, DEFAULT_MAX_PENDING_MS, HandoffChunkAssembler, type IAttachOptions, type IBufferedFrame, type IChunkResult, type IHandoffChunk, type IPeerMessageLedger, type IPeerMessageRejection, type IPeerMessageVerdict, type IPendingStallClock, type IProtocolSession, type IResumeBufferOptions, type ISessionMessageHandlerOptions, type ISessionResumeBridgeOptions, MAX_INBOUND_FRAME_BYTES, PROTOCOL_SESSION_EVENT_CLASSIFICATION, ResumeBuffer, SessionResumeBridge, type TChunkOutcome, type TChunkRejection, type TClientMessage, type TDeliveryErrorHandler, type TMessageDecodeResult, type TOutboundDeliver, type TProtocolSessionEventClassification, type TResumeSink, type TResumeTail, type TSeqServerMessage, type TServerMessage, acknowledgePeerMessage, admitPeerMessage, chunkCountFor, chunkHandoffPayload, createOutboundDelivery, createPeerMessageLedger, createPendingStallClock, createSessionMessageHandler, decodeChannelFrame, decodeClientMessage, decodeFrame, decodeServerMessage, encodeBinaryFrame, encodeChannelEventFrame, forgetPeerOrigin, isChannelFrame, isOverPendingBudget };
593
+ export { ATTACHED_SURFACE_MAX_PENDING_BYTES, CHANNEL_FRAME_MAGIC, CHANNEL_FRAME_VERSION, DEFAULT_MAX_CHUNK_BYTES, DEFAULT_MAX_PENDING_BYTES, DEFAULT_MAX_PENDING_MS, HandoffChunkAssembler, type IAttachOptions, type IBufferedFrame, type IChunkResult, type IHandoffChunk, type IPeerMessageLedger, type IPeerMessageRejection, type IPeerMessageVerdict, type IPendingStallClock, type IProtocolSession, type IResumeBufferOptions, type ISessionMessageHandlerOptions, type ISessionResumeBridgeOptions, type ISettingsReporter, type IWireAgentDefinitionSummary, type IWireHistoryEntry, MAX_INBOUND_FRAME_BYTES, PROTOCOL_SESSION_EVENT_CLASSIFICATION, ResumeBuffer, SessionResumeBridge, type TChunkOutcome, type TChunkRejection, type TClientMessage, type TDeliveryErrorHandler, type TMessageDecodeResult, type TOutboundDeliver, type TProtocolSessionEventClassification, type TResumeSink, type TResumeTail, type TSeqServerMessage, type TServerMessage, type TSessionSurfaceRole, type TSettingsUpdateOutcome, type TWireExecutionResult, acknowledgePeerMessage, admitPeerMessage, chunkCountFor, chunkHandoffPayload, createOutboundDelivery, createPeerMessageLedger, createPendingStallClock, createSessionMessageHandler, decodeChannelFrame, decodeClientMessage, decodeFrame, decodeServerMessage, encodeBinaryFrame, encodeChannelEventFrame, forgetPeerOrigin, handleSettingsMessage, isChannelFrame, isObserverMessageType, isOverPendingBudget, isSettingsMessage };
520
594
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/outbound-delivery.ts","../../src/protocol-session.ts","../../src/usage-messages.ts","../../src/session-events.ts","../../src/session-message-handler.ts","../../src/resume-buffer.ts","../../src/channel-frames.ts","../../src/session-resume-bridge.ts","../../src/peer-message-ledger.ts","../../src/handoff-chunking.ts"],"mappings":";;;;;;cAkCc;;;;;;;;;KAUF,qBAAqB,SAAS;YAC9B;;;;;;;;;;;;;;;WAgBD;;;;;;;;;;KAWC,yBAAyB,OAAO,OAAO,OAAO;cA0B7C;;;;;;;;;;;;iBAaG,oBACd,6BACA;;;;;;;;;;;;;cAiBW;;;;;;;UAQI;WACN;;;;;;EAMT,UAAU;;iBAGI,wBACd,uBACA,qBACC;iBAkBa,uBACd,OAAO,SAAS,yBAChB,iBAAiB,uBACjB,yCACA,0BACA,aAAY,qBACX;;;;UChKc,yBAEb,wBACA,qBACA,kBACA,gBACA,0BACA,0BACA,wBACA,2BACA,yBACA,0BACA;;;UCba;WACN,yBACH,SAAS,0BAA0B,uBAAuB,QAAQ;WAE/D,iBACH,SAAS,qBAAqB,uBAAuB,QAAQ;WAE1D,8BACL,sBAAsB,uBAAuB,QAAQ;;;;KCO/C;;cAGC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UCAI;;EAEf,SAAS;;;;;;;;EAQT,SAAS;;;;;;EAMT,WAAW;;EAEX,UAAU;;EAEV,wBAAwB,YAAY;;EAEpC,gBAAgB,YAAY;;EAE5B,6BAA6B,YAAY;;;;;;;;;;;;;;;;;;;;;iBAsB3B,4BAA4B,SAAS;EACnD,YAAY;EACZ;;;;;UClEe;WACN;WACA,SAAS;;;KAIR;WACG;WAAuB,iBAAiB;;WACxC;;UAEE;;WAEN;;WAEA;;WAEA,UAAU,SAAS;;;;;;cAUjB;mBACM;mBACA;UACT;UACA;mBAES;mBACA;mBACA;EAEE,YAAA,UAAS;;EAOrB,OAAO,SAAS;;EAYhB,WAAW;;;;;;EAWX,UAAU,kBAAkB;;MAWxB;;MAKA;UAIH;;UAeA;;;;;cC3EG,qBAAqB;;cAGrB;;iBAwCG,kBAAkB,OAAO,eAAe;;iBASxC,wBAAwB,OAAO,qBAAqB;;iBAUpD,eAAe,OAAO;;;;;;iBAsCtB,mBAAmB,OAAO,aAAa;;;;KC1G3C,eAAe;;UAGV;;;;;;;;WAQN;;WAEA,kBAAkB,OAAO,OAAO;;;;;;;;WAQhC;;UAGM;WACN,SAAS;WACT,SAAS;;WAET,WAAW;WACX,UAAU;WACV,wBAAwB;WACxB,gBAAgB;WAChB,6BAA6B;;cAG3B;mBACM;mBACA;UACT;mBACS;mBACA;mBACA;UACT;;;;;;;UAOA;;;;;;;;;;;;;;mBAcS;UACT;;UAEA;EAEW,YAAA,SAAS;;EA8BrB,OAAO,MAAM,aAAa,SAAS;;EAanC;;;;;EASA,YAAY,UAAU;;EAKtB,gBAAgB;;EAyBhB;;MAUI;;;;;;;;UAWH;;;;;;;;;;UAgBA;;UAgBA;;UAKA;;;;;;;;;;;;;;;;;;UClMO;;EAEf;;EAEA,WAAW;;EAEX,QAAQ,YAAY;;;UAIL;WACN,SAAS,YAAY;;iBAGhB,2BAA2B;;UAK1B;WACN,OAAO,QAAQ;WACf;;UAGM;WACN,KAAK;;;;;;;;WAQL;;;;;;;WAOA;;;;;;;;;iBAUK,iBACd,QAAQ,oBACR,SAAS,cACT,YAAY,wBACX;;;;;;;;iBAyEa,uBACd,QAAQ,oBACR,yBACA,aACC;;iBAWa,iBAAiB,QAAQ,oBAAoB;;;;;;;;;;UCvJ5C;WACN;;WAEA;;WAEA;;WAEA;;;;;;;;;cAUE;;;;;;;;iBASG,oBACd,mBACA,oBACA,kCACU;;KAqBA;;;;;;;;;KAUA;;;;;;;UASK;WACN,SAAS;WACT,YAAY;;WAEZ;;WAEA;;WAEA;;;;;;;;;;cAWE;mBAIkB;mBAHZ;UACT;EAEqB,YAAA;MAEzB;MAIA;;EAKJ,OAAO,OAAO,gBAAgB;;EAmD9B;;EAQA;UAKQ;;;;;;;;iBAsBM,cACd,WAAW,mBACX"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/outbound-delivery.ts","../../src/protocol-session.ts","../../src/settings-messages.ts","../../src/usage-messages.ts","../../src/session-events.ts","../../src/session-message-handler.ts","../../src/resume-buffer.ts","../../src/channel-frames.ts","../../src/session-resume-bridge.ts","../../src/peer-message-ledger.ts","../../src/handoff-chunking.ts"],"mappings":";;;;;;;cAkCc;;;;;;;;;KAUF,qBAAqB,SAAS;YAC9B;;;;;;;;;;;;;;;WAgBD;;;;;;;;;;KAWC,yBAAyB,OAAO,OAAO,OAAO;cA0B7C;;;;;;;;cASA;;;;;;;;;;;;iBAaG,oBACd,6BACA;;;;;;;;;;;;;cAiBW;;;;;;;UAQI;WACN;;;;;;EAMT,UAAU;;iBAGI,wBACd,uBACA,qBACC;iBAkBa,uBACd,OAAO,SAAS,yBAChB,iBAAiB,uBACjB,yCACA,0BACA,aAAY,qBACX;;;;UCpKc,yBAEb,wBACA,qBACA,kBACA,oBACA,gBACA,0BACA,0BACA,wBACA,2BACA,yBACA,0BACA,4BACA,yBACA,8BAIA;;;;;;;;;KAUQ,6BAA6B,mBAAmB,QAAQ;;;KC3C/D,mBAAmB,QAAQ;EAAkB;;iBAElC,kBAAkB,KAAK,iBAAiB,OAAO;;KAKnD;WACG;WAAmB,UAAU;;WAE7B;WACA;WACA;;;;;;;;;UAUE;EACf,YACE,SAAS,kBACT,WAAW,0BACV,oBAAoB,QAAQ;;;;;;EAM/B,eACE,SAAS,kBACT,OAAO,gBACP,WAAW,0BACV,yBAAyB,QAAQ;;iBAGtB,sBACd,SAAS,kBACT,SAAS,kBACT,KAAK,kBACL,UAAU,+BACV,WAAW;;;UCpCI;WACN,yBACH,SAAS,0BAA0B,uBAAuB,QAAQ;WAE/D,iBACH,SAAS,qBAAqB,uBAAuB,QAAQ;WAE1D,8BACL,sBAAsB,uBAAuB,QAAQ;;;;KCiB/C;;cAGC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KCaD;UAEK;;EAEf,SAAS;;;;;;;;EAQT,SAAS;;;;;;EAMT,WAAW;;EAEX,UAAU;;EAEV,OAAO;;EAEP,wBAAwB,YAAY;;EAEpC,gBAAgB,YAAY;;EAE5B,6BAA6B,YAAY;;EAEzC,mBAAmB;;EAEnB,mBAAmB;;;;;;;EAOnB,yBAAyB;;;;;;;;;;;;;;;;;;;;;iBAsBX,4BAA4B,SAAS;EACnD,YAAY;EACZ;;;;;UCxGe;WACN;WACA,SAAS;;;KAIR;WACG;WAAuB,iBAAiB;;WACxC;;UAEE;;WAEN;;WAEA;;WAEA,UAAU,SAAS;;;;;;cAUjB;mBACM;mBACA;UACT;UACA;mBAES;mBACA;mBACA;EAEE,YAAA,UAAS;;EAOrB,OAAO,SAAS;;EAYhB,WAAW;;;;;;EAWX,UAAU,kBAAkB;;MAWxB;;MAKA;UAIH;;UAeA;;;;;cC3EG,qBAAqB;;cAGrB;;iBAwCG,kBAAkB,OAAO,eAAe;;iBASxC,wBAAwB,OAAO,qBAAqB;;iBAUpD,eAAe,OAAO;;;;;;iBAsCtB,mBAAmB,OAAO,aAAa;;;;KCzG3C,eAAe;;UAGV;;;;;;;;WAQN;;WAEA,kBAAkB,OAAO,OAAO;;;;;;;;WAQhC;;UAGM;WACN,SAAS;WACT,SAAS;;WAET,WAAW;WACX,UAAU;WACV,wBAAwB;WACxB,gBAAgB;WAChB,6BAA6B;;WAE7B,yBAAyB;;cAGvB;mBACM;mBACA;UACT;mBACS;mBACA;mBACA;mBACA;UACT;;;;;;;UAOA;;;;;;;;;;;;;;mBAcS;UACT;;UAEA;EAEW,YAAA,SAAS;;EA+BrB,OAAO,MAAM,aAAa,SAAS;;EAanC;;;;;EASA,YAAY,UAAU;;EAKtB,gBAAgB;;EA4BhB;;MAUI;;;;;;;;UAWH;;;;;;;;;;UAgBA;;UAgBA;;UAKA;;;;;;;;;;;;;;;;;;UC1MO;;EAEf;;EAEA,WAAW;;EAEX,QAAQ,YAAY;;;UAIL;WACN,SAAS,YAAY;;iBAGhB,2BAA2B;;UAK1B;WACN,OAAO,QAAQ;WACf;;UAGM;WACN,KAAK;;;;;;;;WAQL;;;;;;;WAOA;;;;;;;;;iBAUK,iBACd,QAAQ,oBACR,SAAS,cACT,YAAY,wBACX;;;;;;;;iBAyEa,uBACd,QAAQ,oBACR,yBACA,aACC;;iBAWa,iBAAiB,QAAQ,oBAAoB;;;;;;;;;;UCvJ5C;WACN;;WAEA;;WAEA;;WAEA;;;;;;;;;cAUE;;;;;;;;iBASG,oBACd,mBACA,oBACA,kCACU;;KAqBA;;;;;;;;;KAUA;;;;;;;UASK;WACN,SAAS;WACT,YAAY;;WAEZ;;WAEA;;WAEA;;;;;;;;;;cAWE;mBAIkB;mBAHZ;UACT;EAEqB,YAAA;MAEzB;MAIA;;EAKJ,OAAO,OAAO,gBAAgB;;EAmD9B;;EAQA;UAKQ;;;;;;;;iBAsBM,cACd,WAAW,mBACX"}
@@ -1,2 +1,2 @@
1
- import{i as e,n as t,r as n,t as r}from"./message-decoders-CDmDoZPR.js";function i(e,t,n){if(n.type===`get-background-tasks`){t({type:`background_tasks`,tasks:e.listBackgroundTasks(n.filter)});return}if(n.type===`get-background-task`){o(e,t,n);return}if(n.type===`get-background-job-groups`){t({type:`background_job_groups`,groups:e.listBackgroundJobGroups()});return}if(n.type===`get-background-job-group`){c(e,t,n);return}if(n.type===`wait-background-job-group`){l(e,t,n);return}s(e,t,n)}function a(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}if(n.type===`cancel-background-task`){d(t,`cancel`,n.taskId,e.cancelBackgroundTask(n.taskId,n.reason));return}if(n.type===`close-background-task`){d(t,`close`,n.taskId,e.closeBackgroundTask(n.taskId));return}u(e,t,n)}function o(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}t({type:`background_task`,taskId:n.taskId,task:e.getBackgroundTask(n.taskId)??null})}function s(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}e.readBackgroundTaskLog(n.taskId,n.cursor).then(e=>t({type:`background_task_log`,taskId:n.taskId,page:e}),e=>t({type:`protocol_error`,message:e.message}))}function c(e,t,n){if(!n.groupId){t({type:`protocol_error`,message:`groupId is required`});return}t({type:`background_job_group`,groupId:n.groupId,group:e.getBackgroundJobGroup(n.groupId)??null})}function l(e,t,n){if(!n.groupId){t({type:`protocol_error`,message:`groupId is required`});return}e.waitBackgroundJobGroup(n.groupId).then(e=>t({type:`background_job_group`,groupId:n.groupId,group:e}),e=>t({type:`protocol_error`,message:e.message}))}function u(e,t,n){if(!n.input){t({type:`protocol_error`,message:`input is required`});return}d(t,`send`,n.taskId,e.sendBackgroundTask(n.taskId,n.input))}function d(e,t,n,r){r.then(()=>e({type:`background_task_control_result`,action:t,taskId:n,success:!0}),r=>e({type:`background_task_control_result`,action:t,taskId:n,success:!1,message:r.message}))}function f(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function p(e){return typeof e==`string`&&e.length>0?e:void 0}function m(e){if(!(new TextEncoder().encode(e).byteLength>4194304))try{let t=JSON.parse(e);if(!f(t))return;let n=p(t.requestId);if(!n)return;if(t.type===`get-personal-usage-report`)return{type:`personal`,requestId:n};let r=p(t.sessionId);return t.type===`get-stored-session-usage-report`&&r?{type:`stored-session`,requestId:n,sessionId:r}:void 0}catch{return}}function h(e,t,n,r){return n.type===`get-personal-usage-report`?(y(t,n,r.personalUsageReporter),!0):n.type===`get-stored-session-usage-report`?(_(t,n,r.storedSessionUsageReporter),!0):n.type===`get-usage-report`?(g(e,t,r.usageReporter),!0):!1}function g(e,t,n){if(!n){t({type:`protocol_error`,message:`Per-session usage reporting is not available on this host.`});return}try{Promise.resolve(n(e)).then(e=>t({type:`usage_report`,report:e}),e=>t({type:`protocol_error`,message:x(e)}))}catch(e){t({type:`protocol_error`,message:x(e instanceof Error?e:String(e))})}}function _(e,t,n){if(!n){v(e,t,`not_available`,`Stored-session usage reporting is not available on this host.`);return}try{Promise.resolve(n(t.sessionId)).then(n=>e({type:`stored_session_usage_report`,requestId:t.requestId,sessionId:t.sessionId,report:n}),n=>v(e,t,`report_failed`,x(n)))}catch(n){v(e,t,`report_failed`,x(n instanceof Error?n:String(n)))}}function v(e,t,n,r){e({type:`stored_session_usage_report_error`,requestId:t.requestId,sessionId:t.sessionId,code:n,message:r})}function y(e,t,n){if(!n){b(e,t.requestId,`not_available`,`Personal usage reporting is not available on this host.`);return}try{Promise.resolve(n({period:t.period,timezone:t.timezone})).then(n=>e({type:`personal_usage_report`,requestId:t.requestId,report:n}),n=>b(e,t.requestId,`report_failed`,x(n)))}catch(n){b(e,t.requestId,`report_failed`,x(n instanceof Error?n:String(n)))}}function b(e,t,n,r){e({type:`personal_usage_report_error`,requestId:t,code:n,message:r})}function x(e){return e instanceof Error?e.message:String(e)}function S(e,r){let i=n(e,t);if(i.ok)return i.message;let a=m(e);return a?.type===`personal`?(r({type:`personal_usage_report_error`,requestId:a.requestId,code:`report_failed`,message:`Invalid personal usage report request.`}),null):a?.type===`stored-session`?(r({type:`stored_session_usage_report_error`,requestId:a.requestId,sessionId:a.sessionId,code:`report_failed`,message:`Invalid stored-session usage report request.`}),null):(r({type:`protocol_error`,message:i.reason}),null)}const C={text_delta:`forwarded`,tool_start:`forwarded`,tool_end:`forwarded`,thinking:`forwarded`,complete:`forwarded`,error:`forwarded`,context_update:`non-surface`,compact:`non-surface`,interrupted:`forwarded`,skill_activation:`non-surface`,background_task_event:`forwarded`,background_job_group_event:`forwarded`,execution_workspace_event:`forwarded`,user_message:`forwarded`,turn_source:`non-surface`,context_file_refreshed:`forwarded`,memory_event:`non-surface`,goal_event:`non-surface`,plan_event:`forwarded`,branch_event:`forwarded`,permission_request:`forwarded`,ask_request:`forwarded`,prompt_resolved:`forwarded`,ui_intent:`requester-routed`,session_renamed:`forwarded`,history_cleared:`forwarded`};function w(e,t,n={}){let r=()=>{let t=e.getActiveDriverId();return t?{driverId:t}:{}},i=e=>t({type:`user_message`,content:e,...r()}),a=e=>t({type:`text_delta`,delta:e,...r()}),o=e=>t({type:`tool_start`,state:e,...r()}),s=e=>t({type:`tool_end`,state:e,...r()}),c=e=>t({type:`thinking`,isThinking:e,...r()}),l=e=>t({type:`complete`,result:e,...r()}),u=e=>t({type:`interrupted`,result:e,...r()}),d=e=>t({type:`error`,message:e.message,...r()}),f=e=>t({type:`background_task_event`,event:e}),p=e=>t({type:`background_job_group_event`,event:e}),m=e=>t({type:`execution_workspace_event`,snapshot:e.snapshot}),h=e=>t({type:`plan_event`,event:e}),g=e=>t({type:`context_file_refreshed`,event:e}),_=e=>t({type:`branch_event`,event:e}),v=e=>t({type:`permission_request`,event:e}),y=e=>t({type:`ask_request`,event:e}),b=e=>t({type:`prompt_resolved`,event:e}),x=e=>{(e.requesterDriverId===void 0||e.requesterDriverId===n.getSurfaceDriverId?.())&&t({type:`ui_intent`,event:e})},S=e=>t({type:`session_renamed`,event:e}),C=()=>t({type:`history_cleared`});return e.on(`user_message`,i),e.on(`text_delta`,a),e.on(`tool_start`,o),e.on(`tool_end`,s),e.on(`thinking`,c),e.on(`complete`,l),e.on(`interrupted`,u),e.on(`error`,d),e.on(`background_task_event`,f),e.on(`background_job_group_event`,p),e.on(`execution_workspace_event`,m),e.on(`plan_event`,h),e.on(`context_file_refreshed`,g),e.on(`branch_event`,_),e.on(`permission_request`,v),e.on(`ask_request`,y),e.on(`prompt_resolved`,b),e.on(`ui_intent`,x),e.on(`session_renamed`,S),e.on(`history_cleared`,C),()=>{e.off(`user_message`,i),e.off(`text_delta`,a),e.off(`tool_start`,o),e.off(`tool_end`,s),e.off(`thinking`,c),e.off(`complete`,l),e.off(`interrupted`,u),e.off(`error`,d),e.off(`background_task_event`,f),e.off(`background_job_group_event`,p),e.off(`execution_workspace_event`,m),e.off(`plan_event`,h),e.off(`context_file_refreshed`,g),e.off(`branch_event`,_),e.off(`permission_request`,v),e.off(`ask_request`,y),e.off(`prompt_resolved`,b),e.off(`ui_intent`,x),e.off(`session_renamed`,S),e.off(`history_cleared`,C)}}function T(e){return e.type===`get-messages`||e.type===`get-context`||e.type===`get-executing`||e.type===`get-pending`||e.type===`get-execution-workspace`}function ee(e,t,n){n.type===`get-messages`?t({type:`messages`,messages:e.getMessages()}):n.type===`get-context`?t({type:`context`,state:e.getContextState()}):n.type===`get-executing`?t({type:`executing`,executing:e.isExecuting()}):n.type===`get-execution-workspace`?t({type:`execution_workspace_event`,snapshot:e.getExecutionWorkspaceSnapshot()}):t({type:`pending`,pending:e.getPendingPrompt()})}function E(e){let t=w(e.session,e.deliver,{getSurfaceDriverId:()=>e.driverId});return{onMessage:D(e.session,e.deliver,e.driverId,{personalUsageReporter:e.personalUsageReporter,usageReporter:e.usageReporter,storedSessionUsageReporter:e.storedSessionUsageReporter},e.surface),cleanup:t}}function D(e,t,n,r=O,i){return a=>{let o=S(a,t);o&&k(e,t,o,n,r,i)}}const O={personalUsageReporter:void 0,usageReporter:void 0,storedSessionUsageReporter:void 0};function k(e,t,n,r,o=O,s){if(h(e,t,n,o))return;if(te(n)){P(e,t,n,r,s);return}if(T(n)){ee(e,t,n);return}if(A(n)){i(e,t,n);return}if(j(n)){a(e,t,n);return}if(M(n)){N(e,n,r);return}let c=n.type;t({type:`protocol_error`,message:`Unknown message type: ${c}`})}function te(e){return e.type===`submit`||e.type===`command`||e.type===`abort`||e.type===`cancel-queue`}function A(e){return e.type===`get-background-tasks`||e.type===`get-background-task`||e.type===`read-background-task-log`||e.type===`get-background-job-groups`||e.type===`get-background-job-group`||e.type===`wait-background-job-group`}function j(e){return e.type===`cancel-background-task`||e.type===`close-background-task`||e.type===`send-background-task`}function M(e){return e.type===`permission-response`||e.type===`ask-response`}function N(e,t,n){t.type===`permission-response`?e.resolvePermission(t.id,t.result,n):e.resolveAsk(t.id,t.response,n)}function P(e,t,n,r,i){if(n.type===`submit`){if(typeof n.prompt!=`string`||n.prompt.length===0){t({type:`protocol_error`,message:`prompt must be a non-empty string`});return}let a={...r?{driverId:r}:{},...i?{surface:i}:{}};e.submit(n.prompt,void 0,void 0,Object.keys(a).length>0?a:void 0).catch(e=>{t({type:`protocol_error`,message:e.message})})}else if(n.type===`command`){if(!n.name){t({type:`protocol_error`,message:`name is required`});return}e.executeCommand(n.name,n.args??``,`remote`,r).then(e=>{t({type:`command_result`,name:n.name,message:e?.message??`Unknown command: ${n.name}`,success:e?.success??!1,data:e?.data})},e=>{t({type:`protocol_error`,message:e.message})})}else n.type===`abort`?e.abort():e.cancelQueue()}const F=8*1048576;function I(e,t=F){return e!==void 0&&e>t}const L=120*1e3;function R(e=L,t=Date.now){let n;return{maxPendingMs:e,observe(r){if(r===void 0)return;if(r===0){n=void 0;return}let i=t();n??=i;let a=i-n;return a>e?a:void 0}}}function z(e,t,n,r=F,i=R()){let a=!1,o=t=>{if(a)return;let o=n?.();if(I(o,r)){a=!0,s(Error(`outbound backpressure budget exceeded: ${o} byte(s) pending, limit ${r}. The peer has accepted frames it is not reading.`),t.type);return}let c=i.observe(o);if(c!==void 0){a=!0,s(Error(`outbound drain budget exceeded: ${o} byte(s) pending for ${c} ms, limit ${i.maxPendingMs} ms. The peer is reading too slowly to ever drain what it accepted.`),t.type);return}try{e(t)}catch(e){a=!0,s(e instanceof Error?e:Error(String(e)),t.type)}};function s(e,n){try{t(e,n)}catch{}}return Object.assign(o,{pendingBytes:()=>n?.()})}var B=class{frames=[];sizes=[];nextSeq=1;bytes=0;maxFrames;maxBytes;sizeOf;constructor(e={}){this.maxFrames=e.maxFrames??512,this.maxBytes=e.maxBytes??4194304,this.sizeOf=e.sizeOf??(e=>JSON.stringify(e).length)}append(e){let t=this.nextSeq;this.nextSeq+=1;let n=this.sizeOf(e);return this.frames.push({seq:t,message:e}),this.sizes.push(n),this.bytes+=n,this.evict(),t}ackThrough(e){let t=0;for(;t<this.frames.length&&this.frames[t].seq<=e;)t+=1;this.removeOldest(t)}tailAfter(e){return this.frames.length===0?e>=this.nextSeq-1?{kind:`tail`,frames:[]}:{kind:`overrun`}:e<this.frames[0].seq-1?{kind:`overrun`}:{kind:`tail`,frames:this.frames.filter(t=>t.seq>e)}}get lastSeq(){return this.nextSeq-1}get size(){return this.frames.length}evict(){let e=0,t=this.bytes;for(;this.frames.length-e>this.maxFrames||t>this.maxBytes&&this.frames.length-e>1;)t-=this.sizes[e],e+=1;this.removeOldest(e)}removeOldest(e){if(!(e<=0)){for(let t=0;t<e;t+=1)this.bytes-=this.sizes[t]??0;this.frames.splice(0,e),this.sizes.splice(0,e),this.frames.length===0&&(this.bytes=0)}}};const V=new TextEncoder,H=new TextDecoder,U=V.encode(`RBF`),W=1,G=4294967295;function K(e,t){let n=V.encode(e);if(n.byteLength===0||n.byteLength>255)throw Error(`channel name must be 1..255 UTF-8 bytes (got ${n.byteLength})`);if(!Number.isInteger(t)||t<0||t>G)throw Error(`seq must be an integer in 0..${G} (got ${t})`);return n}function q(e,t,n,r){e.set(U,0),e[3]=1,e[4]=t,e[5]=n.byteLength,e.set(n,6);let i=6+n.byteLength;return new DataView(e.buffer,e.byteOffset,e.byteLength).setUint32(i,r,!1),i+4}function J(e){let t=K(e.channel,e.seq),n=new Uint8Array(6+t.byteLength+4+e.payload.byteLength),r=q(n,1,t,e.seq);return n.set(e.payload,r),n}function Y(e){let t=K(e.channel,e.seq),n=V.encode(JSON.stringify({event:e.event,payload:e.payload})),r=new Uint8Array(6+t.byteLength+4+n.byteLength),i=q(r,2,t,e.seq);return r.set(n,i),r}function X(e){return e.byteLength<U.length?!1:U.every((t,n)=>e[n]===t)}function Z(e){let t=H.decode(e),n;try{n=JSON.parse(t)}catch{return{ok:!1,error:`channel frame: malformed JSON body`}}if(typeof n!=`object`||!n||Array.isArray(n))return{ok:!1,error:`channel frame: event body must be a JSON object`};let{event:r,payload:i}=n;return typeof r!=`string`||r.length===0?{ok:!1,error:"channel frame: event body is missing a non-empty `event` name"}:{ok:!0,event:r,payload:i??null}}function ne(e){if(!X(e))return{ok:!1,error:`channel frame: bad magic (not a channel frame)`};if(e.byteLength<6)return{ok:!1,error:`channel frame: truncated header`};if(e[3]!==1)return{ok:!1,error:`channel frame: unsupported version ${String(e[3])}`};let t=e[4],n=e[5]??0;if(n===0)return{ok:!1,error:`channel frame: empty channel name`};let r=6+n,i=r+4;if(e.byteLength<i)return{ok:!1,error:`channel frame: truncated (header longer than the frame)`};let a=H.decode(e.subarray(6,r)),o=new DataView(e.buffer,e.byteOffset,e.byteLength).getUint32(r,!1),s=e.subarray(i);if(t===1)return{ok:!0,frame:{kind:`binary`,channel:a,seq:o,payload:Uint8Array.from(s)}};if(t===2){let e=Z(s);return e.ok?{ok:!0,frame:{kind:`event`,channel:a,seq:o,event:e.event,payload:e.payload}}:{ok:!1,error:e.error}}return{ok:!1,error:`channel frame: unknown kind ${String(t)}`}}var re=class{session;buffer;driverId;reporters;surface;unsubscribe;onDeliveryError;outbound;emitBoundary;disposed=!1;holding=!1;constructor(e){this.session=e.session,this.buffer=new B(e.buffer),this.driverId=e.driverId,this.surface=e.surface,this.reporters={personalUsageReporter:e.personalUsageReporter,usageReporter:e.usageReporter,storedSessionUsageReporter:e.storedSessionUsageReporter},this.emitBoundary=z(e=>this.emit(e),(e,t)=>this.reportDeliveryError(e,t)),this.unsubscribe=w(this.session,this.emitBoundary,{getSurfaceDriverId:()=>this.driverId})}attach(e,t){this.disposed||(this.onDeliveryError=t.onDeliveryError,this.outbound=z(t=>e(JSON.stringify(t)),(e,t)=>this.reportDeliveryError(e,t),t.pendingBytes),this.holding=t.awaitResume===!0)}detach(){this.outbound=void 0,this.onDeliveryError=void 0}setDriverId(e){this.driverId=e}onClientMessage(e){if(this.disposed)return;let t=S(e,this.emitBoundary);if(t){if(t.type===`resume`){this.replay(t.lastSeq);return}if(t.type===`ack`){this.buffer.ackThrough(t.seq);return}k(this.session,this.emitBoundary,t,this.driverId,this.reporters,this.surface)}}dispose(){this.disposed||(this.disposed=!0,this.detach(),this.unsubscribe())}get lastSeq(){return this.buffer.lastSeq}emit(e){if(this.disposed)return;let t=this.buffer.append(e);this.holding||this.deliverFrame({...e,seq:t})}replay(e){let t=this.buffer.tailAfter(e);if(t.kind===`overrun`){this.deliverFrame({type:`resume_gap`}),this.holding=!1;return}for(let e of t.frames)this.deliverFrame({...e.message,seq:e.seq});this.holding=!1}deliverFrame(e){this.outbound?.(e)}reportDeliveryError(e,t){let n=this.onDeliveryError;this.detach();try{n?.(e,t)}catch{}}};function ie(){return{origins:new Map}}function ae(e,t,n){let r=t.origin.sessionId,i=e.origins.get(r);i===void 0&&(i={highestSequence:0,delivered:new Set,issued:new Map},e.origins.set(r,i));let a=i.issued.get(t.id);if(a!==void 0)return{ack:{...a,state:`duplicate`},deliver:!1};if(n!==void 0){let e={id:t.id,sequence:t.sequence,state:n.state,reason:n.reason};return i.issued.set(t.id,e),{ack:e,deliver:!1}}if(i.delivered.has(t.sequence)){let e={id:t.id,sequence:t.sequence,state:`refused`,reason:`sequence ${t.sequence} was already delivered by this origin under a different message id. A retry must repeat its id; a new id on a delivered sequence cannot be ordered against what the receiver already has.`};return i.issued.set(t.id,e),{ack:e,deliver:!1}}let o=i.highestSequence+1,s=t.sequence>o?o:void 0,c={id:t.id,sequence:t.sequence,state:`delivered`};return i.issued.set(t.id,c),i.delivered.add(t.sequence),i.highestSequence=Math.max(i.highestSequence,t.sequence),s===void 0?{ack:c,deliver:!0}:{ack:c,deliver:!0,gapBefore:s}}function oe(e,t,n){let r=e.origins.get(t),i=r?.issued.get(n);if(r===void 0||i===void 0||i.state!==`delivered`)return;let a={...i,state:`acknowledged`};return r.issued.set(n,a),a}function se(e,t){e.origins.delete(t)}const Q=16*1024;function ce(e,t,n=Q){if(!Number.isInteger(n)||n<1)throw Error(`handoff chunking: maxChunkBytes must be a positive integer, got ${n}. A zero or negative budget produces an infinite sequence of empty chunks, which presents as a hang rather than as the configuration error it is.`);let r=Buffer.from(t,`utf8`),i=Math.max(1,Math.ceil(r.byteLength/n)),a=[];for(let t=0;t<i;t+=1){let o=r.subarray(t*n,(t+1)*n);a.push({handoffId:e,index:t,total:i,data:o.toString(`base64`)})}return a}var le=class{handoffId;chunks=new Map;declaredTotal;constructor(e){this.handoffId=e}get received(){return this.chunks.size}get expected(){return this.declaredTotal}accept(e){let t=e=>({outcome:`refused`,rejection:e,received:this.chunks.size,...this.declaredTotal===void 0?{}:{expected:this.declaredTotal}});if(e.handoffId!==this.handoffId)return t(`wrong-handoff`);if(!Number.isInteger(e.total)||e.total<1||this.declaredTotal!==void 0&&e.total!==this.declaredTotal)return t(`inconsistent-total`);if(!Number.isInteger(e.index)||e.index<0||e.index>=e.total)return t(`out-of-range`);let n=Buffer.from(e.data,`base64`);if(n.toString(`base64`)!==e.data)return t(`undecodable`);this.declaredTotal=e.total;let r=this.chunks.get(e.index);return r===void 0?(this.chunks.set(e.index,n),this.chunks.size<e.total?{outcome:`accepted`,received:this.chunks.size,expected:e.total}:{outcome:`complete`,serialized:this.reassemble(e.total),received:this.chunks.size,expected:e.total}):r.equals(n)?{outcome:`duplicate`,received:this.chunks.size,expected:e.total}:t(`inconsistent-total`)}missing(){if(this.declaredTotal===void 0)return[];let e=[];for(let t=0;t<this.declaredTotal;t+=1)this.chunks.has(t)||e.push(t);return e}discard(){this.chunks.clear(),this.declaredTotal=void 0}reassemble(e){let t=[];for(let n=0;n<e;n+=1){let r=this.chunks.get(n);if(r===void 0)throw Error(`handoff chunking: chunk ${n} of ${e} is missing at reassembly.`);t.push(r)}return Buffer.concat(t).toString(`utf8`)}};function $(e,t=Q){return Math.max(1,Math.ceil(e.byteLength/t))}export{U as CHANNEL_FRAME_MAGIC,W as CHANNEL_FRAME_VERSION,Q as DEFAULT_MAX_CHUNK_BYTES,F as DEFAULT_MAX_PENDING_BYTES,L as DEFAULT_MAX_PENDING_MS,le as HandoffChunkAssembler,r as MAX_INBOUND_FRAME_BYTES,C as PROTOCOL_SESSION_EVENT_CLASSIFICATION,B as ResumeBuffer,re as SessionResumeBridge,oe as acknowledgePeerMessage,ae as admitPeerMessage,$ as chunkCountFor,ce as chunkHandoffPayload,z as createOutboundDelivery,ie as createPeerMessageLedger,R as createPendingStallClock,E as createSessionMessageHandler,ne as decodeChannelFrame,t as decodeClientMessage,n as decodeFrame,e as decodeServerMessage,J as encodeBinaryFrame,Y as encodeChannelEventFrame,se as forgetPeerOrigin,X as isChannelFrame,I as isOverPendingBudget};
1
+ import{a as e,i as t,n,r,t as i}from"./observer-messages-CEeisRaF.js";import{isSessionChangeRefusal as a,isSessionDeleteRefusal as o}from"@robota-sdk/agent-interface-session";import{AuthenticationError as s,ModelNotAvailableError as c,NetworkError as l,ProviderError as u,RateLimitError as d}from"@robota-sdk/agent-core";function f(e,t,n){if(n.type===`get-background-tasks`){t({type:`background_tasks`,tasks:e.listBackgroundTasks(n.filter)});return}if(n.type===`get-background-task`){m(e,t,n);return}if(n.type===`get-background-job-groups`){t({type:`background_job_groups`,groups:e.listBackgroundJobGroups()});return}if(n.type===`get-background-job-group`){g(e,t,n);return}if(n.type===`wait-background-job-group`){_(e,t,n);return}h(e,t,n)}function p(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}if(n.type===`cancel-background-task`){y(t,`cancel`,n.taskId,e.cancelBackgroundTask(n.taskId,n.reason));return}if(n.type===`close-background-task`){y(t,`close`,n.taskId,e.closeBackgroundTask(n.taskId));return}v(e,t,n)}function m(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}t({type:`background_task`,taskId:n.taskId,task:e.getBackgroundTask(n.taskId)??null})}function h(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}e.readBackgroundTaskLog(n.taskId,n.cursor).then(e=>t({type:`background_task_log`,taskId:n.taskId,page:e}),e=>t({type:`protocol_error`,message:e.message}))}function g(e,t,n){if(!n.groupId){t({type:`protocol_error`,message:`groupId is required`});return}t({type:`background_job_group`,groupId:n.groupId,group:e.getBackgroundJobGroup(n.groupId)??null})}function _(e,t,n){if(!n.groupId){t({type:`protocol_error`,message:`groupId is required`});return}e.waitBackgroundJobGroup(n.groupId).then(e=>t({type:`background_job_group`,groupId:n.groupId,group:e}),e=>t({type:`protocol_error`,message:e.message}))}function v(e,t,n){if(!n.input){t({type:`protocol_error`,message:`input is required`});return}y(t,`send`,n.taskId,e.sendBackgroundTask(n.taskId,n.input))}function y(e,t,n,r){r.then(()=>e({type:`background_task_control_result`,action:t,taskId:n,success:!0}),r=>e({type:`background_task_control_result`,action:t,taskId:n,success:!1,message:r.message}))}function b(e){return e.type===`stop-waiting-loop`}function x(e,t,n){let{requestId:r}=n;e.stopWaitingSelfPacedLoop().then(e=>t({type:`waiting_loop_stop`,requestId:r,outcome:e}),e=>t({type:`waiting_loop_stop`,requestId:r,outcome:{kind:`failed`,message:S(e)}}))}function S(e){return e instanceof Error?e.message:String(e)}function C(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function w(e){return typeof e==`string`&&e.length>0?e:void 0}function T(e){if(!(new TextEncoder().encode(e).byteLength>4194304))try{let t=JSON.parse(e);if(!C(t))return;let n=w(t.requestId);if(!n)return;if(t.type===`get-personal-usage-report`)return{type:`personal`,requestId:n};let r=w(t.sessionId);return t.type===`get-stored-session-usage-report`&&r?{type:`stored-session`,requestId:n,sessionId:r}:void 0}catch{return}}function E(e,t,n,r){return n.type===`get-personal-usage-report`?(A(t,n,r.personalUsageReporter),!0):n.type===`get-stored-session-usage-report`?(O(t,n,r.storedSessionUsageReporter),!0):n.type===`get-usage-report`?(D(e,t,r.usageReporter),!0):!1}function D(e,t,n){if(!n){t({type:`protocol_error`,message:`Per-session usage reporting is not available on this host.`});return}try{Promise.resolve(n(e)).then(e=>t({type:`usage_report`,report:e}),e=>t({type:`protocol_error`,message:M(e)}))}catch(e){t({type:`protocol_error`,message:M(e instanceof Error?e:String(e))})}}function O(e,t,n){if(!n){k(e,t,`not_available`,`Stored-session usage reporting is not available on this host.`);return}try{Promise.resolve(n(t.sessionId)).then(n=>e({type:`stored_session_usage_report`,requestId:t.requestId,sessionId:t.sessionId,report:n}),n=>k(e,t,`report_failed`,M(n)))}catch(n){k(e,t,`report_failed`,M(n instanceof Error?n:String(n)))}}function k(e,t,n,r){e({type:`stored_session_usage_report_error`,requestId:t.requestId,sessionId:t.sessionId,code:n,message:r})}function A(e,t,n){if(!n){j(e,t.requestId,`not_available`,`Personal usage reporting is not available on this host.`);return}try{Promise.resolve(n({period:t.period,timezone:t.timezone})).then(n=>e({type:`personal_usage_report`,requestId:t.requestId,report:n}),n=>j(e,t.requestId,`report_failed`,M(n)))}catch(n){j(e,t.requestId,`report_failed`,M(n instanceof Error?n:String(n)))}}function j(e,t,n,r){e({type:`personal_usage_report_error`,requestId:t,code:n,message:r})}function M(e){return e instanceof Error?e.message:String(e)}function ee(e,n){let i=t(e,r);if(i.ok)return i.message;let a=T(e);return a?.type===`personal`?(n({type:`personal_usage_report_error`,requestId:a.requestId,code:`report_failed`,message:`Invalid personal usage report request.`}),null):a?.type===`stored-session`?(n({type:`stored_session_usage_report_error`,requestId:a.requestId,sessionId:a.sessionId,code:`report_failed`,message:`Invalid stored-session usage report request.`}),null):(n({type:`protocol_error`,message:i.reason}),null)}function te(e){return e.type===`project-status`||e.type===`project-diff`||e.type===`project-memory`}function N(e,t){e({type:`protocol_error`,message:`This host does not support the Project panel.`,requestId:t})}function ne(e,t,n){let{requestId:r}=n;if(n.type===`project-status`){if(!e.readProjectStatus)return N(t,r);e.readProjectStatus().then(e=>t({type:`project_status`,requestId:r,result:e}),e=>t({type:`project_status`,requestId:r,result:{kind:`failed`,message:e instanceof Error?e.message:String(e)}}))}else if(n.type===`project-diff`){if(!e.readProjectDiff)return N(t,r);e.readProjectDiff(n.path).then(e=>t({type:`project_diff`,requestId:r,result:e}),e=>t({type:`project_diff`,requestId:r,result:{kind:`failed`,message:e instanceof Error?e.message:String(e)}}))}else{if(!e.readProjectMemory)return N(t,r);e.readProjectMemory().then(e=>t({type:`project_memory`,requestId:r,result:e}),e=>t({type:`project_memory`,requestId:r,result:{kind:`unavailable`,message:e instanceof Error?e.message:String(e)}}))}}function re(e){return e.type===`list-sessions`||e.type===`new-session`||e.type===`switch-session`}function ie(e){return e.type===`rename-session`}function ae(e){return e.type===`delete-session`}function oe(e,t,n){if(t.type===`list-sessions`){se(e,t.requestId,n);return}let r=t.requestId===void 0?{}:{requestId:t.requestId};if(!n){e({type:`session_change_failed`,code:`not_available`,message:`Sessions cannot be switched on this host.`,...r});return}Promise.resolve().then(()=>t.type===`new-session`?n.newSession():n.switchSession(t.sessionId)).catch(t=>e({type:`session_change_failed`,code:a(t)?t.code:`failed`,message:P(t),...r}))}function se(e,t,n){if(!n){e({type:`sessions_error`,requestId:t,code:`not_available`,message:`Session listing is not available on this host.`});return}try{e({type:`sessions`,requestId:t,listing:n.listSessions()})}catch(n){e({type:`sessions_error`,requestId:t,code:`list_failed`,message:P(n instanceof Error?n:String(n))})}}function P(e){return e instanceof Error?e.message:String(e)}function ce(e,t,n){if(!n){e({type:`session_rename_failed`,requestId:t.requestId,message:`Sessions cannot be renamed on this host.`});return}n.renameSession(t.sessionId,t.name).then(()=>e({type:`session_renamed_in_list`,requestId:t.requestId,sessionId:t.sessionId,name:t.name}),n=>e({type:`session_rename_failed`,requestId:t.requestId,message:P(n)}))}function le(e,t,n){if(!n){e({type:`session_delete_failed`,requestId:t.requestId,code:`not_available`,message:`Sessions cannot be deleted on this host.`});return}n.deleteSession(t.sessionId).then(()=>e({type:`session_deleted`,requestId:t.requestId,sessionId:t.sessionId}),n=>e({type:`session_delete_failed`,requestId:t.requestId,code:o(n)?n.code:`failed`,message:P(n)}))}const F=new WeakMap;function ue(e){let t=F.get(e);t===void 0&&(t={frames:new Map,holders:0},F.set(e,t));let n=t;n.holders+=1;let r=!1;return{record:e=>{r||n.frames.set(e.event.id,e)},forget:e=>{n.frames.delete(e)},clear:()=>{n.frames.clear()},release:()=>{r||(r=!0,--n.holders,n.holders===0&&F.get(e)===n&&F.delete(e))}}}function de(e){return[...F.get(e)?.frames.values()??[]]}function fe(e){let t=[],n=new Set,r=[e];for(let e=0;e<=8&&r.length>0;e++){let e=[];for(let i of r)if(!(i==null||n.has(i))&&(n.add(i),t.push(i),typeof i==`object`)){let t=i;e.push(t.originalError,t.cause)}r=e}return t}function pe(e){let t;for(let n of fe(e)){if(n instanceof s)return{code:`auth`,...n.provider!==void 0&&{provider:n.provider}};if(n instanceof d)return{code:`rate_limit`,...n.provider!==void 0&&{provider:n.provider},...n.retryAfter!==void 0&&{retryAfterSeconds:n.retryAfter}};if(n instanceof c)return{code:`model_unavailable`,provider:n.provider,...n.model!==void 0&&{model:n.model}};if(n instanceof l)return{code:`network`,...n.provider!==void 0&&{provider:n.provider}};t===void 0&&n instanceof u&&(t={code:`provider`,provider:n.provider})}return t??{}}const me={text_delta:`forwarded`,tool_start:`forwarded`,tool_end:`forwarded`,thinking:`forwarded`,complete:`forwarded`,error:`forwarded`,context_update:`forwarded`,compact:`forwarded`,interrupted:`forwarded`,skill_activation:`forwarded`,background_task_event:`forwarded`,background_job_group_event:`forwarded`,execution_workspace_event:`forwarded`,user_message:`forwarded`,turn_source:`forwarded`,context_file_refreshed:`forwarded`,memory_event:`forwarded`,goal_event:`non-surface`,plan_event:`forwarded`,branch_event:`forwarded`,permission_request:`forwarded`,ask_request:`forwarded`,prompt_resolved:`forwarded`,ui_intent:`requester-routed`,session_renamed:`forwarded`,history_cleared:`forwarded`,session_switched:`forwarded`,status_changed:`forwarded`};function he(e,t,n={}){let r=()=>{let t=e.getActiveDriverId();return t?{driverId:t}:{}},i=e=>t({type:`user_message`,content:e,...r()}),a=e=>t({type:`text_delta`,delta:e,...r()}),o=e=>t({type:`tool_start`,state:e,...r()}),s=e=>t({type:`tool_end`,state:e,...r()}),c=e=>t({type:`thinking`,isThinking:e,...r()}),l=e=>t({type:`complete`,result:I(e),...r()}),u=e=>t({type:`interrupted`,result:I(e),...r()}),d=e=>t({type:`error`,message:e.message,...pe(e),...r()}),f=e=>t({type:`background_task_event`,event:e}),p=e=>t({type:`background_job_group_event`,event:e}),m=e=>t({type:`execution_workspace_event`,snapshot:e.snapshot}),h=e=>t({type:`plan_event`,event:e}),g=e=>t({type:`context_file_refreshed`,event:e}),_=e=>t({type:`branch_event`,event:e}),v=n.receivePrompts??!0,y=v?ue(e):void 0,b=e=>{let n={type:`permission_request`,event:e};y?.record(n),t(n)},x=e=>{let n={type:`ask_request`,event:e};y?.record(n),t(n)},S=e=>{y?.forget(e.id),t({type:`prompt_resolved`,event:e})},C=e=>{(e.requesterDriverId===void 0||e.requesterDriverId===n.getSurfaceDriverId?.())&&t({type:`ui_intent`,event:e})},w=e=>t({type:`session_renamed`,event:e}),T=()=>t({type:`history_cleared`}),E=e=>{y?.clear(),t({type:`session_switched`,event:e})},D=e=>t({type:`context`,state:e}),O=()=>t({type:`history_changed`}),k=e=>t({type:`turn_source`,source:e}),A=e=>t({type:`session_status`,status:e});return e.on(`user_message`,i),e.on(`text_delta`,a),e.on(`tool_start`,o),e.on(`tool_end`,s),e.on(`thinking`,c),e.on(`complete`,l),e.on(`interrupted`,u),e.on(`error`,d),e.on(`background_task_event`,f),e.on(`background_job_group_event`,p),e.on(`execution_workspace_event`,m),e.on(`plan_event`,h),e.on(`context_file_refreshed`,g),e.on(`branch_event`,_),v&&(e.on(`permission_request`,b),e.on(`ask_request`,x)),e.on(`prompt_resolved`,S),e.on(`ui_intent`,C),e.on(`session_renamed`,w),e.on(`history_cleared`,T),e.on(`session_switched`,E),e.on(`context_update`,D),e.on(`compact`,O),e.on(`skill_activation`,O),e.on(`memory_event`,O),e.on(`turn_source`,k),e.on(`status_changed`,A),()=>{e.off(`user_message`,i),e.off(`text_delta`,a),e.off(`tool_start`,o),e.off(`tool_end`,s),e.off(`thinking`,c),e.off(`complete`,l),e.off(`interrupted`,u),e.off(`error`,d),e.off(`background_task_event`,f),e.off(`background_job_group_event`,p),e.off(`execution_workspace_event`,m),e.off(`plan_event`,h),e.off(`context_file_refreshed`,g),e.off(`branch_event`,_),v&&(e.off(`permission_request`,b),e.off(`ask_request`,x)),e.off(`prompt_resolved`,S),e.off(`ui_intent`,C),e.off(`session_renamed`,w),e.off(`history_cleared`,T),e.off(`session_switched`,E),e.off(`context_update`,D),e.off(`compact`,O),e.off(`skill_activation`,O),e.off(`memory_event`,O),e.off(`turn_source`,k),e.off(`status_changed`,A),y?.release()}}function I(e){let{history:t,...n}=e;return n}const ge=new TextEncoder;function _e(e){return e.type===`get-messages`||e.type===`get-history`||e.type===`get-prompts`||e.type===`get-context`||e.type===`get-commands`||e.type===`get-status`||e.type===`list-models`||e.type===`get-agent-definitions`||e.type===`get-executing`||e.type===`get-pending`||e.type===`get-execution-workspace`||e.type===`read-execution-detail`}function ve(e,t,n){if(n.type===`get-messages`)t({type:`messages`,messages:e.getMessages(),display:e.getMessagesDisplay()});else if(n.type===`get-history`)t(be(e,n.fromIndex??0));else if(n.type===`get-prompts`)for(let n of de(e))t(n);else if(n.type===`get-context`)t({type:`context`,state:e.getContextState()});else if(n.type===`get-commands`)t({type:`commands`,commands:e.listCommands(),skills:e.listSkills()});else if(n.type===`get-status`)t({type:`session_status`,status:e.getStatusSnapshot()});else if(n.type===`list-models`){let r=e.listModels();t({type:`model_list`,requestId:n.requestId,...r})}else n.type===`get-agent-definitions`?t({type:`agent_definitions`,requestId:n.requestId,agents:e.listAgentDefinitions(),current:e.getDefaultAgentType()}):n.type===`get-executing`?t({type:`executing`,executing:e.isExecuting()}):n.type===`get-execution-workspace`?t({type:`execution_workspace_event`,snapshot:e.getExecutionWorkspaceSnapshot()}):n.type===`read-execution-detail`?ye(e,t,n):t(L(e))}function ye(e,t,n){let{requestId:r}=n;e.readExecutionWorkspaceDetail(n.entryId,n.cursor).then(e=>t({type:`execution_detail`,requestId:r,page:e}),e=>t({type:`execution_detail_error`,requestId:r,message:e instanceof Error?e.message:String(e)}))}function L(e){return{type:`pending`,pending:e.getPendingPrompt(),pendingCount:e.getPendingCount()}}function be(e,t){let n=e.getFullHistory(),r=n.length,i=Math.min(t,r),a=[],o=0;for(let e=i;e<r;e+=1){let t=xe(n[e]),r=ge.encode(JSON.stringify(t)).byteLength;if(a.length>0&&o+r>262144)break;a.push(t),o+=r}return{type:`history`,startIndex:i,total:r,entries:a}}function xe(e){return{...e,timestamp:Se(e.timestamp)}}function Se(e){return typeof e==`string`?e:e.toISOString()}function R(e){return e.type===`get-settings`||e.type===`update-settings`}function z(e,t,n,r,i){if(!r){B(t,n.requestId,`not_available`,`Settings are not available on this host.`);return}try{if(n.type===`get-settings`){Promise.resolve(r.getSettings(e,i)).then(e=>t({type:`settings`,requestId:n.requestId,settings:e}),e=>B(t,n.requestId,`update_failed`,V(e)));return}Promise.resolve(r.updateSettings(e,n.patch,i)).then(e=>{e.ok?t({type:`settings`,requestId:n.requestId,settings:e.settings}):B(t,n.requestId,e.code,e.message)},e=>B(t,n.requestId,`update_failed`,V(e)))}catch(e){B(t,n.requestId,`update_failed`,V(e instanceof Error?e:String(e)))}}function B(e,t,n,r){e({type:`settings_error`,requestId:t,code:n,message:r})}function V(e){return e instanceof Error?e.message:String(e)}function Ce(e){let t=e.role??`drive`,n=he(e.session,e.deliver,{getSurfaceDriverId:()=>e.driverId,receivePrompts:t===`drive`});return{onMessage:we(e.session,e.deliver,e.driverId,{personalUsageReporter:e.personalUsageReporter,usageReporter:e.usageReporter,storedSessionUsageReporter:e.storedSessionUsageReporter},e.surface,t,e.sessionDirectory,e.settingsReporter,e.commandSurfaceLocality),cleanup:n}}function we(e,t,n,r=Te,a,o=`drive`,s,c,l){return u=>{let d=ee(u,t);if(d){if(o===`observe`&&!i(d.type)){t({type:`protocol_error`,message:`Not permitted for an observer: ${d.type}`});return}H(e,t,d,n,r,a,s,c,l)}}}const Te={personalUsageReporter:void 0,usageReporter:void 0,storedSessionUsageReporter:void 0};function H(e,t,n,r,i=Te,a,o,s,c){if(E(e,t,n,i))return;if(re(n)){oe(t,n,o);return}if(R(n)){z(e,t,n,s,c);return}if(ie(n)){ce(t,n,o);return}if(ae(n)){le(t,n,o);return}if(Ee(n)){je(e,t,n,r,a,c);return}if(b(n)){x(e,t,n);return}if(_e(n)){ve(e,t,n);return}if(te(n)){ne(e,t,n);return}if(De(n)){f(e,t,n);return}if(Oe(n)){p(e,t,n);return}if(ke(n)){Ae(e,n,r);return}let l=n.type;t({type:`protocol_error`,message:`Unknown message type: ${l}`})}function Ee(e){return e.type===`submit`||e.type===`command`||e.type===`abort`||e.type===`cancel-queue`}function De(e){return e.type===`get-background-tasks`||e.type===`get-background-task`||e.type===`read-background-task-log`||e.type===`get-background-job-groups`||e.type===`get-background-job-group`||e.type===`wait-background-job-group`}function Oe(e){return e.type===`cancel-background-task`||e.type===`close-background-task`||e.type===`send-background-task`}function ke(e){return e.type===`permission-response`||e.type===`ask-response`}function Ae(e,t,n){t.type===`permission-response`?e.resolvePermission(t.id,t.result,n):e.resolveAsk(t.id,t.response,n)}function je(e,t,n,r,i,a){if(n.type===`submit`){if(typeof n.prompt!=`string`||n.prompt.length===0){t({type:`protocol_error`,message:`prompt must be a non-empty string`});return}let a={...r?{driverId:r}:{},...i?{surface:i}:{}};e.submit(n.prompt,void 0,void 0,Object.keys(a).length>0?a:void 0).then(()=>t(L(e)),e=>t({type:`protocol_error`,message:e.message}))}else if(n.type===`command`){let i=n.requestId===void 0?{}:{requestId:n.requestId};if(!n.name){t({type:`protocol_error`,message:`name is required`,...i});return}e.executeCommand(n.name,n.args??``,`remote`,r,a).then(e=>{t({type:`command_result`,name:n.name,message:e?.message??`Unknown command: ${n.name}`,success:e?.success??!1,data:e?.data,...i})},e=>{t({type:`protocol_error`,message:e.message,...i})})}else n.type===`abort`?e.abort():e.cancelQueue()}const U=1024*1024,W=8*U,Me=U;function G(e,t=W){return e!==void 0&&e>t}const K=120*1e3;function q(e=K,t=Date.now){let n;return{maxPendingMs:e,observe(r){if(r===void 0)return;if(r===0){n=void 0;return}let i=t();n??=i;let a=i-n;return a>e?a:void 0}}}function J(e,t,n,r=W,i=q()){let a=!1,o=t=>{if(a)return;let o=n?.();if(G(o,r)){a=!0,s(Error(`outbound backpressure budget exceeded: ${o} byte(s) pending, limit ${r}. The peer has accepted frames it is not reading.`),t.type);return}let c=i.observe(o);if(c!==void 0){a=!0,s(Error(`outbound drain budget exceeded: ${o} byte(s) pending for ${c} ms, limit ${i.maxPendingMs} ms. The peer is reading too slowly to ever drain what it accepted.`),t.type);return}try{e(t)}catch(e){a=!0,s(e instanceof Error?e:Error(String(e)),t.type)}};function s(e,n){try{t(e,n)}catch{}}return Object.assign(o,{pendingBytes:()=>n?.()})}var Y=class{frames=[];sizes=[];nextSeq=1;bytes=0;maxFrames;maxBytes;sizeOf;constructor(e={}){this.maxFrames=e.maxFrames??512,this.maxBytes=e.maxBytes??4194304,this.sizeOf=e.sizeOf??(e=>JSON.stringify(e).length)}append(e){let t=this.nextSeq;this.nextSeq+=1;let n=this.sizeOf(e);return this.frames.push({seq:t,message:e}),this.sizes.push(n),this.bytes+=n,this.evict(),t}ackThrough(e){let t=0;for(;t<this.frames.length&&this.frames[t].seq<=e;)t+=1;this.removeOldest(t)}tailAfter(e){return this.frames.length===0?e>=this.nextSeq-1?{kind:`tail`,frames:[]}:{kind:`overrun`}:e<this.frames[0].seq-1?{kind:`overrun`}:{kind:`tail`,frames:this.frames.filter(t=>t.seq>e)}}get lastSeq(){return this.nextSeq-1}get size(){return this.frames.length}evict(){let e=0,t=this.bytes;for(;this.frames.length-e>this.maxFrames||t>this.maxBytes&&this.frames.length-e>1;)t-=this.sizes[e],e+=1;this.removeOldest(e)}removeOldest(e){if(!(e<=0)){for(let t=0;t<e;t+=1)this.bytes-=this.sizes[t]??0;this.frames.splice(0,e),this.sizes.splice(0,e),this.frames.length===0&&(this.bytes=0)}}};const X=new TextEncoder,Z=new TextDecoder,Q=X.encode(`RBF`),Ne=1,Pe=4294967295;function Fe(e,t){let n=X.encode(e);if(n.byteLength===0||n.byteLength>255)throw Error(`channel name must be 1..255 UTF-8 bytes (got ${n.byteLength})`);if(!Number.isInteger(t)||t<0||t>Pe)throw Error(`seq must be an integer in 0..${Pe} (got ${t})`);return n}function Ie(e,t,n,r){e.set(Q,0),e[3]=1,e[4]=t,e[5]=n.byteLength,e.set(n,6);let i=6+n.byteLength;return new DataView(e.buffer,e.byteOffset,e.byteLength).setUint32(i,r,!1),i+4}function Le(e){let t=Fe(e.channel,e.seq),n=new Uint8Array(6+t.byteLength+4+e.payload.byteLength),r=Ie(n,1,t,e.seq);return n.set(e.payload,r),n}function Re(e){let t=Fe(e.channel,e.seq),n=X.encode(JSON.stringify({event:e.event,payload:e.payload})),r=new Uint8Array(6+t.byteLength+4+n.byteLength),i=Ie(r,2,t,e.seq);return r.set(n,i),r}function ze(e){return e.byteLength<Q.length?!1:Q.every((t,n)=>e[n]===t)}function Be(e){let t=Z.decode(e),n;try{n=JSON.parse(t)}catch{return{ok:!1,error:`channel frame: malformed JSON body`}}if(typeof n!=`object`||!n||Array.isArray(n))return{ok:!1,error:`channel frame: event body must be a JSON object`};let{event:r,payload:i}=n;return typeof r!=`string`||r.length===0?{ok:!1,error:"channel frame: event body is missing a non-empty `event` name"}:{ok:!0,event:r,payload:i??null}}function Ve(e){if(!ze(e))return{ok:!1,error:`channel frame: bad magic (not a channel frame)`};if(e.byteLength<6)return{ok:!1,error:`channel frame: truncated header`};if(e[3]!==1)return{ok:!1,error:`channel frame: unsupported version ${String(e[3])}`};let t=e[4],n=e[5]??0;if(n===0)return{ok:!1,error:`channel frame: empty channel name`};let r=6+n,i=r+4;if(e.byteLength<i)return{ok:!1,error:`channel frame: truncated (header longer than the frame)`};let a=Z.decode(e.subarray(6,r)),o=new DataView(e.buffer,e.byteOffset,e.byteLength).getUint32(r,!1),s=e.subarray(i);if(t===1)return{ok:!0,frame:{kind:`binary`,channel:a,seq:o,payload:Uint8Array.from(s)}};if(t===2){let e=Be(s);return e.ok?{ok:!0,frame:{kind:`event`,channel:a,seq:o,event:e.event,payload:e.payload}}:{ok:!1,error:e.error}}return{ok:!1,error:`channel frame: unknown kind ${String(t)}`}}var He=class{session;buffer;driverId;reporters;surface;commandSurfaceLocality;unsubscribe;onDeliveryError;outbound;emitBoundary;disposed=!1;holding=!1;constructor(e){this.session=e.session,this.buffer=new Y(e.buffer),this.driverId=e.driverId,this.surface=e.surface,this.commandSurfaceLocality=e.commandSurfaceLocality,this.reporters={personalUsageReporter:e.personalUsageReporter,usageReporter:e.usageReporter,storedSessionUsageReporter:e.storedSessionUsageReporter},this.emitBoundary=J(e=>this.emit(e),(e,t)=>this.reportDeliveryError(e,t)),this.unsubscribe=he(this.session,this.emitBoundary,{getSurfaceDriverId:()=>this.driverId})}attach(e,t){this.disposed||(this.onDeliveryError=t.onDeliveryError,this.outbound=J(t=>e(JSON.stringify(t)),(e,t)=>this.reportDeliveryError(e,t),t.pendingBytes),this.holding=t.awaitResume===!0)}detach(){this.outbound=void 0,this.onDeliveryError=void 0}setDriverId(e){this.driverId=e}onClientMessage(e){if(this.disposed)return;let t=ee(e,this.emitBoundary);if(t){if(t.type===`resume`){this.replay(t.lastSeq);return}if(t.type===`ack`){this.buffer.ackThrough(t.seq);return}H(this.session,this.emitBoundary,t,this.driverId,this.reporters,this.surface,void 0,void 0,this.commandSurfaceLocality)}}dispose(){this.disposed||(this.disposed=!0,this.detach(),this.unsubscribe())}get lastSeq(){return this.buffer.lastSeq}emit(e){if(this.disposed)return;let t=this.buffer.append(e);this.holding||this.deliverFrame({...e,seq:t})}replay(e){let t=this.buffer.tailAfter(e);if(t.kind===`overrun`){this.deliverFrame({type:`resume_gap`}),this.holding=!1;return}for(let e of t.frames)this.deliverFrame({...e.message,seq:e.seq});this.holding=!1}deliverFrame(e){this.outbound?.(e)}reportDeliveryError(e,t){let n=this.onDeliveryError;this.detach();try{n?.(e,t)}catch{}}};function Ue(){return{origins:new Map}}function We(e,t,n){let r=t.origin.sessionId,i=e.origins.get(r);i===void 0&&(i={highestSequence:0,delivered:new Set,issued:new Map},e.origins.set(r,i));let a=i.issued.get(t.id);if(a!==void 0)return{ack:{...a,state:`duplicate`},deliver:!1};if(n!==void 0){let e={id:t.id,sequence:t.sequence,state:n.state,reason:n.reason};return i.issued.set(t.id,e),{ack:e,deliver:!1}}if(i.delivered.has(t.sequence)){let e={id:t.id,sequence:t.sequence,state:`refused`,reason:`sequence ${t.sequence} was already delivered by this origin under a different message id. A retry must repeat its id; a new id on a delivered sequence cannot be ordered against what the receiver already has.`};return i.issued.set(t.id,e),{ack:e,deliver:!1}}let o=i.highestSequence+1,s=t.sequence>o?o:void 0,c={id:t.id,sequence:t.sequence,state:`delivered`};return i.issued.set(t.id,c),i.delivered.add(t.sequence),i.highestSequence=Math.max(i.highestSequence,t.sequence),s===void 0?{ack:c,deliver:!0}:{ack:c,deliver:!0,gapBefore:s}}function Ge(e,t,n){let r=e.origins.get(t),i=r?.issued.get(n);if(r===void 0||i===void 0||i.state!==`delivered`)return;let a={...i,state:`acknowledged`};return r.issued.set(n,a),a}function Ke(e,t){e.origins.delete(t)}const $=16*1024;function qe(e,t,n=$){if(!Number.isInteger(n)||n<1)throw Error(`handoff chunking: maxChunkBytes must be a positive integer, got ${n}. A zero or negative budget produces an infinite sequence of empty chunks, which presents as a hang rather than as the configuration error it is.`);let r=Buffer.from(t,`utf8`),i=Math.max(1,Math.ceil(r.byteLength/n)),a=[];for(let t=0;t<i;t+=1){let o=r.subarray(t*n,(t+1)*n);a.push({handoffId:e,index:t,total:i,data:o.toString(`base64`)})}return a}var Je=class{handoffId;chunks=new Map;declaredTotal;constructor(e){this.handoffId=e}get received(){return this.chunks.size}get expected(){return this.declaredTotal}accept(e){let t=e=>({outcome:`refused`,rejection:e,received:this.chunks.size,...this.declaredTotal===void 0?{}:{expected:this.declaredTotal}});if(e.handoffId!==this.handoffId)return t(`wrong-handoff`);if(!Number.isInteger(e.total)||e.total<1||this.declaredTotal!==void 0&&e.total!==this.declaredTotal)return t(`inconsistent-total`);if(!Number.isInteger(e.index)||e.index<0||e.index>=e.total)return t(`out-of-range`);let n=Buffer.from(e.data,`base64`);if(n.toString(`base64`)!==e.data)return t(`undecodable`);this.declaredTotal=e.total;let r=this.chunks.get(e.index);return r===void 0?(this.chunks.set(e.index,n),this.chunks.size<e.total?{outcome:`accepted`,received:this.chunks.size,expected:e.total}:{outcome:`complete`,serialized:this.reassemble(e.total),received:this.chunks.size,expected:e.total}):r.equals(n)?{outcome:`duplicate`,received:this.chunks.size,expected:e.total}:t(`inconsistent-total`)}missing(){if(this.declaredTotal===void 0)return[];let e=[];for(let t=0;t<this.declaredTotal;t+=1)this.chunks.has(t)||e.push(t);return e}discard(){this.chunks.clear(),this.declaredTotal=void 0}reassemble(e){let t=[];for(let n=0;n<e;n+=1){let r=this.chunks.get(n);if(r===void 0)throw Error(`handoff chunking: chunk ${n} of ${e} is missing at reassembly.`);t.push(r)}return Buffer.concat(t).toString(`utf8`)}};function Ye(e,t=$){return Math.max(1,Math.ceil(e.byteLength/t))}export{Me as ATTACHED_SURFACE_MAX_PENDING_BYTES,Q as CHANNEL_FRAME_MAGIC,Ne as CHANNEL_FRAME_VERSION,$ as DEFAULT_MAX_CHUNK_BYTES,W as DEFAULT_MAX_PENDING_BYTES,K as DEFAULT_MAX_PENDING_MS,Je as HandoffChunkAssembler,n as MAX_INBOUND_FRAME_BYTES,me as PROTOCOL_SESSION_EVENT_CLASSIFICATION,Y as ResumeBuffer,He as SessionResumeBridge,Ge as acknowledgePeerMessage,We as admitPeerMessage,Ye as chunkCountFor,qe as chunkHandoffPayload,J as createOutboundDelivery,Ue as createPeerMessageLedger,q as createPendingStallClock,Ce as createSessionMessageHandler,Ve as decodeChannelFrame,r as decodeClientMessage,t as decodeFrame,e as decodeServerMessage,Le as encodeBinaryFrame,Re as encodeChannelEventFrame,Ke as forgetPeerOrigin,z as handleSettingsMessage,ze as isChannelFrame,i as isObserverMessageType,G as isOverPendingBudget,R as isSettingsMessage};
2
2
  //# sourceMappingURL=index.js.map