mirror of
https://github.com/Orkas-AI/Orkas.git
synced 2026-11-07 18:36:40 -10:00
fix: commander-created agent/skill is reachable from the same conversation
Two related issues stopped a freshly-created agent / skill from being usable in the same project-scoped conversation that just created it.
1. Project-scoped auto-bind on commander creation (bus.ts).
The <agent> / <skill> container apply path in bus.ts wrote agent.json / SKILL.md to disk but never updated the project's bindings.json. With a strict allowlist, the new id was filtered out everywhere downstream:
- the commander picker (_pickerBoundAgentIds in agents.js::_renderAgentPickerList) hid it,
- getSystemPromptBlock(allowlist) returned an empty skills set, so the LLM in that project conv couldn't see new skills at all.
Fix: after createAgentFromBlocks / applySkillContainerFromCommander succeed, if turnProjectId is non-empty, call projects.addAgentBinding / addSkillBinding to register the new id in the project's bindings. Failures log.warn but do not block the rest of the turn. Both spots use the same await import('../projects') lazy-import pattern bus.ts already uses, no new top-level dependency. Only on the 'created' branch — updates either are already bound (idempotent skip) or were intentionally removed by the user, so re-binding would override intent. Skipped for orphan conversations (no project_id) since they are globally visible.
2. Agents / skills tabs now force-refresh on visit (boot.js).
loadAgents() / loadSkills() short-circuit on a non-empty cache; the only refresh source was conversation.js::_mountCreatedAgentChip's loadAgents(true), and that only fires while the user is on the conversation view. If the user navigated to the agents tab between or during creation streams, the chip handler may not have run, leaving _agentsCache stale and the tab missing the newly-created entries.
Fix: setView('agents' / 'skills') now calls loadAgents(true) / loadSkills(true). One extra IPC + directory scan per tab visit (millisecond-level, imperceptible) — making the tab show ground truth always is worth more than saving the IPC, since this is the user's recovery surface when things go missing.
This commit is contained in:
1 parent
3a997951a2
commit
e83c87d338
2 files changed
+42
-2
No files matched your search
@@ -1152,6 +1152,22 @@ async function runTurn(state: CidState, w: WorkerState, item: QueueItem): Promis
|
||||
const ag = await agentsFeat.createAgentFromBlocks(fields);
|
||||
if (ag) {
|
||||
createdAgents.push({ agent_id: ag.agent_id, name: ag.name, kind: 'created' });
|
||||
// Project-scoped conv: auto-bind the new agent into the project's
|
||||
// bindings.json so it's actually reachable from this conversation
|
||||
// (commander picker filters by `_pickerBoundAgentIds`; LLM
|
||||
// dispatch is gated by the same project scope per CLAUDE.md §5).
|
||||
// Without this hop the user creates an agent and immediately
|
||||
// can't @-mention it from the same conv — observed bug shape
|
||||
// when the project's bindings predate the new agent.
|
||||
if (turnProjectId) {
|
||||
try {
|
||||
const projectsFeatBind = await import('../projects');
|
||||
await projectsFeatBind.addAgentBinding(uid, turnProjectId, ag.agent_id);
|
||||
log.info(`auto-bound agent ${ag.agent_id} to project ${turnProjectId} after commander creation`);
|
||||
} catch (err) {
|
||||
log.warn(`auto-bind agent failed cid=${cid} pid=${turnProjectId} aid=${ag.agent_id}: ${(err as Error).message}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
workingText = `${workingText}\n\n<span style="color:var(--danger)">⚠️ Agent creation failed: missing required field(s) (name / workflow).</span>`;
|
||||
}
|
||||
@@ -1187,6 +1203,20 @@ async function runTurn(state: CidState, w: WorkerState, item: QueueItem): Promis
|
||||
const list = result.rejected.map((p) => `\`${p}\``).join(', ');
|
||||
workingText = `${workingText}\n\n<span style="color:var(--danger)">⚠️ Some skill files were rejected: ${list}</span>`;
|
||||
}
|
||||
// Project-scoped conv: auto-bind the new skill so the LLM in this
|
||||
// conv actually sees it via getSystemPromptBlock allowlist. Same
|
||||
// bug shape as the agent auto-bind above — without this the user
|
||||
// creates a skill, the file lands on disk, but the LLM in this
|
||||
// project conv can never invoke it (allowlist excludes it).
|
||||
if (turnProjectId && result.kind === 'created') {
|
||||
try {
|
||||
const projectsFeatBind = await import('../projects');
|
||||
await projectsFeatBind.addSkillBinding(uid, turnProjectId, result.skillId);
|
||||
log.info(`auto-bound skill ${result.skillId} to project ${turnProjectId} after commander creation`);
|
||||
} catch (err) {
|
||||
log.warn(`auto-bind skill failed cid=${cid} pid=${turnProjectId} sid=${result.skillId}: ${(err as Error).message}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
workingText = `${workingText}\n\n<span style="color:var(--danger)">⚠️ ${result.error || 'Skill operation failed.'}</span>`;
|
||||
}
|
||||
|
||||
@@ -216,10 +216,20 @@ function setView(view, cid, opts = {}) {
|
||||
setTimeout(() => document.getElementById('new-chat-input')?.focus(), 50);
|
||||
} else if (view === 'agents') {
|
||||
currentCid = null;
|
||||
loadAgents();
|
||||
// Force-refresh on every tab visit. The mid-stream chip handler in
|
||||
// `conversation.js::_mountCreatedAgentChip` already calls `loadAgents(true)`
|
||||
// when an agent is created via commander, but that only fires while the
|
||||
// user is on the conversation view. If the user navigates to the agents
|
||||
// tab between or during creation streams, the chip path may not run /
|
||||
// may have raced, leaving `_agentsCache` stale and the tab missing the
|
||||
// newly-created agents. Cheap (one IPC + dir scan), and the tab is the
|
||||
// user's recovery path when something looks off — making it always show
|
||||
// ground truth.
|
||||
loadAgents(true);
|
||||
} else if (view === 'skills') {
|
||||
currentCid = null;
|
||||
loadSkills();
|
||||
// Same reasoning as the agents branch above.
|
||||
loadSkills(true);
|
||||
} else if (view === 'contexts') {
|
||||
currentCid = null;
|
||||
loadContexts();
|
||||
|
||||
Reference in new issue
Block a user