@tenphi/akno 0.1.0

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 (147) hide show
  1. package/LICENSE +83 -0
  2. package/README.md +46 -0
  3. package/dist/args.d.ts +18 -0
  4. package/dist/args.d.ts.map +1 -0
  5. package/dist/args.js +92 -0
  6. package/dist/args.js.map +1 -0
  7. package/dist/bin.d.ts +3 -0
  8. package/dist/bin.d.ts.map +1 -0
  9. package/dist/bin.js +142 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/commands/adopt-cmd.d.ts +2 -0
  12. package/dist/commands/adopt-cmd.d.ts.map +1 -0
  13. package/dist/commands/adopt-cmd.js +61 -0
  14. package/dist/commands/adopt-cmd.js.map +1 -0
  15. package/dist/commands/answer-cmd.d.ts +2 -0
  16. package/dist/commands/answer-cmd.d.ts.map +1 -0
  17. package/dist/commands/answer-cmd.js +150 -0
  18. package/dist/commands/answer-cmd.js.map +1 -0
  19. package/dist/commands/bench-cmd.d.ts +4 -0
  20. package/dist/commands/bench-cmd.d.ts.map +1 -0
  21. package/dist/commands/bench-cmd.js +1542 -0
  22. package/dist/commands/bench-cmd.js.map +1 -0
  23. package/dist/commands/config-cmd.d.ts +7 -0
  24. package/dist/commands/config-cmd.d.ts.map +1 -0
  25. package/dist/commands/config-cmd.js +80 -0
  26. package/dist/commands/config-cmd.js.map +1 -0
  27. package/dist/commands/context-cmd.d.ts +2 -0
  28. package/dist/commands/context-cmd.d.ts.map +1 -0
  29. package/dist/commands/context-cmd.js +130 -0
  30. package/dist/commands/context-cmd.js.map +1 -0
  31. package/dist/commands/doctor-cmd.d.ts +2 -0
  32. package/dist/commands/doctor-cmd.d.ts.map +1 -0
  33. package/dist/commands/doctor-cmd.js +198 -0
  34. package/dist/commands/doctor-cmd.js.map +1 -0
  35. package/dist/commands/dream-cmd.d.ts +26 -0
  36. package/dist/commands/dream-cmd.d.ts.map +1 -0
  37. package/dist/commands/dream-cmd.js +1167 -0
  38. package/dist/commands/dream-cmd.js.map +1 -0
  39. package/dist/commands/dream-model-status.d.ts +5 -0
  40. package/dist/commands/dream-model-status.d.ts.map +1 -0
  41. package/dist/commands/dream-model-status.js +33 -0
  42. package/dist/commands/dream-model-status.js.map +1 -0
  43. package/dist/commands/dream-notifications.d.ts +24 -0
  44. package/dist/commands/dream-notifications.d.ts.map +1 -0
  45. package/dist/commands/dream-notifications.js +168 -0
  46. package/dist/commands/dream-notifications.js.map +1 -0
  47. package/dist/commands/dream-schedule.d.ts +55 -0
  48. package/dist/commands/dream-schedule.d.ts.map +1 -0
  49. package/dist/commands/dream-schedule.js +160 -0
  50. package/dist/commands/dream-schedule.js.map +1 -0
  51. package/dist/commands/folder-cmd.d.ts +2 -0
  52. package/dist/commands/folder-cmd.d.ts.map +1 -0
  53. package/dist/commands/folder-cmd.js +84 -0
  54. package/dist/commands/folder-cmd.js.map +1 -0
  55. package/dist/commands/graph-cmd.d.ts +2 -0
  56. package/dist/commands/graph-cmd.d.ts.map +1 -0
  57. package/dist/commands/graph-cmd.js +126 -0
  58. package/dist/commands/graph-cmd.js.map +1 -0
  59. package/dist/commands/inbox-cmd.d.ts +2 -0
  60. package/dist/commands/inbox-cmd.d.ts.map +1 -0
  61. package/dist/commands/inbox-cmd.js +69 -0
  62. package/dist/commands/inbox-cmd.js.map +1 -0
  63. package/dist/commands/index-cmd.d.ts +2 -0
  64. package/dist/commands/index-cmd.d.ts.map +1 -0
  65. package/dist/commands/index-cmd.js +102 -0
  66. package/dist/commands/index-cmd.js.map +1 -0
  67. package/dist/commands/ingest-cmd.d.ts +2 -0
  68. package/dist/commands/ingest-cmd.d.ts.map +1 -0
  69. package/dist/commands/ingest-cmd.js +167 -0
  70. package/dist/commands/ingest-cmd.js.map +1 -0
  71. package/dist/commands/init-cmd.d.ts +292 -0
  72. package/dist/commands/init-cmd.d.ts.map +1 -0
  73. package/dist/commands/init-cmd.js +476 -0
  74. package/dist/commands/init-cmd.js.map +1 -0
  75. package/dist/commands/init-prompts.d.ts +51 -0
  76. package/dist/commands/init-prompts.d.ts.map +1 -0
  77. package/dist/commands/init-prompts.js +192 -0
  78. package/dist/commands/init-prompts.js.map +1 -0
  79. package/dist/commands/list-cmd.d.ts +2 -0
  80. package/dist/commands/list-cmd.d.ts.map +1 -0
  81. package/dist/commands/list-cmd.js +77 -0
  82. package/dist/commands/list-cmd.js.map +1 -0
  83. package/dist/commands/maintenance-policy-output.d.ts +4 -0
  84. package/dist/commands/maintenance-policy-output.d.ts.map +1 -0
  85. package/dist/commands/maintenance-policy-output.js +72 -0
  86. package/dist/commands/maintenance-policy-output.js.map +1 -0
  87. package/dist/commands/mutate-cmd.d.ts +5 -0
  88. package/dist/commands/mutate-cmd.d.ts.map +1 -0
  89. package/dist/commands/mutate-cmd.js +224 -0
  90. package/dist/commands/mutate-cmd.js.map +1 -0
  91. package/dist/commands/plan-cmd.d.ts +9 -0
  92. package/dist/commands/plan-cmd.d.ts.map +1 -0
  93. package/dist/commands/plan-cmd.js +411 -0
  94. package/dist/commands/plan-cmd.js.map +1 -0
  95. package/dist/commands/read-cmd.d.ts +2 -0
  96. package/dist/commands/read-cmd.d.ts.map +1 -0
  97. package/dist/commands/read-cmd.js +89 -0
  98. package/dist/commands/read-cmd.js.map +1 -0
  99. package/dist/commands/recall-cmd.d.ts +2 -0
  100. package/dist/commands/recall-cmd.d.ts.map +1 -0
  101. package/dist/commands/recall-cmd.js +176 -0
  102. package/dist/commands/recall-cmd.js.map +1 -0
  103. package/dist/commands/redeploy-cmd.d.ts +43 -0
  104. package/dist/commands/redeploy-cmd.d.ts.map +1 -0
  105. package/dist/commands/redeploy-cmd.js +270 -0
  106. package/dist/commands/redeploy-cmd.js.map +1 -0
  107. package/dist/commands/rules-cmd.d.ts +2 -0
  108. package/dist/commands/rules-cmd.d.ts.map +1 -0
  109. package/dist/commands/rules-cmd.js +72 -0
  110. package/dist/commands/rules-cmd.js.map +1 -0
  111. package/dist/commands/serve-cmd.d.ts +23 -0
  112. package/dist/commands/serve-cmd.d.ts.map +1 -0
  113. package/dist/commands/serve-cmd.js +415 -0
  114. package/dist/commands/serve-cmd.js.map +1 -0
  115. package/dist/commands/timeline-cmd.d.ts +2 -0
  116. package/dist/commands/timeline-cmd.d.ts.map +1 -0
  117. package/dist/commands/timeline-cmd.js +67 -0
  118. package/dist/commands/timeline-cmd.js.map +1 -0
  119. package/dist/commands/write-cmd.d.ts +49 -0
  120. package/dist/commands/write-cmd.d.ts.map +1 -0
  121. package/dist/commands/write-cmd.js +269 -0
  122. package/dist/commands/write-cmd.js.map +1 -0
  123. package/dist/ops-handle.d.ts +67 -0
  124. package/dist/ops-handle.d.ts.map +1 -0
  125. package/dist/ops-handle.js +196 -0
  126. package/dist/ops-handle.js.map +1 -0
  127. package/dist/output.d.ts +28 -0
  128. package/dist/output.d.ts.map +1 -0
  129. package/dist/output.js +87 -0
  130. package/dist/output.js.map +1 -0
  131. package/dist/serve/http.d.ts +19 -0
  132. package/dist/serve/http.d.ts.map +1 -0
  133. package/dist/serve/http.js +135 -0
  134. package/dist/serve/http.js.map +1 -0
  135. package/dist/serve/mcp.d.ts +21 -0
  136. package/dist/serve/mcp.d.ts.map +1 -0
  137. package/dist/serve/mcp.js +79 -0
  138. package/dist/serve/mcp.js.map +1 -0
  139. package/dist/serve/socket.d.ts +15 -0
  140. package/dist/serve/socket.d.ts.map +1 -0
  141. package/dist/serve/socket.js +311 -0
  142. package/dist/serve/socket.js.map +1 -0
  143. package/dist/version.d.ts +2 -0
  144. package/dist/version.d.ts.map +1 -0
  145. package/dist/version.js +15 -0
  146. package/dist/version.js.map +1 -0
  147. package/package.json +40 -0
