@parlor/agent-host 0.0.0-stage → 0.2.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
package/dist/main.js
ADDED
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
import { defineCommand, runMain } from "citty";
|
|
7
|
+
import { printable } from "./prompter.js";
|
|
8
|
+
import { HOST_VERSION as version } from "./version.js";
|
|
9
|
+
const KEYCHAIN_SERVICE = "dev.parlor.host";
|
|
10
|
+
function shutdownSignal() {
|
|
11
|
+
const controller = new AbortController();
|
|
12
|
+
const stop = () => {
|
|
13
|
+
process.off("SIGINT", stop);
|
|
14
|
+
process.off("SIGTERM", stop);
|
|
15
|
+
controller.abort();
|
|
16
|
+
};
|
|
17
|
+
process.on("SIGINT", stop);
|
|
18
|
+
process.on("SIGTERM", stop);
|
|
19
|
+
return controller.signal;
|
|
20
|
+
}
|
|
21
|
+
const untilAborted = (signal) => new Promise((resolve) => {
|
|
22
|
+
if (signal.aborted)
|
|
23
|
+
resolve();
|
|
24
|
+
else
|
|
25
|
+
signal.addEventListener("abort", () => resolve(), { once: true });
|
|
26
|
+
});
|
|
27
|
+
const errorText = (error) => error instanceof Error ? error.message : String(error);
|
|
28
|
+
function fail(message) {
|
|
29
|
+
process.stderr.write(`${printable(message)}\n`);
|
|
30
|
+
process.exitCode = 1;
|
|
31
|
+
}
|
|
32
|
+
async function host() {
|
|
33
|
+
const [{ acpLauncher }, { HOST_PROTOCOL }, { CONTROL_PROTOCOL, connectControl }, { createHostDaemon, HostAlreadyRunning }, { fileGrantStore, keychainHostKeys }, { LOCK_TOKEN_ENV }, { createMcpProxy }, { hostPaths }, { changePolicy, DEFAULT_POLICY, loadPolicy }, { createSessionPool }, { macDialogPrompter, terminalPrompter }, { revokeGrant }, { fileTrustStore }, { ensureService },] = await Promise.all([
|
|
34
|
+
import("./acp.js"),
|
|
35
|
+
import("@parlor/chat"),
|
|
36
|
+
import("./control.js"),
|
|
37
|
+
import("./daemon.js"),
|
|
38
|
+
import("./grants.js"),
|
|
39
|
+
import("./lock.js"),
|
|
40
|
+
import("./mcp-proxy.js"),
|
|
41
|
+
import("./paths.js"),
|
|
42
|
+
import("./policy.js"),
|
|
43
|
+
import("./pool.js"),
|
|
44
|
+
import("./prompter.js"),
|
|
45
|
+
import("./revoke.js"),
|
|
46
|
+
import("./trust.js"),
|
|
47
|
+
import("./service.js"),
|
|
48
|
+
]);
|
|
49
|
+
const release = {
|
|
50
|
+
version,
|
|
51
|
+
protocols: { min: 1, max: HOST_PROTOCOL },
|
|
52
|
+
control: CONTROL_PROTOCOL,
|
|
53
|
+
};
|
|
54
|
+
const daemonFor = (paths, grants, prompter) => createHostDaemon({
|
|
55
|
+
release,
|
|
56
|
+
paths,
|
|
57
|
+
grants,
|
|
58
|
+
keys: keychainHostKeys(KEYCHAIN_SERVICE),
|
|
59
|
+
trust: fileTrustStore(paths.trust),
|
|
60
|
+
pool: createSessionPool(paths.sessions),
|
|
61
|
+
proxy: createMcpProxy("parlor-host"),
|
|
62
|
+
launcher: acpLauncher(),
|
|
63
|
+
prompter,
|
|
64
|
+
policy: DEFAULT_POLICY,
|
|
65
|
+
lockToken: process.env[LOCK_TOKEN_ENV],
|
|
66
|
+
});
|
|
67
|
+
const disconnectFrom = async (origin) => {
|
|
68
|
+
const paths = hostPaths();
|
|
69
|
+
const client = await connectControl(paths.control);
|
|
70
|
+
if (client) {
|
|
71
|
+
const reply = await client.send({ op: "disconnect", appOrigin: origin });
|
|
72
|
+
client.close();
|
|
73
|
+
if (!reply.ok)
|
|
74
|
+
throw new Error(reply.error);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const grants = fileGrantStore(paths.grants);
|
|
78
|
+
const grant = await grants.get(origin);
|
|
79
|
+
if (!grant)
|
|
80
|
+
throw new Error(`This computer is not connected to ${origin}.`);
|
|
81
|
+
const keys = keychainHostKeys(KEYCHAIN_SERVICE);
|
|
82
|
+
await revokeGrant({
|
|
83
|
+
appOrigin: origin,
|
|
84
|
+
appName: grant.appName,
|
|
85
|
+
assert: (request) => keys.assert(origin, request),
|
|
86
|
+
});
|
|
87
|
+
await grants.remove(origin);
|
|
88
|
+
await keys.remove(origin);
|
|
89
|
+
await fileTrustStore(paths.trust).forget(origin);
|
|
90
|
+
};
|
|
91
|
+
return {
|
|
92
|
+
changePolicy,
|
|
93
|
+
connectControl,
|
|
94
|
+
DEFAULT_POLICY,
|
|
95
|
+
daemonFor,
|
|
96
|
+
disconnectFrom,
|
|
97
|
+
ensureService,
|
|
98
|
+
fileGrantStore,
|
|
99
|
+
HostAlreadyRunning,
|
|
100
|
+
fileTrustStore,
|
|
101
|
+
hostPaths,
|
|
102
|
+
keychainHostKeys,
|
|
103
|
+
loadPolicy,
|
|
104
|
+
macDialogPrompter,
|
|
105
|
+
release,
|
|
106
|
+
terminalPrompter,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
const link = defineCommand({
|
|
110
|
+
meta: {
|
|
111
|
+
name: "link",
|
|
112
|
+
description: "Link a device showing a link code to this computer's agents",
|
|
113
|
+
},
|
|
114
|
+
args: {
|
|
115
|
+
url: { type: "positional", required: true, description: "The app's URL" },
|
|
116
|
+
code: {
|
|
117
|
+
type: "positional",
|
|
118
|
+
required: true,
|
|
119
|
+
description: "The code the device shows",
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
async run({ args }) {
|
|
123
|
+
const { unsupportedHostPlatform } = await import("./naming.js");
|
|
124
|
+
const unsupported = unsupportedHostPlatform();
|
|
125
|
+
if (unsupported) {
|
|
126
|
+
fail(unsupported);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
const [kit, { linkDevice }, { askYesNo }, { computerName }] = await Promise.all([
|
|
130
|
+
host(),
|
|
131
|
+
import("./link-device.js"),
|
|
132
|
+
import("./prompter.js"),
|
|
133
|
+
import("./naming.js"),
|
|
134
|
+
]);
|
|
135
|
+
const origin = new URL(args.url).origin;
|
|
136
|
+
const paths = kit.hostPaths();
|
|
137
|
+
const grant = await kit.fileGrantStore(paths.grants).get(origin);
|
|
138
|
+
if (!grant || grant.declined) {
|
|
139
|
+
fail(`This computer is not connected to ${origin}. Run \`npx @parlor/agent-host connect ${origin}\` first.`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const keys = kit.keychainHostKeys(KEYCHAIN_SERVICE);
|
|
143
|
+
let outcome;
|
|
144
|
+
try {
|
|
145
|
+
outcome = await linkDevice({
|
|
146
|
+
appOrigin: origin,
|
|
147
|
+
code: args.code,
|
|
148
|
+
assert: (request) => keys.assert(origin, request),
|
|
149
|
+
trust: kit.fileTrustStore(paths.trust),
|
|
150
|
+
confirm: (device) => askYesNo(`Link ${device.name} to your agents on ${computerName()} for ${grant.appName} as ${grant.account.email ?? grant.account.name}?`),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
fail(errorText(error));
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (!outcome.linked) {
|
|
158
|
+
fail("Not linked.");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
const client = await kit.connectControl(paths.control);
|
|
162
|
+
if (client) {
|
|
163
|
+
await client.send({ op: "connect", appOrigin: origin });
|
|
164
|
+
client.close();
|
|
165
|
+
}
|
|
166
|
+
process.stdout.write(`Linked ${printable(outcome.device.name)}. It can use your agents now.\n`);
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
const devices = defineCommand({
|
|
170
|
+
meta: {
|
|
171
|
+
name: "devices",
|
|
172
|
+
description: "List the devices that can use this computer's agents, or remove one",
|
|
173
|
+
},
|
|
174
|
+
args: {
|
|
175
|
+
url: { type: "positional", required: true, description: "The app's URL" },
|
|
176
|
+
remove: { type: "string", description: "The id of a device to remove" },
|
|
177
|
+
},
|
|
178
|
+
async run({ args }) {
|
|
179
|
+
const [kit, { describeDevices, removeDevice }] = await Promise.all([
|
|
180
|
+
host(),
|
|
181
|
+
import("./device-list.js"),
|
|
182
|
+
]);
|
|
183
|
+
const origin = new URL(args.url).origin;
|
|
184
|
+
const paths = kit.hostPaths();
|
|
185
|
+
const grant = await kit.fileGrantStore(paths.grants).get(origin);
|
|
186
|
+
if (!grant || grant.declined) {
|
|
187
|
+
fail(`This computer is not connected to ${origin}.`);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const trust = kit.fileTrustStore(paths.trust);
|
|
191
|
+
if (!args.remove) {
|
|
192
|
+
process.stdout.write(describeDevices(grant.appName, await trust.list(origin)));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
let removed;
|
|
196
|
+
try {
|
|
197
|
+
removed = await removeDevice(trust, origin, args.remove);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
fail(errorText(error));
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const client = await kit.connectControl(paths.control);
|
|
204
|
+
if (client) {
|
|
205
|
+
await client.send({ op: "connect", appOrigin: origin });
|
|
206
|
+
client.close();
|
|
207
|
+
}
|
|
208
|
+
process.stdout.write(`Removed ${printable(removed.name)}. It must be linked again to use your agents here.\n`);
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
const connect = defineCommand({
|
|
212
|
+
meta: { name: "connect", description: "Connect this computer to a Parlor app" },
|
|
213
|
+
args: { url: { type: "positional", required: true, description: "The app's URL" } },
|
|
214
|
+
async run({ args }) {
|
|
215
|
+
const [kit, { pair, UnrevokedGrant }, { computerName, platformName, unsupportedHostPlatform },] = await Promise.all([host(), import("./pairing.js"), import("./naming.js")]);
|
|
216
|
+
const unsupported = unsupportedHostPlatform();
|
|
217
|
+
if (unsupported) {
|
|
218
|
+
fail(unsupported);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const origin = new URL(args.url).origin;
|
|
222
|
+
const paths = kit.hostPaths();
|
|
223
|
+
const grants = kit.fileGrantStore(paths.grants);
|
|
224
|
+
let grant = await grants.get(origin);
|
|
225
|
+
const alreadyConnected = grant !== undefined && !grant.declined;
|
|
226
|
+
if (grant?.declined) {
|
|
227
|
+
try {
|
|
228
|
+
await kit.disconnectFrom(origin);
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
fail(errorText(error));
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
grant = undefined;
|
|
235
|
+
}
|
|
236
|
+
if (!grant) {
|
|
237
|
+
let outcome;
|
|
238
|
+
try {
|
|
239
|
+
outcome = await pair({
|
|
240
|
+
appOrigin: origin,
|
|
241
|
+
hostName: computerName(),
|
|
242
|
+
platform: platformName(),
|
|
243
|
+
keys: kit.keychainHostKeys(KEYCHAIN_SERVICE),
|
|
244
|
+
workspaceRoot: paths.workspaces,
|
|
245
|
+
channel: {
|
|
246
|
+
kind: "browser",
|
|
247
|
+
open: async (url) => {
|
|
248
|
+
process.stdout.write(`Approve the connection in your browser. If it did not open, visit:\n${url}\n`);
|
|
249
|
+
spawn("open", [url], { stdio: "ignore", detached: true })
|
|
250
|
+
.on("error", () => undefined)
|
|
251
|
+
.unref();
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
catch (error) {
|
|
257
|
+
if (!(error instanceof UnrevokedGrant))
|
|
258
|
+
throw error;
|
|
259
|
+
await grants.save(error.grant);
|
|
260
|
+
fail(`${error.message} Run \`parlor-host disconnect ${origin}\` to try again.`);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (!outcome.paired) {
|
|
264
|
+
const why = {
|
|
265
|
+
declined_locally: "You did not confirm the connection.",
|
|
266
|
+
declined_in_app: "The connection was cancelled in the browser.",
|
|
267
|
+
timeout: "The connection was not approved within 10 minutes.",
|
|
268
|
+
}[outcome.reason];
|
|
269
|
+
fail(`Not connected. ${why}`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
grant = outcome.grant;
|
|
273
|
+
await grants.save(grant);
|
|
274
|
+
}
|
|
275
|
+
const adopted = await kit.ensureService(paths, {
|
|
276
|
+
kind: "cli",
|
|
277
|
+
release: kit.release,
|
|
278
|
+
});
|
|
279
|
+
if (adopted.kind === "refused") {
|
|
280
|
+
fail("An older Parlor Host is already running on this computer; stop it, then connect again.");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const client = await kit.connectControl(paths.control);
|
|
284
|
+
if (!client) {
|
|
285
|
+
fail("Parlor Host stopped answering.");
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
const reply = await client.send({ op: "connect", appOrigin: origin });
|
|
289
|
+
client.close();
|
|
290
|
+
if (!reply.ok) {
|
|
291
|
+
fail(reply.error);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
process.stdout.write(`Connected to ${printable(grant.appName)} as ${printable(grant.account.email ?? grant.account.name)}. Your agents are ready in its sidebar.\nNot you? Run \`npx @parlor/agent-host disconnect ${origin}\`.\n`);
|
|
295
|
+
if (alreadyConnected) {
|
|
296
|
+
process.stdout.write("This computer was already connected. To use your agents from another browser or device, open the Agent sidebar there and link it.\n");
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
const disconnect = defineCommand({
|
|
301
|
+
meta: { name: "disconnect", description: "Disconnect this computer from a Parlor app" },
|
|
302
|
+
args: { url: { type: "positional", required: true, description: "The app's URL" } },
|
|
303
|
+
async run({ args }) {
|
|
304
|
+
const kit = await host();
|
|
305
|
+
await kit
|
|
306
|
+
.disconnectFrom(new URL(args.url).origin)
|
|
307
|
+
.catch((error) => fail(errorText(error)));
|
|
308
|
+
},
|
|
309
|
+
});
|
|
310
|
+
const status = defineCommand({
|
|
311
|
+
meta: { name: "status", description: "Show the apps this computer serves" },
|
|
312
|
+
args: { json: { type: "boolean", description: "Print one JSON line" } },
|
|
313
|
+
async run({ args }) {
|
|
314
|
+
const kit = await host();
|
|
315
|
+
const client = await kit.connectControl(kit.hostPaths().control);
|
|
316
|
+
const reply = client ? await client.send({ op: "status" }) : undefined;
|
|
317
|
+
client?.close();
|
|
318
|
+
const current = reply?.ok
|
|
319
|
+
? { ...reply.status, grants: reply.grants }
|
|
320
|
+
: { state: "stopped" };
|
|
321
|
+
if (args.json) {
|
|
322
|
+
process.stdout.write(`${JSON.stringify(current)}\n`);
|
|
323
|
+
}
|
|
324
|
+
else if (current.state === "stopped") {
|
|
325
|
+
process.stdout.write("Parlor Host is not running.\n");
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
const apps = current.apps.map((app) => ` ${app}`).join("\n");
|
|
329
|
+
process.stdout.write(`Parlor Host ${current.version} is serving:\n${apps || " no app yet"}\n`);
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
});
|
|
333
|
+
const daemon = defineCommand({
|
|
334
|
+
meta: {
|
|
335
|
+
name: "daemon",
|
|
336
|
+
description: "Run the background host for every connected app",
|
|
337
|
+
},
|
|
338
|
+
args: {
|
|
339
|
+
ensure: {
|
|
340
|
+
type: "boolean",
|
|
341
|
+
description: "Adopt, install or upgrade the per-user service, print one JSON line, exit",
|
|
342
|
+
},
|
|
343
|
+
app: { type: "string", description: "With --ensure: the app's bundle id" },
|
|
344
|
+
binary: { type: "string", description: "With --ensure: the bundled parlor-host" },
|
|
345
|
+
signature: { type: "string", description: "With --ensure: its parlor-host.sig" },
|
|
346
|
+
},
|
|
347
|
+
async run({ args }) {
|
|
348
|
+
const kit = await host();
|
|
349
|
+
const paths = kit.hostPaths();
|
|
350
|
+
if (args.ensure) {
|
|
351
|
+
if (!args.app || !args.binary || !args.signature) {
|
|
352
|
+
fail("--ensure needs --app, --binary and --signature.");
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const started = performance.now();
|
|
356
|
+
const outcome = await kit.ensureService(paths, {
|
|
357
|
+
kind: "desktop-sidecar",
|
|
358
|
+
app: args.app,
|
|
359
|
+
release: kit.release,
|
|
360
|
+
binary: args.binary,
|
|
361
|
+
signature: args.signature,
|
|
362
|
+
});
|
|
363
|
+
process.stdout.write(`${JSON.stringify({
|
|
364
|
+
event: "ensure",
|
|
365
|
+
outcome: outcome.kind,
|
|
366
|
+
ms: Math.round(performance.now() - started),
|
|
367
|
+
...(outcome.kind === "refused" ? { reason: outcome.reason } : {}),
|
|
368
|
+
})}\n`);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
const shutdown = shutdownSignal();
|
|
372
|
+
const running = kit.daemonFor(paths, kit.fileGrantStore(paths.grants), process.platform === "darwin" ? kit.macDialogPrompter() : kit.terminalPrompter());
|
|
373
|
+
try {
|
|
374
|
+
await running.start();
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
if (error instanceof kit.HostAlreadyRunning)
|
|
378
|
+
process.exit(0);
|
|
379
|
+
throw error;
|
|
380
|
+
}
|
|
381
|
+
const handedOver = running.drained.then(() => true);
|
|
382
|
+
if (await Promise.race([handedOver, untilAborted(shutdown).then(() => false)])) {
|
|
383
|
+
process.exit(0);
|
|
384
|
+
}
|
|
385
|
+
await running.stop();
|
|
386
|
+
process.exit(0);
|
|
387
|
+
},
|
|
388
|
+
});
|
|
389
|
+
const config = defineCommand({
|
|
390
|
+
meta: {
|
|
391
|
+
name: "config",
|
|
392
|
+
description: "Show or set what this computer enforces on remote turns",
|
|
393
|
+
},
|
|
394
|
+
args: {
|
|
395
|
+
answers: {
|
|
396
|
+
type: "string",
|
|
397
|
+
description: "Where an agent's permission prompts are answered: presence or computer",
|
|
398
|
+
},
|
|
399
|
+
"prompt-presence": {
|
|
400
|
+
type: "string",
|
|
401
|
+
description: "Hours a linked device sends before it confirms with Face ID or Touch ID again, or off",
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
async run({ args }) {
|
|
405
|
+
const kit = await host();
|
|
406
|
+
const { policy } = kit.hostPaths();
|
|
407
|
+
let change = {};
|
|
408
|
+
const { answers } = args;
|
|
409
|
+
if (answers !== undefined) {
|
|
410
|
+
if (answers !== "presence" && answers !== "computer") {
|
|
411
|
+
fail("--answers takes presence or computer.");
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
change = { ...change, answers };
|
|
415
|
+
}
|
|
416
|
+
const hours = args["prompt-presence"];
|
|
417
|
+
if (hours !== undefined) {
|
|
418
|
+
const maxAgeHours = Number(hours);
|
|
419
|
+
if (hours !== "off" && !(Number.isFinite(maxAgeHours) && maxAgeHours > 0)) {
|
|
420
|
+
fail("--prompt-presence takes a number of hours or off.");
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
change = { ...change, promptPresence: hours === "off" ? "off" : { maxAgeHours } };
|
|
424
|
+
}
|
|
425
|
+
const current = Object.keys(change).length === 0
|
|
426
|
+
? await kit.loadPolicy(policy, kit.DEFAULT_POLICY)
|
|
427
|
+
: await kit.changePolicy(policy, kit.DEFAULT_POLICY, change);
|
|
428
|
+
process.stdout.write(`${JSON.stringify(current)}\n`);
|
|
429
|
+
},
|
|
430
|
+
});
|
|
431
|
+
const dev = defineCommand({
|
|
432
|
+
meta: { name: "dev", description: "Serve a local `parlor dev` server" },
|
|
433
|
+
args: {
|
|
434
|
+
app: { type: "string", required: true, description: "http://localhost:<port>" },
|
|
435
|
+
},
|
|
436
|
+
async run({ args }) {
|
|
437
|
+
const [kit, { NoDevAuth, requestDevHostToken }] = await Promise.all([
|
|
438
|
+
host(),
|
|
439
|
+
import("./dev-host.js"),
|
|
440
|
+
]);
|
|
441
|
+
const origin = new URL(args.app).origin;
|
|
442
|
+
const shutdown = shutdownSignal();
|
|
443
|
+
const stopped = untilAborted(shutdown);
|
|
444
|
+
let hostToken;
|
|
445
|
+
try {
|
|
446
|
+
hostToken = await requestDevHostToken(origin, shutdown);
|
|
447
|
+
}
|
|
448
|
+
catch (error) {
|
|
449
|
+
if (shutdown.aborted)
|
|
450
|
+
process.exit();
|
|
451
|
+
if (!(error instanceof NoDevAuth))
|
|
452
|
+
throw error;
|
|
453
|
+
process.stdout.write("Parlor Host: this app signs people in itself; connect this computer from its sidebar.\n");
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
const home = kit.hostPaths();
|
|
457
|
+
const shared = await kit.connectControl(home.control);
|
|
458
|
+
if (shared) {
|
|
459
|
+
const reply = await shared.send({ op: "dev_attach", appOrigin: origin, hostToken });
|
|
460
|
+
if (!reply.ok)
|
|
461
|
+
fail(reply.error);
|
|
462
|
+
await stopped;
|
|
463
|
+
await shared.send({ op: "dev_detach", appOrigin: origin });
|
|
464
|
+
shared.close();
|
|
465
|
+
process.exit();
|
|
466
|
+
}
|
|
467
|
+
const root = await mkdtemp(join(tmpdir(), "parlor-host-dev-"));
|
|
468
|
+
const paths = {
|
|
469
|
+
...kit.hostPaths(root),
|
|
470
|
+
agents: home.agents,
|
|
471
|
+
workspaces: home.workspaces,
|
|
472
|
+
};
|
|
473
|
+
const own = kit.daemonFor(paths, memoryGrants(), kit.terminalPrompter());
|
|
474
|
+
await own.start();
|
|
475
|
+
const client = await kit.connectControl(paths.control);
|
|
476
|
+
const reply = await client.send({ op: "dev_attach", appOrigin: origin, hostToken });
|
|
477
|
+
client.close();
|
|
478
|
+
if (!reply.ok)
|
|
479
|
+
fail(reply.error);
|
|
480
|
+
await stopped;
|
|
481
|
+
await own.stop();
|
|
482
|
+
await rm(root, { recursive: true, force: true });
|
|
483
|
+
process.exit();
|
|
484
|
+
},
|
|
485
|
+
});
|
|
486
|
+
function memoryGrants() {
|
|
487
|
+
const grants = new Map();
|
|
488
|
+
return {
|
|
489
|
+
list: async () => [...grants.values()],
|
|
490
|
+
get: async (appOrigin) => grants.get(appOrigin),
|
|
491
|
+
save: async (grant) => void grants.set(grant.appOrigin, grant),
|
|
492
|
+
remove: async (appOrigin) => void grants.delete(appOrigin),
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
const mcpProxy = defineCommand({
|
|
496
|
+
meta: { name: "mcp-proxy", description: "Internal: an agent's stdio MCP server" },
|
|
497
|
+
async run() {
|
|
498
|
+
const { runMcpProxyProcess } = await import("./mcp-proxy.js");
|
|
499
|
+
await runMcpProxyProcess(process.env);
|
|
500
|
+
},
|
|
501
|
+
});
|
|
502
|
+
void runMain(defineCommand({
|
|
503
|
+
meta: {
|
|
504
|
+
name: "parlor-host",
|
|
505
|
+
version,
|
|
506
|
+
description: "Run your own agents for your Parlor apps",
|
|
507
|
+
},
|
|
508
|
+
subCommands: {
|
|
509
|
+
connect,
|
|
510
|
+
link,
|
|
511
|
+
devices,
|
|
512
|
+
disconnect,
|
|
513
|
+
status,
|
|
514
|
+
daemon,
|
|
515
|
+
config,
|
|
516
|
+
dev,
|
|
517
|
+
"mcp-proxy": mcpProxy,
|
|
518
|
+
},
|
|
519
|
+
}));
|
|
520
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { spawn } from \"node:child_process\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { defineCommand, runMain } from \"citty\";\n\nimport type { AppGrant, GrantStore } from \"./grants.js\";\nimport type { RemotePolicy } from \"./policy.js\";\nimport { printable } from \"./prompter.js\";\nimport { HOST_VERSION as version } from \"./version.js\";\n\nconst KEYCHAIN_SERVICE = \"dev.parlor.host\";\n\nfunction shutdownSignal(): AbortSignal {\n const controller = new AbortController();\n const stop = () => {\n process.off(\"SIGINT\", stop);\n process.off(\"SIGTERM\", stop);\n controller.abort();\n };\n process.on(\"SIGINT\", stop);\n process.on(\"SIGTERM\", stop);\n return controller.signal;\n}\n\nconst untilAborted = (signal: AbortSignal) =>\n new Promise<void>((resolve) => {\n if (signal.aborted) resolve();\n else signal.addEventListener(\"abort\", () => resolve(), { once: true });\n });\n\nconst errorText = (error: unknown) =>\n error instanceof Error ? error.message : String(error);\n\nfunction fail(message: string): void {\n process.stderr.write(`${printable(message)}\\n`);\n process.exitCode = 1;\n}\n\nasync function host() {\n const [\n { acpLauncher },\n { HOST_PROTOCOL },\n { CONTROL_PROTOCOL, connectControl },\n { createHostDaemon, HostAlreadyRunning },\n { fileGrantStore, keychainHostKeys },\n { LOCK_TOKEN_ENV },\n { createMcpProxy },\n { hostPaths },\n { changePolicy, DEFAULT_POLICY, loadPolicy },\n { createSessionPool },\n { macDialogPrompter, terminalPrompter },\n { revokeGrant },\n { fileTrustStore },\n { ensureService },\n ] = await Promise.all([\n import(\"./acp.js\"),\n import(\"@parlor/chat\"),\n import(\"./control.js\"),\n import(\"./daemon.js\"),\n import(\"./grants.js\"),\n import(\"./lock.js\"),\n import(\"./mcp-proxy.js\"),\n import(\"./paths.js\"),\n import(\"./policy.js\"),\n import(\"./pool.js\"),\n import(\"./prompter.js\"),\n import(\"./revoke.js\"),\n import(\"./trust.js\"),\n import(\"./service.js\"),\n ]);\n type Paths = ReturnType<typeof hostPaths>;\n type Grants = ReturnType<typeof fileGrantStore>;\n type Prompter = ReturnType<typeof terminalPrompter>;\n const release = {\n version,\n protocols: { min: 1, max: HOST_PROTOCOL },\n control: CONTROL_PROTOCOL,\n };\n const daemonFor = (paths: Paths, grants: Grants, prompter: Prompter) =>\n createHostDaemon({\n release,\n paths,\n grants,\n keys: keychainHostKeys(KEYCHAIN_SERVICE),\n trust: fileTrustStore(paths.trust),\n pool: createSessionPool(paths.sessions),\n proxy: createMcpProxy(\"parlor-host\"),\n launcher: acpLauncher(),\n prompter,\n policy: DEFAULT_POLICY,\n lockToken: process.env[LOCK_TOKEN_ENV],\n });\n const disconnectFrom = async (origin: string) => {\n const paths = hostPaths();\n const client = await connectControl(paths.control);\n if (client) {\n const reply = await client.send({ op: \"disconnect\", appOrigin: origin });\n client.close();\n if (!reply.ok) throw new Error(reply.error);\n return;\n }\n const grants = fileGrantStore(paths.grants);\n const grant = await grants.get(origin);\n if (!grant) throw new Error(`This computer is not connected to ${origin}.`);\n const keys = keychainHostKeys(KEYCHAIN_SERVICE);\n await revokeGrant({\n appOrigin: origin,\n appName: grant.appName,\n assert: (request) => keys.assert(origin, request),\n });\n await grants.remove(origin);\n await keys.remove(origin);\n await fileTrustStore(paths.trust).forget(origin);\n };\n return {\n changePolicy,\n connectControl,\n DEFAULT_POLICY,\n daemonFor,\n disconnectFrom,\n ensureService,\n fileGrantStore,\n HostAlreadyRunning,\n fileTrustStore,\n hostPaths,\n keychainHostKeys,\n loadPolicy,\n macDialogPrompter,\n release,\n terminalPrompter,\n };\n}\n\nconst link = defineCommand({\n meta: {\n name: \"link\",\n description: \"Link a device showing a link code to this computer's agents\",\n },\n args: {\n url: { type: \"positional\", required: true, description: \"The app's URL\" },\n code: {\n type: \"positional\",\n required: true,\n description: \"The code the device shows\",\n },\n },\n async run({ args }) {\n const { unsupportedHostPlatform } = await import(\"./naming.js\");\n const unsupported = unsupportedHostPlatform();\n if (unsupported) {\n fail(unsupported);\n return;\n }\n const [kit, { linkDevice }, { askYesNo }, { computerName }] = await Promise.all([\n host(),\n import(\"./link-device.js\"),\n import(\"./prompter.js\"),\n import(\"./naming.js\"),\n ]);\n const origin = new URL(args.url).origin;\n const paths = kit.hostPaths();\n const grant = await kit.fileGrantStore(paths.grants).get(origin);\n if (!grant || grant.declined) {\n fail(\n `This computer is not connected to ${origin}. Run \\`npx @parlor/agent-host connect ${origin}\\` first.`,\n );\n return;\n }\n const keys = kit.keychainHostKeys(KEYCHAIN_SERVICE);\n let outcome: Awaited<ReturnType<typeof linkDevice>>;\n try {\n outcome = await linkDevice({\n appOrigin: origin,\n code: args.code,\n assert: (request) => keys.assert(origin, request),\n trust: kit.fileTrustStore(paths.trust),\n confirm: (device) =>\n askYesNo(\n `Link ${device.name} to your agents on ${computerName()} for ${grant.appName} as ${grant.account.email ?? grant.account.name}?`,\n ),\n });\n } catch (error) {\n fail(errorText(error));\n return;\n }\n if (!outcome.linked) {\n fail(\"Not linked.\");\n return;\n }\n const client = await kit.connectControl(paths.control);\n if (client) {\n await client.send({ op: \"connect\", appOrigin: origin });\n client.close();\n }\n process.stdout.write(\n `Linked ${printable(outcome.device.name)}. It can use your agents now.\\n`,\n );\n },\n});\n\nconst devices = defineCommand({\n meta: {\n name: \"devices\",\n description: \"List the devices that can use this computer's agents, or remove one\",\n },\n args: {\n url: { type: \"positional\", required: true, description: \"The app's URL\" },\n remove: { type: \"string\", description: \"The id of a device to remove\" },\n },\n async run({ args }) {\n const [kit, { describeDevices, removeDevice }] = await Promise.all([\n host(),\n import(\"./device-list.js\"),\n ]);\n const origin = new URL(args.url).origin;\n const paths = kit.hostPaths();\n const grant = await kit.fileGrantStore(paths.grants).get(origin);\n if (!grant || grant.declined) {\n fail(`This computer is not connected to ${origin}.`);\n return;\n }\n const trust = kit.fileTrustStore(paths.trust);\n if (!args.remove) {\n process.stdout.write(describeDevices(grant.appName, await trust.list(origin)));\n return;\n }\n let removed: Awaited<ReturnType<typeof removeDevice>>;\n try {\n removed = await removeDevice(trust, origin, args.remove);\n } catch (error) {\n fail(errorText(error));\n return;\n }\n const client = await kit.connectControl(paths.control);\n if (client) {\n await client.send({ op: \"connect\", appOrigin: origin });\n client.close();\n }\n process.stdout.write(\n `Removed ${printable(removed.name)}. It must be linked again to use your agents here.\\n`,\n );\n },\n});\n\nconst connect = defineCommand({\n meta: { name: \"connect\", description: \"Connect this computer to a Parlor app\" },\n args: { url: { type: \"positional\", required: true, description: \"The app's URL\" } },\n async run({ args }) {\n const [\n kit,\n { pair, UnrevokedGrant },\n { computerName, platformName, unsupportedHostPlatform },\n ] = await Promise.all([host(), import(\"./pairing.js\"), import(\"./naming.js\")]);\n const unsupported = unsupportedHostPlatform();\n if (unsupported) {\n fail(unsupported);\n return;\n }\n const origin = new URL(args.url).origin;\n const paths = kit.hostPaths();\n const grants = kit.fileGrantStore(paths.grants);\n let grant = await grants.get(origin);\n const alreadyConnected = grant !== undefined && !grant.declined;\n if (grant?.declined) {\n try {\n await kit.disconnectFrom(origin);\n } catch (error) {\n fail(errorText(error));\n return;\n }\n grant = undefined;\n }\n if (!grant) {\n let outcome: Awaited<ReturnType<typeof pair>>;\n try {\n outcome = await pair({\n appOrigin: origin,\n hostName: computerName(),\n platform: platformName(),\n keys: kit.keychainHostKeys(KEYCHAIN_SERVICE),\n workspaceRoot: paths.workspaces,\n channel: {\n kind: \"browser\",\n open: async (url) => {\n process.stdout.write(\n `Approve the connection in your browser. If it did not open, visit:\\n${url}\\n`,\n );\n spawn(\"open\", [url], { stdio: \"ignore\", detached: true })\n .on(\"error\", () => undefined)\n .unref();\n },\n },\n });\n } catch (error) {\n if (!(error instanceof UnrevokedGrant)) throw error;\n await grants.save(error.grant);\n fail(`${error.message} Run \\`parlor-host disconnect ${origin}\\` to try again.`);\n return;\n }\n if (!outcome.paired) {\n const why = {\n declined_locally: \"You did not confirm the connection.\",\n declined_in_app: \"The connection was cancelled in the browser.\",\n timeout: \"The connection was not approved within 10 minutes.\",\n }[outcome.reason];\n fail(`Not connected. ${why}`);\n return;\n }\n grant = outcome.grant;\n await grants.save(grant);\n }\n const adopted = await kit.ensureService(paths, {\n kind: \"cli\",\n release: kit.release,\n });\n if (adopted.kind === \"refused\") {\n fail(\n \"An older Parlor Host is already running on this computer; stop it, then connect again.\",\n );\n return;\n }\n const client = await kit.connectControl(paths.control);\n if (!client) {\n fail(\"Parlor Host stopped answering.\");\n return;\n }\n const reply = await client.send({ op: \"connect\", appOrigin: origin });\n client.close();\n if (!reply.ok) {\n fail(reply.error);\n return;\n }\n process.stdout.write(\n `Connected to ${printable(grant.appName)} as ${printable(grant.account.email ?? grant.account.name)}. Your agents are ready in its sidebar.\\nNot you? Run \\`npx @parlor/agent-host disconnect ${origin}\\`.\\n`,\n );\n if (alreadyConnected) {\n process.stdout.write(\n \"This computer was already connected. To use your agents from another browser or device, open the Agent sidebar there and link it.\\n\",\n );\n }\n },\n});\n\nconst disconnect = defineCommand({\n meta: { name: \"disconnect\", description: \"Disconnect this computer from a Parlor app\" },\n args: { url: { type: \"positional\", required: true, description: \"The app's URL\" } },\n async run({ args }) {\n const kit = await host();\n await kit\n .disconnectFrom(new URL(args.url).origin)\n .catch((error: unknown) => fail(errorText(error)));\n },\n});\n\nconst status = defineCommand({\n meta: { name: \"status\", description: \"Show the apps this computer serves\" },\n args: { json: { type: \"boolean\", description: \"Print one JSON line\" } },\n async run({ args }) {\n const kit = await host();\n const client = await kit.connectControl(kit.hostPaths().control);\n const reply = client ? await client.send({ op: \"status\" }) : undefined;\n client?.close();\n const current = reply?.ok\n ? { ...reply.status, grants: reply.grants }\n : ({ state: \"stopped\" } as const);\n if (args.json) {\n process.stdout.write(`${JSON.stringify(current)}\\n`);\n } else if (current.state === \"stopped\") {\n process.stdout.write(\"Parlor Host is not running.\\n\");\n } else {\n const apps = current.apps.map((app) => ` ${app}`).join(\"\\n\");\n process.stdout.write(\n `Parlor Host ${current.version} is serving:\\n${apps || \" no app yet\"}\\n`,\n );\n }\n },\n});\n\nconst daemon = defineCommand({\n meta: {\n name: \"daemon\",\n description: \"Run the background host for every connected app\",\n },\n args: {\n ensure: {\n type: \"boolean\",\n description:\n \"Adopt, install or upgrade the per-user service, print one JSON line, exit\",\n },\n app: { type: \"string\", description: \"With --ensure: the app's bundle id\" },\n binary: { type: \"string\", description: \"With --ensure: the bundled parlor-host\" },\n signature: { type: \"string\", description: \"With --ensure: its parlor-host.sig\" },\n },\n async run({ args }) {\n const kit = await host();\n const paths = kit.hostPaths();\n if (args.ensure) {\n if (!args.app || !args.binary || !args.signature) {\n fail(\"--ensure needs --app, --binary and --signature.\");\n return;\n }\n const started = performance.now();\n const outcome = await kit.ensureService(paths, {\n kind: \"desktop-sidecar\",\n app: args.app,\n release: kit.release,\n binary: args.binary,\n signature: args.signature,\n });\n process.stdout.write(\n `${JSON.stringify({\n event: \"ensure\",\n outcome: outcome.kind,\n ms: Math.round(performance.now() - started),\n ...(outcome.kind === \"refused\" ? { reason: outcome.reason } : {}),\n })}\\n`,\n );\n return;\n }\n const shutdown = shutdownSignal();\n const running = kit.daemonFor(\n paths,\n kit.fileGrantStore(paths.grants),\n process.platform === \"darwin\" ? kit.macDialogPrompter() : kit.terminalPrompter(),\n );\n try {\n await running.start();\n } catch (error) {\n if (error instanceof kit.HostAlreadyRunning) process.exit(0);\n throw error;\n }\n const handedOver = running.drained.then(() => true);\n if (await Promise.race([handedOver, untilAborted(shutdown).then(() => false)])) {\n process.exit(0);\n }\n await running.stop();\n process.exit(0);\n },\n});\n\nconst config = defineCommand({\n meta: {\n name: \"config\",\n description: \"Show or set what this computer enforces on remote turns\",\n },\n args: {\n answers: {\n type: \"string\",\n description:\n \"Where an agent's permission prompts are answered: presence or computer\",\n },\n \"prompt-presence\": {\n type: \"string\",\n description:\n \"Hours a linked device sends before it confirms with Face ID or Touch ID again, or off\",\n },\n },\n async run({ args }) {\n const kit = await host();\n const { policy } = kit.hostPaths();\n let change: Partial<RemotePolicy> = {};\n const { answers } = args;\n if (answers !== undefined) {\n if (answers !== \"presence\" && answers !== \"computer\") {\n fail(\"--answers takes presence or computer.\");\n return;\n }\n change = { ...change, answers };\n }\n const hours = args[\"prompt-presence\"];\n if (hours !== undefined) {\n const maxAgeHours = Number(hours);\n if (hours !== \"off\" && !(Number.isFinite(maxAgeHours) && maxAgeHours > 0)) {\n fail(\"--prompt-presence takes a number of hours or off.\");\n return;\n }\n change = { ...change, promptPresence: hours === \"off\" ? \"off\" : { maxAgeHours } };\n }\n const current =\n Object.keys(change).length === 0\n ? await kit.loadPolicy(policy, kit.DEFAULT_POLICY)\n : await kit.changePolicy(policy, kit.DEFAULT_POLICY, change);\n process.stdout.write(`${JSON.stringify(current)}\\n`);\n },\n});\n\nconst dev = defineCommand({\n meta: { name: \"dev\", description: \"Serve a local `parlor dev` server\" },\n args: {\n app: { type: \"string\", required: true, description: \"http://localhost:<port>\" },\n },\n async run({ args }) {\n const [kit, { NoDevAuth, requestDevHostToken }] = await Promise.all([\n host(),\n import(\"./dev-host.js\"),\n ]);\n const origin = new URL(args.app).origin;\n const shutdown = shutdownSignal();\n const stopped = untilAborted(shutdown);\n let hostToken: string;\n try {\n hostToken = await requestDevHostToken(origin, shutdown);\n } catch (error) {\n if (shutdown.aborted) process.exit();\n if (!(error instanceof NoDevAuth)) throw error;\n process.stdout.write(\n \"Parlor Host: this app signs people in itself; connect this computer from its sidebar.\\n\",\n );\n return;\n }\n const home = kit.hostPaths();\n const shared = await kit.connectControl(home.control);\n if (shared) {\n const reply = await shared.send({ op: \"dev_attach\", appOrigin: origin, hostToken });\n if (!reply.ok) fail(reply.error);\n await stopped;\n await shared.send({ op: \"dev_detach\", appOrigin: origin });\n shared.close();\n process.exit();\n }\n const root = await mkdtemp(join(tmpdir(), \"parlor-host-dev-\"));\n const paths = {\n ...kit.hostPaths(root),\n agents: home.agents,\n workspaces: home.workspaces,\n };\n const own = kit.daemonFor(paths, memoryGrants(), kit.terminalPrompter());\n await own.start();\n const client = await kit.connectControl(paths.control);\n const reply = await client!.send({ op: \"dev_attach\", appOrigin: origin, hostToken });\n client!.close();\n if (!reply.ok) fail(reply.error);\n await stopped;\n await own.stop();\n await rm(root, { recursive: true, force: true });\n process.exit();\n },\n});\n\nfunction memoryGrants(): GrantStore {\n const grants = new Map<string, AppGrant>();\n return {\n list: async () => [...grants.values()],\n get: async (appOrigin) => grants.get(appOrigin),\n save: async (grant) => void grants.set(grant.appOrigin, grant),\n remove: async (appOrigin) => void grants.delete(appOrigin),\n };\n}\n\nconst mcpProxy = defineCommand({\n meta: { name: \"mcp-proxy\", description: \"Internal: an agent's stdio MCP server\" },\n async run() {\n const { runMcpProxyProcess } = await import(\"./mcp-proxy.js\");\n await runMcpProxyProcess(process.env);\n },\n});\n\nvoid runMain(\n defineCommand({\n meta: {\n name: \"parlor-host\",\n version,\n description: \"Run your own agents for your Parlor apps\",\n },\n subCommands: {\n connect,\n link,\n devices,\n disconnect,\n status,\n daemon,\n config,\n dev,\n \"mcp-proxy\": mcpProxy,\n },\n }),\n);\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Delegation } from "@parlor/server";
|
|
2
|
+
import type { StdioMcpServer } from "./acp.js";
|
|
3
|
+
/**
|
|
4
|
+
* The agent's MCP server for an app is this host: a stdio server (`parlor-host
|
|
5
|
+
* mcp-proxy`) that connects back to the daemon's 0600 socket and names its session by a
|
|
6
|
+
* nonce. The daemon forwards each message to `<app>/_parlor/mcp` with the current turn's
|
|
7
|
+
* token, so no app credential is ever in the agent's config, logs or environment.
|
|
8
|
+
*/
|
|
9
|
+
export interface McpProxy {
|
|
10
|
+
listen(socketPath: string): Promise<void>;
|
|
11
|
+
open(appServer: string, appOrigin: string): ProxySession;
|
|
12
|
+
stopListening(): Promise<void>;
|
|
13
|
+
close(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export interface ProxySession {
|
|
16
|
+
readonly nonce: string;
|
|
17
|
+
/** The entry for `session/new`. */
|
|
18
|
+
readonly server: StdioMcpServer;
|
|
19
|
+
/** Forward with this token until `end`; a `tools/call` outside a turn gets NO_TURN_MESSAGE. */
|
|
20
|
+
begin(token: Delegation): void;
|
|
21
|
+
renew(token: Delegation): void;
|
|
22
|
+
end(): void;
|
|
23
|
+
dispose(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare const NO_TURN_MESSAGE = "No turn is active: the user has not asked anything right now. Wait for their next message.";
|
|
26
|
+
export declare const DISCONNECTED_MESSAGE = "This computer no longer serves the app: it was disconnected, or Parlor Host stopped.";
|
|
27
|
+
export declare function createMcpProxy(hostBinary: string): McpProxy;
|
|
28
|
+
/**
|
|
29
|
+
* `parlor-host mcp-proxy`: stdio to the daemon socket and back. Once the daemon hangs up,
|
|
30
|
+
* every request still unanswered, and every later one, is answered with an error here.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runMcpProxyProcess(env: NodeJS.ProcessEnv): Promise<void>;
|
|
33
|
+
//# sourceMappingURL=mcp-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-proxy.d.ts","sourceRoot":"","sources":["../src/mcp-proxy.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAI/C;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC;IACzD,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mCAAmC;IACnC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,+FAA+F;IAC/F,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/B,GAAG,IAAI,IAAI,CAAC;IACZ,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,eAAO,MAAM,eAAe,+FACkE,CAAC;AAE/F,eAAO,MAAM,oBAAoB,yFACuD,CAAC;AA6LzF,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAiG3D;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAyC9E"}
|