@sessionbus/dsh 0.1.0-pre.10 → 0.1.0-pre.11

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 (3) hide show
  1. package/README.md +3 -0
  2. package/package.json +1 -1
  3. package/plugin.cjs +31 -7
package/README.md CHANGED
@@ -62,6 +62,9 @@ when given a launch token. Install the selected launcher alongside `dsh` at the
62
62
  host level and put their shared `node_modules/.bin` on the daemon service's
63
63
  `PATH`; the `dashi` launcher resolves its child `dsh` by name.
64
64
 
65
+ Without an explicit socket, peers use `$XDG_RUNTIME_DIR/sessionbus/presence.sock`
66
+ or `/tmp/sessionbus-<uid>/presence.sock`, matching the daemon's discovery rule.
67
+
65
68
  Uninstall without invoking DSH by running the installed bin from the profile:
66
69
 
67
70
  ```sh
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sessionbus/dsh",
3
- "version": "0.1.0-pre.10",
3
+ "version": "0.1.0-pre.11",
4
4
  "type": "commonjs",
5
5
  "main": "plugin.cjs",
6
6
  "exports": "./plugin.cjs",
package/plugin.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- const os = require("node:os");
3
+ const net = require("node:net");
4
4
  const path = require("node:path");
5
5
  const kit = require("@sessionbus/kit");
6
6
  const version = require("./package.json").version;
@@ -66,7 +66,10 @@ function readConfiguration(ctx, config = {}, ambient = process.env) {
66
66
  if (config.mode !== undefined && config.mode !== mode) throw new Error(`mode ${config.mode} conflicts with launch environment`);
67
67
  let groups = mode === "lane" ? [] : Object.hasOwn(config, "groups") ? config.groups : JSON.parse(value("SESSIONBUS_GROUPS") || "[]");
68
68
  if (!Array.isArray(groups) || groups.some((group) => !text(group)) || new Set(groups).size !== groups.length) throw new Error("groups are invalid");
69
- const socket = Object.hasOwn(config, "socket") ? config.socket : value("SESSIONBUS_SOCKET") || path.join(value("XDG_STATE_HOME") || path.join(value("HOME") || os.homedir(), ".local/state"), "sessionbus/run/presence.sock");
69
+ const explicitSocket = Object.hasOwn(config, "socket") ? config.socket : value("SESSIONBUS_SOCKET");
70
+ const socket = explicitSocket ? path.resolve(explicitSocket) : value("XDG_RUNTIME_DIR")
71
+ ? path.resolve(value("XDG_RUNTIME_DIR"), "sessionbus/presence.sock")
72
+ : path.join("/tmp", `sessionbus-${process.getuid()}`, "presence.sock");
70
73
  const localKey = Object.hasOwn(config, "local_key") ? config.local_key : value("SESSIONBUS_LOCAL_KEY");
71
74
  if (!text(socket) || localKey !== undefined && !text(localKey)) throw new Error("connection settings are invalid");
72
75
  return { settings: { mode, product: config.product, groups: [...groups], socket, localKey }, token };
@@ -285,26 +288,47 @@ function createRuntime(ctx, config, dependencies, prepared) {
285
288
  let launchToken = configured.token;
286
289
  const native = new NativeSession(ctx, dependencies.createUserMessage);
287
290
  const peers = new Map();
291
+ const publicationErrors = new WeakSet();
288
292
  let worker;
289
293
  let workerExit = Promise.resolve();
290
294
  let ready = false;
291
295
  let warned = false;
292
296
  const warn = (error) => { if (active() && !warned) { warned = true; dependencies.stderr(`sessionbus: ${clean(error)}\n`); } };
293
297
  const root = (agent) => ctx.agents.roots().includes(agent);
298
+ const publicationError = (agent, error, record) => {
299
+ if (record && peers.get(agent) === record) {
300
+ record.peer?.shutdown();
301
+ peers.delete(agent);
302
+ // Leave it unpublished; a later title change may naturally call present() again.
303
+ }
304
+ if (active() && !publicationErrors.has(agent)) {
305
+ publicationErrors.add(agent);
306
+ dependencies.stderr(`sessionbus: ${clean(error)}\n`);
307
+ }
308
+ };
294
309
  const present = (agent) => {
295
310
  if (values.mode !== "peer" || !ready || !root(agent) || peers.has(agent)) return;
296
311
  try {
297
312
  const current = identity(ctx, agent, values.product, values.groups);
298
313
  if (!current) return;
299
- const peer = dependencies.connectPeer(current, (cancel, request) => native.deliver(cancel, request, agent), connectionEnvironment(values));
300
- peers.set(agent, { peer, identity: current, rehello: Promise.resolve() });
301
- } catch (error) { warn(error); }
314
+ const record = { peer: undefined, identity: current, rehello: Promise.resolve() };
315
+ const peer = dependencies.connectPeer(current, (cancel, request) => native.deliver(cancel, request, agent), connectionEnvironment(values), {
316
+ connect: (socket) => {
317
+ const stream = net.createConnection(socket);
318
+ stream.once("error", (error) => publicationError(agent, error, record));
319
+ return stream;
320
+ },
321
+ });
322
+ record.peer = peer;
323
+ peers.set(agent, record);
324
+ void peer.closed?.then(() => { if (peer.error) publicationError(agent, peer.error, record); });
325
+ } catch (error) { publicationError(agent, error); }
302
326
  };
303
327
  const forget = (agent) => { peers.get(agent)?.peer.shutdown(); peers.delete(agent); };
304
328
  let removeCreated = () => {}, removeDisposed = () => {}, removeTitle = () => {};
305
329
  if (values.mode === "peer") {
306
- removeCreated = ctx.on("agent/created", ({ agent }) => present(agent));
307
- removeDisposed = ctx.on("agent/disposed", ({ agent }) => forget(agent));
330
+ removeCreated = ctx.on("agent/created", ({ agent }) => present(agent), { global: true });
331
+ removeDisposed = ctx.on("agent/disposed", ({ agent }) => forget(agent), { global: true });
308
332
  removeTitle = ctx.on("session/event", (session, event) => {
309
333
  if (event.type !== "session/title") return;
310
334
  const agent = ctx.agents.get(session.id);