memoryd (files, the check, edits, journal, index, recall, serving), the memory tools and built-in grants in brokerd, the memory block in loopd, bxctl reindex and memory, and the device checks with memoryd. Each task was built as a reference and gated. Each was replayed on its own at its end state (854 to 936 tests) and mutation-checked. Each skeleton compiles and fails its tests. Every todo comment was read beside its signature. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
77 lines
3.4 KiB
Rust
77 lines
3.4 KiB
Rust
//! The owner's memory commands over `memoryd`'s owner socket: `reindex`, and `memory log`,
|
|
//! `undo`, `pending`, `accept`, `reject` (M5a spec, section 10).
|
|
|
|
use std::io::Write;
|
|
use std::os::unix::net::UnixStream;
|
|
use std::path::{Path, PathBuf};
|
|
use std::time::Duration;
|
|
|
|
use proto::{
|
|
Empty, Envelope, MemoryAdmin, MemoryCommand, Message, PROTOCOL_VERSION, read_frame, write_frame,
|
|
};
|
|
|
|
use crate::cli::{Command, UsageError};
|
|
use crate::escape::escape_json_text;
|
|
|
|
/// How long `bxctl` waits for `memoryd`: a reindex reads every session log.
|
|
pub const MEMORY_TIMEOUT: Duration = Duration::from_secs(300);
|
|
|
|
pub fn default_socket(home: &Path) -> PathBuf {
|
|
home.join("run").join("owner-memory").join("admin.sock")
|
|
}
|
|
|
|
/// What to ask `memoryd`.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum Ask {
|
|
Reindex,
|
|
Admin(MemoryCommand, String),
|
|
}
|
|
|
|
/// `bxctl reindex [--memory-socket PATH]`.
|
|
pub fn parse_reindex(args: &[String], home: &Path) -> Result<Command, UsageError> {
|
|
// `socket_flag(args, home)?`; any argument left -> Err(UsageError). Ok(Command::Memory {
|
|
// socket, ask: Ask::Reindex }).
|
|
todo!()
|
|
}
|
|
|
|
/// `bxctl memory log [N] | undo <id> | pending | accept <id> | reject <id>`, each with an optional
|
|
/// `--memory-socket PATH`.
|
|
pub fn parse_memory(args: &[String], home: &Path) -> Result<Command, UsageError> {
|
|
// `socket_flag(args, home)?`, then match what is left: ["log"] -> Admin(Log, ""); ["log", n]
|
|
// where n parses as usize -> Admin(Log, n); ["pending"] -> Admin(Pending, ""); ["undo", id] ->
|
|
// Admin(Undo, id); ["accept", id] -> Admin(Accept, id); ["reject", id] -> Admin(Reject, id);
|
|
// anything else -> Err(UsageError). Ok(Command::Memory { socket, ask }).
|
|
todo!()
|
|
}
|
|
|
|
/// Take `--memory-socket PATH` out of `args`, once at most; the rest in order.
|
|
fn socket_flag(args: &[String], home: &Path) -> Result<(PathBuf, Vec<String>), UsageError> {
|
|
// Walk `args`: "--memory-socket" takes the next argument as the socket (none ->
|
|
// Err(UsageError); a second --memory-socket -> Err(UsageError)); every other argument is kept
|
|
// in order. The socket defaults to `default_socket(home)`. Ok((socket, rest)).
|
|
todo!()
|
|
}
|
|
|
|
/// `n` with commas between thousands.
|
|
fn grouped(n: u64) -> String {
|
|
// As memoryd's `grouped`: the digits of n with a comma before each char at index i > 0 where
|
|
// `(digits.len() - i).is_multiple_of(3)`.
|
|
todo!()
|
|
}
|
|
|
|
/// Ask `memoryd` and print its answer. `Err` is the line for stderr.
|
|
pub fn run(socket: &Path, ask: &Ask, timeout: Duration, out: &mut dyn Write) -> Result<(), String> {
|
|
// 1. Connect to `socket` and set read and write timeouts of `timeout`; each error ->
|
|
// format!("cannot reach memoryd at {}: {e}", socket.display()).
|
|
// 2. The message: Reindex -> Message::Reindex(Empty {}); Admin(command, arg) ->
|
|
// Message::MemoryAdmin(MemoryAdmin { command, arg }). `write_frame` it in an Envelope { v:
|
|
// PROTOCOL_VERSION, id: 1, final: true } (an error: the same "cannot reach" sentence).
|
|
// 3. `read_frame` (an error -> format!("memoryd did not answer: {e}")). Reindexed(r) ->
|
|
// format!("reindexed: {} logs, {} records, {} notes") with each count `grouped`;
|
|
// MemoryAdminReply(reply) -> reply.text; Error(e) -> Err(format!("memoryd: {}",
|
|
// escape_json_text(&e.detail))); anything else -> Err("memoryd answered with the wrong
|
|
// message").
|
|
// 4. `writeln!(out, "{text}")`, its error as a String.
|
|
todo!()
|
|
}
|