@ours.network/cli 1.0.1 → 2.0.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.
- package/README.md +21 -8
- package/dist/{boot-35BOHNSZ.js → boot-Y3GXCN6X.js} +1 -1
- package/dist/{chunk-QZIL3IT7.js → chunk-DTN7MN44.js} +29 -12
- package/dist/{chunk-MHVYJY3H.js → chunk-IL724CY2.js} +1517 -1013
- package/dist/{chunk-QRNZFPNJ.js → chunk-MS4TDUZY.js} +41 -42
- package/dist/{chunk-TNNBVUKK.js → chunk-NBAZ2NEL.js} +2 -2
- package/dist/{chunk-SDNTPCKW.js → chunk-VA6UQKYN.js} +16 -18
- package/dist/{chunk-ZFE47KH3.js → chunk-VFAC74XR.js} +4 -4
- package/dist/commands.d.ts +16 -18
- package/dist/commands.js +1 -1
- package/dist/{daemon-UUG6P6GK.js → daemon-A2L6UMGZ.js} +2 -2
- package/dist/help.js +3 -3
- package/dist/lifecycle.d.ts +3 -0
- package/dist/lifecycle.js +5 -1
- package/dist/main.js +6 -6
- package/dist/mufl_code/{7962BB01B1D3E782A1F80B083A900AEC30BAC8F8CE79282B31821802B94A39B6.muflo → 351F16D444E6DAA252D4A8D829D17204360D9015FEF670ACE68FB4747BB3B14E.muflo} +0 -0
- package/dist/operations.d.ts +32 -57
- package/dist/operations.js +1 -1
- package/dist/{server-TDJBEWTU.js → server-6BZCHN6Q.js} +206 -143
- package/dist/service.js +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -61,10 +61,11 @@ ours daemon stop
|
|
|
61
61
|
ours daemon restart
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
`stop` and `restart`
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
`stop` and `restart` control the selected daemon regardless of which CLI command
|
|
65
|
+
or service launcher originally started it. The endpoint must identify itself as
|
|
66
|
+
an ours daemon for the exact selected state directory; once that validation
|
|
67
|
+
passes, the daemon-reported PID is authoritative. PID files are compatibility
|
|
68
|
+
metadata and never an authorization or ownership gate.
|
|
68
69
|
`start`, `serve`, and `restart` reject `--endpoint` because they must launch a
|
|
69
70
|
locally selected daemon; this rejection happens before `restart` probes or stops
|
|
70
71
|
anything.
|
|
@@ -114,9 +115,9 @@ identity create | create-root | create-temporary | close-temporary
|
|
|
114
115
|
profile set-bio | set-persona
|
|
115
116
|
invite create | list | revoke | accept
|
|
116
117
|
contact list | local | policy | remove | rename | respond
|
|
117
|
-
message send | list | get
|
|
118
|
-
file send | list | get | fetch
|
|
119
|
-
|
|
118
|
+
message send | list | get
|
|
119
|
+
file send | list | get | fetch
|
|
120
|
+
history list | get | files | file-info
|
|
120
121
|
daemon info | identities | unread | watch
|
|
121
122
|
```
|
|
122
123
|
|
|
@@ -128,13 +129,25 @@ ours profile set-bio --identity BuildBot --bio= # clear the bio
|
|
|
128
129
|
ours profile set-persona --identity BuildBot --persona= # clear the persona
|
|
129
130
|
ours message send --identity BuildBot --contact Peer --text "done" --json
|
|
130
131
|
ours file get --identity BuildBot --wire-ids ID1,ID2 --json
|
|
131
|
-
ours
|
|
132
|
+
ours history list --identity Human --limit 25 --json
|
|
133
|
+
ours history files --identity Human --peer-cid PEER_CID --json
|
|
132
134
|
```
|
|
133
135
|
|
|
134
136
|
An explicit file retrieval accepts 1–32 unique 64-hex wire IDs. `daemon watch`
|
|
135
137
|
first binds its `--identity` without force, changing the CLI lease; it can fail
|
|
136
138
|
with `BOUND_ELSEWHERE` when another live session holds that identity.
|
|
137
139
|
|
|
140
|
+
Message and file payloads live in identity-scoped SQLite/blob storage, not in
|
|
141
|
+
the MUFL packet. `message get` and `file get` consume only the selected unread
|
|
142
|
+
rows; the `history` group provides the persistent read-only view. There is no
|
|
143
|
+
defer, conversation-policy, or manual mark-read command.
|
|
144
|
+
|
|
145
|
+
This storage epoch requires a clean reset. Old daemon state is not migrated:
|
|
146
|
+
startup refuses it without modifying it. Stop applications, optionally copy the
|
|
147
|
+
old state as a manual backup, remove it yourself, and start clean. Old
|
|
148
|
+
identities, contacts, invites, pending payloads, and history are not carried
|
|
149
|
+
forward, and the installer never removes state automatically.
|
|
150
|
+
|
|
138
151
|
Malformed JSON, unknown input fields, invalid booleans/integers, and incomplete
|
|
139
152
|
file inputs fail closed before the request. Destructive identity/contact/invite
|
|
140
153
|
operations require `--yes`.
|
|
@@ -9,6 +9,7 @@ import { spawn as nodeSpawn } from "node:child_process";
|
|
|
9
9
|
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { join, resolve } from "node:path";
|
|
11
11
|
var MANAGED_PID_FILE = "ours-cli-daemon.json";
|
|
12
|
+
var LEGACY_MANAGED_PID_FILE = "daemon.pid";
|
|
12
13
|
var DAEMON_LOG_FILE = "ours-cli-daemon.log";
|
|
13
14
|
var depsDefault = {
|
|
14
15
|
fetch: globalThis.fetch,
|
|
@@ -19,6 +20,17 @@ var depsDefault = {
|
|
|
19
20
|
cliPath: process.argv[1]
|
|
20
21
|
};
|
|
21
22
|
var pidPath = (stateDir) => join(stateDir, MANAGED_PID_FILE);
|
|
23
|
+
var legacyPidPath = (stateDir) => join(stateDir, LEGACY_MANAGED_PID_FILE);
|
|
24
|
+
function readLegacyManagedPid(stateDir) {
|
|
25
|
+
try {
|
|
26
|
+
const raw = readFileSync(legacyPidPath(stateDir), "utf8").trim();
|
|
27
|
+
if (!/^[0-9]+$/.test(raw)) return null;
|
|
28
|
+
const pid = Number(raw);
|
|
29
|
+
return Number.isSafeInteger(pid) && pid > 1 ? pid : null;
|
|
30
|
+
} catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
22
34
|
function readManagedRecord(stateDir) {
|
|
23
35
|
try {
|
|
24
36
|
const value = JSON.parse(readFileSync(pidPath(stateDir), "utf8"));
|
|
@@ -49,7 +61,9 @@ function writeManagedRecord(stateDir, port) {
|
|
|
49
61
|
async function inspectDaemon(config, deps = depsDefault) {
|
|
50
62
|
const stateDir = resolve(config.expectStateDir);
|
|
51
63
|
const record = readManagedRecord(stateDir);
|
|
52
|
-
const
|
|
64
|
+
const legacyPid = readLegacyManagedPid(stateDir);
|
|
65
|
+
const hasOwnershipRecord = record !== null || legacyPid !== null;
|
|
66
|
+
const base = { stateDir, pidFile: pidPath(stateDir), stalePidFile: hasOwnershipRecord };
|
|
53
67
|
let client;
|
|
54
68
|
try {
|
|
55
69
|
client = await attachClient(config, { fetch: deps.fetch, leaseToken: "ours-cli-status" });
|
|
@@ -71,10 +85,7 @@ async function inspectDaemon(config, deps = depsDefault) {
|
|
|
71
85
|
if (info.name !== "ours" || !Number.isInteger(info.pid) || info.pid <= 1 || resolve(info.stateDir) !== stateDir) {
|
|
72
86
|
throw new Error("the selected endpoint did not return a valid ours daemon identity");
|
|
73
87
|
}
|
|
74
|
-
|
|
75
|
-
const selectedPort = Number(selectedUrl.port || (selectedUrl.protocol === "https:" ? 443 : 80));
|
|
76
|
-
const managed = record !== null && record.pid === info.pid && resolve(record.stateDir) === stateDir && record.port === selectedPort;
|
|
77
|
-
return { state: "running", managed, info, ...base, stalePidFile: record !== null && !managed };
|
|
88
|
+
return { state: "running", managed: true, info, ...base, stalePidFile: false };
|
|
78
89
|
}
|
|
79
90
|
function childEnvironment(selection) {
|
|
80
91
|
const env = { ...process.env };
|
|
@@ -87,7 +98,7 @@ function childEnvironment(selection) {
|
|
|
87
98
|
async function serveDaemon(selection, managed = false) {
|
|
88
99
|
if (selection.endpoint !== void 0) throw new Error("--endpoint selects a running daemon and cannot be used with daemon serve");
|
|
89
100
|
Object.assign(process.env, childEnvironment(selection));
|
|
90
|
-
const { startDaemon } = await import("./daemon-
|
|
101
|
+
const { startDaemon } = await import("./daemon-A2L6UMGZ.js");
|
|
91
102
|
const handle = await startDaemon();
|
|
92
103
|
if (managed) {
|
|
93
104
|
const response = await fetch(`http://127.0.0.1:${handle.port}/state-dir`);
|
|
@@ -125,7 +136,7 @@ async function startDaemonManaged(selection, deps = depsDefault) {
|
|
|
125
136
|
while (deps.now() < deadline) {
|
|
126
137
|
await deps.delay(100);
|
|
127
138
|
const status = await inspectDaemon(config, deps);
|
|
128
|
-
if (status.state === "running" && status.
|
|
139
|
+
if (status.state === "running" && status.info?.pid === child.pid) return status;
|
|
129
140
|
try {
|
|
130
141
|
deps.kill(child.pid, 0);
|
|
131
142
|
} catch {
|
|
@@ -146,6 +157,12 @@ function removeOwnedPidFile(status) {
|
|
|
146
157
|
} catch {
|
|
147
158
|
}
|
|
148
159
|
}
|
|
160
|
+
if (readLegacyManagedPid(status.stateDir) !== null) {
|
|
161
|
+
try {
|
|
162
|
+
unlinkSync(legacyPidPath(status.stateDir));
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
}
|
|
149
166
|
}
|
|
150
167
|
async function stopDaemonManaged(config, deps = depsDefault) {
|
|
151
168
|
const status = await inspectDaemon(config, deps);
|
|
@@ -153,10 +170,8 @@ async function stopDaemonManaged(config, deps = depsDefault) {
|
|
|
153
170
|
removeOwnedPidFile(status);
|
|
154
171
|
return status;
|
|
155
172
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
deps.kill(status.info.pid, "SIGTERM");
|
|
173
|
+
const pid = status.info.pid;
|
|
174
|
+
deps.kill(pid, "SIGTERM");
|
|
160
175
|
const deadline = deps.now() + 1e4;
|
|
161
176
|
while (deps.now() < deadline) {
|
|
162
177
|
await deps.delay(100);
|
|
@@ -166,12 +181,14 @@ async function stopDaemonManaged(config, deps = depsDefault) {
|
|
|
166
181
|
return { ...current, stalePidFile: false };
|
|
167
182
|
}
|
|
168
183
|
}
|
|
169
|
-
throw new Error(`daemon pid ${
|
|
184
|
+
throw new Error(`daemon pid ${pid} did not stop within 10 seconds`);
|
|
170
185
|
}
|
|
171
186
|
|
|
172
187
|
export {
|
|
173
188
|
MANAGED_PID_FILE,
|
|
189
|
+
LEGACY_MANAGED_PID_FILE,
|
|
174
190
|
DAEMON_LOG_FILE,
|
|
191
|
+
readLegacyManagedPid,
|
|
175
192
|
readManagedRecord,
|
|
176
193
|
writeManagedRecord,
|
|
177
194
|
inspectDaemon,
|