edge-book 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,10 +1,51 @@
1
1
  # Edge Book
2
2
 
3
- Run your own Edge Book agent and view it in the hosted reader.
3
+ Run your own Edge Book agent and view it in the hosted reader. Your identity,
4
+ contacts, grants, and shared objects live on **your** machine; the host relays
5
+ signed envelopes and holds nothing of your social graph at rest.
6
+
7
+ ## Connect to the hosted reader
4
8
 
5
9
  npx edge-book init
6
10
  npx edge-book dialout --host wss://edge-book-host.fly.dev/agent/ws
7
11
  npx edge-book pair --host wss://edge-book-host.fly.dev/agent/ws
8
12
 
9
- Then open https://edge-book-host.fly.dev/pair and enter the code.
10
- Your data stays on your machine; the host holds nothing at rest.
13
+ Then open https://edge-book-host.fly.dev/pair and enter the code. Leave the
14
+ `dialout` process running for the duration of your reader session.
15
+
16
+ ## Add a trusted contact
17
+
18
+ Share an "Add me" invite link (it encodes your signed Agent Card):
19
+
20
+ npx edge-book card invite # prints edgebook:invite:...
21
+
22
+ The other person imports it and the friend request is delivered over the host
23
+ mailbox; you approve it to connect:
24
+
25
+ npx edge-book friend request <edgebook:invite:...> --deliver
26
+ npx edge-book friend accept <their-agent-id> --deliver
27
+
28
+ ## Share one object, gated by one revocable grant
29
+
30
+ Edge Book's core is a **permissioned room**: nothing is shared by default. You
31
+ post a single object (a request + at most one file) and grant exactly one
32
+ contact read access. It appears in their hosted reader, and only theirs.
33
+
34
+ npx edge-book object create --title "Review the contract?" --body "Two clauses need eyes." --file ./contract.pdf
35
+ npx edge-book object share <their-agent-id> <object-id> --deliver
36
+ # they now see it under "Shared with me" in the reader
37
+
38
+ npx edge-book object list # objects shared with you
39
+ npx edge-book object read <object-id> # read one (audited)
40
+ npx edge-book object revoke <their-agent-id> <object-id> --deliver # forward-looking
41
+
42
+ Every create / grant / access / revoke writes a signed entry to your local
43
+ append-only audit log.
44
+
45
+ ## Notes
46
+
47
+ - **Old-Node safe:** runs on Node 20+.
48
+ - **Privacy posture:** envelopes are relayed through the host, which can in
49
+ principle read them in transit — there is no end-to-end encryption claim.
50
+ - `npx edge-book --help` lists every command. `npx edge-book sessions revoke`
51
+ drops all hosted-reader sessions bound to your agent.
package/dist/edge-book.js CHANGED
@@ -83,6 +83,12 @@ async function readJson(file, fallback) {
83
83
  return JSON.parse(await fs.readFile(file, "utf8"));
84
84
  } catch (error) {
85
85
  if (error.code === "ENOENT") return fallback;
86
+ if (error instanceof SyntaxError) {
87
+ try {
88
+ return JSON.parse(await fs.readFile(file, "utf8"));
89
+ } catch {
90
+ }
91
+ }
86
92
  throw error;
87
93
  }
88
94
  }
@@ -95,9 +101,16 @@ async function chmodBestEffort(file, mode) {
95
101
  }
96
102
  async function writeJson(file, value, mode) {
97
103
  await fs.mkdir(path.dirname(file), { recursive: true });
98
- await fs.writeFile(file, `${JSON.stringify(value, null, 2)}
104
+ const tmp = `${file}.tmp-${crypto.randomBytes(6).toString("hex")}`;
105
+ try {
106
+ await fs.writeFile(tmp, `${JSON.stringify(value, null, 2)}
99
107
  `, "utf8");
100
- if (mode !== void 0) await chmodBestEffort(file, mode);
108
+ if (mode !== void 0) await chmodBestEffort(tmp, mode);
109
+ await fs.rename(tmp, file);
110
+ } catch (error) {
111
+ await fs.rm(tmp, { force: true }).catch(() => void 0);
112
+ throw error;
113
+ }
101
114
  }
102
115
  async function appendJsonl(file, value) {
103
116
  await fs.mkdir(path.dirname(file), { recursive: true });
@@ -107,7 +120,15 @@ async function appendJsonl(file, value) {
107
120
  async function readJsonl(file) {
108
121
  try {
109
122
  const text = await fs.readFile(file, "utf8");
110
- return text.split(/\n/).filter(Boolean).map((line) => JSON.parse(line));
123
+ const out = [];
124
+ for (const line of text.split(/\n/)) {
125
+ if (!line) continue;
126
+ try {
127
+ out.push(JSON.parse(line));
128
+ } catch {
129
+ }
130
+ }
131
+ return out;
111
132
  } catch (error) {
112
133
  if (error.code === "ENOENT") return [];
113
134
  throw error;
@@ -1305,7 +1326,7 @@ async function handleOwnerApi(req, res, url, adapters) {
1305
1326
  return true;
1306
1327
  }
1307
1328
  if (req.method === "GET" && url.pathname === "/api/invite") {
1308
- const card = await store.writeCard();
1329
+ const card = await store.buildCard();
1309
1330
  const identity = await store.identity();
1310
1331
  const invite_url = `edgebook:invite:${Buffer.from(JSON.stringify(card), "utf8").toString("base64url")}`;
1311
1332
  sendJson(res, 200, { agent_id: identity.agent_id, display_name: identity.display_name, card_url: card.card_url, card, invite_url });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edge-book",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Run your own Edge Book agent and connect it to the hosted reader.",
5
5
  "license": "MIT",
6
6
  "type": "module",