effect-herdr-sdk 0.0.0-stage → 0.0.1-beta.0
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/LICENSE +21 -0
- package/NOTICE +2 -0
- package/package.json +38 -4
- package/src/bun.ts +9 -0
- package/src/generated/errors.ts +4 -0
- package/src/generated/events.ts +59 -0
- package/src/generated/index.ts +19 -0
- package/src/generated/params.ts +460 -0
- package/src/generated/results.ts +444 -0
- package/src/herdr.ts +142 -0
- package/src/index.ts +10 -0
- package/src/socket-connector.ts +9 -0
- package/src/socket-path.ts +70 -0
- package/README.md +0 -3
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
// GENERATED by scripts/gen from schema/herdr-api.schema.json — do not edit.
|
|
2
|
+
// herdr protocol 22, schema_version 1.
|
|
3
|
+
|
|
4
|
+
export type AgentInfo = { "agent"?: string | null; "agent_session"?: (AgentSessionInfo) | (null); "agent_status": AgentStatus; "cwd"?: string | null; "display_agent"?: string | null; "focused": boolean; "foreground_cwd"?: string | null; "interactive_ready"?: boolean; "launch_pending"?: boolean; "name"?: string | null; "pane_id": string; "revision": number; "screen_detection_skipped"?: boolean; "state_change_seq"?: number; "state_labels"?: { [key: string]: string; }; "tab_id": string; "terminal_id": string; "terminal_title"?: string | null; "terminal_title_stripped"?: string | null; "title"?: string | null; "tokens"?: { [key: string]: string; }; "workspace_id": string; };
|
|
5
|
+
|
|
6
|
+
export type AgentManifestInfo = { "active_version"?: string | null; "agent": string; "cached_remote_version"?: string | null; "local_override_shadowing_remote": boolean; "remote_last_checked_unix"?: number | null; "remote_update_error"?: string | null; "remote_update_result"?: string | null; "source": string; "source_kind": string; "warning"?: string | null; };
|
|
7
|
+
|
|
8
|
+
export type AgentSessionInfo = { "agent": string; "kind": AgentSessionRefKind; "source": string; "value": string; };
|
|
9
|
+
|
|
10
|
+
export type AgentSessionRefKind = "id" | "path";
|
|
11
|
+
|
|
12
|
+
export type AgentStatus = "idle" | "working" | "blocked" | "done" | "unknown";
|
|
13
|
+
|
|
14
|
+
export type ClientWindowTitleReason = "set" | "cleared" | "no_foreground_client";
|
|
15
|
+
|
|
16
|
+
export type ConfigReloadStatus = "applied" | "partial" | "failed";
|
|
17
|
+
|
|
18
|
+
export type EventData = ({ "type": "workspace_created"; "workspace": WorkspaceInfo; }) | ({ "type": "workspace_updated"; "workspace": WorkspaceInfo; }) | ({ "type": "workspace_metadata_updated"; "workspace": WorkspaceInfo; }) | ({ "type": "workspace_closed"; "workspace"?: (WorkspaceInfo) | (null); "workspace_id": string; }) | ({ "label": string; "type": "workspace_renamed"; "workspace_id": string; }) | ({ "insert_index": number; "type": "workspace_moved"; "workspace_id": string; "workspaces": Array<WorkspaceInfo>; }) | ({ "before_workspace_id"?: string | null; "type": "workspace_reordered"; "workspace_ids": Array<string>; "workspaces": Array<WorkspaceInfo>; }) | ({ "type": "workspace_focused"; "workspace_id": string; }) | ({ "type": "worktree_created"; "workspace": WorkspaceInfo; "worktree": WorktreeInfo; }) | ({ "already_open": boolean; "type": "worktree_opened"; "workspace": WorkspaceInfo; "worktree": WorktreeInfo; }) | ({ "forced": boolean; "type": "worktree_removed"; "workspace"?: (WorkspaceInfo) | (null); "workspace_id": string; "worktree": WorktreeInfo; }) | ({ "tab": TabInfo; "type": "tab_created"; }) | ({ "tab_id": string; "type": "tab_closed"; "workspace_id": string; }) | ({ "label": string; "tab_id": string; "type": "tab_renamed"; "workspace_id": string; }) | ({ "insert_index": number; "tab_id": string; "tabs": Array<TabInfo>; "type": "tab_moved"; "workspace_id": string; }) | ({ "tab_id": string; "type": "tab_focused"; "workspace_id": string; }) | ({ "pane": PaneInfo; "type": "pane_created"; }) | ({ "pane_id": string; "type": "pane_closed"; "workspace_id": string; }) | ({ "pane": PaneInfo; "type": "pane_updated"; }) | ({ "pane_id": string; "type": "pane_focused"; "workspace_id": string; }) | ({ "closed_tab_id"?: string | null; "closed_workspace_id"?: string | null; "created_tab"?: (TabInfo) | (null); "created_workspace"?: (WorkspaceInfo) | (null); "pane": PaneInfo; "previous_pane_id": string; "previous_tab_id": string; "previous_workspace_id": string; "type": "pane_moved"; }) | ({ "pane_id": string; "revision": number; "type": "pane_output_changed"; "workspace_id": string; }) | ({ "pane_id": string; "type": "pane_exited"; "workspace_id": string; }) | ({ "agent"?: string | null; "final_status"?: (AgentStatus) | (null); "pane_id": string; "released"?: boolean; "type": "pane_agent_detected"; "workspace_id": string; }) | ({ "agent"?: string | null; "agent_status": AgentStatus; "display_agent"?: string | null; "pane_id": string; "state_labels"?: { [key: string]: string; }; "title"?: string | null; "type": "pane_agent_status_changed"; "workspace_id": string; }) | ({ "layout": PaneLayoutSnapshot; "type": "layout_updated"; });
|
|
19
|
+
|
|
20
|
+
export type EventEnvelope = { "data": EventData; "event": EventKind; };
|
|
21
|
+
|
|
22
|
+
export type EventKind = "workspace_created" | "workspace_updated" | "workspace_metadata_updated" | "workspace_closed" | "workspace_renamed" | "workspace_moved" | "workspace_reordered" | "workspace_focused" | "worktree_created" | "worktree_opened" | "worktree_removed" | "tab_created" | "tab_closed" | "tab_renamed" | "tab_moved" | "tab_focused" | "pane_created" | "pane_closed" | "pane_updated" | "pane_focused" | "pane_moved" | "pane_output_changed" | "pane_exited" | "pane_agent_detected" | "pane_agent_status_changed" | "layout_updated";
|
|
23
|
+
|
|
24
|
+
export type InstalledPluginInfo = { "actions"?: Array<PluginManifestAction>; "build"?: Array<PluginManifestBuild>; "description"?: string | null; "enabled": boolean; "events"?: Array<PluginManifestEventHook>; "link_handlers"?: Array<PluginManifestLinkHandler>; "manifest_path": string; "min_herdr_version"?: string; "name": string; "panes"?: Array<PluginManifestPane>; "platforms"?: Array<PluginPlatform> | null; "plugin_id": string; "plugin_root": string; "source"?: PluginSourceInfo; "startup"?: Array<PluginManifestStartup>; "version": string; /** Warnings collected at link time or on registry load (e.g. unknown event names,
|
|
25
|
+
missing manifest file). Non-fatal — the entry is kept and surfaced by plugin.list. */ "warnings"?: Array<string>; };
|
|
26
|
+
|
|
27
|
+
export type IntegrationInfo = { "available": boolean; "command": string; "label": string; "state": IntegrationState; "target": IntegrationTarget; };
|
|
28
|
+
|
|
29
|
+
export type IntegrationInstallResult = { "messages": Array<string>; };
|
|
30
|
+
|
|
31
|
+
export type IntegrationState = "not_installed" | "current" | "outdated";
|
|
32
|
+
|
|
33
|
+
export type IntegrationTarget = "pi" | "omp" | "claude" | "codex" | "copilot" | "devin" | "droid" | "kimi" | "opencode" | "kilo" | "hermes" | "qodercli" | "qwen" | "cursor" | "mastracode" | "antigravity_cli" | "grok";
|
|
34
|
+
|
|
35
|
+
export type IntegrationUninstallResult = { "messages": Array<string>; };
|
|
36
|
+
|
|
37
|
+
export type LayoutDescription = { "focused_pane_id": string; "root": LayoutNode; "tab_id": string; "workspace_id": string; "zoomed": boolean; };
|
|
38
|
+
|
|
39
|
+
export type LayoutNode = ({ "command"?: Array<string> | null; "cwd"?: string | null; "env"?: { [key: string]: string; }; "label"?: string | null; "pane_id"?: string | null; "type": "pane"; }) | ({ "direction": SplitDirection; "first": LayoutNode; "ratio": number; "second": LayoutNode; "type": "split"; });
|
|
40
|
+
|
|
41
|
+
export type NotificationShowReason = "shown" | "disabled" | "rate_limited" | "no_foreground_client" | "busy";
|
|
42
|
+
|
|
43
|
+
export type PaneDirection = "left" | "right" | "up" | "down";
|
|
44
|
+
|
|
45
|
+
export type PaneEdgesResult = { "down": boolean; "layout": PaneLayoutSnapshot; "left": boolean; "pane_id": string; "right": boolean; "up": boolean; };
|
|
46
|
+
|
|
47
|
+
export type PaneFocusDirectionReason = "no_neighbor";
|
|
48
|
+
|
|
49
|
+
export type PaneFocusDirectionResult = { "changed": boolean; "focused_pane_id"?: string | null; "layout": PaneLayoutSnapshot; "reason"?: (PaneFocusDirectionReason) | (null); "source_pane_id": string; };
|
|
50
|
+
|
|
51
|
+
export type PaneInfo = { "agent"?: string | null; "agent_session"?: (AgentSessionInfo) | (null); "agent_status": AgentStatus; "cwd"?: string | null; "display_agent"?: string | null; "focused": boolean; "foreground_cwd"?: string | null; "label"?: string | null; "pane_id": string; "revision": number; "scroll"?: (PaneScrollInfo) | (null); "state_labels"?: { [key: string]: string; }; "tab_id": string; "terminal_id": string; "terminal_title"?: string | null; "terminal_title_stripped"?: string | null; "title"?: string | null; "tokens"?: { [key: string]: string; }; "workspace_id": string; };
|
|
52
|
+
|
|
53
|
+
export type PaneLayoutPane = { "focused": boolean; "pane_id": string; "rect": PaneLayoutRect; };
|
|
54
|
+
|
|
55
|
+
export type PaneLayoutRect = { "height": number; "width": number; "x": number; "y": number; };
|
|
56
|
+
|
|
57
|
+
export type PaneLayoutSnapshot = { "area": PaneLayoutRect; "focused_pane_id": string; "panes": Array<PaneLayoutPane>; "splits": Array<PaneLayoutSplit>; "tab_id": string; "workspace_id": string; "zoomed": boolean; };
|
|
58
|
+
|
|
59
|
+
export type PaneLayoutSplit = { "direction": SplitDirection; "id": string; "ratio": number; "rect": PaneLayoutRect; };
|
|
60
|
+
|
|
61
|
+
/** Inclusive display-cell columns on a pane's current viewport. */
|
|
62
|
+
export type PaneLinkRegion = { "end_col": number; "row": number; "start_col": number; };
|
|
63
|
+
|
|
64
|
+
export type PaneMoveReason = "same_tab" | "zoomed_tab";
|
|
65
|
+
|
|
66
|
+
export type PaneMoveResult = { "changed": boolean; "closed_tab_id"?: string | null; "closed_workspace_id"?: string | null; "created_tab"?: (TabInfo) | (null); "created_workspace"?: (WorkspaceInfo) | (null); "focused_pane_id": string; "pane": PaneInfo; "previous_pane_id": string; "previous_tab_id": string; "previous_workspace_id": string; "reason"?: (PaneMoveReason) | (null); "source_layout"?: (PaneLayoutSnapshot) | (null); "target_layout": PaneLayoutSnapshot; };
|
|
67
|
+
|
|
68
|
+
export type PaneNeighborResult = { "direction": PaneDirection; "layout": PaneLayoutSnapshot; "neighbor_pane_id"?: string | null; "pane_id": string; };
|
|
69
|
+
|
|
70
|
+
export type PaneProcessInfo = { "foreground_process_group_id"?: number | null; "foreground_processes"?: Array<PaneProcessInfoProcess>; "pane_id": string; "shell_pid"?: number | null; "tty"?: string | null; };
|
|
71
|
+
|
|
72
|
+
export type PaneProcessInfoProcess = { "argv"?: Array<string> | null; "argv0"?: string | null; "cmdline"?: string | null; "cwd"?: string | null; "name": string; "pid": number; };
|
|
73
|
+
|
|
74
|
+
export type PaneReadResult = { "format": ReadFormat; "pane_id": string; "revision": number; "source": ReadSource; "tab_id": string; "text": string; "truncated": boolean; "workspace_id": string; };
|
|
75
|
+
|
|
76
|
+
export type PaneResizeReason = "unchanged";
|
|
77
|
+
|
|
78
|
+
export type PaneResizeResult = { "changed": boolean; "focused_pane_id": string; "layout": PaneLayoutSnapshot; "pane_id": string; "reason"?: (PaneResizeReason) | (null); };
|
|
79
|
+
|
|
80
|
+
export type PaneScrollInfo = { "max_offset_from_bottom": number; "offset_from_bottom": number; "viewport_rows": number; };
|
|
81
|
+
|
|
82
|
+
export type PaneSwapReason = "no_neighbor" | "same_pane" | "not_found" | "cross_tab";
|
|
83
|
+
|
|
84
|
+
export type PaneSwapResult = { "changed": boolean; "focused_pane_id": string; "layout": PaneLayoutSnapshot; "reason"?: (PaneSwapReason) | (null); "source_pane_id": string; "target_pane_id"?: string | null; };
|
|
85
|
+
|
|
86
|
+
export type PaneTextPoint = { "col": number; "row": number; };
|
|
87
|
+
|
|
88
|
+
export type PaneTextRange = { "end": PaneTextPoint; "start": PaneTextPoint; };
|
|
89
|
+
|
|
90
|
+
export type PaneZoomReason = "single_pane" | "already_zoomed" | "already_unzoomed";
|
|
91
|
+
|
|
92
|
+
export type PaneZoomResult = { "changed": boolean; "focus_changed": boolean; "focused_pane_id": string; "layout": PaneLayoutSnapshot; "pane_id": string; "reason"?: (PaneZoomReason) | (null); "zoom_changed": boolean; "zoomed": boolean; };
|
|
93
|
+
|
|
94
|
+
export type PluginActionContext = "global" | "workspace" | "tab" | "pane" | "selection";
|
|
95
|
+
|
|
96
|
+
export type PluginActionInfo = { "action_id": string; "command": Array<string>; "contexts"?: Array<PluginActionContext>; "description"?: string | null; "platforms"?: Array<PluginPlatform> | null; "plugin_id": string; "title": string; };
|
|
97
|
+
|
|
98
|
+
export type PluginCommandLogInfo = { "action_id"?: string | null; "command": Array<string>; "error"?: string | null; "event"?: string | null; "exit_code"?: number | null; "finished_unix_ms"?: number | null; "log_id": string; "plugin_id": string; "started_unix_ms": number; "status": PluginCommandStatus; "stderr"?: string | null; "stdout"?: string | null; };
|
|
99
|
+
|
|
100
|
+
export type PluginCommandStatus = "running" | "succeeded" | "failed";
|
|
101
|
+
|
|
102
|
+
export type PluginInvocationContext = { "clicked_url"?: string | null; "correlation_id"?: string | null; "focused_pane_agent"?: string | null; "focused_pane_cwd"?: string | null; "focused_pane_id"?: string | null; "focused_pane_status"?: (AgentStatus) | (null); "invocation_source"?: string | null; "link_handler_id"?: string | null; "selected_text"?: string | null; "tab_id"?: string | null; "tab_label"?: string | null; "workspace_cwd"?: string | null; "workspace_id"?: string | null; "workspace_label"?: string | null; "worktree"?: (WorkspaceWorktreeInfo) | (null); };
|
|
103
|
+
|
|
104
|
+
export type PluginManifestAction = { "command": Array<string>; "contexts"?: Array<PluginActionContext>; "description"?: string | null; "id": string; "platforms"?: Array<PluginPlatform> | null; "title": string; };
|
|
105
|
+
|
|
106
|
+
export type PluginManifestBuild = { "command": Array<string>; "platforms"?: Array<PluginPlatform> | null; };
|
|
107
|
+
|
|
108
|
+
export type PluginManifestEventHook = { "command": Array<string>; "on": string; "platforms"?: Array<PluginPlatform> | null; };
|
|
109
|
+
|
|
110
|
+
export type PluginManifestLinkHandler = { "action": string; "id": string; "pattern": string; "platforms"?: Array<PluginPlatform> | null; "title": string; };
|
|
111
|
+
|
|
112
|
+
export type PluginManifestPane = { "command": Array<string>; "description"?: string | null; "height"?: (PopupSize) | (null); "id": string; "placement"?: PluginPanePlacement; "platforms"?: Array<PluginPlatform> | null; "title": string; "width"?: (PopupSize) | (null); };
|
|
113
|
+
|
|
114
|
+
export type PluginManifestStartup = { "command": Array<string>; "platforms"?: Array<PluginPlatform> | null; };
|
|
115
|
+
|
|
116
|
+
export type PluginPaneInfo = { "entrypoint": string; "pane": PaneInfo; "plugin_id": string; };
|
|
117
|
+
|
|
118
|
+
export type PluginPanePlacement = "overlay" | "popup" | "split" | "tab" | "zoomed";
|
|
119
|
+
|
|
120
|
+
export type PluginPlatform = "linux" | "macos" | "windows";
|
|
121
|
+
|
|
122
|
+
export type PluginSourceInfo = { "installed_unix_ms"?: number | null; "kind"?: PluginSourceKind; "managed_path"?: string | null; "owner"?: string | null; "repo"?: string | null; "requested_ref"?: string | null; "resolved_commit"?: string | null; "subdir"?: string | null; };
|
|
123
|
+
|
|
124
|
+
export type PluginSourceKind = "local" | "github";
|
|
125
|
+
|
|
126
|
+
export type PopupSize = (number) | (string);
|
|
127
|
+
|
|
128
|
+
export type ReadFormat = "text" | "ansi";
|
|
129
|
+
|
|
130
|
+
export type ReadSource = "visible" | "recent" | "recent_unwrapped" | "detection";
|
|
131
|
+
|
|
132
|
+
export type ServerCapabilities = { "detached_server_daemon"?: boolean; /** Stable client-owned endpoint generation supported by this server. */ "endpoint_protocol_generation"?: number | null; /** Whether this server supports endpoint health probes. */ "health_check"?: boolean; "live_handoff": boolean; /** Whether this server supports explicit client-shell surface interest. */ "surface_interest"?: boolean; };
|
|
133
|
+
|
|
134
|
+
export type SessionSnapshot = { "agents": Array<AgentInfo>; "focused_pane_id"?: string | null; "focused_tab_id"?: string | null; "focused_workspace_id"?: string | null; "layouts": Array<PaneLayoutSnapshot>; "panes": Array<PaneInfo>; "protocol": number; "tabs": Array<TabInfo>; "version": string; "workspaces": Array<WorkspaceInfo>; };
|
|
135
|
+
|
|
136
|
+
export type SplitDirection = "right" | "down";
|
|
137
|
+
|
|
138
|
+
export type TabInfo = { "agent_status": AgentStatus; "focused": boolean; "label": string; "number": number; "pane_count": number; "tab_id": string; "workspace_id": string; };
|
|
139
|
+
|
|
140
|
+
export type WorkspaceInfo = { "active_tab_id": string; "agent_status": AgentStatus; "focused": boolean; "label": string; "number": number; "pane_count": number; "tab_count": number; "tokens"?: { [key: string]: string; }; "workspace_id": string; "worktree"?: (WorkspaceWorktreeInfo) | (null); };
|
|
141
|
+
|
|
142
|
+
export type WorkspaceWorktreeInfo = { "checkout_path": string; "is_linked_worktree": boolean; "repo_key": string; "repo_name": string; "repo_root": string; };
|
|
143
|
+
|
|
144
|
+
export type WorktreeInfo = { "branch"?: string | null; "is_bare": boolean; "is_detached": boolean; "is_linked_worktree": boolean; "is_prunable": boolean; "label": string; "open_workspace_id"?: string | null; "path": string; };
|
|
145
|
+
|
|
146
|
+
export type WorktreeSourceInfo = { "repo_key": string; "repo_name": string; "repo_root": string; "source_checkout_path": string; "source_workspace_id"?: string | null; };
|
|
147
|
+
|
|
148
|
+
export type Result_pong = { "capabilities"?: (ServerCapabilities) | (null); "protocol": number; "type": "pong"; "version": string; };
|
|
149
|
+
|
|
150
|
+
export type Result_session_snapshot = { "snapshot": SessionSnapshot; "type": "session_snapshot"; };
|
|
151
|
+
|
|
152
|
+
export type Result_workspace_info = { "type": "workspace_info"; "workspace": WorkspaceInfo; };
|
|
153
|
+
|
|
154
|
+
export type Result_workspace_created = { "root_pane": PaneInfo; "tab": TabInfo; "type": "workspace_created"; "workspace": WorkspaceInfo; };
|
|
155
|
+
|
|
156
|
+
export type Result_workspace_list = { "type": "workspace_list"; "workspaces": Array<WorkspaceInfo>; };
|
|
157
|
+
|
|
158
|
+
export type Result_worktree_list = { "source": WorktreeSourceInfo; "type": "worktree_list"; "worktrees": Array<WorktreeInfo>; };
|
|
159
|
+
|
|
160
|
+
export type Result_worktree_created = { "root_pane": PaneInfo; "tab": TabInfo; "type": "worktree_created"; "workspace": WorkspaceInfo; "worktree": WorktreeInfo; };
|
|
161
|
+
|
|
162
|
+
export type Result_worktree_opened = { "already_open": boolean; "root_pane": PaneInfo; "tab": TabInfo; "type": "worktree_opened"; "workspace": WorkspaceInfo; "worktree": WorktreeInfo; };
|
|
163
|
+
|
|
164
|
+
export type Result_worktree_removed = { "forced": boolean; "path": string; "type": "worktree_removed"; "workspace_id": string; };
|
|
165
|
+
|
|
166
|
+
export type Result_tab_info = { "tab": TabInfo; "type": "tab_info"; };
|
|
167
|
+
|
|
168
|
+
export type Result_tab_created = { "root_pane": PaneInfo; "tab": TabInfo; "type": "tab_created"; };
|
|
169
|
+
|
|
170
|
+
export type Result_tab_list = { "tabs": Array<TabInfo>; "type": "tab_list"; };
|
|
171
|
+
|
|
172
|
+
export type Result_agent_info = { "agent": AgentInfo; "type": "agent_info"; };
|
|
173
|
+
|
|
174
|
+
export type Result_agent_started = { "agent": AgentInfo; "argv": Array<string>; "type": "agent_started"; };
|
|
175
|
+
|
|
176
|
+
export type Result_agent_prompted = { "agent": AgentInfo; "type": "agent_prompted"; };
|
|
177
|
+
|
|
178
|
+
export type Result_agent_list = { "agents": Array<AgentInfo>; "type": "agent_list"; };
|
|
179
|
+
|
|
180
|
+
export type Result_agent_view = { "active": boolean; "label"?: string | null; "source"?: string | null; "type": "agent_view"; };
|
|
181
|
+
|
|
182
|
+
export type Result_pane_info = { "pane": PaneInfo; "type": "pane_info"; };
|
|
183
|
+
|
|
184
|
+
export type Result_pane_list = { "panes": Array<PaneInfo>; "type": "pane_list"; };
|
|
185
|
+
|
|
186
|
+
export type Result_pane_current = { "pane": PaneInfo; "type": "pane_current"; };
|
|
187
|
+
|
|
188
|
+
export type Result_pane_swap = { "swap": PaneSwapResult; "type": "pane_swap"; };
|
|
189
|
+
|
|
190
|
+
export type Result_pane_move = { "move_result": PaneMoveResult; "type": "pane_move"; };
|
|
191
|
+
|
|
192
|
+
export type Result_pane_zoom = { "type": "pane_zoom"; "zoom": PaneZoomResult; };
|
|
193
|
+
|
|
194
|
+
export type Result_pane_layout = { "layout": PaneLayoutSnapshot; "type": "pane_layout"; };
|
|
195
|
+
|
|
196
|
+
export type Result_pane_process_info = { "process_info": PaneProcessInfo; "type": "pane_process_info"; };
|
|
197
|
+
|
|
198
|
+
export type Result_layout_export = { "layout": LayoutDescription; "type": "layout_export"; };
|
|
199
|
+
|
|
200
|
+
export type Result_layout_apply = { "layout": LayoutDescription; "type": "layout_apply"; };
|
|
201
|
+
|
|
202
|
+
export type Result_layout_split_ratio_set = { "layout": LayoutDescription; "type": "layout_split_ratio_set"; };
|
|
203
|
+
|
|
204
|
+
export type Result_pane_neighbor = { "neighbor": PaneNeighborResult; "type": "pane_neighbor"; };
|
|
205
|
+
|
|
206
|
+
export type Result_pane_edges = { "edges": PaneEdgesResult; "type": "pane_edges"; };
|
|
207
|
+
|
|
208
|
+
export type Result_pane_focus_direction = { "focus": PaneFocusDirectionResult; "type": "pane_focus_direction"; };
|
|
209
|
+
|
|
210
|
+
export type Result_pane_resize = { "resize": PaneResizeResult; "type": "pane_resize"; };
|
|
211
|
+
|
|
212
|
+
export type Result_pane_read = { "read": PaneReadResult; "type": "pane_read"; };
|
|
213
|
+
|
|
214
|
+
export type Result_pane_selection = { "pane_id": string; "text": string; "type": "pane_selection"; };
|
|
215
|
+
|
|
216
|
+
export type Result_pane_copy_motion = { "content_revision": number; "cursor": PaneTextPoint; "pane_id": string; "type": "pane_copy_motion"; };
|
|
217
|
+
|
|
218
|
+
export type Result_pane_copy_search = { "content_revision": number; "current"?: number | null; "current_global"?: number | null; "matches": Array<PaneTextRange>; "pane_id": string; "total": number; "type": "pane_copy_search"; };
|
|
219
|
+
|
|
220
|
+
export type Result_pane_graphics_frame_ack = { "revision": number; "sequence": number; "type": "pane_graphics_frame_ack"; };
|
|
221
|
+
|
|
222
|
+
export type Result_pane_graphics_info = { "cell_height_px": number; "cell_width_px": number; /** Accepts damage metadata while still consuming a complete canonical file. */ "file_frame_damage"?: boolean; "file_frame_direct_max_bytes"?: number | null; "file_frame_directory"?: string | null; "file_frame_formats"?: Array<string>; "file_frame_max_bytes"?: number | null; "file_frame_transport"?: string | null; "max_layers_per_pane"?: number; /** True only when this pane is on the currently rendered terminal surface. */ "pane_visible": boolean; "pixel_mouse"?: boolean; "type": "pane_graphics_info"; };
|
|
223
|
+
|
|
224
|
+
export type Result_agent_explain = { "explain": unknown; "type": "agent_explain"; };
|
|
225
|
+
|
|
226
|
+
export type Result_subscription_started = { "type": "subscription_started"; };
|
|
227
|
+
|
|
228
|
+
export type Result_wait_matched = { "event": EventEnvelope; "type": "wait_matched"; };
|
|
229
|
+
|
|
230
|
+
export type Result_output_matched = { "matched_line"?: string | null; "pane_id": string; "read": PaneReadResult; "revision": number; "type": "output_matched"; };
|
|
231
|
+
|
|
232
|
+
export type Result_notification_show = { "reason": NotificationShowReason; "shown": boolean; "type": "notification_show"; };
|
|
233
|
+
|
|
234
|
+
export type Result_client_window_title = { "changed": boolean; "reason": ClientWindowTitleReason; "type": "client_window_title"; };
|
|
235
|
+
|
|
236
|
+
export type Result_integration_list = { "integrations": Array<IntegrationInfo>; "type": "integration_list"; };
|
|
237
|
+
|
|
238
|
+
export type Result_integration_install = { "details": IntegrationInstallResult; "target": IntegrationTarget; "type": "integration_install"; };
|
|
239
|
+
|
|
240
|
+
export type Result_integration_uninstall = { "details": IntegrationUninstallResult; "target": IntegrationTarget; "type": "integration_uninstall"; };
|
|
241
|
+
|
|
242
|
+
export type Result_agent_manifest_reload = { "manifests": Array<AgentManifestInfo>; "type": "agent_manifest_reload"; };
|
|
243
|
+
|
|
244
|
+
export type Result_agent_manifest_status = { "last_check_unix"?: number | null; "last_result"?: string | null; "manifests": Array<AgentManifestInfo>; "type": "agent_manifest_status"; };
|
|
245
|
+
|
|
246
|
+
export type Result_plugin_linked = { "plugin": InstalledPluginInfo; "type": "plugin_linked"; };
|
|
247
|
+
|
|
248
|
+
export type Result_plugin_list = { "plugins": Array<InstalledPluginInfo>; "type": "plugin_list"; };
|
|
249
|
+
|
|
250
|
+
export type Result_plugin_unlinked = { "plugin_id": string; "removed": boolean; "type": "plugin_unlinked"; };
|
|
251
|
+
|
|
252
|
+
export type Result_plugin_enabled = { "plugin": InstalledPluginInfo; "type": "plugin_enabled"; };
|
|
253
|
+
|
|
254
|
+
export type Result_plugin_disabled = { "plugin": InstalledPluginInfo; "type": "plugin_disabled"; };
|
|
255
|
+
|
|
256
|
+
export type Result_plugin_action_list = { "actions": Array<PluginActionInfo>; "type": "plugin_action_list"; };
|
|
257
|
+
|
|
258
|
+
export type Result_plugin_action_invoked = { "action": PluginActionInfo; "context": PluginInvocationContext; "log": PluginCommandLogInfo; "type": "plugin_action_invoked"; };
|
|
259
|
+
|
|
260
|
+
export type Result_pane_link_resolved = { "regions": Array<PaneLinkRegion>; "type": "pane_link_resolved"; };
|
|
261
|
+
|
|
262
|
+
export type Result_pane_link_activated = { "handled": boolean; "type": "pane_link_activated"; "url"?: string | null; };
|
|
263
|
+
|
|
264
|
+
export type Result_plugin_log_list = { "logs": Array<PluginCommandLogInfo>; "type": "plugin_log_list"; };
|
|
265
|
+
|
|
266
|
+
export type Result_plugin_pane_opened = { "plugin_pane": PluginPaneInfo; "type": "plugin_pane_opened"; };
|
|
267
|
+
|
|
268
|
+
export type Result_plugin_pane_focused = { "plugin_pane": PluginPaneInfo; "type": "plugin_pane_focused"; };
|
|
269
|
+
|
|
270
|
+
export type Result_plugin_pane_closed = { "pane_id": string; "type": "plugin_pane_closed"; };
|
|
271
|
+
|
|
272
|
+
export type Result_config_reload = { "diagnostics": Array<string>; "status": ConfigReloadStatus; "type": "config_reload"; };
|
|
273
|
+
|
|
274
|
+
export type Result_client_shell_surface_set = { "active": boolean; "projection_revision": number; "type": "client_shell_surface_set"; };
|
|
275
|
+
|
|
276
|
+
export type Result_ok = { "type": "ok"; };
|
|
277
|
+
|
|
278
|
+
/** The full union of every result shape the server can return. */
|
|
279
|
+
export type ResponseResult =
|
|
280
|
+
| Result_pong
|
|
281
|
+
| Result_session_snapshot
|
|
282
|
+
| Result_workspace_info
|
|
283
|
+
| Result_workspace_created
|
|
284
|
+
| Result_workspace_list
|
|
285
|
+
| Result_worktree_list
|
|
286
|
+
| Result_worktree_created
|
|
287
|
+
| Result_worktree_opened
|
|
288
|
+
| Result_worktree_removed
|
|
289
|
+
| Result_tab_info
|
|
290
|
+
| Result_tab_created
|
|
291
|
+
| Result_tab_list
|
|
292
|
+
| Result_agent_info
|
|
293
|
+
| Result_agent_started
|
|
294
|
+
| Result_agent_prompted
|
|
295
|
+
| Result_agent_list
|
|
296
|
+
| Result_agent_view
|
|
297
|
+
| Result_pane_info
|
|
298
|
+
| Result_pane_list
|
|
299
|
+
| Result_pane_current
|
|
300
|
+
| Result_pane_swap
|
|
301
|
+
| Result_pane_move
|
|
302
|
+
| Result_pane_zoom
|
|
303
|
+
| Result_pane_layout
|
|
304
|
+
| Result_pane_process_info
|
|
305
|
+
| Result_layout_export
|
|
306
|
+
| Result_layout_apply
|
|
307
|
+
| Result_layout_split_ratio_set
|
|
308
|
+
| Result_pane_neighbor
|
|
309
|
+
| Result_pane_edges
|
|
310
|
+
| Result_pane_focus_direction
|
|
311
|
+
| Result_pane_resize
|
|
312
|
+
| Result_pane_read
|
|
313
|
+
| Result_pane_selection
|
|
314
|
+
| Result_pane_copy_motion
|
|
315
|
+
| Result_pane_copy_search
|
|
316
|
+
| Result_pane_graphics_frame_ack
|
|
317
|
+
| Result_pane_graphics_info
|
|
318
|
+
| Result_agent_explain
|
|
319
|
+
| Result_subscription_started
|
|
320
|
+
| Result_wait_matched
|
|
321
|
+
| Result_output_matched
|
|
322
|
+
| Result_notification_show
|
|
323
|
+
| Result_client_window_title
|
|
324
|
+
| Result_integration_list
|
|
325
|
+
| Result_integration_install
|
|
326
|
+
| Result_integration_uninstall
|
|
327
|
+
| Result_agent_manifest_reload
|
|
328
|
+
| Result_agent_manifest_status
|
|
329
|
+
| Result_plugin_linked
|
|
330
|
+
| Result_plugin_list
|
|
331
|
+
| Result_plugin_unlinked
|
|
332
|
+
| Result_plugin_enabled
|
|
333
|
+
| Result_plugin_disabled
|
|
334
|
+
| Result_plugin_action_list
|
|
335
|
+
| Result_plugin_action_invoked
|
|
336
|
+
| Result_pane_link_resolved
|
|
337
|
+
| Result_pane_link_activated
|
|
338
|
+
| Result_plugin_log_list
|
|
339
|
+
| Result_plugin_pane_opened
|
|
340
|
+
| Result_plugin_pane_focused
|
|
341
|
+
| Result_plugin_pane_closed
|
|
342
|
+
| Result_config_reload
|
|
343
|
+
| Result_client_shell_surface_set
|
|
344
|
+
| Result_ok;
|
|
345
|
+
|
|
346
|
+
/** Result shape, keyed by its `type` tag. */
|
|
347
|
+
export interface ResultByTag {
|
|
348
|
+
"pong": Result_pong;
|
|
349
|
+
"session_snapshot": Result_session_snapshot;
|
|
350
|
+
"workspace_info": Result_workspace_info;
|
|
351
|
+
"workspace_created": Result_workspace_created;
|
|
352
|
+
"workspace_list": Result_workspace_list;
|
|
353
|
+
"worktree_list": Result_worktree_list;
|
|
354
|
+
"worktree_created": Result_worktree_created;
|
|
355
|
+
"worktree_opened": Result_worktree_opened;
|
|
356
|
+
"worktree_removed": Result_worktree_removed;
|
|
357
|
+
"tab_info": Result_tab_info;
|
|
358
|
+
"tab_created": Result_tab_created;
|
|
359
|
+
"tab_list": Result_tab_list;
|
|
360
|
+
"agent_info": Result_agent_info;
|
|
361
|
+
"agent_started": Result_agent_started;
|
|
362
|
+
"agent_prompted": Result_agent_prompted;
|
|
363
|
+
"agent_list": Result_agent_list;
|
|
364
|
+
"agent_view": Result_agent_view;
|
|
365
|
+
"pane_info": Result_pane_info;
|
|
366
|
+
"pane_list": Result_pane_list;
|
|
367
|
+
"pane_current": Result_pane_current;
|
|
368
|
+
"pane_swap": Result_pane_swap;
|
|
369
|
+
"pane_move": Result_pane_move;
|
|
370
|
+
"pane_zoom": Result_pane_zoom;
|
|
371
|
+
"pane_layout": Result_pane_layout;
|
|
372
|
+
"pane_process_info": Result_pane_process_info;
|
|
373
|
+
"layout_export": Result_layout_export;
|
|
374
|
+
"layout_apply": Result_layout_apply;
|
|
375
|
+
"layout_split_ratio_set": Result_layout_split_ratio_set;
|
|
376
|
+
"pane_neighbor": Result_pane_neighbor;
|
|
377
|
+
"pane_edges": Result_pane_edges;
|
|
378
|
+
"pane_focus_direction": Result_pane_focus_direction;
|
|
379
|
+
"pane_resize": Result_pane_resize;
|
|
380
|
+
"pane_read": Result_pane_read;
|
|
381
|
+
"pane_selection": Result_pane_selection;
|
|
382
|
+
"pane_copy_motion": Result_pane_copy_motion;
|
|
383
|
+
"pane_copy_search": Result_pane_copy_search;
|
|
384
|
+
"pane_graphics_frame_ack": Result_pane_graphics_frame_ack;
|
|
385
|
+
"pane_graphics_info": Result_pane_graphics_info;
|
|
386
|
+
"agent_explain": Result_agent_explain;
|
|
387
|
+
"subscription_started": Result_subscription_started;
|
|
388
|
+
"wait_matched": Result_wait_matched;
|
|
389
|
+
"output_matched": Result_output_matched;
|
|
390
|
+
"notification_show": Result_notification_show;
|
|
391
|
+
"client_window_title": Result_client_window_title;
|
|
392
|
+
"integration_list": Result_integration_list;
|
|
393
|
+
"integration_install": Result_integration_install;
|
|
394
|
+
"integration_uninstall": Result_integration_uninstall;
|
|
395
|
+
"agent_manifest_reload": Result_agent_manifest_reload;
|
|
396
|
+
"agent_manifest_status": Result_agent_manifest_status;
|
|
397
|
+
"plugin_linked": Result_plugin_linked;
|
|
398
|
+
"plugin_list": Result_plugin_list;
|
|
399
|
+
"plugin_unlinked": Result_plugin_unlinked;
|
|
400
|
+
"plugin_enabled": Result_plugin_enabled;
|
|
401
|
+
"plugin_disabled": Result_plugin_disabled;
|
|
402
|
+
"plugin_action_list": Result_plugin_action_list;
|
|
403
|
+
"plugin_action_invoked": Result_plugin_action_invoked;
|
|
404
|
+
"pane_link_resolved": Result_pane_link_resolved;
|
|
405
|
+
"pane_link_activated": Result_pane_link_activated;
|
|
406
|
+
"plugin_log_list": Result_plugin_log_list;
|
|
407
|
+
"plugin_pane_opened": Result_plugin_pane_opened;
|
|
408
|
+
"plugin_pane_focused": Result_plugin_pane_focused;
|
|
409
|
+
"plugin_pane_closed": Result_plugin_pane_closed;
|
|
410
|
+
"config_reload": Result_config_reload;
|
|
411
|
+
"client_shell_surface_set": Result_client_shell_surface_set;
|
|
412
|
+
"ok": Result_ok;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export type ResultTag = keyof ResultByTag;
|
|
416
|
+
|
|
417
|
+
/** See scripts/gen/method-result-map.ts. */
|
|
418
|
+
export const METHOD_RESULT = {
|
|
419
|
+
"ping": "pong",
|
|
420
|
+
"session.snapshot": "session_snapshot",
|
|
421
|
+
"workspace.create": "workspace_created",
|
|
422
|
+
"workspace.list": "workspace_list",
|
|
423
|
+
"workspace.get": "workspace_info",
|
|
424
|
+
"worktree.list": "worktree_list",
|
|
425
|
+
"worktree.create": "worktree_created",
|
|
426
|
+
"worktree.open": "worktree_opened",
|
|
427
|
+
"worktree.remove": "worktree_removed",
|
|
428
|
+
"tab.create": "tab_created",
|
|
429
|
+
"tab.list": "tab_list",
|
|
430
|
+
"tab.get": "tab_info",
|
|
431
|
+
"agent.list": "agent_list",
|
|
432
|
+
"agent.get": "agent_info",
|
|
433
|
+
"agent.read": "pane_read",
|
|
434
|
+
"agent.start": "agent_started",
|
|
435
|
+
"agent.prompt": "agent_prompted",
|
|
436
|
+
"agent.wait": "agent_info",
|
|
437
|
+
"agent.view.set": "agent_view",
|
|
438
|
+
"agent.view.clear": "agent_view",
|
|
439
|
+
"pane.list": "pane_list",
|
|
440
|
+
"pane.current": "pane_current",
|
|
441
|
+
"pane.get": "pane_info",
|
|
442
|
+
"pane.read": "pane_read",
|
|
443
|
+
"events.subscribe": "subscription_started"
|
|
444
|
+
} as const;
|
package/src/herdr.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// Effect-native client for the herdr socket API.
|
|
2
|
+
// Wire facts (herdr 0.9, protocol 22): newline-delimited JSON; `{id, method, params}` → `{id, result}` | `{id, error}`;
|
|
3
|
+
// the server closes after one response, so every call is its own connection. `events.subscribe` acks with
|
|
4
|
+
// `subscription_started` and then keeps the connection open, streaming `{event, data}` frames.
|
|
5
|
+
import { Cause, Config, Context, Effect, Layer, Option, type Path, Random, Schema, Stream } from "effect"
|
|
6
|
+
import * as Socket from "effect/socket/Socket"
|
|
7
|
+
import type { PushFrame } from "./generated/events.js"
|
|
8
|
+
import { PROTOCOL } from "./generated/index.js"
|
|
9
|
+
import type { Method, MethodParams, Subscription } from "./generated/params.js"
|
|
10
|
+
import type { METHOD_RESULT, ResponseResult, ResultByTag } from "./generated/results.js"
|
|
11
|
+
import { SocketConnector } from "./socket-connector.js"
|
|
12
|
+
import { defaultSocketPath, socketEndpoint, type SocketPathOptions } from "./socket-path.js"
|
|
13
|
+
|
|
14
|
+
export type ResultOf<M extends Method> = M extends keyof typeof METHOD_RESULT ? ResultByTag[(typeof METHOD_RESULT)[M]] : ResponseResult
|
|
15
|
+
export type ParamsOf<M extends Method> = MethodParams[M]
|
|
16
|
+
|
|
17
|
+
/** The server answered `{ error }`. `code` is herdr's machine-readable code (`timeout`, `agent_pane_busy`, …). */
|
|
18
|
+
export class HerdrError extends Schema.TaggedError<HerdrError>()("HerdrError", {
|
|
19
|
+
method: Schema.String,
|
|
20
|
+
code: Schema.String,
|
|
21
|
+
message: Schema.String,
|
|
22
|
+
}) {}
|
|
23
|
+
|
|
24
|
+
/** Socket missing, refused, or closed before a response. */
|
|
25
|
+
export class HerdrTransportError extends Schema.TaggedError<HerdrTransportError>()("HerdrTransportError", {
|
|
26
|
+
method: Schema.String,
|
|
27
|
+
message: Schema.String,
|
|
28
|
+
}) {}
|
|
29
|
+
|
|
30
|
+
export type HerdrFailure = HerdrError | HerdrTransportError
|
|
31
|
+
|
|
32
|
+
/** The server speaks a different protocol than the one this SDK's types were generated for (`PROTOCOL`). */
|
|
33
|
+
export class HerdrProtocolMismatch extends Schema.TaggedError<HerdrProtocolMismatch>()("HerdrProtocolMismatch", {
|
|
34
|
+
socketPath: Schema.String,
|
|
35
|
+
expected: Schema.Number,
|
|
36
|
+
actual: Schema.Number,
|
|
37
|
+
serverVersion: Schema.String,
|
|
38
|
+
}) {}
|
|
39
|
+
|
|
40
|
+
export interface HerdrShape {
|
|
41
|
+
readonly socketPath: string
|
|
42
|
+
readonly call: <M extends Method>(method: M, params: ParamsOf<M>) => Effect.Effect<ResultOf<M>, HerdrFailure>
|
|
43
|
+
/** Long-lived push stream. Ends when the server closes the connection. */
|
|
44
|
+
readonly subscribe: (subscriptions: ReadonlyArray<Subscription>) => Stream.Stream<PushFrame, HerdrFailure>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class Herdr extends Context.Service<Herdr, HerdrShape>()("effect-herdr-sdk/Herdr") {
|
|
48
|
+
/**
|
|
49
|
+
* The handshake every consumer runs before trusting a server: the generated types (and the unchecked casts that
|
|
50
|
+
* hand them out, see `call` / `subscribe`) are only true for the protocol they were generated from.
|
|
51
|
+
*/
|
|
52
|
+
static readonly verifyProtocol = (herdr: HerdrShape): Effect.Effect<void, HerdrFailure | HerdrProtocolMismatch> =>
|
|
53
|
+
herdr.call("ping", {}).pipe(
|
|
54
|
+
Effect.flatMap((pong) =>
|
|
55
|
+
pong.protocol === PROTOCOL
|
|
56
|
+
? Effect.void
|
|
57
|
+
: Effect.fail(new HerdrProtocolMismatch({ socketPath: herdr.socketPath, expected: PROTOCOL, actual: pong.protocol, serverVersion: pong.version })),
|
|
58
|
+
),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
/** A client for `socketPath`, dialing through the provided `SocketConnector`. */
|
|
62
|
+
static readonly make = (socketPath: string): Effect.Effect<HerdrShape, never, SocketConnector> =>
|
|
63
|
+
Effect.map(SocketConnector, (connect) => makeClient(socketPath, connect))
|
|
64
|
+
/** Socket from `options.socketPath`, else herdr's own resolution (HERDR_SOCKET_PATH, XDG_CONFIG_HOME, HOME …) read through Config. */
|
|
65
|
+
static readonly layer = (
|
|
66
|
+
options: { socketPath?: string } & SocketPathOptions = {},
|
|
67
|
+
): Layer.Layer<Herdr, Config.ConfigError, SocketConnector | Path.Path> =>
|
|
68
|
+
Layer.effect(
|
|
69
|
+
Herdr,
|
|
70
|
+
(options.socketPath ? Effect.succeed(options.socketPath) : defaultSocketPath(options)).pipe(Effect.flatMap(Herdr.make)),
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Wire frames (herdr protocol 22). `id: ""` = the server could not parse our request; still ours.
|
|
75
|
+
const Response = Schema.Struct({
|
|
76
|
+
id: Schema.String,
|
|
77
|
+
result: Schema.optional(Schema.Unknown),
|
|
78
|
+
error: Schema.optional(Schema.Struct({ code: Schema.String, message: Schema.String })),
|
|
79
|
+
})
|
|
80
|
+
const Push = Schema.Struct({ event: Schema.String, data: Schema.Unknown })
|
|
81
|
+
const decodeLine = Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Union([Response, Push])))
|
|
82
|
+
const Request = Schema.Struct({ id: Schema.String, method: Schema.String, params: Schema.Unknown })
|
|
83
|
+
const encodeRequest = Schema.encodeEffect(Schema.fromJsonString(Request))
|
|
84
|
+
const isResponse = (m: typeof Response.Type | typeof Push.Type): m is typeof Response.Type => "id" in m
|
|
85
|
+
|
|
86
|
+
const requestId = (prefix: string) => Random.nextIntBetween(0, 2 ** 31).pipe(Effect.map((n) => `${prefix}-${n.toString(36)}`))
|
|
87
|
+
|
|
88
|
+
function makeClient(socketPath: string, connect: SocketConnector["Service"]): HerdrShape {
|
|
89
|
+
const transport = (method: string) => (e: { readonly message: string }) => new HerdrTransportError({ method, message: e.message })
|
|
90
|
+
const serverError = (method: string, error: { code: string; message: string }) => new HerdrError({ method, code: error.code, message: error.message })
|
|
91
|
+
|
|
92
|
+
/** Open a connection, send one request line, and expose the decoded response lines. Scoped: closing the scope closes the socket. */
|
|
93
|
+
const open = (method: string, request: typeof Request.Type) =>
|
|
94
|
+
Effect.gen(function* () {
|
|
95
|
+
const socket = yield* connect(socketEndpoint(socketPath))
|
|
96
|
+
// Acquiring the reader dials; the writer waits on that, so writing first would hang forever.
|
|
97
|
+
const pull = yield* Socket.readerString(socket)
|
|
98
|
+
const writer = yield* socket.writer
|
|
99
|
+
yield* writer.write(`${yield* encodeRequest(request).pipe(Effect.orDie)}\n`)
|
|
100
|
+
// Every close surfaces as a SocketError; a clean close is just the end of the stream.
|
|
101
|
+
const text = pull.pipe(Effect.catchIf((e) => e.reason._tag === "SocketCloseError", () => Cause.done()))
|
|
102
|
+
return Stream.fromPull(Effect.succeed(text)).pipe(
|
|
103
|
+
Stream.splitLines,
|
|
104
|
+
Stream.filter((l) => l.length > 0),
|
|
105
|
+
Stream.mapEffect((line) => decodeLine(line)),
|
|
106
|
+
Stream.mapError(transport(method)),
|
|
107
|
+
)
|
|
108
|
+
}).pipe(Effect.mapError(transport(method)))
|
|
109
|
+
|
|
110
|
+
const call = <M extends Method>(method: M, params: ParamsOf<M>) =>
|
|
111
|
+
Effect.gen(function* () {
|
|
112
|
+
const id = yield* requestId("omac")
|
|
113
|
+
const lines = yield* open(method, { id, method, params })
|
|
114
|
+
const found = yield* lines.pipe(
|
|
115
|
+
Stream.filter(isResponse),
|
|
116
|
+
Stream.filter((m) => m.id === id || m.id === ""),
|
|
117
|
+
Stream.runHead,
|
|
118
|
+
)
|
|
119
|
+
if (Option.isNone(found)) return yield* new HerdrTransportError({ method, message: "connection closed before a response" })
|
|
120
|
+
if (found.value.error) return yield* serverError(method, found.value.error)
|
|
121
|
+
// Not decoded at runtime: the shape is herdr's contract for PROTOCOL, checked once per server by verifyProtocol.
|
|
122
|
+
return found.value.result as ResultOf<M>
|
|
123
|
+
}).pipe(Effect.scoped)
|
|
124
|
+
|
|
125
|
+
/** herdr acks with a response first and only then pushes frames, so no ack state is needed. */
|
|
126
|
+
const subscribe = (subscriptions: ReadonlyArray<Subscription>): Stream.Stream<PushFrame, HerdrFailure> => {
|
|
127
|
+
const method = "events.subscribe"
|
|
128
|
+
return Effect.gen(function* () {
|
|
129
|
+
const id = yield* requestId("sub")
|
|
130
|
+
const lines = yield* open(method, { id, method, params: { subscriptions } })
|
|
131
|
+
return lines.pipe(
|
|
132
|
+
Stream.flatMap((m): Stream.Stream<PushFrame, HerdrFailure> =>
|
|
133
|
+
isResponse(m)
|
|
134
|
+
? (m.id === id || m.id === "") && m.error ? Stream.fail(serverError(method, m.error)) : Stream.empty
|
|
135
|
+
: Stream.make(m as PushFrame), // herdr's contract for PROTOCOL, as in `call`
|
|
136
|
+
),
|
|
137
|
+
)
|
|
138
|
+
}).pipe(Stream.unwrap)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return { socketPath, call, subscribe }
|
|
142
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./herdr.js"
|
|
2
|
+
export { SocketConnector } from "./socket-connector.js"
|
|
3
|
+
export { configDir, defaultSocketPath, socketEndpoint, type SocketPathOptions } from "./socket-path.js"
|
|
4
|
+
export * as params from "./generated/params.js"
|
|
5
|
+
export * as results from "./generated/results.js"
|
|
6
|
+
export * as events from "./generated/events.js"
|
|
7
|
+
export type { Method, MethodParams, Subscription } from "./generated/params.js"
|
|
8
|
+
export type { ResponseResult, ResultByTag, ResultTag } from "./generated/results.js"
|
|
9
|
+
export type { AgentStatus, EventFrame, EventKind, PushFrame, SubscriptionEventFrame, SubscriptionEventKind } from "./generated/events.js"
|
|
10
|
+
export { PROTOCOL, SCHEMA_VERSION } from "./generated/index.js"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// The one runtime capability the client needs and `effect` has no service for: dial a local socket.
|
|
2
|
+
// The core only names this service; `effect-herdr-sdk/bun` (or another runtime's layer) provides it.
|
|
3
|
+
import { Context, type Effect } from "effect"
|
|
4
|
+
import type * as Socket from "effect/socket/Socket"
|
|
5
|
+
|
|
6
|
+
/** Dial `endpoint` (a unix socket path, or `\\.\pipe\…` on Windows). Like `WebSocketConstructor`, for local sockets. */
|
|
7
|
+
export class SocketConnector extends Context.Service<SocketConnector, (endpoint: string) => Effect.Effect<Socket.Socket>>()(
|
|
8
|
+
"effect-herdr-sdk/SocketConnector",
|
|
9
|
+
) {}
|