mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 18:44:45 +00:00
feat(slash-commands): list project commands in AGENTS.md block (Phase 1.5)
The chat layer client-side-expands /<name> args, but the agent still needs to know what commands exist so it can answer "what slash commands does this project have?" and recognise the <!-- scarf-slash:<name> --> marker prepended to expanded prompts. ProjectContextBlock.renderMinimalBlock(...) gains an optional slashCommandNames parameter; when non-empty, a new "Project slash commands" bullet lists the names as backticked /<name> entries. Mac's ProjectAgentContextService.renderBlock(for:) reads the names via ProjectSlashCommandService.loadCommands(at:).map(\.name) and emits the same bullet, keeping Mac and iOS block output aligned where the content overlaps. iOS chat resetAndStartInProject splits the slash-command load into a synchronous read on a detached task BEFORE writing the block — needed because the block has to land on disk before `hermes acp` boots, and the async load that populates the chat menu would lose the race. Verified: ScarfCore, Mac, iOS all build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -612,6 +612,19 @@ final class ChatController {
|
||||
// <project.path>/.scarf/slash-commands/ into the chat menu.
|
||||
// Async + non-fatal — degrades cleanly on SFTP failures (logged).
|
||||
vm.loadProjectScopedCommands(at: project.path)
|
||||
// Synchronously load the slash command NAMES so we can list them
|
||||
// in the AGENTS.md block (the agent needs to know what commands
|
||||
// are available). This is a separate read from the async one
|
||||
// above because the block has to land on disk BEFORE `hermes acp`
|
||||
// boots — async loads might lose the race. Blocking load on a
|
||||
// detached task to keep the MainActor responsive.
|
||||
let ctx = context
|
||||
let projectPath = project.path
|
||||
let slashNames: [String] = await Task.detached {
|
||||
ProjectSlashCommandService(context: ctx)
|
||||
.loadCommands(at: projectPath)
|
||||
.map(\.name)
|
||||
}.value
|
||||
// Write the context block first. Non-fatal on failure — chat
|
||||
// still starts, just without the managed block. We capture the
|
||||
// failure (rather than swallowing via `try?`) so the user gets
|
||||
@@ -619,10 +632,9 @@ final class ChatController {
|
||||
// for this session, with the underlying error in "Show details".
|
||||
let block = ProjectContextBlock.renderMinimalBlock(
|
||||
projectName: project.name,
|
||||
projectPath: project.path
|
||||
projectPath: project.path,
|
||||
slashCommandNames: slashNames
|
||||
)
|
||||
let ctx = context
|
||||
let projectPath = project.path
|
||||
let writeResult: Result<Void, Error> = await Task.detached {
|
||||
do {
|
||||
try ProjectContextBlock.writeBlock(
|
||||
|
||||
Reference in New Issue
Block a user