@parlor/agent-host 0.0.0-stage → 0.1.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/README.md +16 -2
- package/dist/acp.d.ts +165 -0
- package/dist/acp.d.ts.map +1 -0
- package/dist/acp.js +626 -0
- package/dist/acp.js.map +1 -0
- package/dist/adapter-launch.d.ts +7 -0
- package/dist/adapter-launch.d.ts.map +1 -0
- package/dist/adapter-launch.js +35 -0
- package/dist/adapter-launch.js.map +1 -0
- package/dist/agents.d.ts +32 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +132 -0
- package/dist/agents.js.map +1 -0
- package/dist/assertion.d.ts +9 -0
- package/dist/assertion.d.ts.map +1 -0
- package/dist/assertion.js +22 -0
- package/dist/assertion.js.map +1 -0
- package/dist/control.d.ts +106 -0
- package/dist/control.d.ts.map +1 -0
- package/dist/control.js +32 -0
- package/dist/control.js.map +1 -0
- package/dist/daemon.d.ts +50 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +543 -0
- package/dist/daemon.js.map +1 -0
- package/dist/dev-host.d.ts +5 -0
- package/dist/dev-host.d.ts.map +1 -0
- package/dist/dev-host.js +29 -0
- package/dist/dev-host.js.map +1 -0
- package/dist/device-list.d.ts +6 -0
- package/dist/device-list.d.ts.map +1 -0
- package/dist/device-list.js +30 -0
- package/dist/device-list.js.map +1 -0
- package/dist/embedded.d.ts +6 -0
- package/dist/embedded.d.ts.map +1 -0
- package/dist/embedded.js +3 -0
- package/dist/embedded.js.map +1 -0
- package/dist/fold.d.ts +38 -0
- package/dist/fold.d.ts.map +1 -0
- package/dist/fold.js +165 -0
- package/dist/fold.js.map +1 -0
- package/dist/grants.d.ts +54 -0
- package/dist/grants.d.ts.map +1 -0
- package/dist/grants.js +157 -0
- package/dist/grants.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/json-file.d.ts +6 -0
- package/dist/json-file.d.ts.map +1 -0
- package/dist/json-file.js +35 -0
- package/dist/json-file.js.map +1 -0
- package/dist/lines.d.ts +5 -0
- package/dist/lines.d.ts.map +1 -0
- package/dist/lines.js +9 -0
- package/dist/lines.js.map +1 -0
- package/dist/link-device.d.ts +28 -0
- package/dist/link-device.d.ts.map +1 -0
- package/dist/link-device.js +40 -0
- package/dist/link-device.js.map +1 -0
- package/dist/link.d.ts +52 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +277 -0
- package/dist/link.js.map +1 -0
- package/dist/lock.d.ts +7 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +105 -0
- package/dist/lock.js.map +1 -0
- package/dist/log.d.ts +3 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +18 -0
- package/dist/log.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +520 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp-proxy.d.ts +33 -0
- package/dist/mcp-proxy.d.ts.map +1 -0
- package/dist/mcp-proxy.js +317 -0
- package/dist/mcp-proxy.js.map +1 -0
- package/dist/naming.d.ts +7 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/naming.js +42 -0
- package/dist/naming.js.map +1 -0
- package/dist/pairing.d.ts +68 -0
- package/dist/pairing.d.ts.map +1 -0
- package/dist/pairing.js +312 -0
- package/dist/pairing.js.map +1 -0
- package/dist/paths.d.ts +19 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +23 -0
- package/dist/paths.js.map +1 -0
- package/dist/policy.d.ts +37 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +60 -0
- package/dist/policy.js.map +1 -0
- package/dist/pool.d.ts +34 -0
- package/dist/pool.d.ts.map +1 -0
- package/dist/pool.js +112 -0
- package/dist/pool.js.map +1 -0
- package/dist/prompter.d.ts +33 -0
- package/dist/prompter.d.ts.map +1 -0
- package/dist/prompter.js +98 -0
- package/dist/prompter.js.map +1 -0
- package/dist/release-main.d.ts +2 -0
- package/dist/release-main.d.ts.map +1 -0
- package/dist/release-main.js +50 -0
- package/dist/release-main.js.map +1 -0
- package/dist/release.d.ts +22 -0
- package/dist/release.d.ts.map +1 -0
- package/dist/release.js +81 -0
- package/dist/release.js.map +1 -0
- package/dist/revoke.d.ts +10 -0
- package/dist/revoke.d.ts.map +1 -0
- package/dist/revoke.js +23 -0
- package/dist/revoke.js.map +1 -0
- package/dist/self.d.ts +7 -0
- package/dist/self.d.ts.map +1 -0
- package/dist/self.js +10 -0
- package/dist/self.js.map +1 -0
- package/dist/service.d.ts +97 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +205 -0
- package/dist/service.js.map +1 -0
- package/dist/shell-path.d.ts +10 -0
- package/dist/shell-path.d.ts.map +1 -0
- package/dist/shell-path.js +64 -0
- package/dist/shell-path.js.map +1 -0
- package/dist/skeleton-kit.d.ts +8 -0
- package/dist/skeleton-kit.d.ts.map +1 -0
- package/dist/skeleton-kit.js +143 -0
- package/dist/skeleton-kit.js.map +1 -0
- package/dist/spec-kit.d.ts +102 -0
- package/dist/spec-kit.d.ts.map +1 -0
- package/dist/spec-kit.js +372 -0
- package/dist/spec-kit.js.map +1 -0
- package/dist/testing/fake-agent.d.ts +65 -0
- package/dist/testing/fake-agent.d.ts.map +1 -0
- package/dist/testing/fake-agent.js +238 -0
- package/dist/testing/fake-agent.js.map +1 -0
- package/dist/trust.d.ts +20 -0
- package/dist/trust.d.ts.map +1 -0
- package/dist/trust.js +27 -0
- package/dist/trust.js.map +1 -0
- package/dist/turn.d.ts +32 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +650 -0
- package/dist/turn.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +57 -3
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { once } from "node:events";
|
|
3
|
+
import { chmod, mkdir, rm } from "node:fs/promises";
|
|
4
|
+
import { connect, createServer } from "node:net";
|
|
5
|
+
import { dirname } from "node:path";
|
|
6
|
+
import { onLines } from "./lines.js";
|
|
7
|
+
import { logEvent } from "./log.js";
|
|
8
|
+
export const NO_TURN_MESSAGE = "No turn is active: the user has not asked anything right now. Wait for their next message.";
|
|
9
|
+
export const DISCONNECTED_MESSAGE = "This computer no longer serves the app: it was disconnected, or Parlor Host stopped.";
|
|
10
|
+
const SOCKET_ENV = "PARLOR_HOST_PROXY_SOCKET";
|
|
11
|
+
const NONCE_ENV = "PARLOR_HOST_PROXY_NONCE";
|
|
12
|
+
const NO_TURN_CODE = -32000;
|
|
13
|
+
const REFUSED_CODE = -32001;
|
|
14
|
+
function parse(text) {
|
|
15
|
+
try {
|
|
16
|
+
const value = JSON.parse(text);
|
|
17
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
18
|
+
? value
|
|
19
|
+
: undefined;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const result = (id, value) => JSON.stringify({ jsonrpc: "2.0", id, result: value });
|
|
26
|
+
const failure = (id, code, message) => JSON.stringify({ jsonrpc: "2.0", id, error: { code, message } });
|
|
27
|
+
/** One line per message on the agent's stdio: only a body with a raw newline is compacted. */
|
|
28
|
+
const asLine = (text) => text.includes("\n") ? JSON.stringify(JSON.parse(text)) : text;
|
|
29
|
+
function betweenTurns(live, message) {
|
|
30
|
+
if (message.id === undefined || typeof message.method !== "string")
|
|
31
|
+
return undefined;
|
|
32
|
+
const { id } = message;
|
|
33
|
+
switch (message.method) {
|
|
34
|
+
case "ping":
|
|
35
|
+
return result(id, {});
|
|
36
|
+
case "initialize":
|
|
37
|
+
return live.initialized === undefined
|
|
38
|
+
? failure(id, NO_TURN_CODE, NO_TURN_MESSAGE)
|
|
39
|
+
: result(id, live.initialized);
|
|
40
|
+
case "tools/list":
|
|
41
|
+
return live.tools === undefined
|
|
42
|
+
? failure(id, NO_TURN_CODE, NO_TURN_MESSAGE)
|
|
43
|
+
: result(id, live.tools);
|
|
44
|
+
case "tools/call":
|
|
45
|
+
return result(id, {
|
|
46
|
+
content: [{ type: "text", text: NO_TURN_MESSAGE }],
|
|
47
|
+
isError: true,
|
|
48
|
+
});
|
|
49
|
+
default:
|
|
50
|
+
return failure(id, NO_TURN_CODE, NO_TURN_MESSAGE);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function* serverSentData(body) {
|
|
54
|
+
const decoder = new TextDecoder();
|
|
55
|
+
let buffer = "";
|
|
56
|
+
let data = [];
|
|
57
|
+
for await (const chunk of body) {
|
|
58
|
+
buffer += decoder.decode(chunk, { stream: true });
|
|
59
|
+
let end = buffer.indexOf("\n");
|
|
60
|
+
while (end !== -1) {
|
|
61
|
+
const line = buffer.slice(0, end).replace(/\r$/, "");
|
|
62
|
+
buffer = buffer.slice(end + 1);
|
|
63
|
+
if (line === "") {
|
|
64
|
+
if (data.length > 0)
|
|
65
|
+
yield data.join("\n");
|
|
66
|
+
data = [];
|
|
67
|
+
}
|
|
68
|
+
else if (line.startsWith("data:")) {
|
|
69
|
+
data.push(line.slice(line.startsWith("data: ") ? 6 : 5));
|
|
70
|
+
}
|
|
71
|
+
end = buffer.indexOf("\n");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (data.length > 0)
|
|
75
|
+
yield data.join("\n");
|
|
76
|
+
}
|
|
77
|
+
function refusal(status) {
|
|
78
|
+
return status === 401
|
|
79
|
+
? "This computer can no longer act for the app: the turn ended or the computer was disconnected."
|
|
80
|
+
: `The app answered HTTP ${status}.`;
|
|
81
|
+
}
|
|
82
|
+
async function forward(live, token, line, message, reply) {
|
|
83
|
+
const method = typeof message.method === "string" ? message.method : "response";
|
|
84
|
+
const controller = new AbortController();
|
|
85
|
+
live.inflight.add(controller);
|
|
86
|
+
let status = 0;
|
|
87
|
+
try {
|
|
88
|
+
const response = await fetch(`${live.appOrigin}/_parlor/mcp`, {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: {
|
|
91
|
+
authorization: `Bearer ${token}`,
|
|
92
|
+
accept: "application/json, text/event-stream",
|
|
93
|
+
"content-type": "application/json",
|
|
94
|
+
...(live.protocolVersion ? { "mcp-protocol-version": live.protocolVersion } : {}),
|
|
95
|
+
},
|
|
96
|
+
body: line,
|
|
97
|
+
signal: controller.signal,
|
|
98
|
+
});
|
|
99
|
+
status = response.status;
|
|
100
|
+
const bodies = [];
|
|
101
|
+
if ((response.headers.get("content-type") ?? "").includes("text/event-stream")) {
|
|
102
|
+
if (response.body)
|
|
103
|
+
for await (const data of serverSentData(response.body))
|
|
104
|
+
bodies.push(data);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
const text = await response.text();
|
|
108
|
+
if (text.trim() !== "")
|
|
109
|
+
bodies.push(text);
|
|
110
|
+
}
|
|
111
|
+
let answered = false;
|
|
112
|
+
for (const text of bodies) {
|
|
113
|
+
const answer = parse(text);
|
|
114
|
+
if (answer?.jsonrpc !== "2.0")
|
|
115
|
+
continue;
|
|
116
|
+
if (answer.id === message.id) {
|
|
117
|
+
answered = true;
|
|
118
|
+
if (method === "initialize" && answer.result !== undefined) {
|
|
119
|
+
live.initialized = answer.result;
|
|
120
|
+
const version = answer.result
|
|
121
|
+
.protocolVersion;
|
|
122
|
+
if (typeof version === "string")
|
|
123
|
+
live.protocolVersion = version;
|
|
124
|
+
}
|
|
125
|
+
if (method === "tools/list" && answer.result !== undefined)
|
|
126
|
+
live.tools = answer.result;
|
|
127
|
+
}
|
|
128
|
+
reply(asLine(text));
|
|
129
|
+
}
|
|
130
|
+
if (message.id !== undefined && !answered) {
|
|
131
|
+
reply(failure(message.id, REFUSED_CODE, refusal(status)));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (message.id !== undefined) {
|
|
136
|
+
reply(controller.signal.aborted
|
|
137
|
+
? failure(message.id, NO_TURN_CODE, NO_TURN_MESSAGE)
|
|
138
|
+
: failure(message.id, REFUSED_CODE, `The app could not be reached: ${String(error)}`));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
live.inflight.delete(controller);
|
|
143
|
+
logEvent("proxy_forward", { appOrigin: live.appOrigin, rpcMethod: method, status });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function handle(live, line, reply) {
|
|
147
|
+
const message = parse(line);
|
|
148
|
+
if (!message)
|
|
149
|
+
return;
|
|
150
|
+
const token = live.token;
|
|
151
|
+
if (token === undefined) {
|
|
152
|
+
const answer = betweenTurns(live, message);
|
|
153
|
+
if (answer)
|
|
154
|
+
reply(answer);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (message.method === "tools/list" &&
|
|
158
|
+
live.tools !== undefined &&
|
|
159
|
+
message.id !== undefined) {
|
|
160
|
+
reply(result(message.id, live.tools));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
void forward(live, token, line, message, reply);
|
|
164
|
+
}
|
|
165
|
+
export function createMcpProxy(hostBinary) {
|
|
166
|
+
const sessions = new Map();
|
|
167
|
+
let server;
|
|
168
|
+
let socketPath;
|
|
169
|
+
const accept = (socket) => {
|
|
170
|
+
let live;
|
|
171
|
+
const reply = (line) => {
|
|
172
|
+
if (!socket.destroyed)
|
|
173
|
+
socket.write(`${line}\n`);
|
|
174
|
+
};
|
|
175
|
+
onLines(socket, (line) => {
|
|
176
|
+
if (live !== undefined) {
|
|
177
|
+
handle(live, line, reply);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
live = sessions.get(line.trim());
|
|
181
|
+
if (live)
|
|
182
|
+
live.sockets.add(socket);
|
|
183
|
+
else
|
|
184
|
+
socket.destroy();
|
|
185
|
+
});
|
|
186
|
+
socket.on("close", () => live?.sockets.delete(socket));
|
|
187
|
+
socket.on("error", () => socket.destroy());
|
|
188
|
+
};
|
|
189
|
+
return {
|
|
190
|
+
async listen(path) {
|
|
191
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
192
|
+
await rm(path, { force: true });
|
|
193
|
+
const listening = createServer(accept);
|
|
194
|
+
await new Promise((resolve, reject) => {
|
|
195
|
+
listening.once("error", reject);
|
|
196
|
+
listening.listen(path, () => resolve());
|
|
197
|
+
});
|
|
198
|
+
await chmod(path, 0o600);
|
|
199
|
+
server = listening;
|
|
200
|
+
socketPath = path;
|
|
201
|
+
},
|
|
202
|
+
open(appServer, appOrigin) {
|
|
203
|
+
if (socketPath === undefined)
|
|
204
|
+
throw new Error("The MCP proxy is not listening yet.");
|
|
205
|
+
const nonce = randomBytes(24).toString("base64url");
|
|
206
|
+
const live = {
|
|
207
|
+
appOrigin: appOrigin.replace(/\/+$/, ""),
|
|
208
|
+
token: undefined,
|
|
209
|
+
protocolVersion: undefined,
|
|
210
|
+
initialized: undefined,
|
|
211
|
+
tools: undefined,
|
|
212
|
+
inflight: new Set(),
|
|
213
|
+
sockets: new Set(),
|
|
214
|
+
};
|
|
215
|
+
sessions.set(nonce, live);
|
|
216
|
+
const end = () => {
|
|
217
|
+
live.token = undefined;
|
|
218
|
+
for (const controller of live.inflight)
|
|
219
|
+
controller.abort();
|
|
220
|
+
};
|
|
221
|
+
return {
|
|
222
|
+
nonce,
|
|
223
|
+
server: {
|
|
224
|
+
name: appServer,
|
|
225
|
+
command: hostBinary,
|
|
226
|
+
args: ["mcp-proxy"],
|
|
227
|
+
env: { [SOCKET_ENV]: socketPath, [NONCE_ENV]: nonce },
|
|
228
|
+
},
|
|
229
|
+
begin: (token) => {
|
|
230
|
+
live.token = token.token;
|
|
231
|
+
},
|
|
232
|
+
renew: (token) => {
|
|
233
|
+
if (live.token !== undefined)
|
|
234
|
+
live.token = token.token;
|
|
235
|
+
},
|
|
236
|
+
end,
|
|
237
|
+
dispose: () => {
|
|
238
|
+
end();
|
|
239
|
+
sessions.delete(nonce);
|
|
240
|
+
for (const socket of live.sockets)
|
|
241
|
+
socket.destroy();
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
},
|
|
245
|
+
async stopListening() {
|
|
246
|
+
const closing = server;
|
|
247
|
+
server = undefined;
|
|
248
|
+
if (!closing)
|
|
249
|
+
return;
|
|
250
|
+
closing.close();
|
|
251
|
+
if (socketPath)
|
|
252
|
+
await rm(socketPath, { force: true });
|
|
253
|
+
},
|
|
254
|
+
async close() {
|
|
255
|
+
for (const live of sessions.values()) {
|
|
256
|
+
for (const controller of live.inflight)
|
|
257
|
+
controller.abort();
|
|
258
|
+
for (const socket of live.sockets)
|
|
259
|
+
socket.destroy();
|
|
260
|
+
}
|
|
261
|
+
sessions.clear();
|
|
262
|
+
const closing = server;
|
|
263
|
+
server = undefined;
|
|
264
|
+
if (closing) {
|
|
265
|
+
await new Promise((resolve) => closing.close(() => resolve()));
|
|
266
|
+
if (socketPath)
|
|
267
|
+
await rm(socketPath, { force: true });
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* `parlor-host mcp-proxy`: stdio to the daemon socket and back. Once the daemon hangs up,
|
|
274
|
+
* every request still unanswered, and every later one, is answered with an error here.
|
|
275
|
+
*/
|
|
276
|
+
export async function runMcpProxyProcess(env) {
|
|
277
|
+
const path = env[SOCKET_ENV];
|
|
278
|
+
const nonce = env[NONCE_ENV];
|
|
279
|
+
if (!path || !nonce)
|
|
280
|
+
throw new Error(`${SOCKET_ENV} and ${NONCE_ENV} must be set.`);
|
|
281
|
+
const unanswered = new Set();
|
|
282
|
+
const toAgent = (line) => void process.stdout.write(`${line}\n`);
|
|
283
|
+
const refuse = (id) => toAgent(failure(id, REFUSED_CODE, DISCONNECTED_MESSAGE));
|
|
284
|
+
process.stdout.on("error", () => undefined);
|
|
285
|
+
const daemon = connect(path);
|
|
286
|
+
daemon.on("error", () => daemon.destroy());
|
|
287
|
+
const hungUp = new Promise((resolve) => daemon.once("close", () => {
|
|
288
|
+
for (const id of unanswered)
|
|
289
|
+
refuse(id);
|
|
290
|
+
unanswered.clear();
|
|
291
|
+
resolve();
|
|
292
|
+
}));
|
|
293
|
+
daemon.write(`${nonce}\n`);
|
|
294
|
+
onLines(daemon, (line) => {
|
|
295
|
+
const message = parse(line);
|
|
296
|
+
if (message?.id !== undefined && message.method === undefined) {
|
|
297
|
+
unanswered.delete(message.id);
|
|
298
|
+
}
|
|
299
|
+
toAgent(line);
|
|
300
|
+
});
|
|
301
|
+
const agent = onLines(process.stdin, (line) => {
|
|
302
|
+
const message = parse(line);
|
|
303
|
+
const id = typeof message?.method === "string" ? message.id : undefined;
|
|
304
|
+
if (!daemon.destroyed) {
|
|
305
|
+
if (id !== undefined)
|
|
306
|
+
unanswered.add(id);
|
|
307
|
+
daemon.write(`${line}\n`);
|
|
308
|
+
}
|
|
309
|
+
else if (id !== undefined) {
|
|
310
|
+
refuse(id);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
await once(agent, "close");
|
|
314
|
+
daemon.end();
|
|
315
|
+
await hungUp;
|
|
316
|
+
}
|
|
317
|
+
//# sourceMappingURL=mcp-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-proxy.js","sourceRoot":"","sources":["../src/mcp-proxy.ts"],"names":[],"mappings":"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"}
|
package/dist/naming.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function workspaceOf(workspaceRoot: string, appOrigin: string): string;
|
|
2
|
+
export declare function appServerOf(appName: string): string;
|
|
3
|
+
export declare function computerName(): string;
|
|
4
|
+
export declare function platformName(): string;
|
|
5
|
+
/** Why this computer cannot connect to an app yet; undefined on macOS. */
|
|
6
|
+
export declare function unsupportedHostPlatform(platform?: NodeJS.Platform): string | undefined;
|
|
7
|
+
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAUrC;AAQD,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,0EAA0E;AAC1E,wBAAgB,uBAAuB,CACrC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,GAAG,SAAS,CAKpB"}
|
package/dist/naming.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { hostname } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
export function workspaceOf(workspaceRoot, appOrigin) {
|
|
5
|
+
return join(workspaceRoot, new URL(appOrigin).host.replaceAll(":", "-"));
|
|
6
|
+
}
|
|
7
|
+
export function appServerOf(appName) {
|
|
8
|
+
const name = appName
|
|
9
|
+
.toLowerCase()
|
|
10
|
+
.replace(/[^a-z0-9_-]+/g, "-")
|
|
11
|
+
.replace(/^-+|-+$/g, "");
|
|
12
|
+
return name || "app";
|
|
13
|
+
}
|
|
14
|
+
export function computerName() {
|
|
15
|
+
if (process.platform === "darwin") {
|
|
16
|
+
try {
|
|
17
|
+
const name = execFileSync("scutil", ["--get", "ComputerName"], {
|
|
18
|
+
encoding: "utf8",
|
|
19
|
+
}).trim();
|
|
20
|
+
if (name)
|
|
21
|
+
return name;
|
|
22
|
+
}
|
|
23
|
+
catch { }
|
|
24
|
+
}
|
|
25
|
+
return hostname();
|
|
26
|
+
}
|
|
27
|
+
const PLATFORMS = {
|
|
28
|
+
darwin: "macos",
|
|
29
|
+
win32: "windows",
|
|
30
|
+
linux: "linux",
|
|
31
|
+
};
|
|
32
|
+
export function platformName() {
|
|
33
|
+
return PLATFORMS[process.platform] ?? process.platform;
|
|
34
|
+
}
|
|
35
|
+
/** Why this computer cannot connect to an app yet; undefined on macOS. */
|
|
36
|
+
export function unsupportedHostPlatform(platform = process.platform) {
|
|
37
|
+
if (platform === "darwin")
|
|
38
|
+
return undefined;
|
|
39
|
+
const name = { win32: "Windows", linux: "Linux" }[platform] ?? platform;
|
|
40
|
+
return `Parlor Host connects to apps from macOS only for now; ${name} is not supported yet, because it keeps its keys in the macOS Keychain. \`parlor dev\` works on every platform.`;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../src/naming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,WAAW,CAAC,aAAqB,EAAE,SAAiB;IAClE,OAAO,IAAI,CAAC,aAAa,EAAE,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAC3E,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,MAAM,IAAI,GAAG,OAAO;SACjB,WAAW,EAAE;SACb,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;SAC7B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,IAAI,IAAI,KAAK,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE;gBAC7D,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAC;QACxB,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IACD,OAAO,QAAQ,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,SAAS,GAAqC;IAClD,MAAM,EAAE,OAAO;IACf,KAAK,EAAE,SAAS;IAChB,KAAK,EAAE,OAAO;CACf,CAAC;AAEF,MAAM,UAAU,YAAY;IAC1B,OAAO,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC;AACzD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,uBAAuB,CACrC,QAAQ,GAAoB,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,IAAI,GACP,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAY,CAAC,QAAkB,CAAC,IAAI,QAAQ,CAAC;IAClF,OAAO,yDAAyD,IAAI,iHAAiH,CAAC;AACxL,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { type AccountSummary, type HostGrantResponse } from "@parlor/auth";
|
|
2
|
+
import type { HostPairing, PairingDevice } from "@parlor/capabilities";
|
|
3
|
+
import type { AppGrant, HostKeys } from "./grants.js";
|
|
4
|
+
export declare const PAIRING_TIMEOUT_MS: number;
|
|
5
|
+
export interface PairingReview {
|
|
6
|
+
readonly appName: string;
|
|
7
|
+
readonly appOrigin: string;
|
|
8
|
+
readonly account: AccountSummary;
|
|
9
|
+
readonly matchingCode: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* `browser`: a one-shot 127.0.0.1 listener (RFC 8252) accepting exactly this attempt's
|
|
13
|
+
* `state`; the consent page is the one decision. `ipc`: the desktop shell's signed-in
|
|
14
|
+
* webview gets the code from the backend and hands it over Tauri IPC, with no consent page,
|
|
15
|
+
* so the shell's native dialog confirms the account the host got back.
|
|
16
|
+
*/
|
|
17
|
+
export type PairingChannel = {
|
|
18
|
+
readonly kind: "browser";
|
|
19
|
+
open(url: string): Promise<void>;
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: "ipc";
|
|
22
|
+
authorize(pairing: HostPairing): Promise<string>;
|
|
23
|
+
confirm(review: PairingReview): Promise<boolean>;
|
|
24
|
+
};
|
|
25
|
+
export interface PairInput {
|
|
26
|
+
readonly appOrigin: string;
|
|
27
|
+
readonly hostName: string;
|
|
28
|
+
readonly platform: string;
|
|
29
|
+
readonly channel: PairingChannel;
|
|
30
|
+
readonly keys: HostKeys;
|
|
31
|
+
readonly workspaceRoot: string;
|
|
32
|
+
}
|
|
33
|
+
export type PairOutcome = {
|
|
34
|
+
readonly paired: true;
|
|
35
|
+
readonly grant: AppGrant;
|
|
36
|
+
readonly approvedBy: HostGrantResponse["approvedBy"];
|
|
37
|
+
} | {
|
|
38
|
+
readonly paired: false;
|
|
39
|
+
readonly reason: "declined_locally" | "declined_in_app" | "timeout";
|
|
40
|
+
};
|
|
41
|
+
export declare class UnrevokedGrant extends Error {
|
|
42
|
+
readonly grant: AppGrant;
|
|
43
|
+
readonly name = "UnrevokedGrant";
|
|
44
|
+
constructor(grant: AppGrant, cause: Error);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Only the host starts a pairing: it makes the PKCE verifier, `state`, the matching code
|
|
48
|
+
* and the key pair, so nothing from the web side can complete one.
|
|
49
|
+
*/
|
|
50
|
+
export declare function pair(input: PairInput): Promise<PairOutcome>;
|
|
51
|
+
export interface LocalPairingReview {
|
|
52
|
+
readonly account: string;
|
|
53
|
+
readonly appName: string;
|
|
54
|
+
readonly matchingCode: string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A pairing driven over the control socket by the desktop shell: `pairing` once the host
|
|
58
|
+
* made its key and code, `finish` with the code the signed-in page got from the backend,
|
|
59
|
+
* `confirm` with the user's answer in the native dialog.
|
|
60
|
+
*/
|
|
61
|
+
export interface LocalPairing {
|
|
62
|
+
readonly pairing: Promise<HostPairing>;
|
|
63
|
+
finish(code: string): Promise<LocalPairingReview>;
|
|
64
|
+
confirm(connect: boolean): Promise<PairOutcome>;
|
|
65
|
+
}
|
|
66
|
+
export declare function startLocalPairing(input: Omit<PairInput, "channel">): LocalPairing;
|
|
67
|
+
export declare function pairingDeviceOf(value: unknown): PairingDevice | undefined;
|
|
68
|
+
//# sourceMappingURL=pairing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.d.ts","sourceRoot":"","sources":["../src/pairing.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,KAAK,cAAc,EAEnB,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGvE,OAAO,KAAK,EAAE,QAAQ,EAAe,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKnE,eAAO,MAAM,kBAAkB,QAAc,CAAC;AAE9C,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAC9D;IACE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAClD,CAAC;AAEN,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,MAAM,WAAW,GACnB;IACE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAC,YAAY,CAAC,CAAC;CACtD,GACD;IACE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,SAAS,CAAC;CACrE,CAAC;AAEN,qBAAa,cAAe,SAAQ,KAAK;IAGrC,QAAQ,CAAC,KAAK,EAAE,QAAQ;IAF1B,SAAkB,IAAI,oBAAoB;IAC1C,YACW,KAAK,EAAE,QAAQ,EACxB,KAAK,EAAE,KAAK,EAGb;CACF;AA6HD;;;GAGG;AACH,wBAAsB,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAoGjE;AAmBD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAClD,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACjD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,YAAY,CA+CjF;AAgCD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,GAAG,SAAS,CAmBzE"}
|