mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-29 14:02:19 +00:00
@@ -293,16 +293,22 @@ const Conversations = ({ variant = 'page', composer = 'text' }: ConversationsPro
|
||||
// return;
|
||||
// }
|
||||
const threadStateForSelect = store.getState().thread;
|
||||
if (data.threads.length > 0) {
|
||||
// Worker/subagent threads are hidden from the conversation list
|
||||
// (see tinyhumansai/openhuman#1624). Match the sidebar filter here so
|
||||
// initial/resume selection can't auto-pick a hidden thread and leave
|
||||
// the UI showing a thread that isn't in the list.
|
||||
const visibleThreads = data.threads.filter(t => !t.parentThreadId);
|
||||
if (visibleThreads.length > 0) {
|
||||
// Prefer the thread the user was last viewing (persisted across
|
||||
// reloads via redux-persist on the `thread` slice). Only fall
|
||||
// through to "most recent" if that thread no longer exists
|
||||
// server-side (deleted, purged, or different user).
|
||||
// server-side (deleted, purged, or different user) — or is now
|
||||
// hidden because it's a worker thread.
|
||||
const persistedId = threadStateForSelect.selectedThreadId;
|
||||
const resumeId =
|
||||
persistedId && data.threads.some(t => t.id === persistedId)
|
||||
persistedId && visibleThreads.some(t => t.id === persistedId)
|
||||
? persistedId
|
||||
: data.threads[0].id;
|
||||
: visibleThreads[0].id;
|
||||
dispatch(setSelectedThread(resumeId));
|
||||
void dispatch(loadThreadMessages(resumeId));
|
||||
} else {
|
||||
@@ -940,6 +946,10 @@ const Conversations = ({ variant = 'page', composer = 'text' }: ConversationsPro
|
||||
|
||||
const filteredThreads = useMemo(() => {
|
||||
const base = threads.filter(t => {
|
||||
// Hide worker/subagent threads from the conversation list. They are
|
||||
// currently surfaced inline inside the parent thread via WorkerThreadRefCard.
|
||||
// A dedicated showcase is tracked in tinyhumansai/openhuman#1624.
|
||||
if (t.parentThreadId) return false;
|
||||
if (selectedLabel === 'all') return true;
|
||||
return t.labels?.includes(selectedLabel);
|
||||
});
|
||||
|
||||
@@ -128,7 +128,7 @@ impl Tool for SpawnSubagentTool {
|
||||
},
|
||||
"dedicated_thread": {
|
||||
"type": "boolean",
|
||||
"description": "Default `false`. Set `true` ONLY for long, complex sub-tasks where the parent thread should not be flooded with sub-agent output. The sub-agent's prompt and final summary land in a fresh worker-labeled thread the user can open from the thread list, and the parent receives a compact reference (worker thread id + brief summary) instead of the full transcript. Worker threads cannot themselves spawn another worker (sub-agents never see this tool), so this is a one-level-deep escape hatch."
|
||||
"description": "Temporarily disabled (see tinyhumansai/openhuman#1624). Passing `true` causes this tool to return an explicit error. Omit the field or pass `false` until the worker-thread UI surface lands."
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -166,10 +166,25 @@ impl Tool for SpawnSubagentTool {
|
||||
.map(|s| s.trim().to_string())
|
||||
.filter(|s| !s.is_empty());
|
||||
|
||||
let dedicated_thread = args
|
||||
// Worker-thread spawning is temporarily disabled until a proper UI
|
||||
// showcase lands (see tinyhumansai/openhuman#1624). Return an
|
||||
// explicit error when callers request a dedicated thread so the
|
||||
// behaviour is observable rather than silently downgraded.
|
||||
let dedicated_thread_requested = args
|
||||
.get("dedicated_thread")
|
||||
.and_then(|v| v.as_bool())
|
||||
.unwrap_or(false);
|
||||
if dedicated_thread_requested {
|
||||
log::debug!(
|
||||
"[spawn_subagent] dedicated_thread requested but temporarily \
|
||||
disabled (see tinyhumansai/openhuman#1624); rejecting call"
|
||||
);
|
||||
return Ok(ToolResult::error(
|
||||
"spawn_subagent: `dedicated_thread` is temporarily disabled \
|
||||
(see tinyhumansai/openhuman#1624); retry without it.",
|
||||
));
|
||||
}
|
||||
let dedicated_thread = false;
|
||||
|
||||
// ── Validation ─────────────────────────────────────────────────
|
||||
if agent_id.is_empty() {
|
||||
|
||||
@@ -29,7 +29,11 @@ use crate::openhuman::agent::harness::definition::{
|
||||
};
|
||||
use crate::openhuman::context::prompt::ConnectedIntegration;
|
||||
|
||||
use super::{ArchetypeDelegationTool, SkillDelegationTool, SpawnWorkerThreadTool, Tool};
|
||||
// SpawnWorkerThreadTool import kept commented while the worker-thread spawn is
|
||||
// temporarily disabled (see tinyhumansai/openhuman#1624).
|
||||
#[allow(unused_imports)]
|
||||
use super::SpawnWorkerThreadTool;
|
||||
use super::{ArchetypeDelegationTool, SkillDelegationTool, Tool};
|
||||
|
||||
/// Synthesise the delegation tool list for an agent based on its
|
||||
/// declarative `subagents` field.
|
||||
@@ -66,9 +70,12 @@ pub fn collect_orchestrator_tools(
|
||||
let mut tools: Vec<Box<dyn Tool>> = Vec::new();
|
||||
|
||||
// Orchestrator-only tool: spawn_worker_thread.
|
||||
if definition.id == "orchestrator" {
|
||||
tools.push(Box::new(SpawnWorkerThreadTool::new()));
|
||||
}
|
||||
// Temporarily disabled — worker threads do not yet have a proper UI
|
||||
// showcase (see tinyhumansai/openhuman#1624). Re-enable once the
|
||||
// dedicated worker-thread surface lands.
|
||||
// if definition.id == "orchestrator" {
|
||||
// tools.push(Box::new(SpawnWorkerThreadTool::new()));
|
||||
// }
|
||||
|
||||
for entry in &definition.subagents {
|
||||
match entry {
|
||||
@@ -298,7 +305,9 @@ mod tests {
|
||||
assert_eq!(
|
||||
names,
|
||||
vec![
|
||||
"spawn_worker_thread", // orchestrator-only, prepended in collect_orchestrator_tools
|
||||
// `spawn_worker_thread` is temporarily disabled — see
|
||||
// tinyhumansai/openhuman#1624. Re-add the leading entry when
|
||||
// the registration in `collect_orchestrator_tools` is restored.
|
||||
"research", // researcher's delegate_name override
|
||||
"delegate_archivist", // archivist has no delegate_name → default
|
||||
"delegate_gmail",
|
||||
@@ -329,10 +338,8 @@ mod tests {
|
||||
let reg = registry_with_targets();
|
||||
let tools = collect_orchestrator_tools(&orch, ®, &[]);
|
||||
let names: Vec<&str> = tools.iter().map(|t| t.name()).collect();
|
||||
assert_eq!(
|
||||
names,
|
||||
vec!["spawn_worker_thread", "research", "delegate_archivist"]
|
||||
);
|
||||
// `spawn_worker_thread` is temporarily disabled — see #1624.
|
||||
assert_eq!(names, vec!["research", "delegate_archivist"]);
|
||||
}
|
||||
|
||||
/// An AgentId entry that points at an id not present in the registry
|
||||
@@ -348,7 +355,8 @@ mod tests {
|
||||
let reg = registry_with_targets();
|
||||
let tools = collect_orchestrator_tools(&orch, ®, &[]);
|
||||
let names: Vec<&str> = tools.iter().map(|t| t.name()).collect();
|
||||
assert_eq!(names, vec!["spawn_worker_thread", "research"]);
|
||||
// `spawn_worker_thread` is temporarily disabled — see #1624.
|
||||
assert_eq!(names, vec!["research"]);
|
||||
}
|
||||
|
||||
/// An empty `subagents` list should produce zero tools — regular
|
||||
|
||||
Reference in New Issue
Block a user