mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
fix(story-mode): slash commands, and where a compaction belongs
A local slash command (`/compact`, `/model`) gets no reply from Claude and no turn_duration, so its turn stayed "Claude is working" until the next prompt. It now ends at the command's own output (<local-command-stdout>, kept for the mission drawer) and reads "You run /compact.". `/compact` writes its compaction marker before the command line itself; a marker that lands between turns now belongs to the turn after it (it was drawn at the end of the previous, finished turn), and one mid-turn stays where it is. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
ea104c8965
commit
db9eb5cea3
3 files changed
+77
-9
No files matched your search
+33
-1
@@ -245,7 +245,8 @@ describe('createStoryReducer', () => {
|
||||
prompt('<local-command-stdout>ok</local-command-stdout>'),
|
||||
prompt('<bash-input>ls</bash-input>'),
|
||||
]);
|
||||
expect(entries).toEqual([]);
|
||||
// None is a prompt; a local command's output is kept apart, as what that command printed.
|
||||
expect(entries).toEqual([{ k: 'local', at: expect.any(String), text: 'ok' }]);
|
||||
});
|
||||
|
||||
it('reads slash commands, task notifications, interrupts and strips system reminders', () => {
|
||||
@@ -506,6 +507,37 @@ describe('buildStoryTurns', () => {
|
||||
expect(pasted.prompt).toBe('Do these steps.');
|
||||
});
|
||||
|
||||
it('/compact is its own turn: you run it, Claude packs up, and the command answers itself', () => {
|
||||
const boundary = { type: 'system', subtype: 'compact_boundary', timestamp: '2026-10-18T09:50:00.000Z' };
|
||||
const summary = prompt('This session is being continued from a previous conversation.', { isCompactSummary: true });
|
||||
const command = prompt(
|
||||
'<command-name>/compact</command-name>\n<command-message>compact</command-message>\n<command-args></command-args>'
|
||||
);
|
||||
const stdout = prompt('<local-command-stdout>\u001b[2mCompacted \u001b[22m</local-command-stdout>', {
|
||||
turnOrigin: undefined,
|
||||
});
|
||||
const turns = buildStoryTurns(
|
||||
entriesOf([prompt('one'), ...bash('b', 'ls', 'List', 'a'), end(1000), boundary, summary, command, stdout])
|
||||
);
|
||||
expect(turns).toHaveLength(2);
|
||||
expect(turns[0].events.some((e) => e.intent === 'compact')).toBe(false);
|
||||
expect(turns[1]).toMatchObject({ prompt: '/compact', ended: true });
|
||||
const page = buildStoryPage(turns[1]);
|
||||
expect(page.panels.map((p) => p.kind)).toEqual(['mission', 'compact', 'complete']);
|
||||
expect(page.panels[0].caption.story).toBe('You run /compact.');
|
||||
expect(page.events[0]).toMatchObject({ tool: 'Command', output: 'Compacted' });
|
||||
// A local command like /model ends at its output too.
|
||||
const [, model] = buildStoryTurns(
|
||||
entriesOf([
|
||||
prompt('one'),
|
||||
end(1000),
|
||||
prompt('<command-name>/model</command-name><command-args>opus</command-args>'),
|
||||
prompt('<local-command-stdout>Set model to opus</local-command-stdout>'),
|
||||
])
|
||||
);
|
||||
expect(model).toMatchObject({ prompt: '/model opus', ended: true });
|
||||
});
|
||||
|
||||
it('an interrupt ends the turn', () => {
|
||||
const turns = buildStoryTurns(
|
||||
entriesOf([prompt('go'), ...bash('b', 'ls', 'List', 'a'), prompt('[Request interrupted by user]')])
|
||||
|
||||
Reference in new issue
Block a user