memoryd: ask_memory served beside recall and memory, outside the lock
Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
@@ -27,6 +27,10 @@ pub const ANSWER_CAP: usize = 2_000;
|
||||
/// The answer when the question holds a known-prefix secret.
|
||||
pub const SECRET: &str = "ask_memory: not asked; the question looks like it holds a secret";
|
||||
|
||||
/// The answer without `[honcho]`: a result, not an error, so that the model reads it and moves on.
|
||||
pub const NOT_CONFIGURED: &str =
|
||||
"ask_memory: Honcho is not configured for this agent; recall searches its own memory";
|
||||
|
||||
/// The text of an answer with no content.
|
||||
pub const NO_ANSWER: &str = "(no answer)";
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
use std::time::Duration;
|
||||
|
||||
use bxcore::AskMemoryArgs;
|
||||
use bxcore::{
|
||||
DataClass, Empty, Envelope, ErrorCode, MemoryArgs, MemoryBlockReply, MemoryCall, Message,
|
||||
PROTOCOL_VERSION, RecallArgs, SessionId, SessionUpdated, Timestamp, ToolResponse, WireError,
|
||||
@@ -16,6 +17,7 @@ use bxcore::{
|
||||
use crate::config::Config;
|
||||
use crate::edit::{self, Context};
|
||||
use crate::files::Store;
|
||||
use crate::honcho::ask;
|
||||
use crate::honcho::ledger::{self, LedgerError};
|
||||
use crate::honcho::mirror::Mirror;
|
||||
use crate::honcho::search;
|
||||
@@ -318,16 +320,17 @@ impl Memoryd {
|
||||
Message::Ok(Empty {})
|
||||
}
|
||||
|
||||
/// A decided call from `brokerd`: `recall` or `memory`. `memory` runs under the one lock;
|
||||
/// `recall` takes it for the local index only (`recall`). `Failed` carries the sentence for
|
||||
/// the model.
|
||||
/// A decided call from `brokerd`: `recall`, `memory` or `ask_memory`. `memory` runs under
|
||||
/// the one lock; `recall` takes it for the local index only (`recall`); `ask_memory` never
|
||||
/// takes it. `Failed` carries the sentence for the model.
|
||||
fn call(&self, call: MemoryCall) -> ToolResponse {
|
||||
let result = match call.request.tool.as_str() {
|
||||
bxcore::memory::RECALL => self.recall(&call),
|
||||
bxcore::memory::MEMORY => self.memory(&self.lock(), &call),
|
||||
bxcore::memory::ASK_MEMORY => self.ask_memory(&call),
|
||||
_ => {
|
||||
return ToolResponse::Failed {
|
||||
message: "memoryd runs only recall and memory".to_string(),
|
||||
message: "memoryd runs only recall, memory and ask_memory".to_string(),
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -362,6 +365,26 @@ impl Memoryd {
|
||||
Ok(reading.recall(local, &args, &self.log))
|
||||
}
|
||||
|
||||
/// `ask_memory` (M5c spec, section 9): the workspaces named, asked by Honcho's chat, never
|
||||
/// under the lock. Its arguments are checked again, as `recall`'s are. Without `[honcho]`, a
|
||||
/// sentence that says so, labelled private and trusted.
|
||||
fn ask_memory(&self, call: &MemoryCall) -> Result<Recalled, String> {
|
||||
let args: AskMemoryArgs = match serde_json::from_str(&call.request.arguments) {
|
||||
Ok(args) => args,
|
||||
Err(e) => return Err(format!("ask_memory's arguments: {e}")),
|
||||
};
|
||||
args.check()?;
|
||||
let Some(reading) = &self.reading else {
|
||||
return Ok(Recalled {
|
||||
text: ask::NOT_CONFIGURED.to_string(),
|
||||
class: DataClass::Private,
|
||||
untrusted: false,
|
||||
});
|
||||
};
|
||||
let asked = ask::ask(&reading.readers, &args, ask::CHAT_WAIT, &self.log);
|
||||
Ok(ask::answer(asked))
|
||||
}
|
||||
|
||||
/// `memory`: refused, staged for review, or applied and journalled; then what it appended to
|
||||
/// `notes.md` is indexed. Its answer is labelled private and trusted: it is `memoryd`'s own
|
||||
/// sentence. A refusal and a flag are logged with the rule's name, never with the text.
|
||||
|
||||
Reference in New Issue
Block a user