@robota-sdk/agent-transport 3.0.0-beta.83 → 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.
- package/CHANGELOG.md +43 -0
- package/README.md +80 -118
- package/dist/browser/client.d.ts +1 -1
- package/dist/browser/client.js +1 -1
- package/dist/browser/index.d.ts +60 -6
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/observer-messages-CEeisRaF.js +2 -0
- package/dist/browser/observer-messages-CEeisRaF.js.map +1 -0
- package/dist/browser/{observer-messages-DC_8VHk9.d.ts → observer-messages-Dnff2Tdb.d.ts} +125 -3
- package/dist/browser/observer-messages-Dnff2Tdb.d.ts.map +1 -0
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.d.cts +181 -6
- package/dist/node/index.d.cts.map +1 -1
- package/dist/node/index.d.ts +181 -6
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +1 -1
- package/dist/node/index.js.map +1 -1
- package/package.json +12 -11
- package/src/__tests__/message-decoders.test.ts +295 -1
- package/src/__tests__/project-read-messages.test.ts +118 -0
- package/src/__tests__/session-directory-messages.test.ts +130 -0
- package/src/__tests__/session-error-classification.test.ts +113 -0
- package/src/__tests__/session-message-handler-observe.test.ts +25 -1
- package/src/__tests__/session-message-handler.test.ts +57 -3
- package/src/__tests__/settings-messages.test.ts +193 -0
- package/src/index.ts +4 -0
- package/src/message-decoders.ts +157 -3
- package/src/observer-messages.ts +11 -0
- package/src/project-read-messages.ts +74 -0
- package/src/protocol-session.ts +17 -1
- package/src/session-directory-messages.ts +78 -1
- package/src/session-error-classification.ts +91 -0
- package/src/session-events.ts +7 -1
- package/src/session-message-handler.ts +58 -8
- package/src/session-query-messages.ts +18 -1
- package/src/session-resume-bridge.ts +8 -0
- package/src/settings-messages.ts +103 -0
- package/src/wire-messages.ts +133 -4
- package/dist/browser/observer-messages-Bx-xReUQ.js +0 -2
- package/dist/browser/observer-messages-Bx-xReUQ.js.map +0 -1
- package/dist/browser/observer-messages-DC_8VHk9.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# @robota-sdk/agent-transport
|
|
2
2
|
|
|
3
|
+
## 3.0.0-beta.84
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 9c6a8db: The wire protocol gained several request/reply pairs so a GUI never has to scrape command output for
|
|
8
|
+
data it can read directly.
|
|
9
|
+
|
|
10
|
+
`get-settings`/`update-settings` read and write the Settings screen; a patch applies through the same
|
|
11
|
+
function its matching slash command uses, so the two paths cannot drift. `list-models` returns the
|
|
12
|
+
configured models grouped by provider profile, with the current profile and model. `get-agent-definitions`
|
|
13
|
+
returns the agent switcher's roster and current selection. `project-status`, `project-diff` and
|
|
14
|
+
`project-memory` back the Project panel's git status, one file's diff, and project memory; a host
|
|
15
|
+
without this capability answers `protocol_error` instead of hanging. `rename-session` and
|
|
16
|
+
`delete-session` rename or remove a stored session from the list, current or not, each with its own
|
|
17
|
+
success/failure reply.
|
|
18
|
+
|
|
19
|
+
The `messages` frame gained an optional `display` field — the same history projected into display
|
|
20
|
+
segments (text runs and finished tool calls, diffs included) — and the connection's own `driverId`, so
|
|
21
|
+
a reload, reconnect or resume shows tool rows and tells a co-driver's turns from its own. The `error`
|
|
22
|
+
frame gained optional `code`, `provider`, `retryAfterSeconds` and `model` fields so a renderer can say
|
|
23
|
+
what kind of failure happened (`auth`, `rate_limit`, `model_unavailable`, `network`, `provider`) instead
|
|
24
|
+
of showing only raw text; a session error this classification does not recognize is unchanged.
|
|
25
|
+
|
|
26
|
+
`TCommandSurfaceLocality` names whether a `'remote'`-sourced command is provably on this machine. The
|
|
27
|
+
WebRTC/device-mesh transport now forwards `'remote'` for it (it proves no locality, the same rule
|
|
28
|
+
already applied to pairing), and both the WS and WebRTC transports forward it into the Settings
|
|
29
|
+
read/write path, so a command that refuses a remote surface (installing a plugin) refuses identically
|
|
30
|
+
regardless of which transport carried it.
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [9f46375]
|
|
33
|
+
- Updated dependencies [e8d70ac]
|
|
34
|
+
- Updated dependencies [9c6a8db]
|
|
35
|
+
- Updated dependencies [9c6a8db]
|
|
36
|
+
- Updated dependencies [9c6a8db]
|
|
37
|
+
- Updated dependencies [9c6a8db]
|
|
38
|
+
- @robota-sdk/agent-core@3.0.0-beta.84
|
|
39
|
+
- @robota-sdk/agent-interface-session@3.0.0-beta.84
|
|
40
|
+
- @robota-sdk/agent-interface-analytics@3.0.0-beta.84
|
|
41
|
+
- @robota-sdk/agent-interface-execution@3.0.0-beta.84
|
|
42
|
+
- @robota-sdk/agent-interface-command@3.0.0-beta.84
|
|
43
|
+
- @robota-sdk/agent-interface-session-mobility@3.0.0-beta.84
|
|
44
|
+
- @robota-sdk/agent-interface-transport@3.0.0-beta.84
|
|
45
|
+
|
|
3
46
|
## 3.0.0-beta.83
|
|
4
47
|
|
|
5
48
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -1,42 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @robota-sdk/agent-transport
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
16
|
+
Requires Node.js 22.12 or later. The root and `./client` entry points also run in the browser.
|
|
48
17
|
|
|
49
|
-
|
|
50
|
-
transport packages.
|
|
18
|
+
## Entry points
|
|
51
19
|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
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
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
35
|
+
import { createOutboundDelivery, createSessionMessageHandler } from '@robota-sdk/agent-transport';
|
|
36
|
+
import type { IProtocolSession, TServerMessage } from '@robota-sdk/agent-transport';
|
|
73
37
|
|
|
74
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
import { WsTransport } from '@robota-sdk/agent-transport-ws';
|
|
48
|
+
const handler = createSessionMessageHandler({ session, deliver });
|
|
81
49
|
|
|
82
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
97
|
-
|
|
98
|
-
|
|
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
|
-
|
|
74
|
+
function buildOffer(request: Omit<IPrepareHandoffOfferInput, 'integrity'>) {
|
|
75
|
+
const readiness = assessHandoffReadiness(request.runtime);
|
|
76
|
+
if (!readiness.ready) return readiness;
|
|
102
77
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
78
|
+
const { serialized, integrity } = sealHandoffRecord(request.record);
|
|
79
|
+
const offer = prepareHandoffOffer({ ...request, integrity });
|
|
80
|
+
if (!offer.built) return offer;
|
|
106
81
|
|
|
107
|
-
|
|
108
|
-
|
|
82
|
+
// Send serialized unchanged: offer.manifest.integrity describes these exact bytes.
|
|
83
|
+
return { manifest: offer.manifest, serialized };
|
|
84
|
+
}
|
|
109
85
|
```
|
|
110
86
|
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
##
|
|
91
|
+
## Transport packages
|
|
115
92
|
|
|
116
|
-
|
|
93
|
+
Each carrier is its own package, so an application installs only the protocol dependencies it uses.
|
|
117
94
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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-
|
|
144
|
-
- `@robota-sdk/agent-interface-command
|
|
145
|
-
|
|
146
|
-
-
|
|
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
|
|
151
|
-
|
|
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
|
-
##
|
|
116
|
+
## Documentation
|
|
156
117
|
|
|
157
|
-
- [
|
|
158
|
-
- [
|
|
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)
|
package/dist/browser/client.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as decodeFrame, c as
|
|
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
2
|
export { type IWireHistoryEntry, MAX_INBOUND_FRAME_BYTES, type TClientMessage, type TMessageDecodeResult, type TSeqServerMessage, type TServerMessage, type TWireExecutionResult, decodeClientMessage, decodeFrame, decodeServerMessage, isObserverMessageType };
|
package/dist/browser/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as e,i as t,n,r,t as i}from"./observer-messages-
|
|
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};
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { a as decodeFrame, c as
|
|
2
|
-
import { ISessionBackgroundGroups, ISessionBackgroundTasks, ISessionCommands, ISessionConversationRead, ISessionDirectory, ISessionDriverAttribution, ISessionEvents, ISessionExecutionDetail, ISessionExecutionState, ISessionExecutionWorkspace, ISessionPromptResolution, ISessionSelfPacedLoopControl, ISessionStatusRead, ISessionTurnControl, ISessionTurnSubmission, TDriverId } from "@robota-sdk/agent-interface-session";
|
|
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";
|
|
3
3
|
import { IPersonalUsageReport, IPersonalUsageRequest, IUsageBySourceReport, TUsageSurface } from "@robota-sdk/agent-interface-analytics";
|
|
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
|
|
@@ -94,7 +95,48 @@ declare function createOutboundDelivery(send: (message: TServerMessage) => void,
|
|
|
94
95
|
//#endregion
|
|
95
96
|
//#region src/protocol-session.d.ts
|
|
96
97
|
/** Session roles required by the shared WebSocket/WebRTC protocol. */
|
|
97
|
-
interface IProtocolSession extends ISessionTurnSubmission, ISessionTurnControl, ISessionCommands, ISessionStatusRead, ISessionEvents, ISessionPromptResolution, ISessionConversationRead, ISessionExecutionState, ISessionDriverAttribution, ISessionBackgroundTasks, ISessionBackgroundGroups, ISessionExecutionWorkspace, ISessionExecutionDetail, ISessionSelfPacedLoopControl {}
|
|
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;
|
|
98
140
|
//#endregion
|
|
99
141
|
//#region src/usage-messages.d.ts
|
|
100
142
|
interface IUsageQueryReporters {
|
|
@@ -145,8 +187,8 @@ declare const PROTOCOL_SESSION_EVENT_CLASSIFICATION: {
|
|
|
145
187
|
*/
|
|
146
188
|
type TSessionSurfaceRole = 'drive' | 'observe';
|
|
147
189
|
interface ISessionMessageHandlerOptions {
|
|
148
|
-
/** IProtocolSession to expose. */
|
|
149
|
-
session:
|
|
190
|
+
/** IProtocolSession to expose — `Partial<ISessionProjectRead>` is probed, not assumed (#3282 §4c). */
|
|
191
|
+
session: TProjectReadCapableSession;
|
|
150
192
|
/**
|
|
151
193
|
* ARCH-030: the CARRIER's connection-scoped outbound delivery boundary — not a raw `send`, and not a
|
|
152
194
|
* `send` plus an error callback for this handler to assemble into one. The carrier owns both the sink
|
|
@@ -173,6 +215,15 @@ interface ISessionMessageHandlerOptions {
|
|
|
173
215
|
storedSessionUsageReporter?: NonNullable<IUsageQueryReporters['storedSessionUsageReporter']>;
|
|
174
216
|
/** Host-owned session directory (#3189): list, start and switch the host's sessions. */
|
|
175
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;
|
|
176
227
|
}
|
|
177
228
|
/**
|
|
178
229
|
* Create a carrier-neutral message handler for an IProtocolSession.
|
|
@@ -302,6 +353,8 @@ interface ISessionResumeBridgeOptions {
|
|
|
302
353
|
readonly personalUsageReporter?: IUsageQueryReporters['personalUsageReporter'];
|
|
303
354
|
readonly usageReporter?: IUsageQueryReporters['usageReporter'];
|
|
304
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;
|
|
305
358
|
}
|
|
306
359
|
declare class SessionResumeBridge {
|
|
307
360
|
private readonly session;
|
|
@@ -309,6 +362,7 @@ declare class SessionResumeBridge {
|
|
|
309
362
|
private driverId?;
|
|
310
363
|
private readonly reporters;
|
|
311
364
|
private readonly surface?;
|
|
365
|
+
private readonly commandSurfaceLocality?;
|
|
312
366
|
private readonly unsubscribe;
|
|
313
367
|
private onDeliveryError?;
|
|
314
368
|
/**
|
|
@@ -536,5 +590,5 @@ declare class HandoffChunkAssembler {
|
|
|
536
590
|
*/
|
|
537
591
|
declare function chunkCountFor(integrity: IHandoffIntegrity, maxChunkBytes?: number): number;
|
|
538
592
|
//#endregion
|
|
539
|
-
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 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 TWireExecutionResult, acknowledgePeerMessage, admitPeerMessage, chunkCountFor, chunkHandoffPayload, createOutboundDelivery, createPeerMessageLedger, createPendingStallClock, createSessionMessageHandler, decodeChannelFrame, decodeClientMessage, decodeFrame, decodeServerMessage, encodeBinaryFrame, encodeChannelEventFrame, forgetPeerOrigin, isChannelFrame, isObserverMessageType, 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 };
|
|
540
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":"
|
|
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"}
|
package/dist/browser/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,i as t,n,r,t as i}from"./observer-messages-Bx-xReUQ.js";import{isSessionChangeRefusal as a}from"@robota-sdk/agent-interface-session";function o(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`){c(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`){u(e,t,n);return}if(n.type===`wait-background-job-group`){d(e,t,n);return}l(e,t,n)}function s(e,t,n){if(!n.taskId){t({type:`protocol_error`,message:`taskId is required`});return}if(n.type===`cancel-background-task`){p(t,`cancel`,n.taskId,e.cancelBackgroundTask(n.taskId,n.reason));return}if(n.type===`close-background-task`){p(t,`close`,n.taskId,e.closeBackgroundTask(n.taskId));return}f(e,t,n)}function c(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 l(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 u(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 d(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 f(e,t,n){if(!n.input){t({type:`protocol_error`,message:`input is required`});return}p(t,`send`,n.taskId,e.sendBackgroundTask(n.taskId,n.input))}function p(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 m(e){return e.type===`stop-waiting-loop`}function h(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:g(e)}}))}function g(e){return e instanceof Error?e.message:String(e)}function _(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function v(e){return typeof e==`string`&&e.length>0?e:void 0}function y(e){if(!(new TextEncoder().encode(e).byteLength>4194304))try{let t=JSON.parse(e);if(!_(t))return;let n=v(t.requestId);if(!n)return;if(t.type===`get-personal-usage-report`)return{type:`personal`,requestId:n};let r=v(t.sessionId);return t.type===`get-stored-session-usage-report`&&r?{type:`stored-session`,requestId:n,sessionId:r}:void 0}catch{return}}function b(e,t,n,r){return n.type===`get-personal-usage-report`?(w(t,n,r.personalUsageReporter),!0):n.type===`get-stored-session-usage-report`?(S(t,n,r.storedSessionUsageReporter),!0):n.type===`get-usage-report`?(x(e,t,r.usageReporter),!0):!1}function x(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:E(e)}))}catch(e){t({type:`protocol_error`,message:E(e instanceof Error?e:String(e))})}}function S(e,t,n){if(!n){C(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=>C(e,t,`report_failed`,E(n)))}catch(n){C(e,t,`report_failed`,E(n instanceof Error?n:String(n)))}}function C(e,t,n,r){e({type:`stored_session_usage_report_error`,requestId:t.requestId,sessionId:t.sessionId,code:n,message:r})}function w(e,t,n){if(!n){T(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=>T(e,t.requestId,`report_failed`,E(n)))}catch(n){T(e,t.requestId,`report_failed`,E(n instanceof Error?n:String(n)))}}function T(e,t,n,r){e({type:`personal_usage_report_error`,requestId:t,code:n,message:r})}function E(e){return e instanceof Error?e.message:String(e)}function D(e,n){let i=t(e,r);if(i.ok)return i.message;let a=y(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 O(e){return e.type===`list-sessions`||e.type===`new-session`||e.type===`switch-session`}function k(e,t,n){if(t.type===`list-sessions`){A(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:j(t),...r}))}function A(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:j(n instanceof Error?n:String(n))})}}function j(e){return e instanceof Error?e.message:String(e)}const M=new WeakMap;function ee(e){let t=M.get(e);t===void 0&&(t={frames:new Map,holders:0},M.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&&M.get(e)===n&&M.delete(e))}}}function te(e){return[...M.get(e)?.frames.values()??[]]}const ne={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 N(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:P(e),...r()}),u=e=>t({type:`interrupted`,result:P(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=n.receivePrompts??!0,y=v?ee(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 P(e){let{history:t,...n}=e;return n}const re=new TextEncoder;function ie(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===`get-executing`||e.type===`get-pending`||e.type===`get-execution-workspace`||e.type===`read-execution-detail`}function ae(e,t,n){if(n.type===`get-messages`)t({type:`messages`,messages:e.getMessages()});else if(n.type===`get-history`)t(se(e,n.fromIndex??0));else if(n.type===`get-prompts`)for(let n of te(e))t(n);else n.type===`get-context`?t({type:`context`,state:e.getContextState()}):n.type===`get-commands`?t({type:`commands`,commands:e.listCommands(),skills:e.listSkills()}):n.type===`get-status`?t({type:`session_status`,status:e.getStatusSnapshot()}):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`?oe(e,t,n):t(F(e))}function oe(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 F(e){return{type:`pending`,pending:e.getPendingPrompt(),pendingCount:e.getPendingCount()}}function se(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=ce(n[e]),r=re.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 ce(e){return{...e,timestamp:le(e.timestamp)}}function le(e){return typeof e==`string`?e:e.toISOString()}function ue(e){let t=e.role??`drive`,n=N(e.session,e.deliver,{getSurfaceDriverId:()=>e.driverId,receivePrompts:t===`drive`});return{onMessage:de(e.session,e.deliver,e.driverId,{personalUsageReporter:e.personalUsageReporter,usageReporter:e.usageReporter,storedSessionUsageReporter:e.storedSessionUsageReporter},e.surface,t,e.sessionDirectory),cleanup:n}}function de(e,t,n,r=I,a,o=`drive`,s){return c=>{let l=D(c,t);if(l){if(o===`observe`&&!i(l.type)){t({type:`protocol_error`,message:`Not permitted for an observer: ${l.type}`});return}L(e,t,l,n,r,a,s)}}}const I={personalUsageReporter:void 0,usageReporter:void 0,storedSessionUsageReporter:void 0};function L(e,t,n,r,i=I,a,c){if(b(e,t,n,i))return;if(O(n)){k(t,n,c);return}if(fe(n)){_e(e,t,n,r,a);return}if(m(n)){h(e,t,n);return}if(ie(n)){ae(e,t,n);return}if(pe(n)){o(e,t,n);return}if(me(n)){s(e,t,n);return}if(he(n)){ge(e,n,r);return}let l=n.type;t({type:`protocol_error`,message:`Unknown message type: ${l}`})}function fe(e){return e.type===`submit`||e.type===`command`||e.type===`abort`||e.type===`cancel-queue`}function pe(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 me(e){return e.type===`cancel-background-task`||e.type===`close-background-task`||e.type===`send-background-task`}function he(e){return e.type===`permission-response`||e.type===`ask-response`}function ge(e,t,n){t.type===`permission-response`?e.resolvePermission(t.id,t.result,n):e.resolveAsk(t.id,t.response,n)}function _e(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).then(()=>t(F(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).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 R=1024*1024,z=8*R,ve=R;function B(e,t=z){return e!==void 0&&e>t}const V=120*1e3;function H(e=V,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 U(e,t,n,r=z,i=H()){let a=!1,o=t=>{if(a)return;let o=n?.();if(B(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 W=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 G=new TextEncoder,K=new TextDecoder,q=G.encode(`RBF`),ye=1,J=4294967295;function Y(e,t){let n=G.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>J)throw Error(`seq must be an integer in 0..${J} (got ${t})`);return n}function X(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 be(e){let t=Y(e.channel,e.seq),n=new Uint8Array(6+t.byteLength+4+e.payload.byteLength),r=X(n,1,t,e.seq);return n.set(e.payload,r),n}function xe(e){let t=Y(e.channel,e.seq),n=G.encode(JSON.stringify({event:e.event,payload:e.payload})),r=new Uint8Array(6+t.byteLength+4+n.byteLength),i=X(r,2,t,e.seq);return r.set(n,i),r}function Z(e){return e.byteLength<q.length?!1:q.every((t,n)=>e[n]===t)}function Se(e){let t=K.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 Ce(e){if(!Z(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=K.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=Se(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 we=class{session;buffer;driverId;reporters;surface;unsubscribe;onDeliveryError;outbound;emitBoundary;disposed=!1;holding=!1;constructor(e){this.session=e.session,this.buffer=new W(e.buffer),this.driverId=e.driverId,this.surface=e.surface,this.reporters={personalUsageReporter:e.personalUsageReporter,usageReporter:e.usageReporter,storedSessionUsageReporter:e.storedSessionUsageReporter},this.emitBoundary=U(e=>this.emit(e),(e,t)=>this.reportDeliveryError(e,t)),this.unsubscribe=N(this.session,this.emitBoundary,{getSurfaceDriverId:()=>this.driverId})}attach(e,t){this.disposed||(this.onDeliveryError=t.onDeliveryError,this.outbound=U(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=D(e,this.emitBoundary);if(t){if(t.type===`resume`){this.replay(t.lastSeq);return}if(t.type===`ack`){this.buffer.ackThrough(t.seq);return}L(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 Q(){return{origins:new Map}}function Te(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 Ee(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 De(e,t){e.origins.delete(t)}const $=16*1024;function Oe(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 ke=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 Ae(e,t=$){return Math.max(1,Math.ceil(e.byteLength/t))}export{ve as ATTACHED_SURFACE_MAX_PENDING_BYTES,q as CHANNEL_FRAME_MAGIC,ye as CHANNEL_FRAME_VERSION,$ as DEFAULT_MAX_CHUNK_BYTES,z as DEFAULT_MAX_PENDING_BYTES,V as DEFAULT_MAX_PENDING_MS,ke as HandoffChunkAssembler,n as MAX_INBOUND_FRAME_BYTES,ne as PROTOCOL_SESSION_EVENT_CLASSIFICATION,W as ResumeBuffer,we as SessionResumeBridge,Ee as acknowledgePeerMessage,Te as admitPeerMessage,Ae as chunkCountFor,Oe as chunkHandoffPayload,U as createOutboundDelivery,Q as createPeerMessageLedger,H as createPendingStallClock,ue as createSessionMessageHandler,Ce as decodeChannelFrame,r as decodeClientMessage,t as decodeFrame,e as decodeServerMessage,be as encodeBinaryFrame,xe as encodeChannelEventFrame,De as forgetPeerOrigin,Z as isChannelFrame,i as isObserverMessageType,B 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
|