screenhand 0.2.0 → 0.3.1
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/README.md +165 -446
- package/bin/darwin-arm64/macos-bridge +0 -0
- package/dist/mcp-desktop.js +3615 -400
- package/dist/scripts/export-help-center.js +112 -0
- package/dist/scripts/marketing-loop.js +117 -0
- package/dist/scripts/observer-daemon.js +288 -0
- package/dist/scripts/orchestrator-daemon.js +399 -0
- package/dist/scripts/threads-campaign.js +208 -0
- package/dist/src/community/fetcher.js +109 -0
- package/dist/src/community/index.js +6 -0
- package/dist/src/community/publisher.js +191 -0
- package/dist/src/community/remote-api.js +121 -0
- package/dist/src/community/types.js +3 -0
- package/dist/src/community/validator.js +95 -0
- package/dist/src/context-tracker.js +489 -0
- package/dist/src/ingestion/coverage-auditor.js +233 -0
- package/dist/src/ingestion/doc-parser.js +164 -0
- package/dist/src/ingestion/index.js +8 -0
- package/dist/src/ingestion/menu-scanner.js +152 -0
- package/dist/src/ingestion/reference-merger.js +186 -0
- package/dist/src/ingestion/shortcut-extractor.js +180 -0
- package/dist/src/ingestion/tutorial-extractor.js +170 -0
- package/dist/src/ingestion/types.js +3 -0
- package/dist/src/jobs/manager.js +82 -14
- package/dist/src/jobs/runner.js +138 -15
- package/dist/src/learning/engine.js +356 -0
- package/dist/src/learning/index.js +9 -0
- package/dist/src/learning/locator-policy.js +120 -0
- package/dist/src/learning/pattern-policy.js +89 -0
- package/dist/src/learning/recovery-policy.js +116 -0
- package/dist/src/learning/sensor-policy.js +115 -0
- package/dist/src/learning/timing-model.js +204 -0
- package/dist/src/learning/topology-policy.js +90 -0
- package/dist/src/learning/types.js +9 -0
- package/dist/src/logging/timeline-logger.js +4 -1
- package/dist/src/memory/playbook-seeds.js +200 -0
- package/dist/src/memory/recall.js +60 -8
- package/dist/src/memory/service.js +30 -5
- package/dist/src/memory/store.js +34 -5
- package/dist/src/native/bridge-client.js +253 -31
- package/dist/src/observer/state.js +199 -0
- package/dist/src/observer/types.js +43 -0
- package/dist/src/orchestrator/state.js +68 -0
- package/dist/src/orchestrator/types.js +22 -0
- package/dist/src/perception/ax-source.js +162 -0
- package/dist/src/perception/cdp-source.js +162 -0
- package/dist/src/perception/coordinator.js +771 -0
- package/dist/src/perception/frame-differ.js +287 -0
- package/dist/src/perception/index.js +22 -0
- package/dist/src/perception/manager.js +199 -0
- package/dist/src/perception/types.js +47 -0
- package/dist/src/perception/vision-source.js +399 -0
- package/dist/src/planner/deterministic.js +298 -0
- package/dist/src/planner/executor.js +870 -0
- package/dist/src/planner/goal-store.js +92 -0
- package/dist/src/planner/index.js +21 -0
- package/dist/src/planner/planner.js +520 -0
- package/dist/src/planner/tool-registry.js +71 -0
- package/dist/src/planner/types.js +22 -0
- package/dist/src/platform/explorer.js +213 -0
- package/dist/src/platform/help-center-markdown.js +527 -0
- package/dist/src/platform/learner.js +257 -0
- package/dist/src/playbook/engine.js +296 -11
- package/dist/src/playbook/mcp-recorder.js +204 -0
- package/dist/src/playbook/recorder.js +3 -2
- package/dist/src/playbook/runner.js +1 -1
- package/dist/src/playbook/store.js +139 -10
- package/dist/src/recovery/detectors.js +156 -0
- package/dist/src/recovery/engine.js +327 -0
- package/dist/src/recovery/index.js +20 -0
- package/dist/src/recovery/strategies.js +274 -0
- package/dist/src/recovery/types.js +20 -0
- package/dist/src/runtime/accessibility-adapter.js +55 -18
- package/dist/src/runtime/applescript-adapter.js +8 -2
- package/dist/src/runtime/cdp-chrome-adapter.js +1 -1
- package/dist/src/runtime/executor.js +23 -3
- package/dist/src/runtime/locator-cache.js +24 -2
- package/dist/src/runtime/service.js +59 -15
- package/dist/src/runtime/session-manager.js +4 -1
- package/dist/src/runtime/vision-adapter.js +2 -1
- package/dist/src/state/app-map-types.js +72 -0
- package/dist/src/state/app-map.js +1974 -0
- package/dist/src/state/entity-tracker.js +108 -0
- package/dist/src/state/fusion.js +96 -0
- package/dist/src/state/index.js +21 -0
- package/dist/src/state/ladder-generator.js +236 -0
- package/dist/src/state/persistence.js +156 -0
- package/dist/src/state/types.js +17 -0
- package/dist/src/state/world-model.js +1456 -0
- package/dist/src/util/atomic-write.js +19 -4
- package/dist/src/util/sanitize.js +146 -0
- package/dist-app-maps/com.figma.Desktop.json +959 -0
- package/dist-app-maps/com.hnc.Discord.json +1146 -0
- package/dist-app-maps/notion.id.json +2831 -0
- package/dist-playbooks/canva-screenhand-carousel.json +445 -0
- package/dist-playbooks/codex-desktop.json +76 -0
- package/dist-playbooks/competitor-research-stack.json +122 -0
- package/dist-playbooks/davinci-color-grade.json +153 -0
- package/dist-playbooks/davinci-edit-timeline.json +162 -0
- package/dist-playbooks/davinci-render.json +114 -0
- package/dist-playbooks/devto.json +52 -0
- package/dist-playbooks/discord.json +41 -0
- package/dist-playbooks/google-flow-create-project.json +59 -0
- package/dist-playbooks/google-flow-edit-image.json +90 -0
- package/dist-playbooks/google-flow-edit-video.json +90 -0
- package/dist-playbooks/google-flow-generate-image.json +68 -0
- package/dist-playbooks/google-flow-generate-video.json +191 -0
- package/dist-playbooks/google-flow-open-project.json +48 -0
- package/dist-playbooks/google-flow-open-scenebuilder.json +64 -0
- package/dist-playbooks/google-flow-search-assets.json +64 -0
- package/dist-playbooks/instagram.json +57 -0
- package/dist-playbooks/linkedin.json +52 -0
- package/dist-playbooks/n8n.json +43 -0
- package/dist-playbooks/reddit.json +52 -0
- package/dist-playbooks/threads.json +59 -0
- package/dist-playbooks/x-twitter.json +59 -0
- package/dist-playbooks/youtube.json +59 -0
- package/dist-references/canva.json +646 -0
- package/dist-references/codex-desktop.json +305 -0
- package/dist-references/davinci-resolve-keyboard.json +594 -0
- package/dist-references/davinci-resolve-menu-map.json +1139 -0
- package/dist-references/davinci-resolve-menus-batch1.json +116 -0
- package/dist-references/davinci-resolve-menus-batch2.json +372 -0
- package/dist-references/davinci-resolve-menus-batch3.json +330 -0
- package/dist-references/davinci-resolve-menus-batch4.json +297 -0
- package/dist-references/davinci-resolve-shortcuts.json +333 -0
- package/dist-references/devpost.json +186 -0
- package/dist-references/devto.json +317 -0
- package/dist-references/discord.json +549 -0
- package/dist-references/figma.json +1186 -0
- package/dist-references/finder.json +146 -0
- package/dist-references/google-ads-transparency.json +95 -0
- package/dist-references/google-flow.json +649 -0
- package/dist-references/instagram.json +341 -0
- package/dist-references/linkedin.json +324 -0
- package/dist-references/meta-ad-library.json +86 -0
- package/dist-references/n8n.json +387 -0
- package/dist-references/notes.json +27 -0
- package/dist-references/notion.json +163 -0
- package/dist-references/reddit.json +341 -0
- package/dist-references/threads.json +337 -0
- package/dist-references/x-twitter.json +403 -0
- package/dist-references/youtube.json +373 -0
- package/native/macos-bridge/Package.swift +22 -0
- package/native/macos-bridge/Sources/AccessibilityBridge.swift +482 -0
- package/native/macos-bridge/Sources/AppManagement.swift +339 -0
- package/native/macos-bridge/Sources/CoreGraphicsBridge.swift +537 -0
- package/native/macos-bridge/Sources/ObserverBridge.swift +120 -0
- package/native/macos-bridge/Sources/StreamCapture.swift +136 -0
- package/native/macos-bridge/Sources/VisionBridge.swift +238 -0
- package/native/macos-bridge/Sources/main.swift +498 -0
- package/native/windows-bridge/AppManagement.cs +234 -0
- package/native/windows-bridge/InputBridge.cs +436 -0
- package/native/windows-bridge/Program.cs +270 -0
- package/native/windows-bridge/ScreenCapture.cs +453 -0
- package/native/windows-bridge/UIAutomationBridge.cs +571 -0
- package/native/windows-bridge/WindowsBridge.csproj +17 -0
- package/package.json +12 -1
- package/scripts/postinstall.cjs +127 -0
- package/dist/.audit-log.jsonl +0 -55
- package/dist/.screenhand/memory/.lock +0 -1
- package/dist/.screenhand/memory/actions.jsonl +0 -85
- package/dist/.screenhand/memory/errors.jsonl +0 -5
- package/dist/.screenhand/memory/errors.jsonl.bak +0 -4
- package/dist/.screenhand/memory/state.json +0 -35
- package/dist/.screenhand/memory/state.json.bak +0 -35
- package/dist/.screenhand/memory/strategies.jsonl +0 -12
- package/dist/agent/cli.js +0 -73
- package/dist/agent/loop.js +0 -258
- package/dist/config.js +0 -9
- package/dist/index.js +0 -56
- package/dist/logging/timeline-logger.js +0 -29
- package/dist/mcp/mcp-stdio-server.js +0 -448
- package/dist/mcp/server.js +0 -347
- package/dist/mcp-entry.js +0 -59
- package/dist/memory/recall.js +0 -160
- package/dist/memory/research.js +0 -98
- package/dist/memory/seeds.js +0 -89
- package/dist/memory/session.js +0 -161
- package/dist/memory/store.js +0 -391
- package/dist/memory/types.js +0 -4
- package/dist/monitor/codex-monitor.js +0 -377
- package/dist/monitor/task-queue.js +0 -84
- package/dist/monitor/types.js +0 -49
- package/dist/native/bridge-client.js +0 -174
- package/dist/native/macos-bridge-client.js +0 -5
- package/dist/npm-publish-helper.js +0 -117
- package/dist/npm-token-cdp.js +0 -113
- package/dist/npm-token-create.js +0 -135
- package/dist/npm-token-finish.js +0 -126
- package/dist/playbook/engine.js +0 -193
- package/dist/playbook/index.js +0 -4
- package/dist/playbook/recorder.js +0 -519
- package/dist/playbook/runner.js +0 -392
- package/dist/playbook/store.js +0 -166
- package/dist/playbook/types.js +0 -4
- package/dist/runtime/accessibility-adapter.js +0 -377
- package/dist/runtime/app-adapter.js +0 -48
- package/dist/runtime/applescript-adapter.js +0 -283
- package/dist/runtime/ax-role-map.js +0 -80
- package/dist/runtime/browser-adapter.js +0 -36
- package/dist/runtime/cdp-chrome-adapter.js +0 -505
- package/dist/runtime/composite-adapter.js +0 -205
- package/dist/runtime/executor.js +0 -250
- package/dist/runtime/locator-cache.js +0 -12
- package/dist/runtime/planning-loop.js +0 -47
- package/dist/runtime/service.js +0 -372
- package/dist/runtime/session-manager.js +0 -28
- package/dist/runtime/state-observer.js +0 -105
- package/dist/runtime/vision-adapter.js +0 -208
- package/dist/test-mcp-protocol.js +0 -138
- package/dist/types.js +0 -1
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
using System.Text.Json;
|
|
2
|
+
using System.Text.Json.Nodes;
|
|
3
|
+
|
|
4
|
+
namespace WindowsBridge;
|
|
5
|
+
|
|
6
|
+
/// <summary>
|
|
7
|
+
/// JSON-RPC over stdio bridge for Windows native APIs.
|
|
8
|
+
/// Reads JSON requests from stdin (one per line), dispatches to the appropriate bridge,
|
|
9
|
+
/// and writes JSON responses to stdout (one per line).
|
|
10
|
+
/// Mirrors the protocol of the macOS Swift bridge exactly.
|
|
11
|
+
/// </summary>
|
|
12
|
+
class Program
|
|
13
|
+
{
|
|
14
|
+
private static readonly AppManagement _appManagement = new();
|
|
15
|
+
private static readonly UIAutomationBridge _uiAutomation = new();
|
|
16
|
+
private static readonly InputBridge _input = new();
|
|
17
|
+
private static readonly ScreenCapture _screenCapture = new();
|
|
18
|
+
|
|
19
|
+
private static readonly object _outputLock = new();
|
|
20
|
+
private static readonly JsonSerializerOptions _jsonOptions = new()
|
|
21
|
+
{
|
|
22
|
+
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
|
23
|
+
WriteIndented = false,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
static void Main(string[] args)
|
|
27
|
+
{
|
|
28
|
+
Console.InputEncoding = System.Text.Encoding.UTF8;
|
|
29
|
+
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
|
30
|
+
|
|
31
|
+
string? line;
|
|
32
|
+
while ((line = Console.ReadLine()) != null)
|
|
33
|
+
{
|
|
34
|
+
if (string.IsNullOrWhiteSpace(line)) continue;
|
|
35
|
+
|
|
36
|
+
try
|
|
37
|
+
{
|
|
38
|
+
var request = JsonSerializer.Deserialize<JsonRpcRequest>(line, _jsonOptions);
|
|
39
|
+
if (request == null)
|
|
40
|
+
{
|
|
41
|
+
WriteError(0, -32700, "Parse error: null request");
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try
|
|
46
|
+
{
|
|
47
|
+
var result = Dispatch(request.Method, request.Params);
|
|
48
|
+
WriteResult(request.Id, result);
|
|
49
|
+
}
|
|
50
|
+
catch (BridgeException ex)
|
|
51
|
+
{
|
|
52
|
+
WriteError(request.Id, -1, ex.Message);
|
|
53
|
+
}
|
|
54
|
+
catch (Exception ex)
|
|
55
|
+
{
|
|
56
|
+
WriteError(request.Id, -1, ex.Message);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (Exception ex)
|
|
60
|
+
{
|
|
61
|
+
WriteError(0, -32700, $"Parse error: {ex.Message}");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private static object Dispatch(string method, JsonObject? p)
|
|
67
|
+
{
|
|
68
|
+
return method switch
|
|
69
|
+
{
|
|
70
|
+
// Lifecycle
|
|
71
|
+
"ping" => new Dictionary<string, object>
|
|
72
|
+
{
|
|
73
|
+
["pong"] = true,
|
|
74
|
+
["pid"] = Environment.ProcessId,
|
|
75
|
+
["accessible"] = true, // UI Automation doesn't need special permissions on Windows
|
|
76
|
+
},
|
|
77
|
+
"check_permissions" => new Dictionary<string, object>
|
|
78
|
+
{
|
|
79
|
+
["trusted"] = true, // No special permissions needed on Windows for UIA
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
// App Management
|
|
83
|
+
"app.launch" => _appManagement.LaunchApp(RequiredParam<string>(p, "bundleId")),
|
|
84
|
+
"app.focus" => _appManagement.FocusApp(RequiredParam<string>(p, "bundleId")),
|
|
85
|
+
"app.list" => _appManagement.ListRunningApps(),
|
|
86
|
+
"app.windows" => _appManagement.ListWindows(),
|
|
87
|
+
"app.frontmost" => _appManagement.FrontmostApp(),
|
|
88
|
+
|
|
89
|
+
// UI Automation (Accessibility equivalent)
|
|
90
|
+
"ax.findElement" => _uiAutomation.FindElement(
|
|
91
|
+
RequiredParam<int>(p, "pid"),
|
|
92
|
+
Param<string>(p, "role"),
|
|
93
|
+
Param<string>(p, "title"),
|
|
94
|
+
Param<string>(p, "value"),
|
|
95
|
+
Param<string>(p, "identifier"),
|
|
96
|
+
Param<bool>(p, "exact") ?? true),
|
|
97
|
+
"ax.getElementTree" => _uiAutomation.GetElementTree(
|
|
98
|
+
RequiredParam<int>(p, "pid"),
|
|
99
|
+
Param<int>(p, "maxDepth") ?? 5),
|
|
100
|
+
"ax.performAction" => _uiAutomation.PerformAction(
|
|
101
|
+
RequiredParam<int>(p, "pid"),
|
|
102
|
+
RequiredParam<int[]>(p, "elementPath"),
|
|
103
|
+
Param<string>(p, "action") ?? "AXPress"),
|
|
104
|
+
"ax.setElementValue" => _uiAutomation.SetElementValue(
|
|
105
|
+
RequiredParam<int>(p, "pid"),
|
|
106
|
+
RequiredParam<int[]>(p, "elementPath"),
|
|
107
|
+
RequiredParam<string>(p, "value")),
|
|
108
|
+
"ax.getElementValue" => _uiAutomation.GetElementValue(
|
|
109
|
+
RequiredParam<int>(p, "pid"),
|
|
110
|
+
RequiredParam<int[]>(p, "elementPath")),
|
|
111
|
+
"ax.menuClick" => _uiAutomation.MenuClick(
|
|
112
|
+
RequiredParam<int>(p, "pid"),
|
|
113
|
+
RequiredParam<string[]>(p, "menuPath")),
|
|
114
|
+
|
|
115
|
+
// Observer (stub — Windows UIA events could be added later)
|
|
116
|
+
"observer.start" => new Dictionary<string, object>
|
|
117
|
+
{
|
|
118
|
+
["ok"] = true,
|
|
119
|
+
["stub"] = true,
|
|
120
|
+
["message"] = "UI Automation event observation not yet implemented on Windows",
|
|
121
|
+
},
|
|
122
|
+
"observer.stop" => new Dictionary<string, object>
|
|
123
|
+
{
|
|
124
|
+
["ok"] = true,
|
|
125
|
+
["stub"] = true,
|
|
126
|
+
["message"] = "UI Automation event observation not yet implemented on Windows",
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
// Input (CoreGraphics equivalent)
|
|
130
|
+
"cg.mouseClick" => _input.MouseClick(
|
|
131
|
+
RequiredParam<double>(p, "x"),
|
|
132
|
+
RequiredParam<double>(p, "y"),
|
|
133
|
+
Param<string>(p, "button") ?? "left",
|
|
134
|
+
Param<int>(p, "clickCount") ?? 1),
|
|
135
|
+
"cg.mouseMove" => _input.MouseMove(
|
|
136
|
+
RequiredParam<double>(p, "x"),
|
|
137
|
+
RequiredParam<double>(p, "y")),
|
|
138
|
+
"cg.mouseDrag" => _input.MouseDrag(
|
|
139
|
+
RequiredParam<double>(p, "fromX"),
|
|
140
|
+
RequiredParam<double>(p, "fromY"),
|
|
141
|
+
RequiredParam<double>(p, "toX"),
|
|
142
|
+
RequiredParam<double>(p, "toY")),
|
|
143
|
+
"cg.mouseFlick" => _input.MouseDrag( // Map flick to fast drag on Windows
|
|
144
|
+
RequiredParam<double>(p, "fromX"),
|
|
145
|
+
RequiredParam<double>(p, "fromY"),
|
|
146
|
+
RequiredParam<double>(p, "toX"),
|
|
147
|
+
RequiredParam<double>(p, "toY")),
|
|
148
|
+
"cg.keyCombo" => _input.KeyCombo(RequiredParam<string[]>(p, "keys")),
|
|
149
|
+
"cg.typeText" => _input.TypeText(RequiredParam<string>(p, "text")),
|
|
150
|
+
"cg.scroll" => _input.Scroll(
|
|
151
|
+
RequiredParam<double>(p, "x"),
|
|
152
|
+
RequiredParam<double>(p, "y"),
|
|
153
|
+
Param<int>(p, "deltaX") ?? 0,
|
|
154
|
+
Param<int>(p, "deltaY") ?? 0),
|
|
155
|
+
"cg.captureScreen" => _screenCapture.CaptureScreen(
|
|
156
|
+
Param<Dictionary<string, double>>(p, "region")),
|
|
157
|
+
"cg.captureWindow" => _screenCapture.CaptureWindow(
|
|
158
|
+
RequiredParam<int>(p, "windowId")),
|
|
159
|
+
"cg.captureWindowBuffer" => _screenCapture.CaptureWindowBuffer(
|
|
160
|
+
RequiredParam<int>(p, "windowId")),
|
|
161
|
+
|
|
162
|
+
// Vision (OCR)
|
|
163
|
+
"vision.findText" => _screenCapture.FindText(
|
|
164
|
+
RequiredParam<string>(p, "imagePath"),
|
|
165
|
+
Param<string>(p, "searchText")),
|
|
166
|
+
"vision.ocr" => _screenCapture.Ocr(
|
|
167
|
+
RequiredParam<string>(p, "imagePath")),
|
|
168
|
+
"vision.ocrRegion" => _screenCapture.OcrRegion(
|
|
169
|
+
RequiredParam<int>(p, "windowId"),
|
|
170
|
+
RequiredParam<Dictionary<string, double>>(p, "region")),
|
|
171
|
+
|
|
172
|
+
_ => throw new BridgeException($"Unknown method: {method}"),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Parameter helpers (mirror Swift's param/requiredParam)
|
|
177
|
+
private static T? Param<T>(JsonObject? p, string key)
|
|
178
|
+
{
|
|
179
|
+
if (p == null || !p.ContainsKey(key) || p[key] == null) return default;
|
|
180
|
+
|
|
181
|
+
var node = p[key]!;
|
|
182
|
+
|
|
183
|
+
// Handle numeric coercion
|
|
184
|
+
if (typeof(T) == typeof(double) && node is JsonValue jv)
|
|
185
|
+
{
|
|
186
|
+
if (jv.TryGetValue<double>(out var d)) return (T)(object)d;
|
|
187
|
+
if (jv.TryGetValue<int>(out var i)) return (T)(object)(double)i;
|
|
188
|
+
if (jv.TryGetValue<long>(out var l)) return (T)(object)(double)l;
|
|
189
|
+
}
|
|
190
|
+
if (typeof(T) == typeof(int) && node is JsonValue jv2)
|
|
191
|
+
{
|
|
192
|
+
if (jv2.TryGetValue<int>(out var i)) return (T)(object)i;
|
|
193
|
+
if (jv2.TryGetValue<double>(out var d)) return (T)(object)(int)d;
|
|
194
|
+
if (jv2.TryGetValue<long>(out var l)) return (T)(object)(int)l;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
try
|
|
198
|
+
{
|
|
199
|
+
return node.Deserialize<T>(_jsonOptions);
|
|
200
|
+
}
|
|
201
|
+
catch
|
|
202
|
+
{
|
|
203
|
+
return default;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private static T RequiredParam<T>(JsonObject? p, string key)
|
|
208
|
+
{
|
|
209
|
+
var value = Param<T>(p, key);
|
|
210
|
+
if (value == null)
|
|
211
|
+
throw new BridgeException($"Missing required parameter: {key}");
|
|
212
|
+
return value;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Output helpers
|
|
216
|
+
private static void WriteResult(int id, object result)
|
|
217
|
+
{
|
|
218
|
+
var response = new Dictionary<string, object?>
|
|
219
|
+
{
|
|
220
|
+
["id"] = id,
|
|
221
|
+
["result"] = result,
|
|
222
|
+
["error"] = null,
|
|
223
|
+
};
|
|
224
|
+
WriteLine(response);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
private static void WriteError(int id, int code, string message)
|
|
228
|
+
{
|
|
229
|
+
var response = new Dictionary<string, object?>
|
|
230
|
+
{
|
|
231
|
+
["id"] = id,
|
|
232
|
+
["result"] = null,
|
|
233
|
+
["error"] = new Dictionary<string, object> { ["code"] = code, ["message"] = message },
|
|
234
|
+
};
|
|
235
|
+
WriteLine(response);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
public static void WriteEvent(Dictionary<string, object> eventData)
|
|
239
|
+
{
|
|
240
|
+
var wrapped = new Dictionary<string, object>
|
|
241
|
+
{
|
|
242
|
+
["id"] = 0,
|
|
243
|
+
["event"] = eventData,
|
|
244
|
+
};
|
|
245
|
+
WriteLine(wrapped);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private static void WriteLine(object obj)
|
|
249
|
+
{
|
|
250
|
+
var json = JsonSerializer.Serialize(obj, _jsonOptions);
|
|
251
|
+
lock (_outputLock)
|
|
252
|
+
{
|
|
253
|
+
Console.WriteLine(json);
|
|
254
|
+
Console.Out.Flush();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// JSON-RPC types
|
|
260
|
+
class JsonRpcRequest
|
|
261
|
+
{
|
|
262
|
+
public int Id { get; set; }
|
|
263
|
+
public string Method { get; set; } = "";
|
|
264
|
+
public JsonObject? Params { get; set; }
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
class BridgeException : Exception
|
|
268
|
+
{
|
|
269
|
+
public BridgeException(string message) : base(message) { }
|
|
270
|
+
}
|