@parlor/agent-host 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/dist/acp.d.ts +21 -0
- package/dist/acp.d.ts.map +1 -1
- package/dist/acp.js +138 -12
- package/dist/acp.js.map +1 -1
- package/dist/agent-options.d.ts +22 -0
- package/dist/agent-options.d.ts.map +1 -0
- package/dist/agent-options.js +105 -0
- package/dist/agent-options.js.map +1 -0
- package/dist/agent-survey.d.ts +15 -0
- package/dist/agent-survey.d.ts.map +1 -0
- package/dist/agent-survey.js +51 -0
- package/dist/agent-survey.js.map +1 -0
- package/dist/agent-tools.d.ts +30 -0
- package/dist/agent-tools.d.ts.map +1 -0
- package/dist/agent-tools.js +71 -0
- package/dist/agent-tools.js.map +1 -0
- package/dist/codex-app-server.d.ts +7 -0
- package/dist/codex-app-server.d.ts.map +1 -0
- package/dist/codex-app-server.js +46 -0
- package/dist/codex-app-server.js.map +1 -0
- package/dist/control.d.ts +15 -0
- package/dist/control.d.ts.map +1 -1
- package/dist/control.js.map +1 -1
- package/dist/daemon.d.ts +10 -2
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +217 -16
- package/dist/daemon.js.map +1 -1
- package/dist/fold.d.ts.map +1 -1
- package/dist/fold.js +2 -0
- package/dist/fold.js.map +1 -1
- package/dist/grants.d.ts +9 -0
- package/dist/grants.d.ts.map +1 -1
- package/dist/grants.js.map +1 -1
- package/dist/learned.d.ts +25 -0
- package/dist/learned.d.ts.map +1 -0
- package/dist/learned.js +37 -0
- package/dist/learned.js.map +1 -0
- package/dist/link.d.ts +3 -1
- package/dist/link.d.ts.map +1 -1
- package/dist/link.js +23 -1
- package/dist/link.js.map +1 -1
- package/dist/main.js +105 -9
- package/dist/main.js.map +1 -1
- package/dist/mcp-proxy.d.ts +26 -3
- package/dist/mcp-proxy.d.ts.map +1 -1
- package/dist/mcp-proxy.js +288 -25
- package/dist/mcp-proxy.js.map +1 -1
- package/dist/pairing.d.ts +2 -0
- package/dist/pairing.d.ts.map +1 -1
- package/dist/pairing.js +25 -3
- package/dist/pairing.js.map +1 -1
- package/dist/paths.d.ts +2 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +1 -0
- package/dist/paths.js.map +1 -1
- package/dist/policy.d.ts +12 -2
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +13 -3
- package/dist/policy.js.map +1 -1
- package/dist/prompter.d.ts +5 -0
- package/dist/prompter.d.ts.map +1 -1
- package/dist/prompter.js +15 -0
- package/dist/prompter.js.map +1 -1
- package/dist/spec-kit.d.ts +4 -1
- package/dist/spec-kit.d.ts.map +1 -1
- package/dist/spec-kit.js +12 -2
- package/dist/spec-kit.js.map +1 -1
- package/dist/testing/fake-agent.d.ts +12 -0
- package/dist/testing/fake-agent.d.ts.map +1 -1
- package/dist/testing/fake-agent.js +11 -1
- package/dist/testing/fake-agent.js.map +1 -1
- package/dist/turn.d.ts +7 -1
- package/dist/turn.d.ts.map +1 -1
- package/dist/turn.js +16 -3
- package/dist/turn.js.map +1 -1
- package/package.json +9 -9
package/dist/link.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CHAT_ACTIVITY_TAG, CHAT_TAG, HOST_PROTOCOL, } from "@parlor/chat";
|
|
1
|
+
import { CHAT_ACTIVITY_TAG, CHAT_CHANNEL, CHAT_TAG, HOST_PROTOCOL, } from "@parlor/chat";
|
|
2
2
|
import { MAX_STREAM_BODY_BYTES } from "@parlor/chat/server";
|
|
3
3
|
import { createActionClient, createPluginClient, } from "@parlor/client";
|
|
4
4
|
import { createSyncClient } from "@parlor/sync/client";
|
|
@@ -68,6 +68,16 @@ function untilHeaders(inner, ms) {
|
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
|
+
/** The turn a `chat` channel frame pushes to this computer; the channel's other frames are for tabs. */
|
|
72
|
+
function pushedTurnOf(data) {
|
|
73
|
+
try {
|
|
74
|
+
const frame = JSON.parse(data);
|
|
75
|
+
return frame.type === "claimed" && frame.turn ? frame.turn : undefined;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
71
81
|
function adaptivePoll(advertised, busy) {
|
|
72
82
|
let activeUntil = 0;
|
|
73
83
|
const idle = () => advertised && !busy() && Date.now() >= activeUntil;
|
|
@@ -246,6 +256,18 @@ export function createAppLink(grant, deps) {
|
|
|
246
256
|
if (modeNow() === "serving" && heads.includes(CHAT_TAG))
|
|
247
257
|
deps.onWake(link);
|
|
248
258
|
},
|
|
259
|
+
channels: [
|
|
260
|
+
{
|
|
261
|
+
event: CHAT_CHANNEL,
|
|
262
|
+
opened: () => undefined,
|
|
263
|
+
closed: () => undefined,
|
|
264
|
+
receive: (data) => {
|
|
265
|
+
const turn = pushedTurnOf(data);
|
|
266
|
+
if (turn && modeNow() === "serving")
|
|
267
|
+
deps.onPushed?.(link, turn);
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
],
|
|
249
271
|
onUnauthorized: () => undefined,
|
|
250
272
|
onError: () => undefined,
|
|
251
273
|
});
|
package/dist/link.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.js","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,QAAQ,EACR,aAAa,GAId,MAAM,cAAc,CAAC;AACtB,OAAO,EAA0B,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACpF,OAAO,EACL,kBAAkB,EAClB,kBAAkB,GAEnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,gBAAgB,EAAmB,MAAM,qBAAqB,CAAC;AAGxE,OAAO,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC;AAEnC,MAAM,qBAAqB,GAAG,CAAC,GAAG,MAAM,CAAC;AACzC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAkDlC,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,eAAe,GAAG,CAAC,qBAAqB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;AAExD,MAAM,QAAS,SAAQ,KAAK;IACR,IAAI,GAAG,UAAU,CAAC;CACrC;AAOD,SAAS,QAAQ,CAAC,MAA4B;IAC5C,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,IACE,IAAI,EAAE,IAAI,KAAK,OAAO;YACtB,KAAK,CAAC,IAAI,KAAK,OAAO;YACtB,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM;YAC5B,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,EAC/C,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACxE,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,OAAO,CAAC,MAA4B;IAC3C,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,IAAI,OAAO,GAAgB,EAAE,CAAC;IAC9B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;QAC1C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,GAAG,IAAI,GAAG,eAAe,EAAE,CAAC;YACzD,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClB,OAAO,GAAG,EAAE,CAAC;YACb,KAAK,GAAG,CAAC,CAAC;QACZ,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,KAAK,IAAI,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEhF,MAAM,cAAe,SAAQ,KAAK;IACd,IAAI,GAAG,gBAAgB,CAAC;IAC1C,YAAY,EAAU;QACpB,KAAK,CAAC,iCAAiC,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;CACF;AAED,SAAS,YAAY,CAAC,KAAmB,EAAE,EAAU;IACnD,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAC3B,MAAM,GAAG,GAAG,IAAI,eAAe,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,cAAc,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;QACtF,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACjD,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,UAAmB,EAAE,IAAmB;IAC5D,IAAI,WAAW,GAAG,CAAC,CAAC;IACpB,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,UAAU,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,WAAW,CAAC;IACtE,OAAO;QACL,WAAW,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAC;QAC3D,KAAK,EAAE,GAAG,EAAE;YACV,MAAM,OAAO,GAAG,IAAI,EAAE,CAAC;YACvB,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,qBAAqB,CAAC;YACjD,OAAO,OAAO,CAAC;QACjB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAe,EAAE,IAAiB;IAC9D,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACnD,IAAI,OAA6B,CAAC;IAClC,IAAI,IAAI,GAAa,MAAM,CAAC;IAC5B,MAAM,OAAO,GAAG,GAAa,EAAE,CAAC,IAAI,CAAC;IACrC,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,IAA4B,CAAC;IACjC,IAAI,SAAqC,CAAC;IAC1C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE9C,IAAI,KAAK,GAAe,GAAG,EAAE,CAAC,SAAS,CAAC;IACxC,IAAI,MAAM,GAA2B,GAAG,EAAE,CAAC,SAAS,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrD,KAAK,GAAG,OAAO,CAAC;QAChB,MAAM,GAAG,MAAM,CAAC;IAClB,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAEhC,MAAM,WAAW,GAAiB,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtD,IAAI,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,QAAQ,CAAC,4BAA4B,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACzD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC/E,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,cAAc,SAAS,EAAE,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;QACrE,QAAQ,CAAC,cAAc,EAAE;YACvB,MAAM;YACN,IAAI,EAAE,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ;YACnC,MAAM,EAAE,QAAQ,CAAC,MAAM;SACxB,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;YAClE,OAAO,GAAG,IAAI,CAAC;YACf,cAAc,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,YAAY,CAAC,WAAW,EAAE,kBAAkB,CAAC,CAAC;IAEjE,MAAM,MAAM,GAAG,kBAAkB,CAC/B,kBAAkB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAC1D,MAAM,CACP,CAAC;IAEF,MAAM,OAAO,GAAG,KAAK,EAAE,MAA0B,EAAE,EAAE;QACnD,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO;QACjC,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;YAC7C,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,MAAM,OAAO,CAAC;QAChB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,MAAM,GAA8C,KAAK,EAC7D,IAAI,EACJ,KAAK,EACL,OAAO,EACP,EAAE;QACF,IAAI,IAAI,KAAK,WAAW;YAAE,MAAM,QAAQ,CAAC;QACzC,IAAI,IAAI,KAAK,YAAY,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YACnD,MAAM,OAAO,CAAE,KAAsC,CAAC,MAAM,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC,CAAC;IACF,MAAM,KAAK,GAAoC;QAC7C,MAAM;QACN,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI;KAChF,CAAC;IAEF,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,IAAa,EAAE,EAAE,CAC3C,UAAU,CAAC,GAAG,MAAM,iBAAiB,IAAI,EAAE,EAAE;QAC3C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC,CAAC;IAEL,MAAM,KAAK,GAAG,KAAK,EAAE,MAAc,EAAE,MAAkB,EAAE,EAAE;QACzD,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,IAAI,IAAI,KAAK,QAAQ;gBAAE,MAAM;YAC7B,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM,CAAC,OAAO,GAAG,EAAE,CAAC;YACpB,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QACD,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC;QAC3B,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC,CAAC;IAEF,MAAM,GAAG,GAAY;QACnB,KAAK;QACL,MAAM,CAAC,KAAK;YACV,IAAI,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAC3D,IAAI,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACvC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;gBAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACpE,CAAC;QACD,KAAK,CAAC,SAAS;YACb,MAAM,QAAQ,CAAC;YACf,MAAM,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;QAC9B,CAAC;KACF,CAAC;IAEF,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,GAAG,QAAQ,CAAC;QAChB,IAAI,EAAE,IAAI,EAAE,CAAC;QACb,IAAI,GAAG,SAAS,CAAC;QACjB,IAAI,SAAS;YAAE,aAAa,CAAC,SAAS,CAAC,CAAC;QACxC,SAAS,GAAG,SAAS,CAAC;QACtB,MAAM,CAAC,IAAI,QAAQ,CAAC,4BAA4B,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,IAAsC,EAAE;QACzD,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,IAAI,CAAC,EAAE,CAAC;YACrC,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,UAAU;gBAAE,OAAO,SAAS,CAAC;YAChE,IAAI,CAAC;gBACH,OAAO,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE;oBACpC,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,aAAa,EAAE;oBACzC,WAAW,EAAE,IAAI,CAAC,WAAW;oBAC7B,IAAI,EAAE,IAAI,CAAC,QAAQ;oBACnB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,MAAM,EAAE,EAAE;iBACX,CAAC,CAAC;YACL,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,OAAO,IAAI,OAAO,EAAE,KAAK,QAAQ;oBAAE,OAAO,SAAS,CAAC;gBACxD,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,IAAI,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,IAAI,GAAY;QACpB,KAAK;QACL,GAAG;QACH,IAAI,QAAQ;YACV,OAAO,OAAO,EAAE,QAAQ,CAAC;QAC3B,CAAC;QACD,IAAI,IAAI;YACN,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK;YACH,IAAI,IAAI,KAAK,MAAM;gBAAE,OAAO;YAC5B,IAAI,GAAG,SAAS,CAAC;YACjB,KAAK,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;gBAC3B,IAAI,CAAC,MAAM,IAAI,OAAO,EAAE,KAAK,QAAQ;oBAAE,OAAO;gBAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACrB,KAAK,EAAE,CAAC;oBACR,QAAQ,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;oBACvE,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;oBACnC,OAAO;gBACT,CAAC;gBACD,OAAO,GAAG,MAAM,CAAC;gBACjB,KAAK,EAAE,CAAC;gBACR,MAAM,OAAO,GAAG,YAAY,CAC1B,MAAM,CAAC,YAAY,KAAK,IAAI,EAC5B,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,KAAK,CAC7B,CAAC;gBACF,IAAI,GAAG,gBAAgB,CAAC;oBACtB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,MAAM,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC;oBAC9D,UAAU,EAAE,CAAC;oBACb,cAAc,EAAE,gBAAgB;oBAChC,WAAW,EAAE,OAAO,CAAC,WAAW;oBAChC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;wBACnB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;wBACzE,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,iBAAiB,CAAC,EAAE,CAAC;4BAC1E,IAAI,OAAO,CAAC,KAAK,EAAE;gCAAE,IAAI,EAAE,YAAY,EAAE,CAAC;wBAC5C,CAAC;wBACD,IAAI,OAAO,EAAE,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;4BAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBAC7E,CAAC;oBACD,cAAc,EAAE,GAAG,EAAE,CAAC,SAAS;oBAC/B,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS;iBACzB,CAAC,CAAC;gBACH,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,SAAS,GAAG,WAAW,CACrB,GAAG,EAAE,CAAC,KAAK,GAAG,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EACjD,MAAM,CAAC,WAAW,CACnB,CAAC;gBACF,SAAS,CAAC,KAAK,EAAE,CAAC;gBAClB,IAAI,OAAO,EAAE,KAAK,SAAS;oBAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACjD,CAAC,CAAC,CAAC;QACL,CAAC;QACD,KAAK;YACH,IAAI,IAAI,KAAK,SAAS;gBAAE,IAAI,GAAG,UAAU,CAAC;QAC5C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,EAAE;YACrB,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;gBACjC,MAAM,WAAW,CAAC;oBAChB,SAAS,EAAE,MAAM;oBACjB,OAAO,EAAE,KAAK,CAAC,OAAO;oBACtB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;oBACtD,KAAK,EAAE,IAAI,CAAC,KAAK;iBAClB,CAAC,CAAC;YACL,CAAC;YACD,KAAK,EAAE,CAAC;QACV,CAAC;KACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import {\n CHAT_ACTIVITY_TAG,\n CHAT_TAG,\n HOST_PROTOCOL,\n type HostFrame,\n type HostStreamBatch,\n type HostWelcome,\n} from \"@parlor/chat\";\nimport { type ChatHostActionMap, MAX_STREAM_BODY_BYTES } from \"@parlor/chat/server\";\nimport {\n createActionClient,\n createPluginClient,\n type PluginClient,\n} from \"@parlor/client\";\nimport type { TurnId } from \"@parlor/core\";\nimport { createSyncClient, type SyncClient } from \"@parlor/sync/client\";\n\nimport type { AppGrant, HostKeys } from \"./grants.js\";\nimport { logEvent } from \"./log.js\";\nimport { revokeGrant } from \"./revoke.js\";\n\nexport const RECONNECT_MAX_MS = 4_000;\nexport const ACTIVE_POLL_MS = 2_000;\nexport const IDLE_POLL_MS = 15_000;\n\nconst USER_ACTIVE_WINDOW_MS = 2 * 60_000;\nconst REQUEST_TIMEOUT_MS = 10_000;\n\nexport interface HostApi {\n readonly calls: PluginClient<ChatHostActionMap>;\n /** At most one post in flight per turn; frames produced meanwhile coalesce into the next. */\n stream(batch: HostStreamBatch): void;\n heartbeat(): Promise<void>;\n}\n\nexport interface AppLinkDeps {\n readonly keys: HostKeys;\n readonly hostVersion: string;\n readonly hostName: string;\n readonly platform: string;\n readonly fetch: typeof fetch;\n /** A turn may be waiting: claim until not_found, then ask for running turns' signals. */\n readonly onWake: (link: AppLink) => void;\n /** Whether a turn runs on this link, which keeps a poll deployment's `/sync` at the active interval. */\n readonly busy?: (() => boolean) | undefined;\n /** Any 401, or the stream closed for revocation. */\n readonly onRevoked: (grant: AppGrant) => void;\n /** No shared protocol: shown locally (\"update Parlor Host\"); the link stays down. */\n readonly onIncompatible: (\n grant: AppGrant,\n welcome: Extract<HostWelcome, { readonly accepted: false }>,\n ) => void;\n}\n\n/**\n * `idle` until started; `serving` wakes the host for turns; `draining` stays up for the\n * turns it runs but wakes nobody (a newer service took over the claiming); `closed` is final.\n */\nexport type LinkMode = \"idle\" | \"serving\" | \"draining\" | \"closed\";\n\n/** The host's whole conversation with one app, each request carrying a fresh assertion. */\nexport interface AppLink {\n readonly grant: AppGrant;\n readonly api: HostApi;\n /** Set once `hostHello` was welcomed; every other call waits for it. */\n readonly protocol: number | undefined;\n readonly mode: LinkMode;\n start(): void;\n /** Stops waking the host and keeps everything else, so running turns finish on this link. */\n drain(): void;\n /** With `revoke`, a refused revoke throws and leaves the link running. */\n stop(options?: { readonly revoke?: boolean | undefined }): Promise<void>;\n}\n\ntype Accepted = Extract<HostWelcome, { readonly accepted: true }>;\n\nconst RETRY_BASE_MS = 250;\nconst MAX_BATCH_BYTES = (MAX_STREAM_BODY_BYTES * 3) / 4;\n\nclass LinkDown extends Error {\n override readonly name = \"LinkDown\";\n}\n\ninterface TurnStream {\n pending: HostFrame[];\n posting: Promise<void> | undefined;\n}\n\nfunction coalesce(frames: readonly HostFrame[]): HostFrame[] {\n const merged: HostFrame[] = [];\n for (const frame of frames) {\n const last = merged.at(-1);\n if (\n last?.type === \"delta\" &&\n frame.type === \"delta\" &&\n last.itemId === frame.itemId &&\n last.offset + last.text.length === frame.offset\n ) {\n merged[merged.length - 1] = { ...last, text: last.text + frame.text };\n } else {\n merged.push(frame);\n }\n }\n return merged;\n}\n\nfunction batches(frames: readonly HostFrame[]): HostFrame[][] {\n const out: HostFrame[][] = [];\n let current: HostFrame[] = [];\n let bytes = 0;\n for (const frame of frames) {\n const size = JSON.stringify(frame).length;\n if (current.length > 0 && bytes + size > MAX_BATCH_BYTES) {\n out.push(current);\n current = [];\n bytes = 0;\n }\n current.push(frame);\n bytes += size;\n }\n if (current.length > 0) out.push(current);\n return out;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nclass RequestTimeout extends Error {\n override readonly name = \"RequestTimeout\";\n constructor(ms: number) {\n super(`The app did not answer within ${ms} ms.`);\n }\n}\n\nfunction untilHeaders(inner: typeof fetch, ms: number): typeof fetch {\n return async (input, init) => {\n const own = new AbortController();\n const timer = setTimeout(() => own.abort(new RequestTimeout(ms)), ms);\n const signal = init?.signal ? AbortSignal.any([init.signal, own.signal]) : own.signal;\n try {\n return await inner(input, { ...init, signal });\n } finally {\n clearTimeout(timer);\n }\n };\n}\n\nfunction adaptivePoll(advertised: boolean, busy: () => boolean) {\n let activeUntil = 0;\n const idle = () => advertised && !busy() && Date.now() >= activeUntil;\n return {\n pollEveryMs: () => (idle() ? IDLE_POLL_MS : ACTIVE_POLL_MS),\n touch: () => {\n const wasIdle = idle();\n activeUntil = Date.now() + USER_ACTIVE_WINDOW_MS;\n return wasIdle;\n },\n };\n}\n\nexport function createAppLink(grant: AppGrant, deps: AppLinkDeps): AppLink {\n const origin = grant.appOrigin.replace(/\\/+$/, \"\");\n let welcome: Accepted | undefined;\n let mode: LinkMode = \"idle\";\n const modeNow = (): LinkMode => mode;\n let revoked = false;\n let sync: SyncClient | undefined;\n let heartbeat: NodeJS.Timeout | undefined;\n const streams = new Map<TurnId, TurnStream>();\n\n let admit: () => void = () => undefined;\n let refuse: (error: Error) => void = () => undefined;\n const welcomed = new Promise<void>((resolve, reject) => {\n admit = resolve;\n refuse = reject;\n });\n welcomed.catch(() => undefined);\n\n const signedFetch: typeof fetch = async (input, init) => {\n if (mode === \"closed\") throw new LinkDown(\"This app's link is closed.\");\n const request = new Request(input, init);\n const method = request.method === \"GET\" ? \"GET\" : \"POST\";\n const assertion = await deps.keys.assert(origin, { method, url: request.url });\n const headers = new Headers(request.headers);\n headers.set(\"authorization\", `ParlorHost ${assertion}`);\n const response = await deps.fetch(new Request(request, { headers }));\n logEvent(\"http_request\", {\n method,\n path: new URL(request.url).pathname,\n status: response.status,\n });\n if (response.status === 401 && !revoked && modeNow() !== \"closed\") {\n revoked = true;\n queueMicrotask(() => deps.onRevoked(grant));\n }\n return response;\n };\n\n const timedFetch = untilHeaders(signedFetch, REQUEST_TIMEOUT_MS);\n\n const plugin = createPluginClient<ChatHostActionMap>(\n createActionClient({ baseUrl: origin, fetch: timedFetch }),\n \"chat\",\n );\n\n const drained = async (turnId: TurnId | undefined) => {\n if (turnId === undefined) return;\n while (true) {\n const posting = streams.get(turnId)?.posting;\n if (!posting) return;\n await posting;\n }\n };\n\n const invoke: PluginClient<ChatHostActionMap>[\"invoke\"] = async (\n name,\n input,\n options,\n ) => {\n if (name !== \"hostHello\") await welcomed;\n if (name === \"hostAppend\" || name === \"hostFinish\") {\n await drained((input as { readonly turnId?: TurnId }).turnId);\n }\n return plugin.invoke(name, input, options);\n };\n const calls: PluginClient<ChatHostActionMap> = {\n invoke,\n call: async (name, input, options) => (await invoke(name, input, options)).data,\n };\n\n const post = (path: string, body: unknown) =>\n timedFetch(`${origin}/_parlor/chat/${path}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n const flush = async (turnId: TurnId, stream: TurnStream) => {\n while (stream.pending.length > 0) {\n if (mode === \"closed\") break;\n const frames = coalesce(stream.pending);\n stream.pending = [];\n for (const chunk of batches(frames)) {\n await post(\"stream\", { turnId, frames: chunk }).catch(() => undefined);\n }\n }\n stream.posting = undefined;\n if (stream.pending.length === 0) streams.delete(turnId);\n };\n\n const api: HostApi = {\n calls,\n stream(batch) {\n if (mode === \"closed\" || batch.frames.length === 0) return;\n let stream = streams.get(batch.turnId);\n if (!stream) {\n stream = { pending: [], posting: undefined };\n streams.set(batch.turnId, stream);\n }\n stream.pending.push(...batch.frames);\n if (!stream.posting) stream.posting = flush(batch.turnId, stream);\n },\n async heartbeat() {\n await welcomed;\n await post(\"heartbeat\", {});\n },\n };\n\n const close = () => {\n mode = \"closed\";\n sync?.stop();\n sync = undefined;\n if (heartbeat) clearInterval(heartbeat);\n heartbeat = undefined;\n refuse(new LinkDown(\"This app's link is closed.\"));\n };\n\n const hello = async (): Promise<HostWelcome | undefined> => {\n for (let attempt = 0; ; attempt += 1) {\n if (mode !== \"serving\" && mode !== \"draining\") return undefined;\n try {\n return await plugin.call(\"hostHello\", {\n protocols: { min: 1, max: HOST_PROTOCOL },\n hostVersion: deps.hostVersion,\n name: deps.hostName,\n platform: deps.platform,\n agents: [],\n });\n } catch {\n if (revoked || modeNow() === \"closed\") return undefined;\n await sleep(Math.min(RETRY_BASE_MS * 2 ** attempt, RECONNECT_MAX_MS));\n }\n }\n };\n\n const link: AppLink = {\n grant,\n api,\n get protocol() {\n return welcome?.protocol;\n },\n get mode() {\n return mode;\n },\n start() {\n if (mode !== \"idle\") return;\n mode = \"serving\";\n void hello().then((answer) => {\n if (!answer || modeNow() === \"closed\") return;\n if (!answer.accepted) {\n close();\n logEvent(\"link_closed\", { appOrigin: origin, reason: \"incompatible\" });\n deps.onIncompatible(grant, answer);\n return;\n }\n welcome = answer;\n admit();\n const polling = adaptivePoll(\n answer.userActivity === true,\n () => deps.busy?.() ?? false,\n );\n sync = createSyncClient({\n request: (path, init) => signedFetch(`${origin}${path}`, init),\n coalesceMs: 0,\n reconnectMaxMs: RECONNECT_MAX_MS,\n pollEveryMs: polling.pollEveryMs,\n onEvents: (events) => {\n const heads = events.flatMap((event) => event.tags.map((tag) => tag[0]));\n if (heads.some((head) => head === CHAT_TAG || head === CHAT_ACTIVITY_TAG)) {\n if (polling.touch()) sync?.reconnectNow();\n }\n if (modeNow() === \"serving\" && heads.includes(CHAT_TAG)) deps.onWake(link);\n },\n onUnauthorized: () => undefined,\n onError: () => undefined,\n });\n sync.start();\n heartbeat = setInterval(\n () => void api.heartbeat().catch(() => undefined),\n answer.heartbeatMs,\n );\n heartbeat.unref();\n if (modeNow() === \"serving\") deps.onWake(link);\n });\n },\n drain() {\n if (mode === \"serving\") mode = \"draining\";\n },\n async stop(options = {}) {\n if (options.revoke && !grant.dev) {\n await revokeGrant({\n appOrigin: origin,\n appName: grant.appName,\n assert: (request) => deps.keys.assert(origin, request),\n fetch: deps.fetch,\n });\n }\n close();\n },\n };\n return link;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"link.js","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CHAT_ACTIVITY_TAG,\n CHAT_CHANNEL,\n CHAT_TAG,\n type ClaimedTurn,\n HOST_PROTOCOL,\n type HostFrame,\n type HostStreamBatch,\n type HostWelcome,\n type PushedTurn,\n} from \"@parlor/chat\";\nimport { type ChatHostActionMap, MAX_STREAM_BODY_BYTES } from \"@parlor/chat/server\";\nimport {\n createActionClient,\n createPluginClient,\n type PluginClient,\n} from \"@parlor/client\";\nimport type { TurnId } from \"@parlor/core\";\nimport { createSyncClient, type SyncClient } from \"@parlor/sync/client\";\n\nimport type { AppGrant, HostKeys } from \"./grants.js\";\nimport { logEvent } from \"./log.js\";\nimport { revokeGrant } from \"./revoke.js\";\n\nexport const RECONNECT_MAX_MS = 4_000;\nexport const ACTIVE_POLL_MS = 2_000;\nexport const IDLE_POLL_MS = 15_000;\n\nconst USER_ACTIVE_WINDOW_MS = 2 * 60_000;\nconst REQUEST_TIMEOUT_MS = 10_000;\n\nexport interface HostApi {\n readonly calls: PluginClient<ChatHostActionMap>;\n /** At most one post in flight per turn; frames produced meanwhile coalesce into the next. */\n stream(batch: HostStreamBatch): void;\n heartbeat(): Promise<void>;\n}\n\nexport interface AppLinkDeps {\n readonly keys: HostKeys;\n readonly hostVersion: string;\n readonly hostName: string;\n readonly platform: string;\n readonly fetch: typeof fetch;\n /** A turn may be waiting: claim until not_found, then ask for running turns' signals. */\n readonly onWake: (link: AppLink) => void;\n /** The app claimed a turn for this computer and pushed it, saving the claim. */\n readonly onPushed?: ((link: AppLink, turn: ClaimedTurn) => void) | undefined;\n /** Whether a turn runs on this link, which keeps a poll deployment's `/sync` at the active interval. */\n readonly busy?: (() => boolean) | undefined;\n /** Any 401, or the stream closed for revocation. */\n readonly onRevoked: (grant: AppGrant) => void;\n /** No shared protocol: shown locally (\"update Parlor Host\"); the link stays down. */\n readonly onIncompatible: (\n grant: AppGrant,\n welcome: Extract<HostWelcome, { readonly accepted: false }>,\n ) => void;\n}\n\n/**\n * `idle` until started; `serving` wakes the host for turns; `draining` stays up for the\n * turns it runs but wakes nobody (a newer service took over the claiming); `closed` is final.\n */\nexport type LinkMode = \"idle\" | \"serving\" | \"draining\" | \"closed\";\n\n/** The host's whole conversation with one app, each request carrying a fresh assertion. */\nexport interface AppLink {\n readonly grant: AppGrant;\n readonly api: HostApi;\n /** Set once `hostHello` was welcomed; every other call waits for it. */\n readonly protocol: number | undefined;\n readonly mode: LinkMode;\n start(): void;\n /** Stops waking the host and keeps everything else, so running turns finish on this link. */\n drain(): void;\n /** With `revoke`, a refused revoke throws and leaves the link running. */\n stop(options?: { readonly revoke?: boolean | undefined }): Promise<void>;\n}\n\ntype Accepted = Extract<HostWelcome, { readonly accepted: true }>;\n\nconst RETRY_BASE_MS = 250;\nconst MAX_BATCH_BYTES = (MAX_STREAM_BODY_BYTES * 3) / 4;\n\nclass LinkDown extends Error {\n override readonly name = \"LinkDown\";\n}\n\ninterface TurnStream {\n pending: HostFrame[];\n posting: Promise<void> | undefined;\n}\n\nfunction coalesce(frames: readonly HostFrame[]): HostFrame[] {\n const merged: HostFrame[] = [];\n for (const frame of frames) {\n const last = merged.at(-1);\n if (\n last?.type === \"delta\" &&\n frame.type === \"delta\" &&\n last.itemId === frame.itemId &&\n last.offset + last.text.length === frame.offset\n ) {\n merged[merged.length - 1] = { ...last, text: last.text + frame.text };\n } else {\n merged.push(frame);\n }\n }\n return merged;\n}\n\nfunction batches(frames: readonly HostFrame[]): HostFrame[][] {\n const out: HostFrame[][] = [];\n let current: HostFrame[] = [];\n let bytes = 0;\n for (const frame of frames) {\n const size = JSON.stringify(frame).length;\n if (current.length > 0 && bytes + size > MAX_BATCH_BYTES) {\n out.push(current);\n current = [];\n bytes = 0;\n }\n current.push(frame);\n bytes += size;\n }\n if (current.length > 0) out.push(current);\n return out;\n}\n\nconst sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));\n\nclass RequestTimeout extends Error {\n override readonly name = \"RequestTimeout\";\n constructor(ms: number) {\n super(`The app did not answer within ${ms} ms.`);\n }\n}\n\nfunction untilHeaders(inner: typeof fetch, ms: number): typeof fetch {\n return async (input, init) => {\n const own = new AbortController();\n const timer = setTimeout(() => own.abort(new RequestTimeout(ms)), ms);\n const signal = init?.signal ? AbortSignal.any([init.signal, own.signal]) : own.signal;\n try {\n return await inner(input, { ...init, signal });\n } finally {\n clearTimeout(timer);\n }\n };\n}\n\n/** The turn a `chat` channel frame pushes to this computer; the channel's other frames are for tabs. */\nfunction pushedTurnOf(data: string): ClaimedTurn | undefined {\n try {\n const frame = JSON.parse(data) as Partial<PushedTurn>;\n return frame.type === \"claimed\" && frame.turn ? frame.turn : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction adaptivePoll(advertised: boolean, busy: () => boolean) {\n let activeUntil = 0;\n const idle = () => advertised && !busy() && Date.now() >= activeUntil;\n return {\n pollEveryMs: () => (idle() ? IDLE_POLL_MS : ACTIVE_POLL_MS),\n touch: () => {\n const wasIdle = idle();\n activeUntil = Date.now() + USER_ACTIVE_WINDOW_MS;\n return wasIdle;\n },\n };\n}\n\nexport function createAppLink(grant: AppGrant, deps: AppLinkDeps): AppLink {\n const origin = grant.appOrigin.replace(/\\/+$/, \"\");\n let welcome: Accepted | undefined;\n let mode: LinkMode = \"idle\";\n const modeNow = (): LinkMode => mode;\n let revoked = false;\n let sync: SyncClient | undefined;\n let heartbeat: NodeJS.Timeout | undefined;\n const streams = new Map<TurnId, TurnStream>();\n\n let admit: () => void = () => undefined;\n let refuse: (error: Error) => void = () => undefined;\n const welcomed = new Promise<void>((resolve, reject) => {\n admit = resolve;\n refuse = reject;\n });\n welcomed.catch(() => undefined);\n\n const signedFetch: typeof fetch = async (input, init) => {\n if (mode === \"closed\") throw new LinkDown(\"This app's link is closed.\");\n const request = new Request(input, init);\n const method = request.method === \"GET\" ? \"GET\" : \"POST\";\n const assertion = await deps.keys.assert(origin, { method, url: request.url });\n const headers = new Headers(request.headers);\n headers.set(\"authorization\", `ParlorHost ${assertion}`);\n const response = await deps.fetch(new Request(request, { headers }));\n logEvent(\"http_request\", {\n method,\n path: new URL(request.url).pathname,\n status: response.status,\n });\n if (response.status === 401 && !revoked && modeNow() !== \"closed\") {\n revoked = true;\n queueMicrotask(() => deps.onRevoked(grant));\n }\n return response;\n };\n\n const timedFetch = untilHeaders(signedFetch, REQUEST_TIMEOUT_MS);\n\n const plugin = createPluginClient<ChatHostActionMap>(\n createActionClient({ baseUrl: origin, fetch: timedFetch }),\n \"chat\",\n );\n\n const drained = async (turnId: TurnId | undefined) => {\n if (turnId === undefined) return;\n while (true) {\n const posting = streams.get(turnId)?.posting;\n if (!posting) return;\n await posting;\n }\n };\n\n const invoke: PluginClient<ChatHostActionMap>[\"invoke\"] = async (\n name,\n input,\n options,\n ) => {\n if (name !== \"hostHello\") await welcomed;\n if (name === \"hostAppend\" || name === \"hostFinish\") {\n await drained((input as { readonly turnId?: TurnId }).turnId);\n }\n return plugin.invoke(name, input, options);\n };\n const calls: PluginClient<ChatHostActionMap> = {\n invoke,\n call: async (name, input, options) => (await invoke(name, input, options)).data,\n };\n\n const post = (path: string, body: unknown) =>\n timedFetch(`${origin}/_parlor/chat/${path}`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n const flush = async (turnId: TurnId, stream: TurnStream) => {\n while (stream.pending.length > 0) {\n if (mode === \"closed\") break;\n const frames = coalesce(stream.pending);\n stream.pending = [];\n for (const chunk of batches(frames)) {\n await post(\"stream\", { turnId, frames: chunk }).catch(() => undefined);\n }\n }\n stream.posting = undefined;\n if (stream.pending.length === 0) streams.delete(turnId);\n };\n\n const api: HostApi = {\n calls,\n stream(batch) {\n if (mode === \"closed\" || batch.frames.length === 0) return;\n let stream = streams.get(batch.turnId);\n if (!stream) {\n stream = { pending: [], posting: undefined };\n streams.set(batch.turnId, stream);\n }\n stream.pending.push(...batch.frames);\n if (!stream.posting) stream.posting = flush(batch.turnId, stream);\n },\n async heartbeat() {\n await welcomed;\n await post(\"heartbeat\", {});\n },\n };\n\n const close = () => {\n mode = \"closed\";\n sync?.stop();\n sync = undefined;\n if (heartbeat) clearInterval(heartbeat);\n heartbeat = undefined;\n refuse(new LinkDown(\"This app's link is closed.\"));\n };\n\n const hello = async (): Promise<HostWelcome | undefined> => {\n for (let attempt = 0; ; attempt += 1) {\n if (mode !== \"serving\" && mode !== \"draining\") return undefined;\n try {\n return await plugin.call(\"hostHello\", {\n protocols: { min: 1, max: HOST_PROTOCOL },\n hostVersion: deps.hostVersion,\n name: deps.hostName,\n platform: deps.platform,\n agents: [],\n });\n } catch {\n if (revoked || modeNow() === \"closed\") return undefined;\n await sleep(Math.min(RETRY_BASE_MS * 2 ** attempt, RECONNECT_MAX_MS));\n }\n }\n };\n\n const link: AppLink = {\n grant,\n api,\n get protocol() {\n return welcome?.protocol;\n },\n get mode() {\n return mode;\n },\n start() {\n if (mode !== \"idle\") return;\n mode = \"serving\";\n void hello().then((answer) => {\n if (!answer || modeNow() === \"closed\") return;\n if (!answer.accepted) {\n close();\n logEvent(\"link_closed\", { appOrigin: origin, reason: \"incompatible\" });\n deps.onIncompatible(grant, answer);\n return;\n }\n welcome = answer;\n admit();\n const polling = adaptivePoll(\n answer.userActivity === true,\n () => deps.busy?.() ?? false,\n );\n sync = createSyncClient({\n request: (path, init) => signedFetch(`${origin}${path}`, init),\n coalesceMs: 0,\n reconnectMaxMs: RECONNECT_MAX_MS,\n pollEveryMs: polling.pollEveryMs,\n onEvents: (events) => {\n const heads = events.flatMap((event) => event.tags.map((tag) => tag[0]));\n if (heads.some((head) => head === CHAT_TAG || head === CHAT_ACTIVITY_TAG)) {\n if (polling.touch()) sync?.reconnectNow();\n }\n if (modeNow() === \"serving\" && heads.includes(CHAT_TAG)) deps.onWake(link);\n },\n channels: [\n {\n event: CHAT_CHANNEL,\n opened: () => undefined,\n closed: () => undefined,\n receive: (data) => {\n const turn = pushedTurnOf(data);\n if (turn && modeNow() === \"serving\") deps.onPushed?.(link, turn);\n },\n },\n ],\n onUnauthorized: () => undefined,\n onError: () => undefined,\n });\n sync.start();\n heartbeat = setInterval(\n () => void api.heartbeat().catch(() => undefined),\n answer.heartbeatMs,\n );\n heartbeat.unref();\n if (modeNow() === \"serving\") deps.onWake(link);\n });\n },\n drain() {\n if (mode === \"serving\") mode = \"draining\";\n },\n async stop(options = {}) {\n if (options.revoke && !grant.dev) {\n await revokeGrant({\n appOrigin: origin,\n appName: grant.appName,\n assert: (request) => deps.keys.assert(origin, request),\n fetch: deps.fetch,\n });\n }\n close();\n },\n };\n return link;\n}\n"]}
|
package/dist/main.js
CHANGED
|
@@ -30,7 +30,7 @@ function fail(message) {
|
|
|
30
30
|
process.exitCode = 1;
|
|
31
31
|
}
|
|
32
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([
|
|
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 }, { unregisterAgentTools, agentNames }, { detectAgents, loadProfiles }, { agentEnvironment },] = await Promise.all([
|
|
34
34
|
import("./acp.js"),
|
|
35
35
|
import("@parlor/chat"),
|
|
36
36
|
import("./control.js"),
|
|
@@ -45,6 +45,9 @@ async function host() {
|
|
|
45
45
|
import("./revoke.js"),
|
|
46
46
|
import("./trust.js"),
|
|
47
47
|
import("./service.js"),
|
|
48
|
+
import("./agent-tools.js"),
|
|
49
|
+
import("./agents.js"),
|
|
50
|
+
import("./shell-path.js"),
|
|
48
51
|
]);
|
|
49
52
|
const release = {
|
|
50
53
|
version,
|
|
@@ -72,12 +75,25 @@ async function host() {
|
|
|
72
75
|
client.close();
|
|
73
76
|
if (!reply.ok)
|
|
74
77
|
throw new Error(reply.error);
|
|
75
|
-
return;
|
|
78
|
+
return reply.agentTools;
|
|
76
79
|
}
|
|
77
80
|
const grants = fileGrantStore(paths.grants);
|
|
78
81
|
const grant = await grants.get(origin);
|
|
79
82
|
if (!grant)
|
|
80
83
|
throw new Error(`This computer is not connected to ${origin}.`);
|
|
84
|
+
const tools = grant.agentTools;
|
|
85
|
+
let removed;
|
|
86
|
+
if (tools?.name && tools.agents?.length) {
|
|
87
|
+
const profiles = await loadProfiles(paths.agents);
|
|
88
|
+
const installed = await detectAgents(profiles);
|
|
89
|
+
const listed = { name: tools.name, agents: tools.agents };
|
|
90
|
+
await unregisterAgentTools({
|
|
91
|
+
profiles: profiles.filter((profile) => installed.some((a) => a.id === profile.id)),
|
|
92
|
+
hostCommand: join(paths.root, "bin", "parlor-host"),
|
|
93
|
+
env: agentEnvironment,
|
|
94
|
+
}, listed);
|
|
95
|
+
removed = { name: tools.name, agents: agentNames(profiles, listed) };
|
|
96
|
+
}
|
|
81
97
|
const keys = keychainHostKeys(KEYCHAIN_SERVICE);
|
|
82
98
|
await revokeGrant({
|
|
83
99
|
appOrigin: origin,
|
|
@@ -87,6 +103,7 @@ async function host() {
|
|
|
87
103
|
await grants.remove(origin);
|
|
88
104
|
await keys.remove(origin);
|
|
89
105
|
await fileTrustStore(paths.trust).forget(origin);
|
|
106
|
+
return removed;
|
|
90
107
|
};
|
|
91
108
|
return {
|
|
92
109
|
changePolicy,
|
|
@@ -242,6 +259,7 @@ const connect = defineCommand({
|
|
|
242
259
|
platform: platformName(),
|
|
243
260
|
keys: kit.keychainHostKeys(KEYCHAIN_SERVICE),
|
|
244
261
|
workspaceRoot: paths.workspaces,
|
|
262
|
+
offerAgentTools: true,
|
|
245
263
|
channel: {
|
|
246
264
|
kind: "browser",
|
|
247
265
|
open: async (url) => {
|
|
@@ -291,20 +309,74 @@ const connect = defineCommand({
|
|
|
291
309
|
fail(reply.error);
|
|
292
310
|
return;
|
|
293
311
|
}
|
|
294
|
-
|
|
312
|
+
const app = printable(grant.appName);
|
|
313
|
+
process.stdout.write(`Connected to ${app} as ${printable(grant.account.email ?? grant.account.name)}.\n${usage(app, reply.agentTools)}Not you? Run \`npx @parlor/agent-host disconnect ${origin}\`.\n`);
|
|
295
314
|
if (alreadyConnected) {
|
|
296
315
|
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");
|
|
316
|
+
if (grant.agentTools === undefined) {
|
|
317
|
+
process.stdout.write(`To use ${app} from Claude Code and Codex here too, run \`npx @parlor/agent-host tools ${origin}\`.\n`);
|
|
318
|
+
}
|
|
297
319
|
}
|
|
298
320
|
},
|
|
299
321
|
});
|
|
322
|
+
/** The two ways to use the app from this computer, for the lines after "Connected". */
|
|
323
|
+
function usage(app, tools) {
|
|
324
|
+
const sidebar = ` - In ${app}'s agent sidebar.\n`;
|
|
325
|
+
if (!tools)
|
|
326
|
+
return `Use your agents in ${app}'s agent sidebar.\n`;
|
|
327
|
+
return `Use it two ways:\n${sidebar} - In ${tools.agents} on this computer: ask them to "use ${tools.name} to ...". They ask you before their first change in each conversation.\n`;
|
|
328
|
+
}
|
|
329
|
+
const tools = defineCommand({
|
|
330
|
+
meta: {
|
|
331
|
+
name: "tools",
|
|
332
|
+
description: "Let the coding agents on this computer use an app outside its sidebar, or stop them",
|
|
333
|
+
},
|
|
334
|
+
args: {
|
|
335
|
+
url: { type: "positional", required: true, description: "The app's URL" },
|
|
336
|
+
off: { type: "boolean", description: "Stop them; the sidebar keeps working" },
|
|
337
|
+
},
|
|
338
|
+
async run({ args }) {
|
|
339
|
+
const kit = await host();
|
|
340
|
+
const origin = new URL(args.url).origin;
|
|
341
|
+
const client = await kit.connectControl(kit.hostPaths().control);
|
|
342
|
+
if (!client) {
|
|
343
|
+
fail(`Parlor Host is not running. Run \`npx @parlor/agent-host connect ${origin}\` first.`);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const reply = await client.send({
|
|
347
|
+
op: "agent_tools",
|
|
348
|
+
appOrigin: origin,
|
|
349
|
+
on: !args.off,
|
|
350
|
+
});
|
|
351
|
+
client.close();
|
|
352
|
+
if (!reply.ok) {
|
|
353
|
+
fail(reply.error);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
process.stdout.write(args.off
|
|
357
|
+
? `The coding agents on this computer no longer use ${origin}. Its sidebar still works.\n`
|
|
358
|
+
: reply.agentTools
|
|
359
|
+
? `${reply.agentTools.agents} can use ${origin}: ask them to "use ${reply.agentTools.name} to ...".\n`
|
|
360
|
+
: "No coding agent here can take it: install Claude Code or Codex, then run this again.\n");
|
|
361
|
+
},
|
|
362
|
+
});
|
|
300
363
|
const disconnect = defineCommand({
|
|
301
364
|
meta: { name: "disconnect", description: "Disconnect this computer from a Parlor app" },
|
|
302
365
|
args: { url: { type: "positional", required: true, description: "The app's URL" } },
|
|
303
366
|
async run({ args }) {
|
|
304
367
|
const kit = await host();
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
368
|
+
const origin = new URL(args.url).origin;
|
|
369
|
+
let removed;
|
|
370
|
+
try {
|
|
371
|
+
removed = await kit.disconnectFrom(origin);
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
fail(errorText(error));
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
process.stdout.write(`Disconnected this computer from ${origin}: its sidebar can no longer reach your agents here.\n${removed
|
|
378
|
+
? `Removed ${removed.name} from ${removed.agents}, so they cannot change it either.\n`
|
|
379
|
+
: ""}`);
|
|
308
380
|
},
|
|
309
381
|
});
|
|
310
382
|
const status = defineCommand({
|
|
@@ -400,6 +472,10 @@ const config = defineCommand({
|
|
|
400
472
|
type: "string",
|
|
401
473
|
description: "Hours a linked device sends before it confirms with Face ID or Touch ID again, or off",
|
|
402
474
|
},
|
|
475
|
+
"agent-mode": {
|
|
476
|
+
type: "string",
|
|
477
|
+
description: "auto: the agent's own safety review decides and asks only for what it flags; ask: it asks before every action",
|
|
478
|
+
},
|
|
403
479
|
},
|
|
404
480
|
async run({ args }) {
|
|
405
481
|
const kit = await host();
|
|
@@ -422,6 +498,14 @@ const config = defineCommand({
|
|
|
422
498
|
}
|
|
423
499
|
change = { ...change, promptPresence: hours === "off" ? "off" : { maxAgeHours } };
|
|
424
500
|
}
|
|
501
|
+
const agentMode = args["agent-mode"];
|
|
502
|
+
if (agentMode !== undefined) {
|
|
503
|
+
if (agentMode !== "auto" && agentMode !== "ask") {
|
|
504
|
+
fail("--agent-mode takes auto or ask.");
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
change = { ...change, agentMode };
|
|
508
|
+
}
|
|
425
509
|
const current = Object.keys(change).length === 0
|
|
426
510
|
? await kit.loadPolicy(policy, kit.DEFAULT_POLICY)
|
|
427
511
|
: await kit.changePolicy(policy, kit.DEFAULT_POLICY, change);
|
|
@@ -494,9 +578,20 @@ function memoryGrants() {
|
|
|
494
578
|
}
|
|
495
579
|
const mcpProxy = defineCommand({
|
|
496
580
|
meta: { name: "mcp-proxy", description: "Internal: an agent's stdio MCP server" },
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
581
|
+
args: {
|
|
582
|
+
app: {
|
|
583
|
+
type: "string",
|
|
584
|
+
description: "Serve this app to a coding agent outside the sidebar",
|
|
585
|
+
},
|
|
586
|
+
},
|
|
587
|
+
async run({ args }) {
|
|
588
|
+
const [{ runMcpProxyProcess }, { hostPaths }] = await Promise.all([
|
|
589
|
+
import("./mcp-proxy.js"),
|
|
590
|
+
import("./paths.js"),
|
|
591
|
+
]);
|
|
592
|
+
await runMcpProxyProcess(process.env, args.app
|
|
593
|
+
? { appOrigin: new URL(args.app).origin, socketPath: hostPaths().proxy }
|
|
594
|
+
: undefined);
|
|
500
595
|
},
|
|
501
596
|
});
|
|
502
597
|
void runMain(defineCommand({
|
|
@@ -515,6 +610,7 @@ void runMain(defineCommand({
|
|
|
515
610
|
config,
|
|
516
611
|
dev,
|
|
517
612
|
"mcp-proxy": mcpProxy,
|
|
613
|
+
tools,
|
|
518
614
|
},
|
|
519
615
|
}));
|
|
520
616
|
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
CHANGED
|
@@ -1 +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"]}
|
|
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 { unregisterAgentTools, agentNames },\n { detectAgents, loadProfiles },\n { agentEnvironment },\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 import(\"./agent-tools.js\"),\n import(\"./agents.js\"),\n import(\"./shell-path.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 reply.agentTools;\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 tools = grant.agentTools;\n let removed: { readonly name: string; readonly agents: string } | undefined;\n if (tools?.name && tools.agents?.length) {\n const profiles = await loadProfiles(paths.agents);\n const installed = await detectAgents(profiles);\n const listed = { name: tools.name, agents: tools.agents };\n await unregisterAgentTools(\n {\n profiles: profiles.filter((profile) =>\n installed.some((a) => a.id === profile.id),\n ),\n hostCommand: join(paths.root, \"bin\", \"parlor-host\"),\n env: agentEnvironment,\n },\n listed,\n );\n removed = { name: tools.name, agents: agentNames(profiles, listed) };\n }\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 return removed;\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 offerAgentTools: true,\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 const app = printable(grant.appName);\n process.stdout.write(\n `Connected to ${app} as ${printable(grant.account.email ?? grant.account.name)}.\\n${usage(app, reply.agentTools)}Not 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 if (grant.agentTools === undefined) {\n process.stdout.write(\n `To use ${app} from Claude Code and Codex here too, run \\`npx @parlor/agent-host tools ${origin}\\`.\\n`,\n );\n }\n }\n },\n});\n\n/** The two ways to use the app from this computer, for the lines after \"Connected\". */\nfunction usage(\n app: string,\n tools: { readonly name: string; readonly agents: string } | undefined,\n): string {\n const sidebar = ` - In ${app}'s agent sidebar.\\n`;\n if (!tools) return `Use your agents in ${app}'s agent sidebar.\\n`;\n return `Use it two ways:\\n${sidebar} - In ${tools.agents} on this computer: ask them to \"use ${tools.name} to ...\". They ask you before their first change in each conversation.\\n`;\n}\n\nconst tools = defineCommand({\n meta: {\n name: \"tools\",\n description:\n \"Let the coding agents on this computer use an app outside its sidebar, or stop them\",\n },\n args: {\n url: { type: \"positional\", required: true, description: \"The app's URL\" },\n off: { type: \"boolean\", description: \"Stop them; the sidebar keeps working\" },\n },\n async run({ args }) {\n const kit = await host();\n const origin = new URL(args.url).origin;\n const client = await kit.connectControl(kit.hostPaths().control);\n if (!client) {\n fail(\n `Parlor Host is not running. Run \\`npx @parlor/agent-host connect ${origin}\\` first.`,\n );\n return;\n }\n const reply = await client.send({\n op: \"agent_tools\",\n appOrigin: origin,\n on: !args.off,\n });\n client.close();\n if (!reply.ok) {\n fail(reply.error);\n return;\n }\n process.stdout.write(\n args.off\n ? `The coding agents on this computer no longer use ${origin}. Its sidebar still works.\\n`\n : reply.agentTools\n ? `${reply.agentTools.agents} can use ${origin}: ask them to \"use ${reply.agentTools.name} to ...\".\\n`\n : \"No coding agent here can take it: install Claude Code or Codex, then run this again.\\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 const origin = new URL(args.url).origin;\n let removed: Awaited<ReturnType<typeof kit.disconnectFrom>>;\n try {\n removed = await kit.disconnectFrom(origin);\n } catch (error) {\n fail(errorText(error));\n return;\n }\n process.stdout.write(\n `Disconnected this computer from ${origin}: its sidebar can no longer reach your agents here.\\n${\n removed\n ? `Removed ${removed.name} from ${removed.agents}, so they cannot change it either.\\n`\n : \"\"\n }`,\n );\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 \"agent-mode\": {\n type: \"string\",\n description:\n \"auto: the agent's own safety review decides and asks only for what it flags; ask: it asks before every action\",\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 agentMode = args[\"agent-mode\"];\n if (agentMode !== undefined) {\n if (agentMode !== \"auto\" && agentMode !== \"ask\") {\n fail(\"--agent-mode takes auto or ask.\");\n return;\n }\n change = { ...change, agentMode };\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 args: {\n app: {\n type: \"string\",\n description: \"Serve this app to a coding agent outside the sidebar\",\n },\n },\n async run({ args }) {\n const [{ runMcpProxyProcess }, { hostPaths }] = await Promise.all([\n import(\"./mcp-proxy.js\"),\n import(\"./paths.js\"),\n ]);\n await runMcpProxyProcess(\n process.env,\n args.app\n ? { appOrigin: new URL(args.app).origin, socketPath: hostPaths().proxy }\n : undefined,\n );\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 tools,\n },\n }),\n);\n"]}
|
package/dist/mcp-proxy.d.ts
CHANGED
|
@@ -9,6 +9,11 @@ import type { StdioMcpServer } from "./acp.js";
|
|
|
9
9
|
export interface McpProxy {
|
|
10
10
|
listen(socketPath: string): Promise<void>;
|
|
11
11
|
open(appServer: string, appOrigin: string): ProxySession;
|
|
12
|
+
/**
|
|
13
|
+
* Serves `parlor-host mcp-proxy --app <origin>`: a coding agent on this computer outside
|
|
14
|
+
* any turn, such as Claude Code in a terminal. `undefined` refuses the app.
|
|
15
|
+
*/
|
|
16
|
+
serveOutside(resolve: (appOrigin: string) => OutsideApp | undefined): void;
|
|
12
17
|
stopListening(): Promise<void>;
|
|
13
18
|
close(): Promise<void>;
|
|
14
19
|
}
|
|
@@ -22,12 +27,30 @@ export interface ProxySession {
|
|
|
22
27
|
end(): void;
|
|
23
28
|
dispose(): void;
|
|
24
29
|
}
|
|
30
|
+
/** An app a coding agent on this computer may use outside its sidebar. */
|
|
31
|
+
export interface OutsideApp {
|
|
32
|
+
readonly appOrigin: string;
|
|
33
|
+
readonly appName: string;
|
|
34
|
+
/** The name the user asks the agent with, its MCP server name. */
|
|
35
|
+
readonly name: string;
|
|
36
|
+
/** Whose account the agent acts as: its email, or its name. */
|
|
37
|
+
readonly account: string;
|
|
38
|
+
/** A token for `agent`'s calls, fresh enough to use now. */
|
|
39
|
+
token(agent: string): Promise<string>;
|
|
40
|
+
/** Asks on this computer, for an agent that cannot ask the user itself. */
|
|
41
|
+
askHere(question: string): Promise<boolean>;
|
|
42
|
+
}
|
|
25
43
|
export declare const NO_TURN_MESSAGE = "No turn is active: the user has not asked anything right now. Wait for their next message.";
|
|
26
44
|
export declare const DISCONNECTED_MESSAGE = "This computer no longer serves the app: it was disconnected, or Parlor Host stopped.";
|
|
27
45
|
export declare function createMcpProxy(hostBinary: string): McpProxy;
|
|
28
46
|
/**
|
|
29
|
-
* `parlor-host mcp-proxy`: stdio to the daemon socket and back.
|
|
30
|
-
*
|
|
47
|
+
* `parlor-host mcp-proxy`: stdio to the daemon socket and back. Inside a turn the
|
|
48
|
+
* environment names the session; `--app` serves an agent outside any turn. Once the daemon
|
|
49
|
+
* hangs up, every request still unanswered, and every later one, is answered with an error
|
|
50
|
+
* here.
|
|
31
51
|
*/
|
|
32
|
-
export declare function runMcpProxyProcess(env: NodeJS.ProcessEnv
|
|
52
|
+
export declare function runMcpProxyProcess(env: NodeJS.ProcessEnv, outside?: {
|
|
53
|
+
readonly appOrigin: string;
|
|
54
|
+
readonly socketPath: string;
|
|
55
|
+
}): Promise<void>;
|
|
33
56
|
//# sourceMappingURL=mcp-proxy.d.ts.map
|
package/dist/mcp-proxy.d.ts.map
CHANGED
|
@@ -1 +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;
|
|
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;;;OAGG;IACH,YAAY,CAAC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC3E,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,0EAA0E;AAC1E,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtC,2EAA2E;IAC3E,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7C;AAED,eAAO,MAAM,eAAe,+FACkE,CAAC;AAE/F,eAAO,MAAM,oBAAoB,yFACuD,CAAC;AA6bzF,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,CA8H3D;AAUD;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACpE,OAAO,CAAC,IAAI,CAAC,CAmDf"}
|