@ours.network/cli 2.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 CHANGED
@@ -61,10 +61,11 @@ ours daemon stop
61
61
  ours daemon restart
62
62
  ```
63
63
 
64
- `stop` and `restart` signal a process only when all three facts agree: the
65
- CLI-owned PID record, the PID reported by the selected daemon, and its expected
66
- state directory/port. A daemon started by ours-mcp, a container, systemd, or any
67
- other launcher remains fully attachable, but these commands refuse to signal it.
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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  bootWrapper,
3
3
  wrapperBooted
4
- } from "./chunk-LJ35FDQH.js";
4
+ } from "./chunk-IL724CY2.js";
5
5
  import "./chunk-FXKFSNKS.js";
6
6
  export {
7
7
  bootWrapper,
@@ -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 base = { stateDir, pidFile: pidPath(stateDir), stalePidFile: record !== null };
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
- const selectedUrl = new URL(config.baseUrl.value);
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-YCC24SVU.js");
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.managed && status.info?.pid === child.pid) return 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
- if (!status.managed || !status.info) {
157
- throw new Error("the daemon is running but was not started by @ours.network/cli; refusing to signal an external shared daemon");
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 ${status.info.pid} did not stop within 10 seconds`);
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,
@@ -89,7 +89,7 @@ function createStartupProgressReporter(stateDir, opts = {}) {
89
89
  }
90
90
 
91
91
  // ../../src/runtime/env.ts
92
- var VERSION = true ? "3.0.1" : "0.0.0-dev";
92
+ var VERSION = true ? "3.0.2" : "0.0.0-dev";
93
93
  var CONFIG = loadConfig();
94
94
  var STATE_DIR = CONFIG.stateDir;
95
95
  var BROKER_URL = CONFIG.brokerUrl;
