edge-book 0.2.2 → 0.2.3

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.
Files changed (2) hide show
  1. package/dist/edge-book.js +69 -1
  2. package/package.json +1 -1
package/dist/edge-book.js CHANGED
@@ -2778,6 +2778,8 @@ var EdgeBookDialoutClient = class {
2778
2778
  currentBackoff;
2779
2779
  opened;
2780
2780
  pendingSessionRevokes = /* @__PURE__ */ new Map();
2781
+ // Generic request_id-keyed RPC waiters for sessions_list / session_revoke_one.
2782
+ pendingRpc = /* @__PURE__ */ new Map();
2781
2783
  pendingMailboxSends = /* @__PURE__ */ new Map();
2782
2784
  constructor(options) {
2783
2785
  this.options = {
@@ -2817,6 +2819,30 @@ var EdgeBookDialoutClient = class {
2817
2819
  this.send(frame);
2818
2820
  return frame;
2819
2821
  }
2822
+ // List this agent's remembered devices on the host (ea-claude-057).
2823
+ async listSessionsAndWait(timeoutMs = 5e3) {
2824
+ const frame = await this.rpc("sessions_list", {}, "sessions_list_ok", timeoutMs);
2825
+ return frame.devices || [];
2826
+ }
2827
+ // Revoke ONE device by its public device_id (ea-claude-057).
2828
+ async revokeOneSessionAndWait(device_id, timeoutMs = 5e3) {
2829
+ const frame = await this.rpc("session_revoke_one", { device_id }, "session_revoke_one_ok", timeoutMs);
2830
+ return Boolean(frame.revoked);
2831
+ }
2832
+ // Small request/response helper over the dial-out socket, correlated by
2833
+ // request_id. `expect` documents the ack type; resolution is by request_id.
2834
+ async rpc(type, extra, expect, timeoutMs) {
2835
+ const request_id = crypto2.randomUUID();
2836
+ const promise = new Promise((resolve, reject) => {
2837
+ const timer = setTimeout(() => {
2838
+ this.pendingRpc.delete(request_id);
2839
+ reject(new EdgeBookError("host_rpc_timeout", `Timed out waiting for ${expect}`));
2840
+ }, timeoutMs);
2841
+ this.pendingRpc.set(request_id, { resolve, reject, timer });
2842
+ });
2843
+ this.send({ type, request_id, ...extra });
2844
+ return promise;
2845
+ }
2820
2846
  async revokeSessionsAndWait(timeoutMs = 5e3) {
2821
2847
  const frame = await createSessionsRevokeFrame(this.store);
2822
2848
  const ackPromise = new Promise((resolve, reject) => {
@@ -2959,6 +2985,16 @@ var EdgeBookDialoutClient = class {
2959
2985
  this.send({ type: "pong" });
2960
2986
  return;
2961
2987
  }
2988
+ if (frame.type === "sessions_list_ok" || frame.type === "session_revoke_one_ok") {
2989
+ const ack = frame;
2990
+ const pending = this.pendingRpc.get(ack.request_id || "");
2991
+ if (pending) {
2992
+ clearTimeout(pending.timer);
2993
+ this.pendingRpc.delete(ack.request_id || "");
2994
+ pending.resolve(frame);
2995
+ }
2996
+ return;
2997
+ }
2962
2998
  if (frame.type === "stand_down" || frame.type === "dialout_idle") {
2963
2999
  await this.standDown(frame);
2964
3000
  return;
@@ -3082,6 +3118,26 @@ async function sendSessionsRevoke(options) {
3082
3118
  await client.stop();
3083
3119
  return { ...frame, channel_id: ack.channel_id };
3084
3120
  }
3121
+ async function listSessions(options) {
3122
+ const client = new EdgeBookDialoutClient({ ...options, reconnect: false, openLocalApi: false });
3123
+ await client.start();
3124
+ await new Promise((resolve) => setTimeout(resolve, 0));
3125
+ try {
3126
+ return await client.listSessionsAndWait();
3127
+ } finally {
3128
+ await client.stop();
3129
+ }
3130
+ }
3131
+ async function revokeOneSession(options) {
3132
+ const client = new EdgeBookDialoutClient({ ...options, reconnect: false, openLocalApi: false });
3133
+ await client.start();
3134
+ await new Promise((resolve) => setTimeout(resolve, 0));
3135
+ try {
3136
+ return await client.revokeOneSessionAndWait(options.deviceId);
3137
+ } finally {
3138
+ await client.stop();
3139
+ }
3140
+ }
3085
3141
 
3086
3142
  // src/cli.ts
3087
3143
  function usage() {
@@ -3093,7 +3149,8 @@ Usage:
3093
3149
  Hosted reader:
3094
3150
  edge-book dialout [--host <ws-url>] [--home <dir>]
3095
3151
  edge-book pair [--host <ws-url>] [--ttl-ms <ms>] [--home <dir>]
3096
- edge-book sessions revoke [--host <ws-url>] [--home <dir>]
3152
+ edge-book sessions list [--host <ws-url>] [--home <dir>]
3153
+ edge-book sessions revoke [--device <id>] [--host <ws-url>] [--home <dir>]
3097
3154
 
3098
3155
  Local agent:
3099
3156
  edge-book doctor [--home <dir>]
@@ -3396,8 +3453,19 @@ Expires in: ${registration.frame.ttl_ms}ms`, json: registration };
3396
3453
  }
3397
3454
  if (command === "sessions") {
3398
3455
  const action = args.shift();
3456
+ if (action === "list") {
3457
+ const hostUrl = parseHost(args, ctx);
3458
+ const devices = await listSessions({ home, host: hostUrl, socketFactory: ctx.socketFactory });
3459
+ const lines = devices.length ? devices.map((d) => `${d.device_id} ${d.label} (added ${new Date(d.created_at).toISOString()}, last seen ${new Date(d.last_seen_at).toISOString()})`).join("\n") : "No remembered devices.";
3460
+ return { text: lines, json: { devices } };
3461
+ }
3399
3462
  if (action === "revoke") {
3400
3463
  const hostUrl = parseHost(args, ctx);
3464
+ const deviceId = takeFlag(args, "--device");
3465
+ if (deviceId) {
3466
+ const revoked = await revokeOneSession({ home, host: hostUrl, socketFactory: ctx.socketFactory, deviceId });
3467
+ return { text: revoked ? `Revoked device ${deviceId}` : `No device ${deviceId} found on your channel`, json: { device_id: deviceId, revoked } };
3468
+ }
3401
3469
  const frame = await sendSessionsRevoke({ home, host: hostUrl, socketFactory: ctx.socketFactory });
3402
3470
  const channel = frame.channel_id || "unknown-channel";
3403
3471
  return { text: `Received sessions_revoke_ok for request ${frame.request_id} on ${channel}`, json: frame };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "edge-book",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Run your own Edge Book agent and connect it to the hosted reader.",
5
5
  "license": "MIT",
6
6
  "type": "module",