@parlor/agent-host 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +16 -2
- package/dist/acp.d.ts +165 -0
- package/dist/acp.d.ts.map +1 -0
- package/dist/acp.js +626 -0
- package/dist/acp.js.map +1 -0
- package/dist/adapter-launch.d.ts +7 -0
- package/dist/adapter-launch.d.ts.map +1 -0
- package/dist/adapter-launch.js +35 -0
- package/dist/adapter-launch.js.map +1 -0
- package/dist/agents.d.ts +32 -0
- package/dist/agents.d.ts.map +1 -0
- package/dist/agents.js +132 -0
- package/dist/agents.js.map +1 -0
- package/dist/assertion.d.ts +9 -0
- package/dist/assertion.d.ts.map +1 -0
- package/dist/assertion.js +22 -0
- package/dist/assertion.js.map +1 -0
- package/dist/control.d.ts +106 -0
- package/dist/control.d.ts.map +1 -0
- package/dist/control.js +32 -0
- package/dist/control.js.map +1 -0
- package/dist/daemon.d.ts +50 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +543 -0
- package/dist/daemon.js.map +1 -0
- package/dist/dev-host.d.ts +5 -0
- package/dist/dev-host.d.ts.map +1 -0
- package/dist/dev-host.js +29 -0
- package/dist/dev-host.js.map +1 -0
- package/dist/device-list.d.ts +6 -0
- package/dist/device-list.d.ts.map +1 -0
- package/dist/device-list.js +30 -0
- package/dist/device-list.js.map +1 -0
- package/dist/embedded.d.ts +6 -0
- package/dist/embedded.d.ts.map +1 -0
- package/dist/embedded.js +3 -0
- package/dist/embedded.js.map +1 -0
- package/dist/fold.d.ts +38 -0
- package/dist/fold.d.ts.map +1 -0
- package/dist/fold.js +165 -0
- package/dist/fold.js.map +1 -0
- package/dist/grants.d.ts +54 -0
- package/dist/grants.d.ts.map +1 -0
- package/dist/grants.js +157 -0
- package/dist/grants.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/json-file.d.ts +6 -0
- package/dist/json-file.d.ts.map +1 -0
- package/dist/json-file.js +35 -0
- package/dist/json-file.js.map +1 -0
- package/dist/lines.d.ts +5 -0
- package/dist/lines.d.ts.map +1 -0
- package/dist/lines.js +9 -0
- package/dist/lines.js.map +1 -0
- package/dist/link-device.d.ts +28 -0
- package/dist/link-device.d.ts.map +1 -0
- package/dist/link-device.js +40 -0
- package/dist/link-device.js.map +1 -0
- package/dist/link.d.ts +52 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +277 -0
- package/dist/link.js.map +1 -0
- package/dist/lock.d.ts +7 -0
- package/dist/lock.d.ts.map +1 -0
- package/dist/lock.js +105 -0
- package/dist/lock.js.map +1 -0
- package/dist/log.d.ts +3 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +18 -0
- package/dist/log.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +520 -0
- package/dist/main.js.map +1 -0
- package/dist/mcp-proxy.d.ts +33 -0
- package/dist/mcp-proxy.d.ts.map +1 -0
- package/dist/mcp-proxy.js +317 -0
- package/dist/mcp-proxy.js.map +1 -0
- package/dist/naming.d.ts +7 -0
- package/dist/naming.d.ts.map +1 -0
- package/dist/naming.js +42 -0
- package/dist/naming.js.map +1 -0
- package/dist/pairing.d.ts +68 -0
- package/dist/pairing.d.ts.map +1 -0
- package/dist/pairing.js +312 -0
- package/dist/pairing.js.map +1 -0
- package/dist/paths.d.ts +19 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +23 -0
- package/dist/paths.js.map +1 -0
- package/dist/policy.d.ts +37 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +60 -0
- package/dist/policy.js.map +1 -0
- package/dist/pool.d.ts +34 -0
- package/dist/pool.d.ts.map +1 -0
- package/dist/pool.js +112 -0
- package/dist/pool.js.map +1 -0
- package/dist/prompter.d.ts +33 -0
- package/dist/prompter.d.ts.map +1 -0
- package/dist/prompter.js +98 -0
- package/dist/prompter.js.map +1 -0
- package/dist/release-main.d.ts +2 -0
- package/dist/release-main.d.ts.map +1 -0
- package/dist/release-main.js +50 -0
- package/dist/release-main.js.map +1 -0
- package/dist/release.d.ts +22 -0
- package/dist/release.d.ts.map +1 -0
- package/dist/release.js +81 -0
- package/dist/release.js.map +1 -0
- package/dist/revoke.d.ts +10 -0
- package/dist/revoke.d.ts.map +1 -0
- package/dist/revoke.js +23 -0
- package/dist/revoke.js.map +1 -0
- package/dist/self.d.ts +7 -0
- package/dist/self.d.ts.map +1 -0
- package/dist/self.js +10 -0
- package/dist/self.js.map +1 -0
- package/dist/service.d.ts +97 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +205 -0
- package/dist/service.js.map +1 -0
- package/dist/shell-path.d.ts +10 -0
- package/dist/shell-path.d.ts.map +1 -0
- package/dist/shell-path.js +64 -0
- package/dist/shell-path.js.map +1 -0
- package/dist/skeleton-kit.d.ts +8 -0
- package/dist/skeleton-kit.d.ts.map +1 -0
- package/dist/skeleton-kit.js +143 -0
- package/dist/skeleton-kit.js.map +1 -0
- package/dist/spec-kit.d.ts +102 -0
- package/dist/spec-kit.d.ts.map +1 -0
- package/dist/spec-kit.js +372 -0
- package/dist/spec-kit.js.map +1 -0
- package/dist/testing/fake-agent.d.ts +65 -0
- package/dist/testing/fake-agent.d.ts.map +1 -0
- package/dist/testing/fake-agent.js +238 -0
- package/dist/testing/fake-agent.js.map +1 -0
- package/dist/trust.d.ts +20 -0
- package/dist/trust.d.ts.map +1 -0
- package/dist/trust.js +27 -0
- package/dist/trust.js.map +1 -0
- package/dist/turn.d.ts +32 -0
- package/dist/turn.d.ts.map +1 -0
- package/dist/turn.js +650 -0
- package/dist/turn.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +57 -3
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { printable } from "./prompter.js";
|
|
2
|
+
const day = (at) => new Date(at).toLocaleDateString("en-CA");
|
|
3
|
+
function how(device, all) {
|
|
4
|
+
if (device.via === "pairing")
|
|
5
|
+
return "approved connect on this computer";
|
|
6
|
+
if (device.via === "local")
|
|
7
|
+
return "linked on this computer";
|
|
8
|
+
const voucher = all.find((candidate) => candidate.deviceId === device.voucher);
|
|
9
|
+
return `linked from ${voucher ? printable(voucher.name) : "a removed device"}`;
|
|
10
|
+
}
|
|
11
|
+
/** The devices that can use this computer's agents for one app, one per line. */
|
|
12
|
+
export function describeDevices(appName, devices) {
|
|
13
|
+
if (devices.length === 0) {
|
|
14
|
+
return `No device can use your agents for ${printable(appName)} yet. Open the app's Agent sidebar on one to link it.\n`;
|
|
15
|
+
}
|
|
16
|
+
const lines = [...devices]
|
|
17
|
+
.sort((a, b) => a.approvedAt - b.approvedAt)
|
|
18
|
+
.map((device) => ` ${device.deviceId} ${printable(device.name)}, ${day(device.approvedAt)}, ${how(device, devices)}`);
|
|
19
|
+
return `Devices that can use your agents for ${printable(appName)}:\n${lines.join("\n")}\n`;
|
|
20
|
+
}
|
|
21
|
+
/** Unlinks a device from this computer's agents; it must be linked again to use them. */
|
|
22
|
+
export async function removeDevice(trust, appOrigin, deviceId) {
|
|
23
|
+
const device = await trust.get(appOrigin, deviceId);
|
|
24
|
+
if (!device) {
|
|
25
|
+
throw new Error(`No linked device ${deviceId}. Run \`npx @parlor/agent-host devices ${appOrigin}\` to list them.`);
|
|
26
|
+
}
|
|
27
|
+
await trust.forget(appOrigin, deviceId);
|
|
28
|
+
return device;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=device-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-list.js","sourceRoot":"","sources":["../src/device-list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAG1C,MAAM,GAAG,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAErE,SAAS,GAAG,CAAC,MAAqB,EAAE,GAA6B;IAC/D,IAAI,MAAM,CAAC,GAAG,KAAK,SAAS;QAAE,OAAO,mCAAmC,CAAC;IACzE,IAAI,MAAM,CAAC,GAAG,KAAK,OAAO;QAAE,OAAO,yBAAyB,CAAC;IAC7D,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,KAAK,MAAM,CAAC,OAAO,CAAC,CAAC;IAC/E,OAAO,eAAe,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;AACjF,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,eAAe,CAC7B,OAAe,EACf,OAAiC;IAEjC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,qCAAqC,SAAS,CAAC,OAAO,CAAC,yDAAyD,CAAC;IAC1H,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC;SACvB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC;SAC3C,GAAG,CACF,CAAC,MAAM,EAAE,EAAE,CACT,KAAK,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CACxG,CAAC;IACJ,OAAO,wCAAwC,SAAS,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAC9F,CAAC;AAED,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAiB,EACjB,SAAiB,EACjB,QAAgB;IAEhB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,oBAAoB,QAAQ,0CAA0C,SAAS,kBAAkB,CAClG,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded.d.ts","sourceRoot":"","sources":["../src/embedded.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,qBAA4B,CAAC;AAE1D,eAAO,MAAM,UAAU,WAAY;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,WAA0C,CAAC"}
|
package/dist/embedded.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"embedded.js","sourceRoot":"","sources":["../src/embedded.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAkB,CAAC;AAE1D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,MAG1B,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC"}
|
package/dist/fold.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { HostFrame, HostItemDraft } from "@parlor/chat";
|
|
2
|
+
import { type TurnId } from "@parlor/core";
|
|
3
|
+
import type { AgentUpdate } from "./acp.js";
|
|
4
|
+
interface OpenText {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly kind: "reply" | "reasoning";
|
|
7
|
+
readonly text: string;
|
|
8
|
+
}
|
|
9
|
+
interface OpenTool {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly title: string;
|
|
12
|
+
readonly app: boolean;
|
|
13
|
+
readonly name: string;
|
|
14
|
+
}
|
|
15
|
+
export interface TurnFold {
|
|
16
|
+
readonly turnId: TurnId;
|
|
17
|
+
readonly open: OpenText | undefined;
|
|
18
|
+
readonly tools: ReadonlyMap<string, OpenTool>;
|
|
19
|
+
readonly plan: Extract<AgentUpdate, {
|
|
20
|
+
kind: "plan";
|
|
21
|
+
}>["entries"] | undefined;
|
|
22
|
+
readonly nextId: number;
|
|
23
|
+
}
|
|
24
|
+
export interface FoldStep {
|
|
25
|
+
readonly fold: TurnFold;
|
|
26
|
+
/** Ephemeral, streamed now. */
|
|
27
|
+
readonly frames: readonly HostFrame[];
|
|
28
|
+
/** Finished, appended durably. */
|
|
29
|
+
readonly closed: readonly HostItemDraft[];
|
|
30
|
+
}
|
|
31
|
+
/** Pure: knows no ACP, HTTP or time. Item ids are `<turnId>.<n>`. */
|
|
32
|
+
export declare function startFold(turnId: TurnId): TurnFold;
|
|
33
|
+
/** `appServer` is the MCP server name the host gave the agent for this app. */
|
|
34
|
+
export declare function foldUpdate(fold: TurnFold, update: AgentUpdate, appServer: string): FoldStep;
|
|
35
|
+
/** Closes what is open; `interrupted` marks the last reply when the user stopped the turn. */
|
|
36
|
+
export declare function finishFold(fold: TurnFold, interrupted: boolean): FoldStep;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=fold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fold.d.ts","sourceRoot":"","sources":["../src/fold.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAqB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,UAAU,QAAQ;IAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,WAAW,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,UAAU,QAAQ;IAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC9C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAC7E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,+BAA+B;IAC/B,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,kCAAkC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;CAC3C;AA+ID,qEAAqE;AACrE,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAElD;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CACxB,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,GAChB,QAAQ,CA4BV;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,GAAG,QAAQ,CAazE"}
|
package/dist/fold.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { asId } from "@parlor/core";
|
|
2
|
+
const MAX_DETAIL_CHARS = 4_000;
|
|
3
|
+
const itemId = (id) => asId("item", id);
|
|
4
|
+
const entriesOf = (entries) => entries.map((entry) => ({ ...entry }));
|
|
5
|
+
const unchanged = (fold) => ({ fold, frames: [], closed: [] });
|
|
6
|
+
const planItemOf = (fold) => itemId(`${fold.turnId}.0`);
|
|
7
|
+
function allocate(fold) {
|
|
8
|
+
return {
|
|
9
|
+
id: `${fold.turnId}.${fold.nextId}`,
|
|
10
|
+
fold: { ...fold, nextId: fold.nextId + 1 },
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function closeText(fold, interrupted = false) {
|
|
14
|
+
const open = fold.open;
|
|
15
|
+
if (!open)
|
|
16
|
+
return unchanged(fold);
|
|
17
|
+
const closed = open.kind === "reply"
|
|
18
|
+
? {
|
|
19
|
+
id: itemId(open.id),
|
|
20
|
+
kind: "reply",
|
|
21
|
+
body: {
|
|
22
|
+
text: open.text,
|
|
23
|
+
...(interrupted ? { interrupted: true } : {}),
|
|
24
|
+
},
|
|
25
|
+
}
|
|
26
|
+
: { id: itemId(open.id), kind: "reasoning", body: { text: open.text } };
|
|
27
|
+
return { fold: { ...fold, open: undefined }, frames: [], closed: [closed] };
|
|
28
|
+
}
|
|
29
|
+
function toolFrame(tool, status) {
|
|
30
|
+
return {
|
|
31
|
+
type: "item",
|
|
32
|
+
item: { id: itemId(tool.id), kind: "tool", title: tool.title, status },
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function toolDraft(tool, status, detail) {
|
|
36
|
+
return {
|
|
37
|
+
id: itemId(tool.id),
|
|
38
|
+
kind: "tool",
|
|
39
|
+
body: {
|
|
40
|
+
title: tool.title,
|
|
41
|
+
tool: { kind: tool.app ? "app" : "local", name: tool.name },
|
|
42
|
+
status,
|
|
43
|
+
...(detail ? { detail: detail.slice(0, MAX_DETAIL_CHARS) } : {}),
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function withTool(fold, toolCallId, tool) {
|
|
48
|
+
const tools = new Map(fold.tools);
|
|
49
|
+
if (tool)
|
|
50
|
+
tools.set(toolCallId, tool);
|
|
51
|
+
else
|
|
52
|
+
tools.delete(toolCallId);
|
|
53
|
+
return { ...fold, tools };
|
|
54
|
+
}
|
|
55
|
+
function appendText(fold, kind, text) {
|
|
56
|
+
if (text === "")
|
|
57
|
+
return unchanged(fold);
|
|
58
|
+
const switched = fold.open && fold.open.kind !== kind ? closeText(fold) : unchanged(fold);
|
|
59
|
+
let current = switched.fold;
|
|
60
|
+
let open = current.open;
|
|
61
|
+
if (!open) {
|
|
62
|
+
const next = allocate(current);
|
|
63
|
+
current = next.fold;
|
|
64
|
+
open = { id: next.id, kind, text: "" };
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
fold: { ...current, open: { ...open, text: open.text + text } },
|
|
68
|
+
frames: [
|
|
69
|
+
{ type: "delta", itemId: itemId(open.id), kind, offset: open.text.length, text },
|
|
70
|
+
],
|
|
71
|
+
closed: switched.closed,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function startTool(fold, update, appServer) {
|
|
75
|
+
const known = fold.tools.get(update.toolCallId);
|
|
76
|
+
if (known) {
|
|
77
|
+
const tool = { ...known, title: update.title || known.title };
|
|
78
|
+
return {
|
|
79
|
+
fold: withTool(fold, update.toolCallId, tool),
|
|
80
|
+
frames: [toolFrame(tool, "pending")],
|
|
81
|
+
closed: [],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const text = closeText(fold);
|
|
85
|
+
const next = allocate(text.fold);
|
|
86
|
+
const tool = {
|
|
87
|
+
id: next.id,
|
|
88
|
+
title: update.title,
|
|
89
|
+
app: update.mcp !== undefined && update.mcp.server === appServer,
|
|
90
|
+
name: update.mcp?.tool ?? update.toolKind,
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
fold: withTool(next.fold, update.toolCallId, tool),
|
|
94
|
+
frames: [toolFrame(tool, "pending")],
|
|
95
|
+
closed: text.closed,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
function updateTool(fold, update) {
|
|
99
|
+
const known = fold.tools.get(update.toolCallId);
|
|
100
|
+
if (!known)
|
|
101
|
+
return unchanged(fold);
|
|
102
|
+
const tool = { ...known, title: update.title || known.title };
|
|
103
|
+
if (update.status === "completed" || update.status === "failed") {
|
|
104
|
+
return {
|
|
105
|
+
fold: withTool(fold, update.toolCallId, undefined),
|
|
106
|
+
frames: [],
|
|
107
|
+
closed: [
|
|
108
|
+
toolDraft(tool, update.status === "completed" ? "done" : "failed", update.detail),
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
fold: withTool(fold, update.toolCallId, tool),
|
|
114
|
+
frames: [toolFrame(tool, update.status === "in_progress" ? "running" : "pending")],
|
|
115
|
+
closed: [],
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Pure: knows no ACP, HTTP or time. Item ids are `<turnId>.<n>`. */
|
|
119
|
+
export function startFold(turnId) {
|
|
120
|
+
return { turnId, open: undefined, tools: new Map(), plan: undefined, nextId: 1 };
|
|
121
|
+
}
|
|
122
|
+
/** `appServer` is the MCP server name the host gave the agent for this app. */
|
|
123
|
+
export function foldUpdate(fold, update, appServer) {
|
|
124
|
+
switch (update.kind) {
|
|
125
|
+
case "text":
|
|
126
|
+
return appendText(fold, "reply", update.text);
|
|
127
|
+
case "thought":
|
|
128
|
+
return appendText(fold, "reasoning", update.text);
|
|
129
|
+
case "tool_start":
|
|
130
|
+
return startTool(fold, update, appServer);
|
|
131
|
+
case "tool_update":
|
|
132
|
+
return updateTool(fold, update);
|
|
133
|
+
case "plan":
|
|
134
|
+
return {
|
|
135
|
+
fold: { ...fold, plan: update.entries },
|
|
136
|
+
frames: [
|
|
137
|
+
{
|
|
138
|
+
type: "item",
|
|
139
|
+
item: {
|
|
140
|
+
id: planItemOf(fold),
|
|
141
|
+
kind: "plan",
|
|
142
|
+
entries: entriesOf(update.entries),
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
closed: [],
|
|
147
|
+
};
|
|
148
|
+
case "mode":
|
|
149
|
+
return unchanged(fold);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Closes what is open; `interrupted` marks the last reply when the user stopped the turn. */
|
|
153
|
+
export function finishFold(fold, interrupted) {
|
|
154
|
+
const text = closeText(fold, interrupted);
|
|
155
|
+
const tools = [...fold.tools.values()].map((tool) => toolDraft(tool, interrupted ? "cancelled" : "done", undefined));
|
|
156
|
+
const plan = fold.plan
|
|
157
|
+
? [{ id: planItemOf(fold), kind: "plan", body: { entries: entriesOf(fold.plan) } }]
|
|
158
|
+
: [];
|
|
159
|
+
return {
|
|
160
|
+
fold: { ...text.fold, tools: new Map(), plan: undefined },
|
|
161
|
+
frames: [],
|
|
162
|
+
closed: [...text.closed, ...tools, ...plan],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=fold.js.map
|
package/dist/fold.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fold.js","sourceRoot":"","sources":["../src/fold.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAA4B,MAAM,cAAc,CAAC;AAiC9D,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAI/B,MAAM,MAAM,GAAG,CAAC,EAAU,EAAU,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAExD,MAAM,SAAS,GAAG,CAChB,OAA0D,EACzB,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;AAE7E,MAAM,SAAS,GAAG,CAAC,IAAc,EAAY,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;AAEnF,MAAM,UAAU,GAAG,CAAC,IAAc,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;AAElE,SAAS,QAAQ,CAAC,IAAc;IAC9B,OAAO;QACL,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,EAAE;QACnC,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;KAC3C,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAC,IAAc,EAAE,WAAW,GAAG,KAAK;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;IACvB,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,MAAM,GACV,IAAI,CAAC,IAAI,KAAK,OAAO;QACnB,CAAC,CAAC;YACE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE;gBACJ,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvD;SACF;QACH,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;IAC5E,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;AAC9E,CAAC;AAED,SAAS,SAAS,CAAC,IAAc,EAAE,MAAuB;IACxD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE;KACvE,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAChB,IAAc,EACd,MAAsC,EACtC,MAA0B;IAE1B,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACnB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE;YACJ,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;YAC3D,MAAM;YACN,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjE;KACF,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,IAAc,EAAE,UAAkB,EAAE,IAA0B;IAC9E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,IAAI;QAAE,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;;QACjC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC9B,OAAO,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED,SAAS,UAAU,CAAC,IAAc,EAAE,IAAsB,EAAE,IAAY;IACtE,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GACZ,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3E,IAAI,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC5B,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IACxB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/B,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;QACpB,IAAI,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACzC,CAAC;IACD,OAAO;QACL,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,IAAI,EAAE,EAAE;QAC/D,MAAM,EAAE;YACN,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE;SACjF;QACD,MAAM,EAAE,QAAQ,CAAC,MAAM;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAChB,IAAc,EACd,MAAoD,EACpD,SAAiB;IAEjB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAC9D,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;YAC7C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACpC,MAAM,EAAE,EAAE;SACX,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,IAAI,GAAa;QACrB,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,GAAG,EAAE,MAAM,CAAC,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,GAAG,CAAC,MAAM,KAAK,SAAS;QAChE,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,IAAI,IAAI,MAAM,CAAC,QAAQ;KAC1C,CAAC;IACF,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;QAClD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACpC,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CACjB,IAAc,EACd,MAAqD;IAErD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;IAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,CAAC;YAClD,MAAM,EAAE,EAAE;YACV,MAAM,EAAE;gBACN,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC;aAClF;SACF,CAAC;IACJ,CAAC;IACD,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;QAC7C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAClF,MAAM,EAAE,EAAE;KACX,CAAC;AACJ,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AACnF,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CACxB,IAAc,EACd,MAAmB,EACnB,SAAiB;IAEjB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,MAAM;YACT,OAAO,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAChD,KAAK,SAAS;YACZ,OAAO,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACpD,KAAK,YAAY;YACf,OAAO,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC;QAC5C,KAAK,aAAa;YAChB,OAAO,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAClC,KAAK,MAAM;YACT,OAAO;gBACL,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE;gBACvC,MAAM,EAAE;oBACN;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;4BACJ,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC;4BACpB,IAAI,EAAE,MAAM;4BACZ,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC;yBACnC;qBACF;iBACF;gBACD,MAAM,EAAE,EAAE;aACX,CAAC;QACJ,KAAK,MAAM;YACT,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,UAAU,CAAC,IAAc,EAAE,WAAoB;IAC7D,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAClD,SAAS,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAC/D,CAAC;IACF,MAAM,IAAI,GAAoB,IAAI,CAAC,IAAI;QACrC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACnF,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;QACL,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACzD,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;KAC5C,CAAC;AACJ,CAAC"}
|
package/dist/grants.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { AccountSummary } from "@parlor/auth";
|
|
2
|
+
import type { GrantId, HostId } from "@parlor/core";
|
|
3
|
+
/** One app this computer is connected to. Its key lives in `HostKeys`, never here. */
|
|
4
|
+
export interface AppGrant {
|
|
5
|
+
readonly appOrigin: string;
|
|
6
|
+
readonly appName: string;
|
|
7
|
+
readonly grantId: GrantId;
|
|
8
|
+
readonly hostId: HostId;
|
|
9
|
+
readonly account: AccountSummary;
|
|
10
|
+
/** The agents' working directory for this app; only the user changes it, here. */
|
|
11
|
+
readonly workspace: string;
|
|
12
|
+
readonly createdAt: number;
|
|
13
|
+
/** A `parlor dev` grant: in memory only. */
|
|
14
|
+
readonly dev?: true | undefined;
|
|
15
|
+
/** Refused here but not yet revoked by the app: kept only to retry the revoke, never served. */
|
|
16
|
+
readonly declined?: true | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Handed only to the browser that approved `connect`, through the loopback redirect; that
|
|
19
|
+
* browser proves it on its first prompt and is trusted without asking, then this is dropped.
|
|
20
|
+
*/
|
|
21
|
+
readonly pairingSecret?: string | undefined;
|
|
22
|
+
}
|
|
23
|
+
/** One key per app grant in the OS keychain; the server holds only its public half. */
|
|
24
|
+
export interface HostKeys {
|
|
25
|
+
/** A pairing's new key pair, kept only once the pairing completes. */
|
|
26
|
+
create(appOrigin: string): Promise<HostKeyPair>;
|
|
27
|
+
/** A fresh `ParlorHost` assertion for one request. */
|
|
28
|
+
assert(appOrigin: string, request: {
|
|
29
|
+
readonly method: "GET" | "POST";
|
|
30
|
+
readonly url: string;
|
|
31
|
+
}): Promise<string>;
|
|
32
|
+
remove(appOrigin: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
export interface HostKeyPair {
|
|
35
|
+
readonly publicKey: JsonWebKey;
|
|
36
|
+
/** RFC 7638, the assertion's `kid`. */
|
|
37
|
+
readonly thumbprint: string;
|
|
38
|
+
sign(payload: Uint8Array): Promise<string>;
|
|
39
|
+
/** Binds the key to the grant the pairing produced and stores it. */
|
|
40
|
+
keep(grantId: GrantId): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
export interface GrantStore {
|
|
43
|
+
list(): Promise<readonly AppGrant[]>;
|
|
44
|
+
get(appOrigin: string): Promise<AppGrant | undefined>;
|
|
45
|
+
save(grant: AppGrant): Promise<void>;
|
|
46
|
+
remove(appOrigin: string): Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
/** `~/.parlor/host/grants.json`, 0600, written atomically. */
|
|
49
|
+
export declare function fileGrantStore(file: string): GrantStore;
|
|
50
|
+
/** The macOS Keychain; other platforms are refused before pairing (`unsupportedHostPlatform`). */
|
|
51
|
+
export declare function keychainHostKeys(service: string): HostKeys;
|
|
52
|
+
/** For `parlor-host dev`: one dev host token for every request, nothing on disk. */
|
|
53
|
+
export declare function devHostKeys(hostToken: string): HostKeys;
|
|
54
|
+
//# sourceMappingURL=grants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAKpD,sFAAsF;AACtF,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IAChC,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7C;AAED,uFAAuF;AACvF,MAAM,WAAW,QAAQ;IACvB,sEAAsE;IACtE,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAChD,sDAAsD;IACtD,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GACjE,OAAO,CAAC,MAAM,CAAC,CAAC;IACnB,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,uCAAuC;IACvC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,qEAAqE;IACrE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,IAAI,OAAO,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC;IACrC,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IACtD,IAAI,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1C;AAED,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAcvD;AA0JD,kGAAkG;AAClG,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAE1D;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,QAAQ,CAMvD"}
|
package/dist/grants.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
import { hostAssertion } from "./assertion.js";
|
|
5
|
+
import { jsonFile } from "./json-file.js";
|
|
6
|
+
/** `~/.parlor/host/grants.json`, 0600, written atomically. */
|
|
7
|
+
export function fileGrantStore(file) {
|
|
8
|
+
const grants = jsonFile(file);
|
|
9
|
+
return {
|
|
10
|
+
list: async () => Object.values(await grants.read()),
|
|
11
|
+
get: async (appOrigin) => (await grants.read())[appOrigin],
|
|
12
|
+
save: (grant) => grants.change((all) => {
|
|
13
|
+
all[grant.appOrigin] = grant;
|
|
14
|
+
}),
|
|
15
|
+
remove: (appOrigin) => grants.change((all) => {
|
|
16
|
+
delete all[appOrigin];
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const EC_P256 = { name: "ECDSA", namedCurve: "P-256" };
|
|
21
|
+
const ES256 = { name: "ECDSA", hash: "SHA-256" };
|
|
22
|
+
const ORIGIN = /^https?:\/\/[A-Za-z0-9.\-[\]:]+$/;
|
|
23
|
+
function thumbprintOf({ crv, kty, x, y }) {
|
|
24
|
+
return createHash("sha256")
|
|
25
|
+
.update(JSON.stringify({ crv, kty, x, y }))
|
|
26
|
+
.digest("base64url");
|
|
27
|
+
}
|
|
28
|
+
const signer = (key) => async (payload) => Buffer.from(await crypto.subtle.sign(ES256, key, new Uint8Array(payload))).toString("base64url");
|
|
29
|
+
function keysIn(secrets) {
|
|
30
|
+
const loaded = new Map();
|
|
31
|
+
const load = (appOrigin) => {
|
|
32
|
+
let entry = loaded.get(appOrigin);
|
|
33
|
+
if (!entry) {
|
|
34
|
+
entry = (async () => {
|
|
35
|
+
const secret = await secrets.read(appOrigin);
|
|
36
|
+
if (secret === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
const stored = JSON.parse(Buffer.from(secret, "base64url").toString("utf8"));
|
|
39
|
+
const key = await crypto.subtle.importKey("jwk", stored.jwk, EC_P256, false, [
|
|
40
|
+
"sign",
|
|
41
|
+
]);
|
|
42
|
+
return { key, kid: stored.kid, grantId: stored.grantId };
|
|
43
|
+
})();
|
|
44
|
+
entry.catch(() => loaded.delete(appOrigin));
|
|
45
|
+
loaded.set(appOrigin, entry);
|
|
46
|
+
}
|
|
47
|
+
return entry;
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
async create(appOrigin) {
|
|
51
|
+
const pair = await crypto.subtle.generateKey(EC_P256, true, ["sign", "verify"]);
|
|
52
|
+
const exported = await crypto.subtle.exportKey("jwk", pair.publicKey);
|
|
53
|
+
const publicKey = {
|
|
54
|
+
kty: exported.kty,
|
|
55
|
+
crv: exported.crv,
|
|
56
|
+
x: exported.x,
|
|
57
|
+
y: exported.y,
|
|
58
|
+
};
|
|
59
|
+
const thumbprint = thumbprintOf(publicKey);
|
|
60
|
+
return {
|
|
61
|
+
publicKey,
|
|
62
|
+
thumbprint,
|
|
63
|
+
sign: signer(pair.privateKey),
|
|
64
|
+
keep: async (grantId) => {
|
|
65
|
+
const jwk = await crypto.subtle.exportKey("jwk", pair.privateKey);
|
|
66
|
+
const stored = { jwk, kid: thumbprint, grantId };
|
|
67
|
+
await secrets.write(appOrigin, Buffer.from(JSON.stringify(stored)).toString("base64url"));
|
|
68
|
+
loaded.delete(appOrigin);
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
async assert(appOrigin, request) {
|
|
73
|
+
const key = await load(appOrigin);
|
|
74
|
+
if (!key)
|
|
75
|
+
throw new Error(`This computer holds no key for ${appOrigin}.`);
|
|
76
|
+
return hostAssertion(signer(key.key), key, request);
|
|
77
|
+
},
|
|
78
|
+
async remove(appOrigin) {
|
|
79
|
+
loaded.delete(appOrigin);
|
|
80
|
+
await secrets.remove(appOrigin);
|
|
81
|
+
},
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const run = promisify(execFile);
|
|
85
|
+
const NOT_FOUND = 44;
|
|
86
|
+
function macKeychain(service) {
|
|
87
|
+
const checked = (account) => {
|
|
88
|
+
if (!ORIGIN.test(account))
|
|
89
|
+
throw new Error(`${account} is not an app origin.`);
|
|
90
|
+
return account;
|
|
91
|
+
};
|
|
92
|
+
return {
|
|
93
|
+
async read(account) {
|
|
94
|
+
try {
|
|
95
|
+
const { stdout } = await run("security", [
|
|
96
|
+
"find-generic-password",
|
|
97
|
+
"-s",
|
|
98
|
+
service,
|
|
99
|
+
"-a",
|
|
100
|
+
checked(account),
|
|
101
|
+
"-w",
|
|
102
|
+
]);
|
|
103
|
+
return stdout.trim();
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
if (error.code === NOT_FOUND)
|
|
107
|
+
return undefined;
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
async write(account, secret) {
|
|
112
|
+
// Through `security -i` on stdin, so the private key never shows in a process list.
|
|
113
|
+
const command = `add-generic-password -U -s ${service} -a ${checked(account)} -w ${secret}\n`;
|
|
114
|
+
await new Promise((resolve, reject) => {
|
|
115
|
+
const child = spawn("security", ["-i"], { stdio: ["pipe", "ignore", "pipe"] });
|
|
116
|
+
let stderr = "";
|
|
117
|
+
child.stderr.on("data", (chunk) => (stderr += chunk.toString()));
|
|
118
|
+
child.once("error", reject);
|
|
119
|
+
child.once("exit", (code) => code === 0 && stderr.trim() === ""
|
|
120
|
+
? resolve()
|
|
121
|
+
: reject(new Error(`The Keychain refused the key: ${stderr.trim() || code}`)));
|
|
122
|
+
child.stdin.end(command);
|
|
123
|
+
});
|
|
124
|
+
if ((await this.read(account)) !== secret) {
|
|
125
|
+
throw new Error("The Keychain did not keep the key.");
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
async remove(account) {
|
|
129
|
+
try {
|
|
130
|
+
await run("security", [
|
|
131
|
+
"delete-generic-password",
|
|
132
|
+
"-s",
|
|
133
|
+
service,
|
|
134
|
+
"-a",
|
|
135
|
+
checked(account),
|
|
136
|
+
]);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
if (error.code !== NOT_FOUND)
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
/** The macOS Keychain; other platforms are refused before pairing (`unsupportedHostPlatform`). */
|
|
146
|
+
export function keychainHostKeys(service) {
|
|
147
|
+
return keysIn(macKeychain(service));
|
|
148
|
+
}
|
|
149
|
+
/** For `parlor-host dev`: one dev host token for every request, nothing on disk. */
|
|
150
|
+
export function devHostKeys(hostToken) {
|
|
151
|
+
return {
|
|
152
|
+
create: () => Promise.reject(new Error("A parlor dev server needs no pairing.")),
|
|
153
|
+
assert: async () => hostToken,
|
|
154
|
+
remove: async () => undefined,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=grants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grants.js","sourceRoot":"","sources":["../src/grants.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { type AcpAgentHandlers, type AcpStdio, acpLauncher, type AgentAsk, type AgentAskAnswer, type AgentCapabilities, type AgentConnection, type AgentExit, type AgentLauncher, type AgentModes, type AgentSession, type AgentUpdate, type AskEffect, type LaunchOptions, type McpToolRef, type OpenSessionInput, type PromptBlock, serveAcpAgent, SessionRefused, type StdioMcpServer, type StopReason, type ToolKind, type TurnHandlers, } from "./acp.js";
|
|
2
|
+
export { AGENT_PROFILES, type AgentLaunch, type AgentProfile, DETECT_TIMEOUT_MS, detectAgents, loadProfiles, } from "./agents.js";
|
|
3
|
+
export { connectControl, type ControlClient, type ControlFailure, type ControlOp, CONTROL_PROTOCOL, type ControlRequest, type ControlResponse, } from "./control.js";
|
|
4
|
+
export { createHostDaemon, type DaemonDeps, type HostDaemon } from "./daemon.js";
|
|
5
|
+
export { finishFold, type FoldStep, foldUpdate, startFold, type TurnFold, } from "./fold.js";
|
|
6
|
+
export { type AppGrant, devHostKeys, fileGrantStore, type GrantStore, type HostKeyPair, type HostKeys, keychainHostKeys, } from "./grants.js";
|
|
7
|
+
export { ACTIVE_POLL_MS, type AppLink, type AppLinkDeps, createAppLink, type HostApi, IDLE_POLL_MS, RECONNECT_MAX_MS, } from "./link.js";
|
|
8
|
+
export { createMcpProxy, type McpProxy, NO_TURN_MESSAGE, type ProxySession, runMcpProxyProcess, } from "./mcp-proxy.js";
|
|
9
|
+
export { pair, PAIRING_TIMEOUT_MS, type PairingChannel, type PairInput, type PairOutcome, } from "./pairing.js";
|
|
10
|
+
export { type HostPaths, hostPaths } from "./paths.js";
|
|
11
|
+
export { approvalFor, changePolicy, DEFAULT_POLICY, DEV_POLICY, isAppTool, loadPolicy, type RemotePolicy, } from "./policy.js";
|
|
12
|
+
export { createSessionPool, type LiveSession, type PooledGrant, type SessionPool, } from "./pool.js";
|
|
13
|
+
export { type LocalPrompter, macDialogPrompter, terminalPrompter } from "./prompter.js";
|
|
14
|
+
export { type AdoptOutcome, ensureService, type HostRelease, installLoginItem, type ServiceClient, } from "./service.js";
|
|
15
|
+
export { fileTrustStore, type TrustedDevice, type TrustStore } from "./trust.js";
|
|
16
|
+
export { PROMPT_MAX_AGE_MS, runTurn, type TurnDeps } from "./turn.js";
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EACb,WAAW,EACX,KAAK,QAAQ,EACb,KAAK,cAAc,EACnB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,aAAa,EACb,cAAc,EACd,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,QAAQ,EACb,KAAK,YAAY,GAClB,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,gBAAgB,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EACL,UAAU,EACV,KAAK,QAAQ,EACb,UAAU,EACV,SAAS,EACT,KAAK,QAAQ,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,KAAK,QAAQ,EACb,WAAW,EACX,cAAc,EACd,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,aAAa,EACb,KAAK,OAAO,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,KAAK,QAAQ,EACb,eAAe,EACf,KAAK,YAAY,EACjB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,IAAI,EACJ,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,WAAW,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EACL,WAAW,EACX,YAAY,EACZ,cAAc,EACd,UAAU,EACV,SAAS,EACT,UAAU,EACV,KAAK,YAAY,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,aAAa,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACxF,OAAO,EACL,KAAK,YAAY,EACjB,aAAa,EACb,KAAK,WAAW,EAChB,gBAAgB,EAChB,KAAK,aAAa,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { acpLauncher, serveAcpAgent, SessionRefused, } from "./acp.js";
|
|
2
|
+
export { AGENT_PROFILES, DETECT_TIMEOUT_MS, detectAgents, loadProfiles, } from "./agents.js";
|
|
3
|
+
export { connectControl, CONTROL_PROTOCOL, } from "./control.js";
|
|
4
|
+
export { createHostDaemon } from "./daemon.js";
|
|
5
|
+
export { finishFold, foldUpdate, startFold, } from "./fold.js";
|
|
6
|
+
export { devHostKeys, fileGrantStore, keychainHostKeys, } from "./grants.js";
|
|
7
|
+
export { ACTIVE_POLL_MS, createAppLink, IDLE_POLL_MS, RECONNECT_MAX_MS, } from "./link.js";
|
|
8
|
+
export { createMcpProxy, NO_TURN_MESSAGE, runMcpProxyProcess, } from "./mcp-proxy.js";
|
|
9
|
+
export { pair, PAIRING_TIMEOUT_MS, } from "./pairing.js";
|
|
10
|
+
export { hostPaths } from "./paths.js";
|
|
11
|
+
export { approvalFor, changePolicy, DEFAULT_POLICY, DEV_POLICY, isAppTool, loadPolicy, } from "./policy.js";
|
|
12
|
+
export { createSessionPool, } from "./pool.js";
|
|
13
|
+
export { macDialogPrompter, terminalPrompter } from "./prompter.js";
|
|
14
|
+
export { ensureService, installLoginItem, } from "./service.js";
|
|
15
|
+
export { fileTrustStore } from "./trust.js";
|
|
16
|
+
export { PROMPT_MAX_AGE_MS, runTurn } from "./turn.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,WAAW,EAeX,aAAa,EACb,cAAc,GAKf,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,cAAc,EAGd,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EAId,gBAAgB,GAGjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAoC,MAAM,aAAa,CAAC;AACjF,OAAO,EACL,UAAU,EAEV,UAAU,EACV,SAAS,GAEV,MAAM,WAAW,CAAC;AACnB,OAAO,EAEL,WAAW,EACX,cAAc,EAId,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EAGd,aAAa,EAEb,YAAY,EACZ,gBAAgB,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EAEd,eAAe,EAEf,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,IAAI,EACJ,kBAAkB,GAInB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAkB,SAAS,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EACL,WAAW,EACX,YAAY,EACZ,cAAc,EACd,UAAU,EACV,SAAS,EACT,UAAU,GAEX,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,GAIlB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAsB,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACxF,OAAO,EAEL,aAAa,EAEb,gBAAgB,GAEjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAuC,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,OAAO,EAAiB,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-file.d.ts","sourceRoot":"","sources":["../src/json-file.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,QAAQ,CAAC,CAAC,SAAS,MAAM;IACxC,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;IACnB,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjD;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CA4BpE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { withFileLock } from "./lock.js";
|
|
4
|
+
export function jsonFile(file) {
|
|
5
|
+
let writing = Promise.resolve();
|
|
6
|
+
const read = async () => {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(await readFile(file, "utf8"));
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
if (error.code === "ENOENT")
|
|
12
|
+
return {};
|
|
13
|
+
throw error;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
return {
|
|
17
|
+
read,
|
|
18
|
+
change(edit) {
|
|
19
|
+
const next = writing.then(async () => {
|
|
20
|
+
await mkdir(dirname(file), { recursive: true, mode: 0o700 });
|
|
21
|
+
await withFileLock(`${file}.lock`, async () => {
|
|
22
|
+
const value = await read();
|
|
23
|
+
edit(value);
|
|
24
|
+
const staged = `${file}.${process.pid}.tmp`;
|
|
25
|
+
await writeFile(staged, `${JSON.stringify(value, null, 2)}\n`, { mode: 0o600 });
|
|
26
|
+
await chmod(staged, 0o600);
|
|
27
|
+
await rename(staged, file);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
writing = next.catch(() => undefined);
|
|
31
|
+
return next;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=json-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-file.js","sourceRoot":"","sources":["../src/json-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAOzC,MAAM,UAAU,QAAQ,CAAmB,IAAY;IACrD,IAAI,OAAO,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAClD,MAAM,IAAI,GAAG,KAAK,IAAgB,EAAE;QAClC,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAM,CAAC;QACvD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,EAAO,CAAC;YACvE,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC,CAAC;IACF,OAAO;QACL,IAAI;QACJ,MAAM,CAAC,IAAI;YACT,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBACnC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC7D,MAAM,YAAY,CAAC,GAAG,IAAI,OAAO,EAAE,KAAK,IAAI,EAAE;oBAC5C,MAAM,KAAK,GAAG,MAAM,IAAI,EAAE,CAAC;oBAC3B,IAAI,CAAC,KAAK,CAAC,CAAC;oBACZ,MAAM,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;oBAC5C,MAAM,SAAS,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;oBAChF,MAAM,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;oBAC3B,MAAM,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC7B,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;YACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/lines.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Interface } from "node:readline";
|
|
2
|
+
import type { Readable } from "node:stream";
|
|
3
|
+
/** Newline-delimited input; a broken stream ends it instead of throwing from readline. */
|
|
4
|
+
export declare function onLines(input: Readable, handle: (line: string) => void): Interface;
|
|
5
|
+
//# sourceMappingURL=lines.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lines.d.ts","sourceRoot":"","sources":["../src/lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,0FAA0F;AAC1F,wBAAgB,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,SAAS,CAKlF"}
|
package/dist/lines.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
/** Newline-delimited input; a broken stream ends it instead of throwing from readline. */
|
|
3
|
+
export function onLines(input, handle) {
|
|
4
|
+
const lines = createInterface({ input, crlfDelay: Infinity });
|
|
5
|
+
lines.on("line", handle);
|
|
6
|
+
lines.on("error", () => input.destroy());
|
|
7
|
+
return lines;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=lines.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lines.js","sourceRoot":"","sources":["../src/lines.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkB,MAAM,eAAe,CAAC;AAGhE,0FAA0F;AAC1F,MAAM,UAAU,OAAO,CAAC,KAAe,EAAE,MAA8B;IACrE,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9D,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC;AACf,CAAC"}
|