nandi/oripublic Fork 0
2434cc7fb724f02b34c0189dfd5fb30c1a8a68e3
Commits
Clone
git clone https://git.rickub.com/nandi/ori.git
git clone ssh://git@rickub.com/nandi/ori.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

forked from bots-garden/ori

protocol.go · 91 lines · 3.7 KBGo Blame HistoryRaw
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package bridge

import "encoding/json"

// This file is the wire contract between the SPA and the backend, over a
// WebSocket carrying one JSON message per text frame. ACP payloads (session
// updates, permission requests) are relayed verbatim so the frontend works
// with the protocol's own shapes, documented at
// https://agentclientprotocol.com.

// Incoming message types (browser → server).
const (
	// IncomingPrompt starts a turn: {"type":"prompt","text":"..."}.
	IncomingPrompt = "prompt"
	// IncomingCancel interrupts the current turn: {"type":"cancel"}.
	IncomingCancel = "cancel"
	// IncomingPermissionResponse answers a permission request:
	// {"type":"permission_response","requestId":"...","optionId":"..."} or
	// {"type":"permission_response","requestId":"...","cancelled":true}.
	IncomingPermissionResponse = "permission_response"
)

// Outgoing message types (server → browser).
const (
	// OutgoingHello is sent once per connection with the session state.
	OutgoingHello = "hello"
	// OutgoingUserMessage echoes the prompt that started a turn, so every
	// client (and every reconnection replay) renders the user's side of the
	// conversation from the same source of truth as the agent's side.
	OutgoingUserMessage = "user_message"
	// OutgoingSessionUpdate relays one ACP session/update notification;
	// its "update" field is the raw ACP SessionUpdate object.
	OutgoingSessionUpdate = "session_update"
	// OutgoingPermissionRequest relays an ACP permission request; its
	// "request" field is the raw ACP RequestPermissionRequest object.
	OutgoingPermissionRequest = "permission_request"
	// OutgoingPermissionResolved tells every client a permission request
	// was answered (so open dialogs close everywhere).
	OutgoingPermissionResolved = "permission_resolved"
	// OutgoingTurnStarted marks the start of a prompt turn.
	OutgoingTurnStarted = "turn_started"
	// OutgoingTurnEnded marks the end of a turn, with its stop reason.
	OutgoingTurnEnded = "turn_ended"
	// OutgoingError carries a human-readable error message.
	OutgoingError = "error"
)

// Incoming is a message sent by the browser.
type Incoming struct {
	Type string `json:"type"`
	// Text is the prompt text (IncomingPrompt).
	Text string `json:"text,omitempty"`
	// RequestId identifies the permission request being answered.
	RequestId string `json:"requestId,omitempty"`
	// OptionId is the chosen ACP permission option.
	OptionId string `json:"optionId,omitempty"`
	// Cancelled dismisses the permission request instead of choosing.
	Cancelled bool `json:"cancelled,omitempty"`
}

// Outgoing is a message sent to the browser.
type Outgoing struct {
	Type string `json:"type"`
	// SessionId is set on OutgoingHello.
	SessionId string `json:"sessionId,omitempty"`
	// TurnActive is set on OutgoingHello: true while a prompt turn runs.
	TurnActive bool `json:"turnActive,omitempty"`
	// Update is the raw ACP SessionUpdate (OutgoingSessionUpdate).
	Update json.RawMessage `json:"update,omitempty"`
	// RequestId identifies a permission request across messages.
	RequestId string `json:"requestId,omitempty"`
	// Request is the raw ACP RequestPermissionRequest (OutgoingPermissionRequest).
	Request json.RawMessage `json:"request,omitempty"`
	// Text is the user's prompt text (OutgoingUserMessage).
	Text string `json:"text,omitempty"`
	// StopReason is the ACP stop reason (OutgoingTurnEnded).
	StopReason string `json:"stopReason,omitempty"`
	// Message is a human-readable error (OutgoingError).
	Message string `json:"message,omitempty"`
}

// encode marshals an Outgoing message; the bridge treats a marshalling
// failure as a programming error and panics, because every field is
// marshal-safe by construction.
func encode(msg Outgoing) []byte {
	raw, err := json.Marshal(msg)
	if err != nil {
		panic(err)
	}
	return raw
}