@@ -639,12 +639,30 @@ function listIncomingMessages(id) {
639
639
  function takeUnreadMessages(id, input = {}) {
640
640
  const db = openHistory(id);
641
641
  const limit = batchLimit(input.limit);
642
+ const requested = input.wire_ids;
642
643
  return db.transaction(() => {
643
- const rows = db.prepare(`
644
- SELECT * FROM messages
645
- WHERE direction = 'in' AND inbox_state = 'unread'
646
- ORDER BY seq ASC LIMIT ?
647
- `).all(limit);
644
+ let rows;
645
+ if (requested !== void 0) {
646
+ if (requested.length < 1 || requested.length > MAX_BATCH) {
647
+ throw new Error(`wire_ids must contain 1-${MAX_BATCH} items`);
648
+ }
649
+ if (new Set(requested).size !== requested.length) {
650
+ throw new Error("wire_ids must not contain duplicates");
651
+ }
652
+ const get = db.prepare(`
653
+ SELECT * FROM messages WHERE wire_id = ? AND direction = 'in' AND inbox_state = 'unread'
654
+ `);
655
+ rows = requested.map((wireId) => get.get(wireId)).filter((row) => !!row);
656
+ if (rows.length !== requested.length) {
657
+ throw new Error("selected message wire_id is unknown, stale, or no longer unread");
658
+ }
659
+ } else {
660
+ rows = db.prepare(`
661
+ SELECT * FROM messages
662
+ WHERE direction = 'in' AND inbox_state = 'unread'
663
+ ORDER BY seq ASC LIMIT ?
664
+ `).all(limit);
665
+ }
648
666
  const mark = db.prepare(`
649
667
  UPDATE messages SET inbox_state = 'read'
650
668
  WHERE seq = ? AND direction = 'in' AND inbox_state = 'unread'
@@ -729,6 +747,14 @@ function getMessageHistoryItem(id, wireId) {
729
747
  const row = openHistory(id).prepare("SELECT * FROM messages WHERE wire_id = ?").get(wireId);
730
748
  return row ? messageFromRow(row) : null;
731
749
  }
750
+ function getMessageHistorySummary(id, input) {
751
+ const row = openHistory(id).prepare(`
752
+ SELECT COUNT(*) AS total,
753
+ SUM(CASE WHEN direction = 'in' AND inbox_state = 'unread' THEN 1 ELSE 0 END) AS unread
754
+ FROM messages WHERE peer_cid = ?
755
+ `).get(input.peer_cid);
756
+ return { total: Number(row.total), unread: Number(row.unread ?? 0) };
757
+ }
732
758
  function listFileHistory(id, query = {}) {
733
759
  const db = openHistory(id);
734
760
  const limit = batchLimit(query.limit);
@@ -2942,6 +2968,7 @@ export {
2942
2968
  takeUnreadFiles,
2943
2969
  listMessageHistory,
2944
2970
  getMessageHistoryItem,
2971
+ getMessageHistorySummary,
2945
2972
  listFileHistory,
2946
2973
  getFileHistoryItem,
2947
2974
  FILE_SELECTION_CAP,
@@ -73,7 +73,7 @@ function createLinuxUserSystemdAdapter(deps = defaultDeps) {
73
73
  const unitName = unitNameForStateDir(stateDir);
74
74
  const serviceFile = join(home, ".config", "systemd", "user", unitName);
75
75
  const unitConfig = context.configPath ? resolve(context.configPath) : void 0;
76
- const args = [process.execPath, resolve(context.cliPath), "daemon", "serve"];
76
+ const args = [process.execPath, resolve(context.cliPath), "daemon", "serve", "--managed"];
77
77
  if (unitConfig) args.push("--config", unitConfig);
78
78
  const environment = `Environment=OURS_STATE_DIR=${systemdEscapeArgument(stateDir)}
79
79
  `;
@@ -165,7 +165,7 @@ function createMacosUserLaunchdAdapter(deps = defaultDeps) {
165
165
  async install(context) {
166
166
  const { stateDir, unitName, serviceFile } = plan(context);
167
167
  const unitConfig = context.configPath ? resolve(context.configPath) : void 0;
168
- const args = [process.execPath, resolve(context.cliPath), "daemon", "serve"];
168
+ const args = [process.execPath, resolve(context.cliPath), "daemon", "serve", "--managed"];
169
169
  if (unitConfig) args.push("--config", unitConfig);
170
170
  const unit = `<?xml version="1.0" encoding="UTF-8"?>
171
171
  ${PLIST_MARKER}
@@ -8,7 +8,7 @@ var COMMAND_GROUPS = {
8
8
  kind: "daemon",
9
9
  handler: "serve",
10
10
  summary: "Run the daemon in the foreground until interrupted.",
11
- effects: "Starts a daemon in this process. --managed also writes the CLI-owned PID record used by stop and restart.",
11
+ effects: "Starts a daemon in this process. --managed writes process metadata for compatibility and cleanup.",
12
12
  example: "ours daemon serve --config /etc/ours/config.json"
13
13
  },
14
14
  start: {
@@ -21,21 +21,21 @@ var COMMAND_GROUPS = {
21
21
  stop: {
22
22
  kind: "daemon",
23
23
  handler: "stop",
24
- summary: "Stop a daemon previously started by this CLI.",
25
- effects: "Signals only a process corroborated by the selected daemon and CLI-owned PID record; it refuses to signal externally managed daemons.",
24
+ summary: "Stop the selected ours daemon.",
25
+ effects: "Signals the process identity reported by the selected valid ours daemon.",
26
26
  example: "ours daemon stop --config /etc/ours/config.json"
27
27
  },
28
28
  restart: {
29
29
  kind: "daemon",
30
30
  handler: "restart",
31
- summary: "Stop and start a CLI-managed daemon.",
32
- effects: "Uses the same ownership checks as stop, then starts a detached replacement.",
31
+ summary: "Stop and start the selected ours daemon.",
32
+ effects: "Stops the selected valid ours daemon, then starts a detached replacement.",
33
33
  example: "ours daemon restart --config /etc/ours/config.json"
34
34
  },
35
35
  status: {
36
36
  kind: "daemon",
37
37
  handler: "status",
38
- summary: "Report whether the selected daemon is running and CLI-managed.",
38
+ summary: "Report whether the selected ours daemon is running.",
39
39
  effects: "Read-only. Exit status is 0 when running and 3 when stopped.",
40
40
  example: "ours daemon status --json"
41
41
  },
@@ -13,7 +13,7 @@ import {
13
13
  IDENTITY_PREBIND_EXCEPTIONS,
14
14
  commandSpec,
15
15
  isCommandGroup
16
- } from "./chunk-NWRXKQBD.js";
16
+ } from "./chunk-VA6UQKYN.js";
17
17
 
18
18
  // src/help.ts
19
19
  var pad = (value, width = 32) => value.length >= width ? `${value} ` : value.padEnd(width);
@@ -109,7 +109,7 @@ function nativeDaemonOptions(action) {
109
109
  ["--identity NAME", "Compatibility-only/ignored by daemon lifecycle and service commands."],
110
110
  ["--json", action === "serve" ? "Compatibility-only/ignored because serve runs until interrupted." : "Write one JSON result to stdout."],
111
111
  ["--yes", service.has(action) ? "Confirm the service-manager change; not needed with --dry-run." : "Compatibility-only/ignored for this action."],
112
- ["--managed", action === "serve" ? "Write the CLI-owned PID record after the foreground daemon starts." : "Compatibility-only/ignored for this action."],
112
+ ["--managed", action === "serve" ? "Write daemon process metadata after the foreground daemon starts." : "Compatibility-only/ignored for this action."],
113
113
  ["--dry-run", service.has(action) ? "Return the planned service-manager changes without writing or running systemctl." : "Compatibility-only/ignored for this action."],
114
114
  ["--force", install ? "Allow replacement of an existing user unit not marked as CLI-managed." : "Compatibility-only/ignored for this action."],
115
115
  ["--help", "Show this help and exit without starting, stopping, probing, or installing anything."]
@@ -30,7 +30,7 @@ export declare const COMMAND_GROUPS: {
30
30
  readonly kind: "daemon";
31
31
  readonly handler: "serve";
32
32
  readonly summary: "Run the daemon in the foreground until interrupted.";
33
- readonly effects: "Starts a daemon in this process. --managed also writes the CLI-owned PID record used by stop and restart.";
33
+ readonly effects: "Starts a daemon in this process. --managed writes process metadata for compatibility and cleanup.";
34
34
  readonly example: "ours daemon serve --config /etc/ours/config.json";
35
35
  };
36
36
  readonly start: {
@@ -43,21 +43,21 @@ export declare const COMMAND_GROUPS: {
43
43
  readonly stop: {
44
44
  readonly kind: "daemon";
45
45
  readonly handler: "stop";
46
- readonly summary: "Stop a daemon previously started by this CLI.";
47
- readonly effects: "Signals only a process corroborated by the selected daemon and CLI-owned PID record; it refuses to signal externally managed daemons.";
46
+ readonly summary: "Stop the selected ours daemon.";
47
+ readonly effects: "Signals the process identity reported by the selected valid ours daemon.";
48
48
  readonly example: "ours daemon stop --config /etc/ours/config.json";
49
49
  };
50
50
  readonly restart: {
51
51
  readonly kind: "daemon";
52
52
  readonly handler: "restart";
53
- readonly summary: "Stop and start a CLI-managed daemon.";
54
- readonly effects: "Uses the same ownership checks as stop, then starts a detached replacement.";
53
+ readonly summary: "Stop and start the selected ours daemon.";
54
+ readonly effects: "Stops the selected valid ours daemon, then starts a detached replacement.";
55
55
  readonly example: "ours daemon restart --config /etc/ours/config.json";
56
56
  };
57
57
  readonly status: {
58
58
  readonly kind: "daemon";
59
59
  readonly handler: "status";
60
- readonly summary: "Report whether the selected daemon is running and CLI-managed.";
60
+ readonly summary: "Report whether the selected ours daemon is running.";
61
61
  readonly effects: "Read-only. Exit status is 0 when running and 3 when stopped.";
62
62
  readonly example: "ours daemon status --json";
63
63
  };
package/dist/commands.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  IDENTITY_PREBIND_EXCEPTIONS,
5
5
  commandSpec,
6
6
  isCommandGroup
7
- } from "./chunk-NWRXKQBD.js";
7
+ } from "./chunk-VA6UQKYN.js";
8
8
  export {
9
9
  COMMAND_GROUPS,
10
10
  DESTRUCTIVE_OPERATIONS,
@@ -204,7 +204,7 @@ async function releaseHeld(lock) {
204
204
  async function bootKernel() {
205
205
  const { lock, acquired } = await ensureLock();
206
206
  try {
207
- const { bootWrapper } = await import("./boot-LJ2V4NSS.js");
207
+ const { bootWrapper } = await import("./boot-Y3GXCN6X.js");
208
208
  await bootWrapper();
209
209
  } catch (error) {
210
210
  if (acquired) await releaseHeld(lock);
@@ -214,7 +214,7 @@ async function bootKernel() {
214
214
  async function startDaemon(opts = {}) {
215
215
  const { lock, acquired } = await ensureLock();
216
216
  try {
217
- const runtime = await import("./server-2RIEOKDA.js");
217
+ const runtime = await import("./server-6BZCHN6Q.js");
218
218
  const { onRuntimeLoaded, ...daemonOptions } = opts;
219
219
  onRuntimeLoaded?.();
220
220
  const handle = await runtime.startDaemon({
package/dist/help.js CHANGED
@@ -3,10 +3,10 @@ import {
3
3
  helpRequestPath,
4
4
  renderHelp,
5
5
  renderTopHelp
6
- } from "./chunk-FKSRG5UJ.js";
6
+ } from "./chunk-VFAC74XR.js";
7
7
  import "./chunk-MS4TDUZY.js";
8
8
  import "./chunk-6NFATG6P.js";
9
- import "./chunk-NWRXKQBD.js";
9
+ import "./chunk-VA6UQKYN.js";
10
10
  export {
11
11
  helpHint,
12
12
  helpRequestPath,
@@ -2,6 +2,8 @@ import { spawn as nodeSpawn, type ChildProcess } from 'node:child_process';
2
2
  import type { DaemonInfo, ResolvedDaemonConfig } from '@ours.network/sdk/client';
3
3
  import { type SelectionOptions } from './connection.js';
4
4
  export declare const MANAGED_PID_FILE = "ours-cli-daemon.json";
5
+ /** PID file written by the pre-split @ours.network/mcp CLI. Retained only for cleanup. */
6
+ export declare const LEGACY_MANAGED_PID_FILE = "daemon.pid";
5
7
  export declare const DAEMON_LOG_FILE = "ours-cli-daemon.log";
6
8
  interface ManagedRecord {
7
9
  version: 1;
@@ -27,6 +29,7 @@ export interface LifecycleDeps {
27
29
  delay(ms: number): Promise<void>;
28
30
  cliPath: string;
29
31
  }
32
+ export declare function readLegacyManagedPid(stateDir: string): number | null;
30
33
  export declare function readManagedRecord(stateDir: string): ManagedRecord | null;
31
34
  export declare function writeManagedRecord(stateDir: string, port: number): string;
32
35
  export declare function inspectDaemon(config: ResolvedDaemonConfig, deps?: LifecycleDeps): Promise<DaemonStatus>;
package/dist/lifecycle.js CHANGED
@@ -1,18 +1,22 @@
1
1
  import {
2
2
  DAEMON_LOG_FILE,
3
+ LEGACY_MANAGED_PID_FILE,
3
4
  MANAGED_PID_FILE,
4
5
  inspectDaemon,
6
+ readLegacyManagedPid,
5
7
  readManagedRecord,
6
8
  serveDaemon,
7
9
  startDaemonManaged,
8
10
  stopDaemonManaged,
9
11
  writeManagedRecord
10
- } from "./chunk-NRPPG3WH.js";
12
+ } from "./chunk-DTN7MN44.js";
11
13
  import "./chunk-6K2JBKHI.js";
12
14
  export {
13
15
  DAEMON_LOG_FILE,
16
+ LEGACY_MANAGED_PID_FILE,
14
17
  MANAGED_PID_FILE,
15
18
  inspectDaemon,
19
+ readLegacyManagedPid,
16
20
  readManagedRecord,
17
21
  serveDaemon,
18
22
  startDaemonManaged,
package/dist/main.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-YC7QBGVC.js";
6
6
  import {
7
7
  createServiceAdapter
8
- } from "./chunk-TNNBVUKK.js";
8
+ } from "./chunk-NBAZ2NEL.js";
9
9
  import {
10
10
  instanceNameFromStateDir
11
11
  } from "./chunk-UZQWSOUB.js";
@@ -17,7 +17,7 @@ import {
17
17
  helpHint,
18
18
  helpRequestPath,
19
19
  renderHelp
20
- } from "./chunk-FKSRG5UJ.js";
20
+ } from "./chunk-VFAC74XR.js";
21
21
  import {
22
22
  invokeOperation,
23
23
  isOperationName,
@@ -37,13 +37,13 @@ import {
37
37
  IDENTITY_PREBIND_EXCEPTIONS,
38
38
  commandSpec,
39
39
  isCommandGroup
40
- } from "./chunk-NWRXKQBD.js";
40
+ } from "./chunk-VA6UQKYN.js";
41
41
  import {
42
42
  inspectDaemon,
43
43
  serveDaemon,
44
44
  startDaemonManaged,
45
45
  stopDaemonManaged
46
- } from "./chunk-NRPPG3WH.js";
46
+ } from "./chunk-DTN7MN44.js";
47
47
  import {
48
48
  attachClient,
49
49
  defaultConfigPath,
@@ -54,7 +54,7 @@ import {
54
54
  import { existsSync, readFileSync } from "node:fs";
55
55
  import { homedir } from "node:os";
56
56
  import { join, resolve } from "node:path";
57
- var CLI_VERSION = false ? "0.0.0-dev" : "2.0.1";
57
+ var CLI_VERSION = false ? "0.0.0-dev" : "2.0.2";
58
58
  var COMMON_VALUES = /* @__PURE__ */ new Set(["--endpoint", "--port", "--state-dir", "--config", "--identity"]);
59
59
  var COMMON_BOOLEANS = /* @__PURE__ */ new Set(["--json", "--yes", "--help"]);
60
60
  function selectionFrom(values) {
@@ -29,6 +29,7 @@ import {
29
29
  findIdentityFile,
30
30
  getFileHistoryItem,
31
31
  getMessageHistoryItem,
32
+ getMessageHistorySummary,
32
33
  hashLeaseToken,
33
34
  identities,
34
35
  isSelectableWireId,
@@ -78,7 +79,7 @@ import {
78
79
  withScope,
79
80
  withScopeAsync,
80
81
  writeTempMetaFile
81
- } from "./chunk-LJ35FDQH.js";
82
+ } from "./chunk-IL724CY2.js";
82
83
  import {
83
84
  buildIdentityFile,
84
85
  writeIdentityFile
@@ -1482,6 +1483,14 @@ function getHistoryItem(ctx, input) {
1482
1483
  throw errTool("get_history_item", String(error));
1483
1484
  }
1484
1485
  }
1486
+ function getHistorySummary(ctx, input) {
1487
+ const id = requireBound(ctx);
1488
+ try {
1489
+ return getMessageHistorySummary(id, input);
1490
+ } catch (error) {
1491
+ throw errTool("get_history_summary", String(error));
1492
+ }
1493
+ }
1485
1494
  function listFiles(ctx, query = {}) {
1486
1495
  const id = requireBound(ctx);
1487
1496
  try {
@@ -1539,6 +1548,7 @@ var API_OPERATIONS = {
1539
1548
  getMessages: op(getMessages),
1540
1549
  listHistory: op(listHistory),
1541
1550
  getHistoryItem: op(getHistoryItem),
1551
+ getHistorySummary: op(getHistorySummary),
1542
1552
  listFiles: op(listFiles),
1543
1553
  getFileInfo: op(getFileInfo),
1544
1554
  // ----- files (Task 12) -----------------------------------------------------
package/dist/service.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  createLinuxUserSystemdAdapter,
6
6
  createMacosUserLaunchdAdapter,
7
7
  createServiceAdapter
8
- } from "./chunk-TNNBVUKK.js";
8
+ } from "./chunk-NBAZ2NEL.js";
9
9
  import "./chunk-UZQWSOUB.js";
10
10
  export {
11
11
  SERVICE_NAME,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ours.network/cli",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "Transport-neutral operator CLI for the ours shared daemon",
5
5
  "type": "module",
6
6
  "license": "FSL-1.1-Apache-2.0",