Skip to content

Commit 7ce19cc

Browse files
committed
fixup! feat(navie): differentiate telemetry events by command mode
1 parent 434f04b commit 7ce19cc

3 files changed

Lines changed: 61 additions & 34 deletions

File tree

packages/cli/src/rpc/explain/navie/navie-local.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ export default class LocalNavie extends EventEmitter implements INavie {
209209
// - Separating these prevents pollution of user behavior analytics
210210
// - All other commands (explain, fix, review, etc.) use the standard navie:response event
211211
let eventName: string = events.NavieResponse;
212-
const commandMode = this.activeNavie?.commandMode;
212+
const commandMode = this.activeNavie.commandMode;
213213
if (commandMode === CommandMode.Welcome) {
214214
eventName = events.NavieWelcomeResponse;
215215
} else if (commandMode === CommandMode.Suggest) {

packages/cli/tests/integration/rpc.explain.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
Help,
77
navie,
88
applyContext,
9+
CommandMode,
910
Navie,
1011
TestInvocation,
1112
} from '@appland/navie';
@@ -71,14 +72,15 @@ describe('RPC', () => {
7172

7273
it('answers the question', async () => {
7374
jest.spyOn(Telemetry, 'enabled', 'get').mockReturnValue(true);
74-
const navieImpl = {
75+
const navieImpl: Navie.INavie = {
7576
on(_event: any, _listener: any) {},
7677
execute(): AsyncIterable<string> {
7778
return (async function* () {
7879
yield answer;
7980
})();
8081
},
8182
terminate: () => false,
83+
commandMode: CommandMode.Explain,
8284
};
8385

8486
jest.mocked(navie).mockReturnValue(navieImpl);

packages/navie/test/navie.spec.ts

Lines changed: 57 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,74 @@
1+
import { CommandMode } from '../src/command';
12
import ExplainCommand from '../src/commands/explain-command';
2-
import { ContextV2 } from '../src/context';
3-
import { HelpProvider } from '../src/help';
43
import { ClientRequest, NavieOptions, default as navie } from '../src/navie';
5-
import { ProjectInfoProvider } from '../src/project-info';
6-
import { TestInvocationProvider } from '../src/test-invocation';
4+
5+
jest.mock('../src/commands/explain-command');
6+
jest.mock('../src/services/openai-completion-service');
7+
8+
// eslint-disable-next-line @typescript-eslint/require-await
9+
ExplainCommand.prototype.execute = jest.fn().mockImplementation(async function* () {
10+
yield 'This is a test response';
11+
});
712

813
describe('Navie Function', () => {
914
let clientRequest: ClientRequest;
10-
let contextProvider: ContextV2.ContextProvider;
11-
let projectInfoProvider: ProjectInfoProvider;
12-
let helpProvider: HelpProvider;
13-
let testInvocationProvider: TestInvocationProvider;
14-
let options: NavieOptions;
1515

16-
beforeEach(() => {
17-
clientRequest = { question: '' };
18-
contextProvider = jest.fn().mockResolvedValue({});
19-
projectInfoProvider = jest.fn().mockResolvedValue({});
20-
helpProvider = jest.fn().mockResolvedValue({});
21-
testInvocationProvider = jest.fn().mockResolvedValue({});
22-
options = new NavieOptions();
23-
});
16+
const createNavie = () => {
17+
const contextProvider = jest.fn().mockResolvedValue({});
18+
const projectInfoProvider = jest.fn().mockResolvedValue({});
19+
const helpProvider = jest.fn().mockResolvedValue({});
20+
const testInvocationProvider = jest.fn().mockResolvedValue({});
21+
const options = new NavieOptions();
2422

25-
test('uses default command if question is empty', async () => {
26-
const instance = navie(
23+
return navie(
2724
clientRequest,
2825
contextProvider,
2926
projectInfoProvider,
3027
helpProvider,
3128
testInvocationProvider,
3229
options
3330
);
34-
const result = [];
35-
for await (const chunk of instance.execute()) {
36-
result.push(chunk);
37-
}
38-
expect(result).toBeTruthy();
39-
expect(clientRequest.question).toEqual('explain');
31+
};
32+
33+
beforeEach(() => {
34+
clientRequest = { question: '' };
4035
});
41-
});
4236

43-
jest.mock('../src/commands/explain-command');
44-
// eslint-disable-next-line @typescript-eslint/require-await
45-
ExplainCommand.prototype.execute = jest.fn().mockImplementation(async function* () {
46-
yield 'This is a test response';
47-
});
37+
describe('commandMode property', () => {
38+
test.each([
39+
['empty question', '', CommandMode.Explain],
40+
['no command prefix', 'How does this work?', CommandMode.Explain],
41+
['only whitespace', ' ', CommandMode.Explain],
42+
['@welcome prefix', '@welcome', CommandMode.Welcome],
43+
['@suggest prefix with text', '@suggest What should I do next?', CommandMode.Suggest],
44+
['@suggest prefix alone', '@suggest', CommandMode.Suggest],
45+
['@review prefix', '@review Check this code', CommandMode.Review],
46+
[
47+
'@review prefix multiline',
48+
'@review\nCheck this implementation\nfor potential bugs',
49+
CommandMode.Review,
50+
],
51+
['@observe prefix', '@observe What changed?', CommandMode.Observe],
52+
['@fix prefix', '@fix Resolve this issue', CommandMode.Fix],
53+
['@context prefix', '@context Show me relevant files', CommandMode.Context],
54+
])('should set commandMode correctly for %s', (description, question, expectedMode) => {
55+
clientRequest.question = question;
56+
const instance = createNavie();
57+
expect(instance.commandMode).toEqual(expectedMode);
58+
});
59+
});
4860

49-
jest.mock('../src/services/openai-completion-service');
61+
describe('execution', () => {
62+
test('executes successfully and normalizes empty question', async () => {
63+
clientRequest.question = '';
64+
const instance = createNavie();
65+
const result = [];
66+
for await (const chunk of instance.execute()) {
67+
result.push(chunk);
68+
}
69+
expect(result).toHaveLength(1);
70+
expect(result[0]).toBe('This is a test response');
71+
expect(clientRequest.question).toBe('explain');
72+
});
73+
});
74+
});

0 commit comments

Comments
 (0)