@@ -0,0 +1,415 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { open } from '@tenphi/akno-core';
4
+ import { openOptionsFrom, parse } from "../args.js";
5
+ import { heading, kv, line, ms, style, warn } from "../output.js";
6
+ import { serveSocket } from "../serve/socket.js";
7
+ import { serveHttp } from "../serve/http.js";
8
+ import { serveMcp } from "../serve/mcp.js";
9
+ import { resolveOps } from "../ops-handle.js";
10
+ import { AknoError } from '@tenphi/akno-protocol';
11
+ import { DREAM_HEALTH_LABEL, DREAM_SCHEDULE_LABEL } from "./dream-schedule.js";
12
+ const SERVE_HELP = `akno serve [options]
13
+
14
+ Hold the index, the watcher and the model connections in one long-lived
15
+ process. Spawning a process per memory call costs 33ms against 0.04ms for a
16
+ long-lived handle — an 800x difference, and none of it is the database.
17
+
18
+ --mcp stdio MCP, for any agent that speaks it. Logs go to
19
+ stderr because stdout is the protocol.
20
+ --http <host:port> Loopback HTTP, for agents in containers or on another
21
+ host. No auth of its own — put it behind one.
22
+ --socket <path> Override the unix socket path.
23
+ --no-watch Do not watch the knowledge base.
24
+ --index-on-start Reconcile before accepting connections.
25
+ --allow <op,...> Restrict which ops this door exposes.`;
26
+ export async function serveCommand(argv) {
27
+ const { values } = parse(argv, {
28
+ mcp: { type: 'boolean', default: false },
29
+ http: { type: 'string' },
30
+ socket: { type: 'string' },
31
+ watch: { type: 'boolean', default: true },
32
+ 'index-on-start': { type: 'boolean', default: false },
33
+ allow: { type: 'string' },
34
+ });
35
+ if (values.help) {
36
+ line(SERVE_HELP);
37
+ return 0;
38
+ }
39
+ // stdout belongs to the MCP protocol. Anything written there corrupts the
40
+ // stream, so every log line goes to stderr in that mode.
41
+ const isMcp = values.mcp;
42
+ const log = (message) => {
43
+ const stamp = new Date().toISOString().slice(11, 19);
44
+ process.stderr.write(`${style.grey(stamp)} ${message}\n`);
45
+ };
46
+ // A second door in front of the service that already holds the write handle, rather than a
47
+ // second Akno. Opening the index here would give this process a read-only handle — the MCP
48
+ // tools would all be present and every write would fail, which is the worst of both. The
49
+ // service owns the index, the watcher and the models; this is stdio translated onto its socket.
50
+ //
51
+ // Only for `--mcp`: the socket door *is* the service, so serving it this way would be a
52
+ // process forwarding to itself.
53
+ if (isMcp) {
54
+ const forwarded = await serveMcpThroughService(values, log);
55
+ if (forwarded !== null)
56
+ return forwarded;
57
+ }
58
+ const mem = await open({
59
+ ...openOptionsFrom(values),
60
+ // A service start is nearly always a restart, and the outgoing process is usually still closing
61
+ // its database when this one opens. Without a wait, the replacement comes up read-only and stays
62
+ // that way — refusing every write for its whole life, naming a pid that has already exited.
63
+ writeLockWaitMs: 10_000,
64
+ watch: values.watch,
65
+ watchEvents: {
66
+ onIndexed: (report, changed) => {
67
+ if (report.pagesIndexed === 0 && report.pagesRemoved === 0 && report.pagesRenamed === 0)
68
+ return;
69
+ const what = changed.length > 0 && changed.length <= 3 ? changed.join(', ') : `${report.pagesIndexed} pages`;
70
+ log(`indexed ${what} in ${ms(report.durationMs)}` +
71
+ `${report.pagesRenamed > 0 ? ` (${report.pagesRenamed} renamed)` : ''}` +
72
+ `${report.pagesRemoved > 0 ? ` (${report.pagesRemoved} removed)` : ''}`);
73
+ for (const warning of report.warnings.slice(0, 3))
74
+ log(style.yellow(` ${warning}`));
75
+ },
76
+ onError: (error) => log(style.red(`watcher: ${error.message}`)),
77
+ },
78
+ });
79
+ if (!mem.writable) {
80
+ warn(`pid ${mem.lockHeldBy} holds the write handle. This instance is read-only: it will serve ` +
81
+ 'reads but will not index or watch. Do not run two Aknos against one knowledge base.');
82
+ // Read-only is decided once, when the database is opened, and the connection itself is opened
83
+ // that way — so a service that lost the race cannot promote itself in place. It can notice that
84
+ // the holder is gone and stand down, which under a supervisor means coming straight back with
85
+ // the handle. Without that, losing a restart race by a second costs every write until somebody
86
+ // notices, which on this install was hours of refusals naming a pid that had long exited.
87
+ watchForAReleasedHandle(mem.lockHeldBy, log);
88
+ }
89
+ const allow = values.allow
90
+ ? values.allow.split(',').map((op) => op.trim())
91
+ : isMcp
92
+ ? mem.config.server.mcpAllow
93
+ : undefined;
94
+ if (values['index-on-start'] && mem.writable) {
95
+ const report = await mem.index({});
96
+ log(`startup index: ${report.pagesIndexed} indexed, ${report.pagesUnchanged} unchanged in ${ms(report.durationMs)}`);
97
+ }
98
+ const closers = [];
99
+ try {
100
+ if (isMcp) {
101
+ const server = await serveMcp(mem, { ...(allow ? { allow } : {}), log });
102
+ closers.push(() => server.close());
103
+ log(`MCP ready over stdio — ${(allow ?? []).length || 'all'} ops, ${mem.config.aknoPath}`);
104
+ }
105
+ else {
106
+ const socketPath = values.socket ? path.resolve(values.socket) : mem.config.socketPath;
107
+ const socket = await serveSocket(mem, socketPath, { ...(allow ? { allow } : {}), log });
108
+ closers.push(() => socket.close());
109
+ heading('Akno serving');
110
+ kv([
111
+ ['knowledge base', mem.config.aknoPath],
112
+ ['socket', socket.path],
113
+ ['watching', values.watch && mem.writable ? 'yes' : 'no'],
114
+ ['writable', mem.writable ? 'yes' : `no (pid ${mem.lockHeldBy})`],
115
+ ]);
116
+ }
117
+ const httpAddress = values.http ?? mem.config.server.http;
118
+ if (httpAddress) {
119
+ const server = await serveHttp(mem, httpAddress, { ...(allow ? { allow } : {}), log });
120
+ closers.push(() => server.close());
121
+ const [host] = server.address.split(':');
122
+ if (host !== '127.0.0.1' && host !== 'localhost') {
123
+ warn(`the HTTP door is bound to ${server.address}, not loopback. It has no authentication of ` +
124
+ 'its own — anything that can reach that address can read your knowledge base.');
125
+ }
126
+ log(`HTTP ready on ${server.address}`);
127
+ }
128
+ // `KeepAlive` under launchd means the service outlives every host that
129
+ // talks to it, which is the whole point of running it separately. Shutting
130
+ // down cleanly is what makes a restart cost 3ms instead of a WAL replay.
131
+ await waitForShutdown(log, { onStdinEnd: isMcp });
132
+ return 0;
133
+ }
134
+ finally {
135
+ for (const close of closers)
136
+ await close().catch(() => { });
137
+ await mem.close();
138
+ }
139
+ }
140
+ /**
141
+ * Serves MCP over an existing service, or returns null when there is none to serve over.
142
+ *
143
+ * `--connect` turns "there is no service" into an error instead, for a host that would rather
144
+ * fail loudly at spawn than quietly get a second Akno it did not ask for.
145
+ */
146
+ async function serveMcpThroughService(values, log) {
147
+ const handle = await resolveOps({ ...values, json: true }, openOptionsFrom(values));
148
+ if (handle.via !== 'socket') {
149
+ await handle.close();
150
+ return null;
151
+ }
152
+ // The service's own `mcp_allow` cannot be read through the socket, so an explicit `--allow`
153
+ // is the only narrowing available here. Saying so beats a door that is quietly wider than
154
+ // the operator believes: the socket door they connected to has its own allow list, and this
155
+ // one inherits nothing from it.
156
+ const allow = values.allow?.split(',').map((op) => op.trim());
157
+ const server = await serveMcp(handle.ops, { ...(allow ? { allow } : {}), log });
158
+ log(`MCP ready over stdio — ${allow ? `${allow.length} ops` : 'all ops'}, through the running service`);
159
+ try {
160
+ await waitForShutdown(log, { onStdinEnd: true });
161
+ return 0;
162
+ }
163
+ finally {
164
+ await server.close();
165
+ await handle.close();
166
+ }
167
+ }
168
+ function waitForShutdown(log, options = {}) {
169
+ return new Promise((resolve) => {
170
+ let done = false;
171
+ const finish = (signal) => {
172
+ if (done)
173
+ return;
174
+ done = true;
175
+ log(`${signal} — shutting down`);
176
+ resolve();
177
+ };
178
+ process.once('SIGINT', () => finish('SIGINT'));
179
+ process.once('SIGTERM', () => finish('SIGTERM'));
180
+ // launchd sends SIGHUP on a `launchctl kickstart -k`.
181
+ process.once('SIGHUP', () => finish('SIGHUP'));
182
+ // An MCP server is a child of the agent that spawned it, and stdio is the whole
183
+ // relationship: when that pipe closes the client is gone and there is nobody left to serve.
184
+ // Waiting for a signal instead leaves a process per spawn holding a socket connection.
185
+ if (options.onStdinEnd) {
186
+ process.stdin.once('end', () => finish('stdin closed'));
187
+ process.stdin.once('close', () => finish('stdin closed'));
188
+ process.stdin.resume();
189
+ }
190
+ });
191
+ }
192
+ const SERVICE_HELP = `akno service <install | uninstall | status> [options]
193
+
194
+ Manage the macOS launchd user agents, so nobody hand-edits XML.
195
+
196
+ dev.akno KeepAlive — the index, watcher and models in one process, which
197
+ is why it outlives every host that talks to it.
198
+ dev.akno.dream Nightly — the maintenance cycle. Observe runs on a schedule,
199
+ and this is that schedule. It resolves maintenance.profile at
200
+ run time, so changing authority does not require reinstalling it.
201
+ dev.akno.dream-health
202
+ Daily — after the two-hour grace window, reports a missed cycle
203
+ when local maintenance notifications are enabled.
204
+
205
+ --http <addr> Serve loopback HTTP as well as the socket.
206
+ --dream-hour <0-23> When the nightly cycle runs. Default 3.
207
+ --no-dream Do not install the nightly agent.`;
208
+ const PLIST_LABEL = 'dev.akno';
209
+ export async function serviceCommand(argv) {
210
+ const { values, positionals } = parse(argv, {
211
+ http: { type: 'string' },
212
+ 'dream-hour': { type: 'string' },
213
+ dream: { type: 'boolean', default: true },
214
+ });
215
+ if (values.help || positionals.length === 0) {
216
+ line(SERVICE_HELP);
217
+ return values.help ? 0 : 1;
218
+ }
219
+ if (process.platform !== 'darwin') {
220
+ warn('`akno service` manages a macOS launchd agent; v1 targets macOS only.');
221
+ return 1;
222
+ }
223
+ const agents = path.join(process.env.HOME ?? '', 'Library', 'LaunchAgents');
224
+ const plistPath = path.join(agents, `${PLIST_LABEL}.plist`);
225
+ const dreamPath = path.join(agents, `${DREAM_SCHEDULE_LABEL}.plist`);
226
+ const dreamHealthPath = path.join(agents, `${DREAM_HEALTH_LABEL}.plist`);
227
+ const action = positionals[0];
228
+ if (action === 'status') {
229
+ let installed = false;
230
+ for (const [label, target] of [
231
+ [PLIST_LABEL, plistPath],
232
+ [DREAM_SCHEDULE_LABEL, dreamPath],
233
+ [DREAM_HEALTH_LABEL, dreamHealthPath],
234
+ ]) {
235
+ if (fs.existsSync(target)) {
236
+ installed = true;
237
+ line(`${style.green('installed')} ${target}`);
238
+ line(style.grey(` launchctl print gui/$(id -u)/${label} # live state`));
239
+ }
240
+ else {
241
+ line(`${style.grey('not installed')} ${target}`);
242
+ }
243
+ }
244
+ return installed ? 0 : 1;
245
+ }
246
+ if (action === 'uninstall') {
247
+ const removed = [plistPath, dreamPath, dreamHealthPath].filter((target) => fs.existsSync(target));
248
+ if (removed.length === 0) {
249
+ line(style.grey('not installed'));
250
+ return 0;
251
+ }
252
+ for (const target of removed) {
253
+ fs.rmSync(target);
254
+ line(`removed ${target}`);
255
+ }
256
+ line(style.grey(`run: launchctl bootout gui/$(id -u)/${PLIST_LABEL}`));
257
+ if (removed.includes(dreamPath)) {
258
+ line(style.grey(`run: launchctl bootout gui/$(id -u)/${DREAM_SCHEDULE_LABEL}`));
259
+ }
260
+ if (removed.includes(dreamHealthPath)) {
261
+ line(style.grey(`run: launchctl bootout gui/$(id -u)/${DREAM_HEALTH_LABEL}`));
262
+ }
263
+ return 0;
264
+ }
265
+ if (action !== 'install') {
266
+ line(SERVICE_HELP);
267
+ return 1;
268
+ }
269
+ // Before anything is written. A bad hour used to abort between the two agents, leaving the
270
+ // service installed, the nightly cycle not, and an error message about neither.
271
+ const hour = dreamHour(values['dream-hour']);
272
+ const { loadConfig } = await import('@tenphi/akno-core');
273
+ const config = loadConfig(openOptionsFrom(values));
274
+ const binary = process.argv[1] ?? 'akno';
275
+ // An installer reached through guided setup carries the exact target the user confirmed.
276
+ // Persist those flags in every agent; otherwise launchd would later resolve whichever
277
+ // checkout config happens to be visible from its working directory.
278
+ const targetArgs = serviceTargetArgs(values);
279
+ const args = ['serve', ...targetArgs, ...(values.http ? ['--http', values.http] : [])];
280
+ fs.mkdirSync(agents, { recursive: true });
281
+ fs.mkdirSync(config.logDir, { recursive: true });
282
+ fs.writeFileSync(plistPath, plist({
283
+ label: PLIST_LABEL,
284
+ node: process.execPath,
285
+ script: binary,
286
+ args,
287
+ logDir: config.logDir,
288
+ keepAlive: true,
289
+ }), 'utf8');
290
+ line(`wrote ${plistPath}`);
291
+ line(style.grey(`run: launchctl bootstrap gui/$(id -u) ${plistPath}`));
292
+ if (values.dream) {
293
+ // Observe runs on a schedule. A second agent rather than a timer inside `serve`,
294
+ // because the cycle is a *pass* with an exit code and a log — something a person can run
295
+ // by hand, read the output of, and undo — not a background thread nobody can address.
296
+ fs.writeFileSync(dreamPath, plist({
297
+ label: DREAM_SCHEDULE_LABEL,
298
+ node: process.execPath,
299
+ script: binary,
300
+ // Keep authority unqualified: `dream` resolves the current named profile every night.
301
+ // The marker enables local notification delivery; it does not change dream behaviour.
302
+ args: ['dream', '--scheduled', ...targetArgs],
303
+ logDir: config.logDir,
304
+ logName: 'dream',
305
+ calendarHour: hour,
306
+ }), 'utf8');
307
+ line(`wrote ${dreamPath} ${style.grey(`(daily at ${String(hour).padStart(2, '0')}:00)`)}`);
308
+ line(style.grey(` maintenance profile: ${config.maintenance.profile} (resolved at run time)`));
309
+ line(style.grey(`run: launchctl bootstrap gui/$(id -u) ${dreamPath}`));
310
+ const healthHour = (hour + 2) % 24;
311
+ fs.writeFileSync(dreamHealthPath, plist({
312
+ label: DREAM_HEALTH_LABEL,
313
+ node: process.execPath,
314
+ script: binary,
315
+ args: ['dream', 'notify', '--schedule-health', ...targetArgs],
316
+ logDir: config.logDir,
317
+ logName: 'dream-health',
318
+ calendarHour: healthHour,
319
+ calendarMinute: 5,
320
+ }), 'utf8');
321
+ line(`wrote ${dreamHealthPath} ${style.grey(`(daily at ${String(healthHour).padStart(2, '0')}:05; notification policy resolved at run time)`)}`);
322
+ line(style.grey(`run: launchctl bootstrap gui/$(id -u) ${dreamHealthPath}`));
323
+ }
324
+ line(style.grey(`logs: ${config.logDir}`));
325
+ return 0;
326
+ }
327
+ export function serviceTargetArgs(values) {
328
+ return [
329
+ ...(values['akno-path'] ? ['--akno-path', values['akno-path']] : []),
330
+ ...(values['state-dir'] ? ['--state-dir', values['state-dir']] : []),
331
+ ];
332
+ }
333
+ /** An hour outside 0-23 is a typo, and a nightly job at "25:00" would silently never run. */
334
+ function dreamHour(raw) {
335
+ if (raw === undefined)
336
+ return 3;
337
+ const hour = Number(raw);
338
+ if (!Number.isInteger(hour) || hour < 0 || hour > 23) {
339
+ throw new AknoError('invalid', `--dream-hour wants 0-23, not '${raw}'`);
340
+ }
341
+ return hour;
342
+ }
343
+ /** Exported for exact scheduler fixture tests; service installation is the only production caller. */
344
+ export function plist(options) {
345
+ const { label, node, script, args, logDir } = options;
346
+ const logName = options.logName ?? 'akno';
347
+ const programArgs = [node, script, ...args]
348
+ .map((arg) => ` <string>${escapeXml(arg)}</string>`)
349
+ .join('\n');
350
+ const schedule = options.calendarHour === undefined
351
+ ? ` <key>RunAtLoad</key><true/>\n <key>KeepAlive</key>${options.keepAlive ? '<true/>' : '<false/>'}`
352
+ : ` <key>StartCalendarInterval</key>\n <dict><key>Hour</key><integer>${options.calendarHour}</integer><key>Minute</key><integer>${options.calendarMinute ?? 0}</integer></dict>`;
353
+ return `<?xml version="1.0" encoding="UTF-8"?>
354
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
355
+ <plist version="1.0">
356
+ <dict>
357
+ <key>Label</key><string>${label}</string>
358
+ <key>ProgramArguments</key>
359
+ <array>
360
+ ${programArgs}
361
+ </array>
362
+ ${schedule}
363
+ <key>ProcessType</key><string>Background</string>
364
+ <key>StandardOutPath</key><string>${escapeXml(path.join(logDir, `${logName}.log`))}</string>
365
+ <key>StandardErrorPath</key><string>${escapeXml(path.join(logDir, `${logName}.err.log`))}</string>
366
+ </dict>
367
+ </plist>
368
+ `;
369
+ }
370
+ function escapeXml(value) {
371
+ return value.replace(/[<>&'"]/g, (char) => {
372
+ switch (char) {
373
+ case '<':
374
+ return '&lt;';
375
+ case '>':
376
+ return '&gt;';
377
+ case '&':
378
+ return '&amp;';
379
+ case "'":
380
+ return '&apos;';
381
+ default:
382
+ return '&quot;';
383
+ }
384
+ });
385
+ }
386
+ /**
387
+ * Wait for the process holding the write handle to exit, then stand down so a supervisor can
388
+ * restart this one with the handle.
389
+ *
390
+ * Exit code 0 on purpose: nothing failed. Under launchd's `KeepAlive` the replacement is up in a
391
+ * second, and under no supervisor at all the operator gets a line saying exactly what happened and
392
+ * what to do.
393
+ */
394
+ function watchForAReleasedHandle(heldBy, log) {
395
+ if (heldBy === null)
396
+ return;
397
+ const timer = setInterval(() => {
398
+ if (isAlive(heldBy))
399
+ return;
400
+ clearInterval(timer);
401
+ log(`pid ${heldBy} has exited and the write handle is free — restarting to take it`);
402
+ process.exit(0);
403
+ }, 15_000);
404
+ timer.unref();
405
+ }
406
+ function isAlive(pid) {
407
+ try {
408
+ process.kill(pid, 0);
409
+ return true;
410
+ }
411
+ catch (err) {
412
+ return err.code === 'EPERM';
413
+ }
414
+ }
415
+ //# sourceMappingURL=serve-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-cmd.js","sourceRoot":"","sources":["../../src/commands/serve-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function timelineCommand(argv: string[]): Promise<number>;
2
+ //# sourceMappingURL=timeline-cmd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-cmd.d.ts","sourceRoot":"","sources":["../../src/commands/timeline-cmd.ts"],"names":[],"mappings":"AAkBA,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA+DrE"}
@@ -0,0 +1,67 @@
1
+ import { openOptionsFrom, parse } from "../args.js";
2
+ import { json, line, statusLabel, style, truncate } from "../output.js";
3
+ import { resolveOps } from "../ops-handle.js";
4
+ const TIMELINE_HELP = `akno timeline [options]
5
+
6
+ When things happened. Authored events remain distinct from dated orphan
7
+ document evidence, whose date basis and source citation are shown explicitly.
8
+
9
+ --since <YYYY[-MM[-DD]]>
10
+ --until <YYYY[-MM[-DD]]>
11
+ --match <text> Substring match on the summary.
12
+ --subject <id> Page slug or orphan document id/path.
13
+ --source <kind> event | document | both (default)
14
+ --order <o> newest | oldest
15
+ --limit <n>
16
+ --json`;
17
+ export async function timelineCommand(argv) {
18
+ const { values } = parse(argv, {
19
+ since: { type: 'string' },
20
+ until: { type: 'string' },
21
+ match: { type: 'string' },
22
+ subject: { type: 'string' },
23
+ order: { type: 'string' },
24
+ limit: { type: 'string' },
25
+ source: { type: 'string' },
26
+ });
27
+ if (values.help) {
28
+ line(TIMELINE_HELP);
29
+ return 0;
30
+ }
31
+ const handle = await resolveOps(values, openOptionsFrom(values));
32
+ try {
33
+ const result = await handle.ops.timeline({
34
+ ...(values.since ? { since: values.since } : {}),
35
+ ...(values.until ? { until: values.until } : {}),
36
+ ...(values.match ? { match: values.match } : {}),
37
+ ...(values.subject ? { subject: values.subject } : {}),
38
+ ...(values.order ? { order: values.order } : {}),
39
+ ...(values.limit ? { limit: Number(values.limit) } : {}),
40
+ ...(values.source ? { source: values.source } : {}),
41
+ });
42
+ if (values.json) {
43
+ json(result);
44
+ return 0;
45
+ }
46
+ line(`${statusLabel(result.status)} ${style.grey(`${result.total} result${result.total === 1 ? '' : 's'}`)}` +
47
+ `${result.results.length < result.total ? style.grey(` (showing ${result.results.length})`) : ''}`);
48
+ for (const entry of result.results) {
49
+ if (entry.type === 'document_evidence') {
50
+ const page = entry.matched_page ? ` p${entry.matched_page}` : '';
51
+ line(` ${style.bold(entry.date)} ${truncate(entry.label, 80)} ` +
52
+ style.grey(`[${entry.date_basis}; ${entry.path}${page}]`));
53
+ if (entry.quote)
54
+ line(` ${truncate(entry.quote.replaceAll('\n', ' '), 100)}`);
55
+ continue;
56
+ }
57
+ const target = entry.slug ? style.cyan(` → ${entry.slug}`) : '';
58
+ const source = style.grey(` [${entry.source}${entry.line ? `:${entry.line}` : ''}]`);
59
+ line(` ${style.bold(entry.date)} ${truncate(entry.summary, 80)}${target}${source}`);
60
+ }
61
+ return 0;
62
+ }
63
+ finally {
64
+ await handle.close();
65
+ }
66
+ }
67
+ //# sourceMappingURL=timeline-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline-cmd.js","sourceRoot":"","sources":["../../src/commands/timeline-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ export declare function writeCommand(argv: string[]): Promise<number>;
2
+ /**
3
+ * `conflict`, `requires_approval` and `requires_folder` are not failures — they are the layer
4
+ * doing its job, and they must reach the caller as distinguishable results. Exit code 2 marks
5
+ * "needs a decision", separate from 1.
6
+ *
7
+ * The three are not the same kind of thing, and the output says which. A conflict and an
8
+ * approval want a person; `requires_folder` wants a sentence from whoever is writing, and
9
+ * printing it under a heading that says "approval" is how a caller learns to wait for
10
+ * somebody who is never coming.
11
+ */
12
+ export declare function printWriteOutcome(result: {
13
+ outcome: string;
14
+ status: string;
15
+ change_id?: string;
16
+ wrote?: {
17
+ slug: string;
18
+ line?: number;
19
+ action: string;
20
+ }[];
21
+ facts?: {
22
+ retired: number;
23
+ added: number;
24
+ };
25
+ documents?: {
26
+ id: string;
27
+ rel_path: string;
28
+ text_from?: string;
29
+ }[];
30
+ conflict?: {
31
+ slug: string;
32
+ line: number;
33
+ existing: string;
34
+ incoming: string;
35
+ token: string;
36
+ };
37
+ approval?: {
38
+ proposal_id: string;
39
+ reason: string;
40
+ nearest: string[];
41
+ };
42
+ requires_folder?: {
43
+ folder: string;
44
+ nearest: string[];
45
+ };
46
+ note?: string;
47
+ }): number;
48
+ export declare function rememberCommand(argv: string[]): Promise<number>;
49
+ //# sourceMappingURL=write-cmd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-cmd.d.ts","sourceRoot":"","sources":["../../src/commands/write-cmd.ts"],"names":[],"mappings":"AAiCA,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA4FlE;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1D,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,SAAS,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACnE,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7F,QAAQ,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACtE,eAAe,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACxD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,MAAM,CAgET;AAqCD,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAsFrE"}