kernelpm 0.1.3 → 0.1.9

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/control.js CHANGED
@@ -134,6 +134,10 @@ class SocketClient {
134
134
  await this.daemon.restart(msg.id);
135
135
  this.send({ t: 'ok', rid });
136
136
  break;
137
+ case 'renameSession':
138
+ await this.daemon.rename(msg.id, msg.title);
139
+ this.send({ t: 'ok', rid });
140
+ break;
137
141
  case 'listDir': {
138
142
  const dir = resolveDir(msg.path);
139
143
  this.send({ t: 'dir', rid, path: dir, entries: await readDir(dir) });
package/dist/daemon.js CHANGED
@@ -82,16 +82,28 @@ class Daemon {
82
82
  }
83
83
  async init() {
84
84
  await this.store.init();
85
- for (const meta of this.store.list()) {
86
- if (meta.status === 'exited')
87
- continue;
85
+ const metas = this.store.list().filter((m) => m.status !== 'exited');
86
+ // Kick off all session recoveries concurrently WITHOUT awaiting: the
87
+ // control socket must open immediately so the broker can connect, and a
88
+ // slow / stuck `opencode serve` (one that never becomes healthy) must not
89
+ // keep the daemon from coming up — otherwise `kernelpm daemon start` polls
90
+ // its readiness window, sees no socket, and reports "did not come up in
91
+ // time" even though the daemon is still busy reattaching. A session that
92
+ // fails to recover is marked 'exited' so the app sees the truth instead of
93
+ // a perpetual 'starting'.
94
+ for (const meta of metas) {
88
95
  const session = this.spawn(meta);
89
- try {
90
- await session.start(true); // reattach if alive, resume if not
91
- }
92
- catch (err) {
96
+ void session
97
+ .start(true)
98
+ .catch(async (err) => {
93
99
  console.error(`[kernelpm] could not recover session ${meta.id}:`, err);
94
- }
100
+ try {
101
+ await this.store.upsert({ ...meta, status: 'exited', updatedAt: Date.now() });
102
+ }
103
+ catch {
104
+ /* best-effort — store may already be in a bad state */
105
+ }
106
+ });
95
107
  }
96
108
  }
97
109
  list() {
@@ -130,6 +142,23 @@ class Daemon {
130
142
  restart(id) {
131
143
  return this.require(id).restart();
132
144
  }
145
+ /**
146
+ * Update a session's title. Persists the new meta and pushes a `status`
147
+ * message to every attached client so the app re-renders the row immediately.
148
+ * Throws if the session id is unknown or the new title is empty.
149
+ */
150
+ async rename(id, title) {
151
+ const trimmed = title.trim();
152
+ if (!trimmed)
153
+ throw new Error('el título no puede estar vacío');
154
+ const meta = this.store.get(id);
155
+ if (!meta)
156
+ throw new Error('no such session');
157
+ const next = { ...meta, title: trimmed, updatedAt: Date.now() };
158
+ await this.store.upsert(next);
159
+ this.broadcast(id, { t: 'status', id, meta: next });
160
+ return next;
161
+ }
133
162
  /* ------------------------------ client fan-out ----------------------------- */
134
163
  addClient(c) {
135
164
  this.clients.add(c);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kernelpm",
3
- "version": "0.1.3",
3
+ "version": "0.1.9",
4
4
  "description": "kernelpm daemon — keeps opencode sessions alive on a server (via `opencode serve`) and exposes them over a local control socket.",
5
5
  "license": "MIT",
6
6
  "bin": {