reviewflow 3.30.0 → 3.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/dist/dashboard/index.html +35 -11
- package/dist/dashboard/styles.css +139 -5
- package/dist/frameworks/claude/claudeInvoker.d.ts +7 -0
- package/dist/frameworks/claude/claudeInvoker.d.ts.map +1 -1
- package/dist/frameworks/claude/claudeInvoker.js +1 -1
- package/dist/frameworks/claude/claudeInvoker.js.map +1 -1
- package/dist/main/routes.d.ts.map +1 -1
- package/dist/main/routes.js +9 -16
- package/dist/main/routes.js.map +1 -1
- package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.gateway.d.ts +1 -1
- package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.gateway.d.ts.map +1 -1
- package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.guard.d.ts +1 -1
- package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.d.ts +2 -0
- package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.d.ts.map +1 -1
- package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.js +1 -1
- package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.js.map +1 -1
- package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.d.ts +24 -0
- package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.d.ts.map +1 -0
- package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js +2 -0
- package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js.map +1 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.gateway.d.ts +8 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.gateway.d.ts.map +1 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.gateway.js +2 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.gateway.js.map +1 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.guard.d.ts +8 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.guard.d.ts.map +1 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.guard.js +4 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.guard.js.map +1 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.schema.d.ts +17 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.schema.d.ts.map +1 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.schema.js +11 -0
- package/dist/modules/ember-chat/entities/emberMemory/emberMemory.schema.js.map +1 -0
- package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.d.ts +4 -3
- package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.d.ts.map +1 -1
- package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js +12 -4
- package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js.map +1 -1
- package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.d.ts +46 -0
- package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.d.ts.map +1 -0
- package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.js +176 -0
- package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.js.map +1 -0
- package/dist/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.d.ts +22 -0
- package/dist/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.d.ts.map +1 -0
- package/dist/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.js +55 -0
- package/dist/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.js.map +1 -0
- package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.d.ts +2 -1
- package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.d.ts.map +1 -1
- package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js +8 -2
- package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js.map +1 -1
- package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.d.ts +1 -1
- package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.d.ts.map +1 -1
- package/dist/modules/ember-chat/services/emberSystemPrompt.d.ts +2 -0
- package/dist/modules/ember-chat/services/emberSystemPrompt.d.ts.map +1 -1
- package/dist/modules/ember-chat/services/emberSystemPrompt.js +87 -11
- package/dist/modules/ember-chat/services/emberSystemPrompt.js.map +1 -1
- package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.d.ts +7 -4
- package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.d.ts.map +1 -1
- package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.js +90 -8
- package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.js.map +1 -1
- package/dist/modules/ember-chat/usecases/askEmber/emberStream.d.ts +8 -0
- package/dist/modules/ember-chat/usecases/askEmber/emberStream.d.ts.map +1 -0
- package/dist/modules/ember-chat/usecases/askEmber/emberStream.js +2 -0
- package/dist/modules/ember-chat/usecases/askEmber/emberStream.js.map +1 -0
- package/dist/modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.d.ts +7 -0
- package/dist/modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.d.ts.map +1 -0
- package/dist/modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.js +4 -0
- package/dist/modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.js.map +1 -0
- package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.d.ts +2 -0
- package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.js +165 -0
- package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.js.map +1 -0
- package/dist/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.d.ts +2 -0
- package/dist/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.d.ts.map +1 -0
- package/dist/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.js +261 -0
- package/dist/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.js.map +1 -0
- package/dist/tests/factories/emberMemory.factory.d.ts +8 -0
- package/dist/tests/factories/emberMemory.factory.d.ts.map +1 -0
- package/dist/tests/factories/emberMemory.factory.js +19 -0
- package/dist/tests/factories/emberMemory.factory.js.map +1 -0
- package/dist/tests/stubs/emberAnswerTransport.stub.d.ts +21 -0
- package/dist/tests/stubs/emberAnswerTransport.stub.d.ts.map +1 -0
- package/dist/tests/stubs/emberAnswerTransport.stub.js +54 -0
- package/dist/tests/stubs/emberAnswerTransport.stub.js.map +1 -0
- package/dist/tests/stubs/emberMemory.stub.d.ts +25 -0
- package/dist/tests/stubs/emberMemory.stub.d.ts.map +1 -0
- package/dist/tests/stubs/emberMemory.stub.js +61 -0
- package/dist/tests/stubs/emberMemory.stub.js.map +1 -0
- package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.js +35 -14
- package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.js.map +1 -1
- package/dist/tests/units/modules/ember-chat/entities/emberMemory.guard.test.d.ts +2 -0
- package/dist/tests/units/modules/ember-chat/entities/emberMemory.guard.test.d.ts.map +1 -0
- package/dist/tests/units/modules/ember-chat/entities/emberMemory.guard.test.js +51 -0
- package/dist/tests/units/modules/ember-chat/entities/emberMemory.guard.test.js.map +1 -0
- package/dist/tests/units/modules/ember-chat/gateways/emberMemory.fileSystem.gateway.test.d.ts +2 -0
- package/dist/tests/units/modules/ember-chat/gateways/emberMemory.fileSystem.gateway.test.d.ts.map +1 -0
- package/dist/tests/units/modules/ember-chat/gateways/emberMemory.fileSystem.gateway.test.js +82 -0
- package/dist/tests/units/modules/ember-chat/gateways/emberMemory.fileSystem.gateway.test.js.map +1 -0
- package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.js +13 -0
- package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.js.map +1 -1
- package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.js +93 -2
- package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.js.map +1 -1
- package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.js +108 -20
- package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.js.map +1 -1
- package/dist/tests/units/modules/ember-chat/usecases/clearEmberMemory.usecase.test.d.ts +2 -0
- package/dist/tests/units/modules/ember-chat/usecases/clearEmberMemory.usecase.test.d.ts.map +1 -0
- package/dist/tests/units/modules/ember-chat/usecases/clearEmberMemory.usecase.test.js +14 -0
- package/dist/tests/units/modules/ember-chat/usecases/clearEmberMemory.usecase.test.js.map +1 -0
- package/package.json +1 -1
- package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.d.ts +0 -7
- package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.d.ts.map +0 -1
- package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.js +0 -3
- package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.js.map +0 -1
- package/dist/modules/ember-chat/entities/emberSession/emberSessionState.d.ts +0 -13
- package/dist/modules/ember-chat/entities/emberSession/emberSessionState.d.ts.map +0 -1
- package/dist/modules/ember-chat/entities/emberSession/emberSessionState.js +0 -35
- package/dist/modules/ember-chat/entities/emberSession/emberSessionState.js.map +0 -1
- package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.d.ts +0 -26
- package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.d.ts.map +0 -1
- package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js +0 -2
- package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js.map +0 -1
- package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.d.ts +0 -13
- package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.d.ts.map +0 -1
- package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.js +0 -130
- package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.js.map +0 -1
- package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.d.ts +0 -36
- package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.d.ts.map +0 -1
- package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.js +0 -59
- package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.js.map +0 -1
- package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.d.ts +0 -2
- package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.d.ts.map +0 -1
- package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.js +0 -124
- package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.js.map +0 -1
- package/dist/tests/stubs/emberSessionTransport.stub.d.ts +0 -18
- package/dist/tests/stubs/emberSessionTransport.stub.d.ts.map +0 -1
- package/dist/tests/stubs/emberSessionTransport.stub.js +0 -75
- package/dist/tests/stubs/emberSessionTransport.stub.js.map +0 -1
- package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.d.ts +0 -2
- package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.d.ts.map +0 -1
- package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.js +0 -42
- package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.js.map +0 -1
- package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.d.ts +0 -2
- package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.d.ts.map +0 -1
- package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.js +0 -88
- package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.js.map +0 -1
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { ProjectStatsFactory, ReviewStatsFactory } from '../../tests/factories/projectStats.factory.js';
|
|
3
|
+
import { StubEnvironmentGateway } from '../../tests/stubs/environment.stub.js';
|
|
4
|
+
import { StubEmberReadDataGateway } from '../../tests/stubs/emberReadData.stub.js';
|
|
5
|
+
import { StubEmberAnswerTransportGateway } from '../../tests/stubs/emberAnswerTransport.stub.js';
|
|
6
|
+
import { StubEmberMemoryGateway, StubEmberMemoryStore, } from '../../tests/stubs/emberMemory.stub.js';
|
|
7
|
+
import { askEmber } from '../../modules/ember-chat/usecases/askEmber/askEmber.usecase.js';
|
|
8
|
+
import { clearEmberMemory } from '../../modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.js';
|
|
9
|
+
const PROJECT_PATH = '/projects/alpha';
|
|
10
|
+
const OTHER_PROJECT_PATH = '/projects/beta';
|
|
11
|
+
function largeReviewData() {
|
|
12
|
+
const reviews = Array.from({ length: 500 }, (_, index) => ReviewStatsFactory.create({ mrNumber: index, score: index % 10, blocking: index % 3 }));
|
|
13
|
+
const readData = new StubEmberReadDataGateway();
|
|
14
|
+
readData.setReviewScores(PROJECT_PATH, ProjectStatsFactory.withReviews(reviews));
|
|
15
|
+
return readData;
|
|
16
|
+
}
|
|
17
|
+
function environment(hasApiKey) {
|
|
18
|
+
const stub = new StubEnvironmentGateway();
|
|
19
|
+
stub.setHasAnthropicApiKey(hasApiKey);
|
|
20
|
+
return stub;
|
|
21
|
+
}
|
|
22
|
+
function collectStream(subscribe) {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
let answer = '';
|
|
25
|
+
const statuses = [];
|
|
26
|
+
subscribe({
|
|
27
|
+
onStatus: (state) => {
|
|
28
|
+
statuses.push(state);
|
|
29
|
+
},
|
|
30
|
+
onChunk: (text) => {
|
|
31
|
+
answer += text;
|
|
32
|
+
},
|
|
33
|
+
onDone: () => resolve({ answer, statuses }),
|
|
34
|
+
onError: () => resolve({ answer, statuses }),
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
describe('Ground Ember on demand and remember per project (acceptance, SPEC-192)', () => {
|
|
39
|
+
describe('Ember can reach any review data on demand, not only the most recent items', () => {
|
|
40
|
+
it('old specific review on demand: MR-1 lies far outside the recent window yet is reachable', async () => {
|
|
41
|
+
const transport = new StubEmberAnswerTransportGateway();
|
|
42
|
+
transport.answerFromSystemPrompt();
|
|
43
|
+
const result = await askEmber({ question: 'Pourquoi MR-1 a-t-elle été bloquée il y a longtemps ?' }, {
|
|
44
|
+
transport,
|
|
45
|
+
environment: environment(false),
|
|
46
|
+
readData: largeReviewData(),
|
|
47
|
+
memory: new StubEmberMemoryGateway(),
|
|
48
|
+
projectPath: PROJECT_PATH,
|
|
49
|
+
});
|
|
50
|
+
expect(result.status).toBe('streaming');
|
|
51
|
+
if (result.status !== 'streaming') {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const { answer, statuses } = await collectStream(result.subscribe);
|
|
55
|
+
expect(statuses.at(-1)).toBe('idle');
|
|
56
|
+
expect(answer.toLowerCase()).toContain('à la demande');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe('a question is never refused merely because the data falls outside a recent window', () => {
|
|
60
|
+
it('no recent-window refusal: the framing carries no window-ceiling refusal text', async () => {
|
|
61
|
+
const transport = new StubEmberAnswerTransportGateway();
|
|
62
|
+
transport.answerFromSystemPrompt();
|
|
63
|
+
const result = await askEmber({ question: 'Liste toutes les reviews du début du projet.' }, {
|
|
64
|
+
transport,
|
|
65
|
+
environment: environment(false),
|
|
66
|
+
readData: largeReviewData(),
|
|
67
|
+
memory: new StubEmberMemoryGateway(),
|
|
68
|
+
projectPath: PROJECT_PATH,
|
|
69
|
+
});
|
|
70
|
+
expect(result.status).toBe('streaming');
|
|
71
|
+
if (result.status !== 'streaming') {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const { answer } = await collectStream(result.subscribe);
|
|
75
|
+
expect(answer).not.toContain('résumé agrégé seulement');
|
|
76
|
+
expect(answer).not.toContain('aucun autre accès');
|
|
77
|
+
expect(answer).not.toContain('ni système de fichiers');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
describe('read-only and subscription-only guarantees are preserved (Phase B regressions)', () => {
|
|
81
|
+
it('read-only preserved: the answer framing still states it performs no writes', async () => {
|
|
82
|
+
const transport = new StubEmberAnswerTransportGateway();
|
|
83
|
+
transport.answerFromSystemPrompt();
|
|
84
|
+
const result = await askEmber({ question: 'Crée un quality gate à 80 pour le projet.' }, {
|
|
85
|
+
transport,
|
|
86
|
+
environment: environment(false),
|
|
87
|
+
readData: largeReviewData(),
|
|
88
|
+
memory: new StubEmberMemoryGateway(),
|
|
89
|
+
projectPath: PROJECT_PATH,
|
|
90
|
+
});
|
|
91
|
+
expect(result.status).toBe('streaming');
|
|
92
|
+
if (result.status !== 'streaming') {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const { answer } = await collectStream(result.subscribe);
|
|
96
|
+
expect(answer.toLowerCase()).toContain('lecture seule');
|
|
97
|
+
});
|
|
98
|
+
it('api key present: refuses to answer when an Anthropic API key is set', async () => {
|
|
99
|
+
const transport = new StubEmberAnswerTransportGateway();
|
|
100
|
+
transport.answerFromSystemPrompt();
|
|
101
|
+
const result = await askEmber({ question: 'Statut ?' }, {
|
|
102
|
+
transport,
|
|
103
|
+
environment: environment(true),
|
|
104
|
+
readData: largeReviewData(),
|
|
105
|
+
memory: new StubEmberMemoryGateway(),
|
|
106
|
+
projectPath: PROJECT_PATH,
|
|
107
|
+
});
|
|
108
|
+
expect(result.status).toBe('billing-regression-prevented');
|
|
109
|
+
expect(transport.startCount).toBe(0);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
describe('Ember keeps a per-project conversation memory that survives a restart', () => {
|
|
113
|
+
it('follow-up across restart: a later instance recalls the earlier turn without repeating the subject', async () => {
|
|
114
|
+
const store = new StubEmberMemoryStore();
|
|
115
|
+
const firstTransport = new StubEmberAnswerTransportGateway();
|
|
116
|
+
firstTransport.respondWith(async () => 'Le projet alpha régresse chaque vendredi.');
|
|
117
|
+
const firstSession = await askEmber({ question: 'Quel est le constat récurrent du projet alpha ?' }, {
|
|
118
|
+
transport: firstTransport,
|
|
119
|
+
environment: environment(false),
|
|
120
|
+
readData: largeReviewData(),
|
|
121
|
+
memory: new StubEmberMemoryGateway(store),
|
|
122
|
+
projectPath: PROJECT_PATH,
|
|
123
|
+
});
|
|
124
|
+
expect(firstSession.status).toBe('streaming');
|
|
125
|
+
if (firstSession.status !== 'streaming') {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
await collectStream(firstSession.subscribe);
|
|
129
|
+
const restartedTransport = new StubEmberAnswerTransportGateway();
|
|
130
|
+
restartedTransport.answerFromSystemPrompt();
|
|
131
|
+
const followUp = await askEmber({ question: 'Et le mois dernier ?' }, {
|
|
132
|
+
transport: restartedTransport,
|
|
133
|
+
environment: environment(false),
|
|
134
|
+
readData: largeReviewData(),
|
|
135
|
+
memory: new StubEmberMemoryGateway(store),
|
|
136
|
+
projectPath: PROJECT_PATH,
|
|
137
|
+
});
|
|
138
|
+
expect(followUp.status).toBe('streaming');
|
|
139
|
+
if (followUp.status !== 'streaming') {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const { answer, statuses } = await collectStream(followUp.subscribe);
|
|
143
|
+
expect(statuses.at(-1)).toBe('idle');
|
|
144
|
+
expect(answer).toContain('Le projet alpha régresse chaque vendredi.');
|
|
145
|
+
});
|
|
146
|
+
it("per-project isolation: project A's memory never reaches project B's answer", async () => {
|
|
147
|
+
const store = new StubEmberMemoryStore();
|
|
148
|
+
const seedTransport = new StubEmberAnswerTransportGateway();
|
|
149
|
+
seedTransport.respondWith(async () => 'Constat confidentiel sur le projet alpha.');
|
|
150
|
+
const seedSession = await askEmber({ question: 'Quel est le constat du projet alpha ?' }, {
|
|
151
|
+
transport: seedTransport,
|
|
152
|
+
environment: environment(false),
|
|
153
|
+
readData: largeReviewData(),
|
|
154
|
+
memory: new StubEmberMemoryGateway(store),
|
|
155
|
+
projectPath: PROJECT_PATH,
|
|
156
|
+
});
|
|
157
|
+
expect(seedSession.status).toBe('streaming');
|
|
158
|
+
if (seedSession.status !== 'streaming') {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
await collectStream(seedSession.subscribe);
|
|
162
|
+
const otherTransport = new StubEmberAnswerTransportGateway();
|
|
163
|
+
otherTransport.answerFromSystemPrompt();
|
|
164
|
+
const otherReadData = new StubEmberReadDataGateway();
|
|
165
|
+
otherReadData.setReviewScores(OTHER_PROJECT_PATH, ProjectStatsFactory.withReviews([ReviewStatsFactory.create({ mrNumber: 1 })]));
|
|
166
|
+
const otherSession = await askEmber({ question: 'Quoi de neuf sur le projet beta ?' }, {
|
|
167
|
+
transport: otherTransport,
|
|
168
|
+
environment: environment(false),
|
|
169
|
+
readData: otherReadData,
|
|
170
|
+
memory: new StubEmberMemoryGateway(store),
|
|
171
|
+
projectPath: OTHER_PROJECT_PATH,
|
|
172
|
+
});
|
|
173
|
+
expect(otherSession.status).toBe('streaming');
|
|
174
|
+
if (otherSession.status !== 'streaming') {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const { answer } = await collectStream(otherSession.subscribe);
|
|
178
|
+
expect(answer).not.toContain('Constat confidentiel sur le projet alpha.');
|
|
179
|
+
});
|
|
180
|
+
it('corrupted memory: an answer is still produced when the memory is unreadable', async () => {
|
|
181
|
+
const transport = new StubEmberAnswerTransportGateway();
|
|
182
|
+
transport.answerFromSystemPrompt();
|
|
183
|
+
const memory = new StubEmberMemoryGateway();
|
|
184
|
+
memory.markCorrupted();
|
|
185
|
+
const result = await askEmber({ question: 'Statut ?' }, {
|
|
186
|
+
transport,
|
|
187
|
+
environment: environment(false),
|
|
188
|
+
readData: largeReviewData(),
|
|
189
|
+
memory,
|
|
190
|
+
projectPath: PROJECT_PATH,
|
|
191
|
+
});
|
|
192
|
+
expect(result.status).toBe('streaming');
|
|
193
|
+
if (result.status !== 'streaming') {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const { statuses } = await collectStream(result.subscribe);
|
|
197
|
+
expect(statuses.at(-1)).toBe('idle');
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
describe('Ember reuses recorded recurring insights and the operator can clear the memory', () => {
|
|
201
|
+
it('reused insight: a recorded recurring finding is surfaced for reuse without recomputation', async () => {
|
|
202
|
+
const store = new StubEmberMemoryStore();
|
|
203
|
+
const recorder = new StubEmberMemoryGateway(store);
|
|
204
|
+
await recorder.appendInsight(PROJECT_PATH, 'Le projet X régresse chaque vendredi.');
|
|
205
|
+
const transport = new StubEmberAnswerTransportGateway();
|
|
206
|
+
transport.answerFromSystemPrompt();
|
|
207
|
+
const result = await askEmber({ question: 'Quoi de neuf sur X ?' }, {
|
|
208
|
+
transport,
|
|
209
|
+
environment: environment(false),
|
|
210
|
+
readData: largeReviewData(),
|
|
211
|
+
memory: new StubEmberMemoryGateway(store),
|
|
212
|
+
projectPath: PROJECT_PATH,
|
|
213
|
+
});
|
|
214
|
+
expect(result.status).toBe('streaming');
|
|
215
|
+
if (result.status !== 'streaming') {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
const { answer } = await collectStream(result.subscribe);
|
|
219
|
+
expect(answer.toLowerCase()).toContain('constats récurrents');
|
|
220
|
+
expect(answer).toContain('Le projet X régresse chaque vendredi.');
|
|
221
|
+
});
|
|
222
|
+
it('clear memory: after clearing, the next question starts with no prior context', async () => {
|
|
223
|
+
const store = new StubEmberMemoryStore();
|
|
224
|
+
const seedTransport = new StubEmberAnswerTransportGateway();
|
|
225
|
+
seedTransport.respondWith(async () => 'Constat antérieur sur le projet alpha.');
|
|
226
|
+
const seedSession = await askEmber({ question: 'Quel est le constat du projet alpha ?' }, {
|
|
227
|
+
transport: seedTransport,
|
|
228
|
+
environment: environment(false),
|
|
229
|
+
readData: largeReviewData(),
|
|
230
|
+
memory: new StubEmberMemoryGateway(store),
|
|
231
|
+
projectPath: PROJECT_PATH,
|
|
232
|
+
});
|
|
233
|
+
expect(seedSession.status).toBe('streaming');
|
|
234
|
+
if (seedSession.status !== 'streaming') {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
await collectStream(seedSession.subscribe);
|
|
238
|
+
await clearEmberMemory({
|
|
239
|
+
memory: new StubEmberMemoryGateway(store),
|
|
240
|
+
projectPath: PROJECT_PATH,
|
|
241
|
+
});
|
|
242
|
+
const nextTransport = new StubEmberAnswerTransportGateway();
|
|
243
|
+
nextTransport.answerFromSystemPrompt();
|
|
244
|
+
const nextSession = await askEmber({ question: 'Et maintenant ?' }, {
|
|
245
|
+
transport: nextTransport,
|
|
246
|
+
environment: environment(false),
|
|
247
|
+
readData: largeReviewData(),
|
|
248
|
+
memory: new StubEmberMemoryGateway(store),
|
|
249
|
+
projectPath: PROJECT_PATH,
|
|
250
|
+
});
|
|
251
|
+
expect(nextSession.status).toBe('streaming');
|
|
252
|
+
if (nextSession.status !== 'streaming') {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
const { answer } = await collectStream(nextSession.subscribe);
|
|
256
|
+
expect(answer).not.toContain('Constat antérieur sur le projet alpha.');
|
|
257
|
+
expect(answer.toLowerCase()).not.toContain('conversation précédente');
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
//# sourceMappingURL=192-ember-ondemand-grounding-and-memory.acceptance.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"192-ember-ondemand-grounding-and-memory.acceptance.test.js","sourceRoot":"","sources":["../../../src/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EmberMemory, EmberMemoryTurn } from '../../modules/ember-chat/entities/emberMemory/emberMemory.schema.js';
|
|
2
|
+
export declare class EmberMemoryTurnFactory {
|
|
3
|
+
static create(overrides?: Partial<EmberMemoryTurn>): EmberMemoryTurn;
|
|
4
|
+
}
|
|
5
|
+
export declare class EmberMemoryFactory {
|
|
6
|
+
static create(overrides?: Partial<EmberMemory>): EmberMemory;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=emberMemory.factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emberMemory.factory.d.ts","sourceRoot":"","sources":["../../../src/tests/factories/emberMemory.factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EAChB,MAAM,iEAAiE,CAAC;AAEzE,qBAAa,sBAAsB;IACjC,MAAM,CAAC,MAAM,CAAC,SAAS,GAAE,OAAO,CAAC,eAAe,CAAM,GAAG,eAAe;CAOzE;AAED,qBAAa,kBAAkB;IAC7B,MAAM,CAAC,MAAM,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW;CAOjE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class EmberMemoryTurnFactory {
|
|
2
|
+
static create(overrides = {}) {
|
|
3
|
+
return {
|
|
4
|
+
question: 'Quel projet régresse le vendredi ?',
|
|
5
|
+
answer: 'Le projet X régresse chaque vendredi.',
|
|
6
|
+
...overrides,
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export class EmberMemoryFactory {
|
|
11
|
+
static create(overrides = {}) {
|
|
12
|
+
return {
|
|
13
|
+
turns: [EmberMemoryTurnFactory.create()],
|
|
14
|
+
insights: [],
|
|
15
|
+
...overrides,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=emberMemory.factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emberMemory.factory.js","sourceRoot":"","sources":["../../../src/tests/factories/emberMemory.factory.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,sBAAsB;IACjC,MAAM,CAAC,MAAM,CAAC,YAAsC,EAAE;QACpD,OAAO;YACL,QAAQ,EAAE,oCAAoC;YAC9C,MAAM,EAAE,uCAAuC;YAC/C,GAAG,SAAS;SACb,CAAC;IACJ,CAAC;CACF;AAED,MAAM,OAAO,kBAAkB;IAC7B,MAAM,CAAC,MAAM,CAAC,YAAkC,EAAE;QAChD,OAAO;YACL,KAAK,EAAE,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC;YACxC,QAAQ,EAAE,EAAE;YACZ,GAAG,SAAS;SACb,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { EmberAnswerStartOptions, EmberAnswerStartResult, EmberAnswerSubscriber, EmberAnswerTransportGateway } from '../../modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js';
|
|
2
|
+
type AnswerBuilder = (question: string, systemPrompt: string) => Promise<string>;
|
|
3
|
+
export declare class StubEmberAnswerTransportGateway implements EmberAnswerTransportGateway {
|
|
4
|
+
startCount: number;
|
|
5
|
+
private shouldFailStart;
|
|
6
|
+
private shouldFailMidStream;
|
|
7
|
+
private answerBuilder;
|
|
8
|
+
failStart(): void;
|
|
9
|
+
failMidStream(): void;
|
|
10
|
+
respondWith(builder: AnswerBuilder): void;
|
|
11
|
+
/**
|
|
12
|
+
* Makes the stub answer with the system prompt it was started with. The grounding
|
|
13
|
+
* data lives in that prompt, so this proves the real path: readData → askEmber →
|
|
14
|
+
* prompt → transport, rather than the stub fabricating an answer of its own.
|
|
15
|
+
*/
|
|
16
|
+
answerFromSystemPrompt(): void;
|
|
17
|
+
start(options: EmberAnswerStartOptions, subscriber: EmberAnswerSubscriber): EmberAnswerStartResult;
|
|
18
|
+
private deliver;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=emberAnswerTransport.stub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emberAnswerTransport.stub.d.ts","sourceRoot":"","sources":["../../../src/tests/stubs/emberAnswerTransport.stub.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC5B,MAAM,2EAA2E,CAAC;AAEnF,KAAK,aAAa,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEjF,qBAAa,+BAAgC,YAAW,2BAA2B;IACjF,UAAU,SAAK;IACf,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,aAAa,CAAgE;IAErF,SAAS,IAAI,IAAI;IAIjB,aAAa,IAAI,IAAI;IAIrB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAIzC;;;;OAIG;IACH,sBAAsB,IAAI,IAAI;IAI9B,KAAK,CACH,OAAO,EAAE,uBAAuB,EAChC,UAAU,EAAE,qBAAqB,GAChC,sBAAsB;YASX,OAAO;CAwBtB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export class StubEmberAnswerTransportGateway {
|
|
2
|
+
startCount = 0;
|
|
3
|
+
shouldFailStart = false;
|
|
4
|
+
shouldFailMidStream = false;
|
|
5
|
+
answerBuilder = async (question) => `Réponse à : ${question}`;
|
|
6
|
+
failStart() {
|
|
7
|
+
this.shouldFailStart = true;
|
|
8
|
+
}
|
|
9
|
+
failMidStream() {
|
|
10
|
+
this.shouldFailMidStream = true;
|
|
11
|
+
}
|
|
12
|
+
respondWith(builder) {
|
|
13
|
+
this.answerBuilder = builder;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Makes the stub answer with the system prompt it was started with. The grounding
|
|
17
|
+
* data lives in that prompt, so this proves the real path: readData → askEmber →
|
|
18
|
+
* prompt → transport, rather than the stub fabricating an answer of its own.
|
|
19
|
+
*/
|
|
20
|
+
answerFromSystemPrompt() {
|
|
21
|
+
this.answerBuilder = async (_question, systemPrompt) => systemPrompt;
|
|
22
|
+
}
|
|
23
|
+
start(options, subscriber) {
|
|
24
|
+
if (this.shouldFailStart) {
|
|
25
|
+
return { status: 'failed', reason: 'stub-start-failed' };
|
|
26
|
+
}
|
|
27
|
+
this.startCount += 1;
|
|
28
|
+
void this.deliver(options, subscriber);
|
|
29
|
+
return { status: 'started', run: { cancel: () => undefined } };
|
|
30
|
+
}
|
|
31
|
+
async deliver(options, subscriber) {
|
|
32
|
+
try {
|
|
33
|
+
const answer = await this.answerBuilder(options.question, options.systemPrompt);
|
|
34
|
+
const words = answer.split(' ');
|
|
35
|
+
const emitted = this.shouldFailMidStream
|
|
36
|
+
? Math.ceil(words.length / 2)
|
|
37
|
+
: words.length;
|
|
38
|
+
for (let index = 0; index < emitted; index += 1) {
|
|
39
|
+
const fragment = index === 0 ? words[index] : ` ${words[index]}`;
|
|
40
|
+
subscriber.onChunk(fragment);
|
|
41
|
+
}
|
|
42
|
+
if (this.shouldFailMidStream) {
|
|
43
|
+
subscriber.onError('stub-mid-stream-failed');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
subscriber.onDone();
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
const message = error instanceof Error ? error.message : 'stub-answer-failed';
|
|
50
|
+
subscriber.onError(message);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=emberAnswerTransport.stub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emberAnswerTransport.stub.js","sourceRoot":"","sources":["../../../src/tests/stubs/emberAnswerTransport.stub.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,+BAA+B;IAC1C,UAAU,GAAG,CAAC,CAAC;IACP,eAAe,GAAG,KAAK,CAAC;IACxB,mBAAmB,GAAG,KAAK,CAAC;IAC5B,aAAa,GAAkB,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,eAAe,QAAQ,EAAE,CAAC;IAErF,SAAS;QACP,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;IAC9B,CAAC;IAED,aAAa;QACX,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAClC,CAAC;IAED,WAAW,CAAC,OAAsB;QAChC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACH,sBAAsB;QACpB,IAAI,CAAC,aAAa,GAAG,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC;IACvE,CAAC;IAED,KAAK,CACH,OAAgC,EAChC,UAAiC;QAEjC,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;QAC3D,CAAC;QACD,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC;QACrB,KAAK,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QACvC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC;IACjE,CAAC;IAEO,KAAK,CAAC,OAAO,CACnB,OAAgC,EAChC,UAAiC;QAEjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;YAChF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAChC,MAAM,OAAO,GAAG,IAAI,CAAC,mBAAmB;gBACtC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC7B,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;YACjB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;gBAChD,MAAM,QAAQ,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjE,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAC/B,CAAC;YACD,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBAC7B,UAAU,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC;gBAC7C,OAAO;YACT,CAAC;YACD,UAAU,CAAC,MAAM,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC;YAC9E,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { EmberMemoryGateway } from '../../modules/ember-chat/entities/emberMemory/emberMemory.gateway.js';
|
|
2
|
+
import type { EmberMemory, EmberMemoryTurn, EmberRecurringInsight } from '../../modules/ember-chat/entities/emberMemory/emberMemory.schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Backing store shared across gateway instances so a "restart" (a new gateway
|
|
5
|
+
* over the same store) reloads what a previous instance persisted — mirroring
|
|
6
|
+
* the durable filesystem gateway without touching disk.
|
|
7
|
+
*/
|
|
8
|
+
export declare class StubEmberMemoryStore {
|
|
9
|
+
private readonly memoryByProject;
|
|
10
|
+
read(projectPath: string): EmberMemory | null;
|
|
11
|
+
appendTurn(projectPath: string, turn: EmberMemoryTurn): void;
|
|
12
|
+
appendInsight(projectPath: string, insight: EmberRecurringInsight): void;
|
|
13
|
+
remove(projectPath: string): void;
|
|
14
|
+
}
|
|
15
|
+
export declare class StubEmberMemoryGateway implements EmberMemoryGateway {
|
|
16
|
+
private readonly store;
|
|
17
|
+
private corrupted;
|
|
18
|
+
constructor(store?: StubEmberMemoryStore);
|
|
19
|
+
markCorrupted(): void;
|
|
20
|
+
load(projectPath: string): Promise<EmberMemory | null>;
|
|
21
|
+
appendTurn(projectPath: string, turn: EmberMemoryTurn): Promise<void>;
|
|
22
|
+
appendInsight(projectPath: string, insight: EmberRecurringInsight): Promise<void>;
|
|
23
|
+
clear(projectPath: string): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=emberMemory.stub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emberMemory.stub.d.ts","sourceRoot":"","sources":["../../../src/tests/stubs/emberMemory.stub.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kEAAkE,CAAC;AAC3G,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,qBAAqB,EACtB,MAAM,iEAAiE,CAAC;AAEzE;;;;GAIG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkC;IAElE,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAW7C,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,IAAI;IAQ5D,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI;IAQxE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;CAGlC;AAED,qBAAa,sBAAuB,YAAW,kBAAkB;IAGnD,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,OAAO,CAAC,SAAS,CAAS;gBAEG,KAAK,GAAE,oBAAiD;IAErF,aAAa,IAAI,IAAI;IAIf,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAOtD,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjF,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGhD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backing store shared across gateway instances so a "restart" (a new gateway
|
|
3
|
+
* over the same store) reloads what a previous instance persisted — mirroring
|
|
4
|
+
* the durable filesystem gateway without touching disk.
|
|
5
|
+
*/
|
|
6
|
+
export class StubEmberMemoryStore {
|
|
7
|
+
memoryByProject = new Map();
|
|
8
|
+
read(projectPath) {
|
|
9
|
+
const memory = this.memoryByProject.get(projectPath);
|
|
10
|
+
if (memory === undefined) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
turns: memory.turns.map((turn) => ({ ...turn })),
|
|
15
|
+
insights: [...memory.insights],
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
appendTurn(projectPath, turn) {
|
|
19
|
+
const current = this.memoryByProject.get(projectPath) ?? { turns: [], insights: [] };
|
|
20
|
+
this.memoryByProject.set(projectPath, {
|
|
21
|
+
turns: [...current.turns, turn],
|
|
22
|
+
insights: current.insights,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
appendInsight(projectPath, insight) {
|
|
26
|
+
const current = this.memoryByProject.get(projectPath) ?? { turns: [], insights: [] };
|
|
27
|
+
this.memoryByProject.set(projectPath, {
|
|
28
|
+
turns: current.turns,
|
|
29
|
+
insights: [...current.insights, insight],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
remove(projectPath) {
|
|
33
|
+
this.memoryByProject.delete(projectPath);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export class StubEmberMemoryGateway {
|
|
37
|
+
store;
|
|
38
|
+
corrupted = false;
|
|
39
|
+
constructor(store = new StubEmberMemoryStore()) {
|
|
40
|
+
this.store = store;
|
|
41
|
+
}
|
|
42
|
+
markCorrupted() {
|
|
43
|
+
this.corrupted = true;
|
|
44
|
+
}
|
|
45
|
+
async load(projectPath) {
|
|
46
|
+
if (this.corrupted) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return this.store.read(projectPath);
|
|
50
|
+
}
|
|
51
|
+
async appendTurn(projectPath, turn) {
|
|
52
|
+
this.store.appendTurn(projectPath, turn);
|
|
53
|
+
}
|
|
54
|
+
async appendInsight(projectPath, insight) {
|
|
55
|
+
this.store.appendInsight(projectPath, insight);
|
|
56
|
+
}
|
|
57
|
+
async clear(projectPath) {
|
|
58
|
+
this.store.remove(projectPath);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=emberMemory.stub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emberMemory.stub.js","sourceRoot":"","sources":["../../../src/tests/stubs/emberMemory.stub.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,MAAM,OAAO,oBAAoB;IACd,eAAe,GAAG,IAAI,GAAG,EAAuB,CAAC;IAElE,IAAI,CAAC,WAAmB;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACrD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;YAChD,QAAQ,EAAE,CAAC,GAAG,MAAM,CAAC,QAAQ,CAAC;SAC/B,CAAC;IACJ,CAAC;IAED,UAAU,CAAC,WAAmB,EAAE,IAAqB;QACnD,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACrF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE;YACpC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC;YAC/B,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC,CAAC;IACL,CAAC;IAED,aAAa,CAAC,WAAmB,EAAE,OAA8B;QAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACrF,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,WAAW,EAAE;YACpC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,QAAQ,EAAE,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC;SACzC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,WAAmB;QACxB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC;CACF;AAED,MAAM,OAAO,sBAAsB;IAGJ;IAFrB,SAAS,GAAG,KAAK,CAAC;IAE1B,YAA6B,QAA8B,IAAI,oBAAoB,EAAE;QAAxD,UAAK,GAAL,KAAK,CAAmD;IAAG,CAAC;IAEzF,aAAa;QACX,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAmB;QAC5B,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,WAAmB,EAAE,IAAqB;QACzD,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,WAAmB,EAAE,OAA8B;QACrE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,WAAmB;QAC7B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;CACF"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
2
|
import Fastify from 'fastify';
|
|
3
3
|
import { emberChatRoutes } from '../../../../../modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js';
|
|
4
|
-
import {
|
|
5
|
-
import { StubEmberSessionTransportGateway } from '../../../../../tests/stubs/emberSessionTransport.stub.js';
|
|
4
|
+
import { StubEmberAnswerTransportGateway } from '../../../../../tests/stubs/emberAnswerTransport.stub.js';
|
|
6
5
|
import { StubEmberReadDataGateway } from '../../../../../tests/stubs/emberReadData.stub.js';
|
|
7
6
|
import { StubEnvironmentGateway } from '../../../../../tests/stubs/environment.stub.js';
|
|
7
|
+
import { StubEmberMemoryGateway } from '../../../../../tests/stubs/emberMemory.stub.js';
|
|
8
|
+
import { EmberMemoryTurnFactory } from '../../../../../tests/factories/emberMemory.factory.js';
|
|
8
9
|
import { createStubLogger } from '../../../../../tests/stubs/logger.stub.js';
|
|
9
10
|
const PROJECT_PATH = '/projects/alpha';
|
|
10
11
|
function parseSseEvents(body) {
|
|
@@ -17,23 +18,20 @@ describe('emberChat routes', () => {
|
|
|
17
18
|
let application;
|
|
18
19
|
let transport;
|
|
19
20
|
let environment;
|
|
21
|
+
let memory;
|
|
20
22
|
function buildApplication() {
|
|
21
|
-
transport = new
|
|
23
|
+
transport = new StubEmberAnswerTransportGateway();
|
|
22
24
|
transport.respondWith(async (question) => `Réponse à ${question}`);
|
|
23
25
|
environment = new StubEnvironmentGateway();
|
|
24
26
|
environment.setHasAnthropicApiKey(false);
|
|
25
|
-
|
|
26
|
-
transport,
|
|
27
|
-
now: () => new Date('2026-05-28T10:00:00Z'),
|
|
28
|
-
idleTimeoutMs: 60_000,
|
|
29
|
-
});
|
|
27
|
+
memory = new StubEmberMemoryGateway();
|
|
30
28
|
const instance = Fastify();
|
|
31
29
|
void instance.register(emberChatRoutes, {
|
|
32
|
-
|
|
30
|
+
transport,
|
|
33
31
|
environment,
|
|
34
32
|
readData: new StubEmberReadDataGateway(),
|
|
33
|
+
memory,
|
|
35
34
|
projectPath: PROJECT_PATH,
|
|
36
|
-
now: () => new Date('2026-05-28T10:00:00Z'),
|
|
37
35
|
logger: createStubLogger(),
|
|
38
36
|
});
|
|
39
37
|
return instance;
|
|
@@ -45,14 +43,14 @@ describe('emberChat routes', () => {
|
|
|
45
43
|
afterEach(async () => {
|
|
46
44
|
await application.close();
|
|
47
45
|
});
|
|
48
|
-
it('rejects an empty question with 400 and never
|
|
46
|
+
it('rejects an empty question with 400 and never starts', async () => {
|
|
49
47
|
const response = await application.inject({
|
|
50
48
|
method: 'POST',
|
|
51
49
|
url: '/api/ember/ask',
|
|
52
50
|
payload: { question: '' },
|
|
53
51
|
});
|
|
54
52
|
expect(response.statusCode).toBe(400);
|
|
55
|
-
expect(transport.
|
|
53
|
+
expect(transport.startCount).toBe(0);
|
|
56
54
|
});
|
|
57
55
|
it('streams chunk, status and end events for a valid question', async () => {
|
|
58
56
|
const response = await application.inject({
|
|
@@ -71,7 +69,21 @@ describe('emberChat routes', () => {
|
|
|
71
69
|
});
|
|
72
70
|
it('emits an error event when the assistant is unreachable', async () => {
|
|
73
71
|
application = buildApplication();
|
|
74
|
-
transport.
|
|
72
|
+
transport.failStart();
|
|
73
|
+
await application.ready();
|
|
74
|
+
const response = await application.inject({
|
|
75
|
+
method: 'POST',
|
|
76
|
+
url: '/api/ember/ask',
|
|
77
|
+
payload: { question: 'Quel projet a le pire score ?' },
|
|
78
|
+
});
|
|
79
|
+
const events = parseSseEvents(response.body);
|
|
80
|
+
const errors = events.filter((event) => event.type === 'error');
|
|
81
|
+
expect(errors.length).toBeGreaterThan(0);
|
|
82
|
+
expect(String(errors[0].message)).toContain('INDISPONIBLE');
|
|
83
|
+
});
|
|
84
|
+
it('emits an error event when answering fails mid-stream', async () => {
|
|
85
|
+
application = buildApplication();
|
|
86
|
+
transport.failMidStream();
|
|
75
87
|
await application.ready();
|
|
76
88
|
const response = await application.inject({
|
|
77
89
|
method: 'POST',
|
|
@@ -95,7 +107,16 @@ describe('emberChat routes', () => {
|
|
|
95
107
|
const events = parseSseEvents(response.body);
|
|
96
108
|
const errors = events.filter((event) => event.type === 'error');
|
|
97
109
|
expect(errors.length).toBeGreaterThan(0);
|
|
98
|
-
expect(transport.
|
|
110
|
+
expect(transport.startCount).toBe(0);
|
|
111
|
+
});
|
|
112
|
+
it('clears the project memory on POST /api/ember/memory/clear', async () => {
|
|
113
|
+
await memory.appendTurn(PROJECT_PATH, EmberMemoryTurnFactory.create());
|
|
114
|
+
const response = await application.inject({
|
|
115
|
+
method: 'POST',
|
|
116
|
+
url: '/api/ember/memory/clear',
|
|
117
|
+
});
|
|
118
|
+
expect(response.statusCode).toBe(200);
|
|
119
|
+
expect(await memory.load(PROJECT_PATH)).toBeNull();
|
|
99
120
|
});
|
|
100
121
|
});
|
|
101
122
|
//# sourceMappingURL=emberChat.routes.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"emberChat.routes.test.js","sourceRoot":"","sources":["../../../../../../src/tests/units/modules/ember-chat/controllers/emberChat.routes.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,eAAe,EAAE,MAAM,8EAA8E,CAAC;AAC/G,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"emberChat.routes.test.js","sourceRoot":"","sources":["../../../../../../src/tests/units/modules/ember-chat/controllers/emberChat.routes.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emberMemory.guard.test.d.ts","sourceRoot":"","sources":["../../../../../../src/tests/units/modules/ember-chat/entities/emberMemory.guard.test.ts"],"names":[],"mappings":""}
|