@drisp/cli 0.4.0 → 0.4.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.
@@ -0,0 +1,255 @@
1
+ import {
2
+ acquirePidLock,
3
+ ensureDaemonStateDir,
4
+ runDashboardRuntimeDaemon,
5
+ startUdsServer
6
+ } from "./chunk-WHELLVBL.js";
7
+ import "./chunk-BTKQ67RE.js";
8
+ import {
9
+ readDashboardClientConfig,
10
+ refreshDashboardAccessToken
11
+ } from "./chunk-4CRZXLIP.js";
12
+ import "./chunk-GE6PPB6Z.js";
13
+
14
+ // src/infra/daemon/logFile.ts
15
+ import fs from "fs";
16
+ import path from "path";
17
+ var DEFAULT_MAX_BYTES = 5 * 1024 * 1024;
18
+ var DEFAULT_MAX_FILES = 5;
19
+ function openDaemonLog(logPath, options = {}) {
20
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
21
+ const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
22
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
23
+ fs.mkdirSync(path.dirname(logPath), { recursive: true, mode: 448 });
24
+ let fd = fs.openSync(logPath, "a", 384);
25
+ if (process.platform !== "win32") {
26
+ try {
27
+ fs.chmodSync(logPath, 384);
28
+ } catch {
29
+ }
30
+ }
31
+ function rotate() {
32
+ try {
33
+ fs.closeSync(fd);
34
+ } catch {
35
+ }
36
+ for (let i = maxFiles - 1; i >= 1; i -= 1) {
37
+ const src = `${logPath}.${i}`;
38
+ const dst = `${logPath}.${i + 1}`;
39
+ try {
40
+ fs.renameSync(src, dst);
41
+ } catch (err) {
42
+ if (err.code !== "ENOENT") {
43
+ }
44
+ }
45
+ }
46
+ try {
47
+ fs.renameSync(logPath, `${logPath}.1`);
48
+ } catch (err) {
49
+ if (err.code !== "ENOENT") {
50
+ }
51
+ }
52
+ fd = fs.openSync(logPath, "a", 384);
53
+ if (process.platform !== "win32") {
54
+ try {
55
+ fs.chmodSync(logPath, 384);
56
+ } catch {
57
+ }
58
+ }
59
+ }
60
+ function write(level, message) {
61
+ const line = `${now().toISOString()} ${level.toUpperCase()} ${redactSecrets(message)}
62
+ `;
63
+ const buf = Buffer.from(line, "utf-8");
64
+ let stat = null;
65
+ try {
66
+ stat = fs.fstatSync(fd);
67
+ } catch {
68
+ }
69
+ if (stat && stat.size + buf.length > maxBytes) {
70
+ rotate();
71
+ }
72
+ try {
73
+ fs.writeSync(fd, buf);
74
+ } catch {
75
+ try {
76
+ fs.closeSync(fd);
77
+ } catch {
78
+ }
79
+ try {
80
+ fd = fs.openSync(logPath, "a", 384);
81
+ fs.writeSync(fd, buf);
82
+ } catch {
83
+ }
84
+ }
85
+ }
86
+ function close() {
87
+ try {
88
+ fs.closeSync(fd);
89
+ } catch {
90
+ }
91
+ }
92
+ return { write, close, path: logPath };
93
+ }
94
+ var SECRET_PATTERNS = [
95
+ [/Bearer\s+[A-Za-z0-9._\-+/=]+/g, "Bearer ***"],
96
+ [
97
+ /(["']?(?:access|refresh)_?token["']?\s*[:=]\s*)["']?[A-Za-z0-9._\-+/=]+/gi,
98
+ '$1"***"'
99
+ ],
100
+ [/(Sec-WebSocket-Protocol:\s*)\S+/gi, "$1***"],
101
+ [
102
+ /eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{4,}/g,
103
+ "***.***.***"
104
+ ]
105
+ ];
106
+ function redactSecrets(message) {
107
+ let out = message;
108
+ for (const [pattern, replacement] of SECRET_PATTERNS) {
109
+ out = out.replace(pattern, replacement);
110
+ }
111
+ return out;
112
+ }
113
+
114
+ // src/app/entry/dashboardDaemon.ts
115
+ async function runDashboardDaemonEntry() {
116
+ const stateDir = ensureDaemonStateDir();
117
+ const writer = openDaemonLog(stateDir.logPath);
118
+ const log = (level, message) => writer.write(level, message);
119
+ let pidLock;
120
+ try {
121
+ pidLock = acquirePidLock(stateDir.pidPath);
122
+ } catch (err) {
123
+ const message = err instanceof Error ? err.message : String(err);
124
+ log("error", `daemon startup: ${message}`);
125
+ writer.close();
126
+ process.stderr.write(`drisp dashboard daemon: ${message}
127
+ `);
128
+ return 1;
129
+ }
130
+ const config = readDashboardClientConfig();
131
+ if (!config) {
132
+ log("error", "daemon startup: not paired");
133
+ pidLock.release();
134
+ writer.close();
135
+ process.stderr.write(
136
+ 'drisp dashboard daemon: not paired. Run "drisp dashboard pair" first.\n'
137
+ );
138
+ return 1;
139
+ }
140
+ let stopReason = "sigterm";
141
+ const stopSignal = createDeferred();
142
+ let daemonHandle = null;
143
+ try {
144
+ daemonHandle = await runDashboardRuntimeDaemon({
145
+ log,
146
+ refreshAccessToken: async () => refreshDashboardAccessToken({})
147
+ });
148
+ } catch (err) {
149
+ const message = err instanceof Error ? err.message : String(err);
150
+ log("error", `runtime startup failed: ${message}`);
151
+ pidLock.release();
152
+ writer.close();
153
+ process.stderr.write(`drisp dashboard daemon: ${message}
154
+ `);
155
+ return 1;
156
+ }
157
+ const handler = (req) => {
158
+ if (!daemonHandle) {
159
+ return { ok: false, error: "daemon shutting down" };
160
+ }
161
+ switch (req.cmd) {
162
+ case "status": {
163
+ const snap = daemonHandle.snapshot();
164
+ return {
165
+ ok: true,
166
+ cmd: "status",
167
+ pid: pidLock.pid,
168
+ ...snap
169
+ };
170
+ }
171
+ case "runs": {
172
+ const runs = daemonHandle.listRuns({
173
+ ...req.active === true ? { active: true } : {},
174
+ ...typeof req.limit === "number" ? { limit: req.limit } : {}
175
+ });
176
+ return { ok: true, cmd: "runs", runs };
177
+ }
178
+ case "reload": {
179
+ return { ok: true, cmd: "reload" };
180
+ }
181
+ case "restart": {
182
+ stopReason = req.cmd;
183
+ stopSignal.resolve("restart");
184
+ return { ok: true, cmd: "restart" };
185
+ }
186
+ case "stop": {
187
+ stopReason = req.reason ?? "stop";
188
+ stopSignal.resolve("stop");
189
+ return { ok: true, cmd: "stop" };
190
+ }
191
+ default: {
192
+ const _exhaustive = req;
193
+ return {
194
+ ok: false,
195
+ error: `unknown command: ${JSON.stringify(_exhaustive)}`
196
+ };
197
+ }
198
+ }
199
+ };
200
+ const udsServer = await startUdsServer(stateDir.socketPath, handler, log);
201
+ log("info", `dashboard daemon listening on ${stateDir.socketPath}`);
202
+ const onSignal = (signal) => {
203
+ log("info", `received ${signal}`);
204
+ stopReason = signal;
205
+ stopSignal.resolve(signal);
206
+ };
207
+ process.on("SIGINT", onSignal);
208
+ process.on("SIGTERM", onSignal);
209
+ const reason = await stopSignal.promise;
210
+ process.off("SIGINT", onSignal);
211
+ process.off("SIGTERM", onSignal);
212
+ log("info", `daemon stopping: ${reason}`);
213
+ try {
214
+ await daemonHandle.stop(reason);
215
+ } catch (err) {
216
+ log(
217
+ "warn",
218
+ `runtime stop failed: ${err instanceof Error ? err.message : String(err)}`
219
+ );
220
+ }
221
+ try {
222
+ await udsServer.close();
223
+ } catch (err) {
224
+ log(
225
+ "warn",
226
+ `uds close failed: ${err instanceof Error ? err.message : String(err)}`
227
+ );
228
+ }
229
+ pidLock.release();
230
+ log("info", `daemon stopped: ${stopReason}`);
231
+ writer.close();
232
+ return 0;
233
+ }
234
+ function createDeferred() {
235
+ let resolve;
236
+ const promise = new Promise((r) => {
237
+ resolve = r;
238
+ });
239
+ let settled = false;
240
+ return {
241
+ promise,
242
+ resolve(value) {
243
+ if (settled) return;
244
+ settled = true;
245
+ resolve(value);
246
+ }
247
+ };
248
+ }
249
+ void runDashboardDaemonEntry().then((code) => {
250
+ process.exit(code);
251
+ });
252
+ export {
253
+ runDashboardDaemonEntry
254
+ };
255
+ //# sourceMappingURL=dashboard-daemon.js.map
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import "./chunk-HXBCZAP7.js";
2
3
  import {
3
4
  ATHENA_HOOK_SOCKET_ENV,
4
5
  generateId
5
- } from "./chunk-PSD3WBN4.js";
6
+ } from "./chunk-BTKQ67RE.js";
6
7
 
7
8
  // src/harnesses/claude/hook-forwarder.ts
8
9
  import * as net from "net";
package/package.json CHANGED
@@ -17,11 +17,12 @@
17
17
  "hooks",
18
18
  "dashboard"
19
19
  ],
20
- "version": "0.4.0",
20
+ "version": "0.4.2",
21
21
  "license": "MIT",
22
22
  "bin": {
23
23
  "drisp": "dist/cli.js",
24
- "drisp-hook-forwarder": "dist/hook-forwarder.js"
24
+ "drisp-hook-forwarder": "dist/hook-forwarder.js",
25
+ "drisp-dashboard-daemon": "dist/dashboard-daemon.js"
25
26
  },
26
27
  "type": "module",
27
28
  "engines": {