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.
Files changed (144) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/dashboard/index.html +35 -11
  3. package/dist/dashboard/styles.css +139 -5
  4. package/dist/frameworks/claude/claudeInvoker.d.ts +7 -0
  5. package/dist/frameworks/claude/claudeInvoker.d.ts.map +1 -1
  6. package/dist/frameworks/claude/claudeInvoker.js +1 -1
  7. package/dist/frameworks/claude/claudeInvoker.js.map +1 -1
  8. package/dist/main/routes.d.ts.map +1 -1
  9. package/dist/main/routes.js +9 -16
  10. package/dist/main/routes.js.map +1 -1
  11. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.gateway.d.ts +1 -1
  12. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.gateway.d.ts.map +1 -1
  13. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.guard.d.ts +1 -1
  14. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.d.ts +2 -0
  15. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.d.ts.map +1 -1
  16. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.js +1 -1
  17. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.js.map +1 -1
  18. package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.d.ts +24 -0
  19. package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.d.ts.map +1 -0
  20. package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js +2 -0
  21. package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js.map +1 -0
  22. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.gateway.d.ts +8 -0
  23. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.gateway.d.ts.map +1 -0
  24. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.gateway.js +2 -0
  25. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.gateway.js.map +1 -0
  26. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.guard.d.ts +8 -0
  27. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.guard.d.ts.map +1 -0
  28. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.guard.js +4 -0
  29. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.guard.js.map +1 -0
  30. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.schema.d.ts +17 -0
  31. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.schema.d.ts.map +1 -0
  32. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.schema.js +11 -0
  33. package/dist/modules/ember-chat/entities/emberMemory/emberMemory.schema.js.map +1 -0
  34. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.d.ts +4 -3
  35. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.d.ts.map +1 -1
  36. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js +12 -4
  37. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js.map +1 -1
  38. package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.d.ts +46 -0
  39. package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.d.ts.map +1 -0
  40. package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.js +176 -0
  41. package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.js.map +1 -0
  42. package/dist/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.d.ts +22 -0
  43. package/dist/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.d.ts.map +1 -0
  44. package/dist/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.js +55 -0
  45. package/dist/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.js.map +1 -0
  46. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.d.ts +2 -1
  47. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.d.ts.map +1 -1
  48. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js +8 -2
  49. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js.map +1 -1
  50. package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.d.ts +1 -1
  51. package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.d.ts.map +1 -1
  52. package/dist/modules/ember-chat/services/emberSystemPrompt.d.ts +2 -0
  53. package/dist/modules/ember-chat/services/emberSystemPrompt.d.ts.map +1 -1
  54. package/dist/modules/ember-chat/services/emberSystemPrompt.js +87 -11
  55. package/dist/modules/ember-chat/services/emberSystemPrompt.js.map +1 -1
  56. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.d.ts +7 -4
  57. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.d.ts.map +1 -1
  58. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.js +90 -8
  59. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.js.map +1 -1
  60. package/dist/modules/ember-chat/usecases/askEmber/emberStream.d.ts +8 -0
  61. package/dist/modules/ember-chat/usecases/askEmber/emberStream.d.ts.map +1 -0
  62. package/dist/modules/ember-chat/usecases/askEmber/emberStream.js +2 -0
  63. package/dist/modules/ember-chat/usecases/askEmber/emberStream.js.map +1 -0
  64. package/dist/modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.d.ts +7 -0
  65. package/dist/modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.d.ts.map +1 -0
  66. package/dist/modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.js +4 -0
  67. package/dist/modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.js.map +1 -0
  68. package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.d.ts +2 -0
  69. package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.d.ts.map +1 -0
  70. package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.js +165 -0
  71. package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.js.map +1 -0
  72. package/dist/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.d.ts +2 -0
  73. package/dist/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.d.ts.map +1 -0
  74. package/dist/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.js +261 -0
  75. package/dist/tests/acceptance/192-ember-ondemand-grounding-and-memory.acceptance.test.js.map +1 -0
  76. package/dist/tests/factories/emberMemory.factory.d.ts +8 -0
  77. package/dist/tests/factories/emberMemory.factory.d.ts.map +1 -0
  78. package/dist/tests/factories/emberMemory.factory.js +19 -0
  79. package/dist/tests/factories/emberMemory.factory.js.map +1 -0
  80. package/dist/tests/stubs/emberAnswerTransport.stub.d.ts +21 -0
  81. package/dist/tests/stubs/emberAnswerTransport.stub.d.ts.map +1 -0
  82. package/dist/tests/stubs/emberAnswerTransport.stub.js +54 -0
  83. package/dist/tests/stubs/emberAnswerTransport.stub.js.map +1 -0
  84. package/dist/tests/stubs/emberMemory.stub.d.ts +25 -0
  85. package/dist/tests/stubs/emberMemory.stub.d.ts.map +1 -0
  86. package/dist/tests/stubs/emberMemory.stub.js +61 -0
  87. package/dist/tests/stubs/emberMemory.stub.js.map +1 -0
  88. package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.js +35 -14
  89. package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.js.map +1 -1
  90. package/dist/tests/units/modules/ember-chat/entities/emberMemory.guard.test.d.ts +2 -0
  91. package/dist/tests/units/modules/ember-chat/entities/emberMemory.guard.test.d.ts.map +1 -0
  92. package/dist/tests/units/modules/ember-chat/entities/emberMemory.guard.test.js +51 -0
  93. package/dist/tests/units/modules/ember-chat/entities/emberMemory.guard.test.js.map +1 -0
  94. package/dist/tests/units/modules/ember-chat/gateways/emberMemory.fileSystem.gateway.test.d.ts +2 -0
  95. package/dist/tests/units/modules/ember-chat/gateways/emberMemory.fileSystem.gateway.test.d.ts.map +1 -0
  96. package/dist/tests/units/modules/ember-chat/gateways/emberMemory.fileSystem.gateway.test.js +82 -0
  97. package/dist/tests/units/modules/ember-chat/gateways/emberMemory.fileSystem.gateway.test.js.map +1 -0
  98. package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.js +13 -0
  99. package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.js.map +1 -1
  100. package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.js +93 -2
  101. package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.js.map +1 -1
  102. package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.js +108 -20
  103. package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.js.map +1 -1
  104. package/dist/tests/units/modules/ember-chat/usecases/clearEmberMemory.usecase.test.d.ts +2 -0
  105. package/dist/tests/units/modules/ember-chat/usecases/clearEmberMemory.usecase.test.d.ts.map +1 -0
  106. package/dist/tests/units/modules/ember-chat/usecases/clearEmberMemory.usecase.test.js +14 -0
  107. package/dist/tests/units/modules/ember-chat/usecases/clearEmberMemory.usecase.test.js.map +1 -0
  108. package/package.json +1 -1
  109. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.d.ts +0 -7
  110. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.d.ts.map +0 -1
  111. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.js +0 -3
  112. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.js.map +0 -1
  113. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.d.ts +0 -13
  114. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.d.ts.map +0 -1
  115. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.js +0 -35
  116. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.js.map +0 -1
  117. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.d.ts +0 -26
  118. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.d.ts.map +0 -1
  119. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js +0 -2
  120. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js.map +0 -1
  121. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.d.ts +0 -13
  122. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.d.ts.map +0 -1
  123. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.js +0 -130
  124. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.js.map +0 -1
  125. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.d.ts +0 -36
  126. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.d.ts.map +0 -1
  127. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.js +0 -59
  128. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.js.map +0 -1
  129. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.d.ts +0 -2
  130. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.d.ts.map +0 -1
  131. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.js +0 -124
  132. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.js.map +0 -1
  133. package/dist/tests/stubs/emberSessionTransport.stub.d.ts +0 -18
  134. package/dist/tests/stubs/emberSessionTransport.stub.d.ts.map +0 -1
  135. package/dist/tests/stubs/emberSessionTransport.stub.js +0 -75
  136. package/dist/tests/stubs/emberSessionTransport.stub.js.map +0 -1
  137. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.d.ts +0 -2
  138. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.d.ts.map +0 -1
  139. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.js +0 -42
  140. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.js.map +0 -1
  141. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.d.ts +0 -2
  142. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.d.ts.map +0 -1
  143. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.js +0 -88
  144. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.js.map +0 -1
@@ -13,7 +13,7 @@ export const claudeSessionStatusSchema = z.enum([
13
13
  'timed-out',
14
14
  'cleaned',
15
15
  ]);
16
- export const claudeSessionJobTypeSchema = z.enum(['review', 'followup']);
16
+ export const claudeSessionJobTypeSchema = z.enum(['review', 'followup', 'ember-chat']);
17
17
  export const claudeSessionSchema = z.object({
18
18
  sessionId: sessionIdSchema,
19
19
  jobId: z.string().min(1),
@@ -1 +1 @@
1
- {"version":3,"file":"claudeSession.schema.js","sourceRoot":"","sources":["../../../../../src/modules/claude-invocation/entities/claudeSession/claudeSession.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC;KAC7B,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,EAAE,8BAA8B,CAAC;KACtC,KAAK,EAAe,CAAC;AAIxB,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAO,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC9C,YAAY;IACZ,WAAW;IACX,QAAQ;IACR,WAAW;IACX,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;AAEzE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,SAAS,EAAE,eAAe;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,OAAO,EAAE,0BAA0B;IACnC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,YAAY,EAAE,CAAC,CAAC,IAAI,EAAE;IACtB,MAAM,EAAE,yBAAyB;IACjC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC"}
1
+ {"version":3,"file":"claudeSession.schema.js","sourceRoot":"","sources":["../../../../../src/modules/claude-invocation/entities/claudeSession/claudeSession.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC;KAC7B,MAAM,EAAE;KACR,GAAG,CAAC,CAAC,EAAE,8BAA8B,CAAC;KACtC,KAAK,EAAe,CAAC;AAIxB,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,OAAO,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC9C,YAAY;IACZ,WAAW;IACX,QAAQ;IACR,WAAW;IACX,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;AAEvF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,SAAS,EAAE,eAAe;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACxB,OAAO,EAAE,0BAA0B;IACnC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,YAAY,EAAE,CAAC,CAAC,IAAI,EAAE;IACtB,MAAM,EAAE,yBAAyB;IACjC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ export interface EmberAnswerSubscriber {
2
+ onChunk: (text: string) => void;
3
+ onDone: () => void;
4
+ onError: (message: string) => void;
5
+ }
6
+ export interface EmberAnswerStartOptions {
7
+ question: string;
8
+ systemPrompt: string;
9
+ projectPath: string;
10
+ }
11
+ export interface EmberAnswerRun {
12
+ cancel(): void;
13
+ }
14
+ export type EmberAnswerStartResult = {
15
+ status: 'started';
16
+ run: EmberAnswerRun;
17
+ } | {
18
+ status: 'failed';
19
+ reason: string;
20
+ };
21
+ export interface EmberAnswerTransportGateway {
22
+ start(options: EmberAnswerStartOptions, subscriber: EmberAnswerSubscriber): EmberAnswerStartResult;
23
+ }
24
+ //# sourceMappingURL=emberAnswerTransport.gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberAnswerTransport.gateway.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,IAAI,IAAI,CAAC;CAChB;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,cAAc,CAAA;CAAE,GAC1C;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,WAAW,2BAA2B;IAC1C,KAAK,CACH,OAAO,EAAE,uBAAuB,EAChC,UAAU,EAAE,qBAAqB,GAChC,sBAAsB,CAAC;CAC3B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=emberAnswerTransport.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberAnswerTransport.gateway.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ import type { EmberMemory, EmberMemoryTurn, EmberRecurringInsight } from '../../../../modules/ember-chat/entities/emberMemory/emberMemory.schema.js';
2
+ export interface EmberMemoryGateway {
3
+ load(projectPath: string): Promise<EmberMemory | null>;
4
+ appendTurn(projectPath: string, turn: EmberMemoryTurn): Promise<void>;
5
+ appendInsight(projectPath: string, insight: EmberRecurringInsight): Promise<void>;
6
+ clear(projectPath: string): Promise<void>;
7
+ }
8
+ //# sourceMappingURL=emberMemory.gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberMemory.gateway.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberMemory/emberMemory.gateway.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,qBAAqB,EACtB,MAAM,iEAAiE,CAAC;AAEzE,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACvD,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3C"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=emberMemory.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberMemory.gateway.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberMemory/emberMemory.gateway.ts"],"names":[],"mappings":""}
@@ -0,0 +1,8 @@
1
+ export declare const emberMemoryGuard: import("../../../../shared/foundation/guard.base.js").Guard<{
2
+ turns: {
3
+ question: string;
4
+ answer: string;
5
+ }[];
6
+ insights: string[];
7
+ }>;
8
+ //# sourceMappingURL=emberMemory.guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberMemory.guard.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberMemory/emberMemory.guard.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB;;;;;;EAAgD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { createGuard } from '../../../../shared/foundation/guard.base.js';
2
+ import { emberMemorySchema } from '../../../../modules/ember-chat/entities/emberMemory/emberMemory.schema.js';
3
+ export const emberMemoryGuard = createGuard(emberMemorySchema, 'emberMemory');
4
+ //# sourceMappingURL=emberMemory.guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberMemory.guard.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberMemory/emberMemory.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iEAAiE,CAAC;AAEpG,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { z } from 'zod';
2
+ export declare const emberMemoryTurnSchema: z.ZodObject<{
3
+ question: z.ZodString;
4
+ answer: z.ZodString;
5
+ }, z.core.$strip>;
6
+ export declare const emberRecurringInsightSchema: z.ZodString;
7
+ export declare const emberMemorySchema: z.ZodObject<{
8
+ turns: z.ZodArray<z.ZodObject<{
9
+ question: z.ZodString;
10
+ answer: z.ZodString;
11
+ }, z.core.$strip>>;
12
+ insights: z.ZodDefault<z.ZodArray<z.ZodString>>;
13
+ }, z.core.$strip>;
14
+ export type EmberMemoryTurn = z.infer<typeof emberMemoryTurnSchema>;
15
+ export type EmberRecurringInsight = z.infer<typeof emberRecurringInsightSchema>;
16
+ export type EmberMemory = z.infer<typeof emberMemorySchema>;
17
+ //# sourceMappingURL=emberMemory.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberMemory.schema.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberMemory/emberMemory.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,qBAAqB;;;iBAGhC,CAAC;AAEH,eAAO,MAAM,2BAA2B,aAA2B,CAAC;AAEpE,eAAO,MAAM,iBAAiB;;;;;;iBAG5B,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAChF,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ export const emberMemoryTurnSchema = z.object({
3
+ question: z.string().trim().min(1),
4
+ answer: z.string().trim().min(1),
5
+ });
6
+ export const emberRecurringInsightSchema = z.string().trim().min(1);
7
+ export const emberMemorySchema = z.object({
8
+ turns: z.array(emberMemoryTurnSchema),
9
+ insights: z.array(emberRecurringInsightSchema).default([]),
10
+ });
11
+ //# sourceMappingURL=emberMemory.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberMemory.schema.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/entities/emberMemory/emberMemory.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACjC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC;IACrC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CAC3D,CAAC,CAAC"}
@@ -1,14 +1,15 @@
1
1
  import type { FastifyPluginAsync } from 'fastify';
2
2
  import type { Logger } from 'pino';
3
- import type { EmberSessionRegistry } from '../../../../../modules/ember-chat/usecases/emberSession/emberSessionRegistry.js';
3
+ import type { EmberAnswerTransportGateway } from '../../../../../modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js';
4
4
  import type { EmberReadDataGateway } from '../../../../../modules/ember-chat/entities/emberTool/emberTool.gateway.js';
5
+ import type { EmberMemoryGateway } from '../../../../../modules/ember-chat/entities/emberMemory/emberMemory.gateway.js';
5
6
  import type { EnvironmentGateway } from '../../../../../modules/claude-invocation/entities/billingState/environment.gateway.js';
6
7
  export interface EmberChatRoutesOptions {
7
- registry: EmberSessionRegistry;
8
+ transport: EmberAnswerTransportGateway;
8
9
  environment: EnvironmentGateway;
9
10
  readData: EmberReadDataGateway;
11
+ memory: EmberMemoryGateway;
10
12
  projectPath: string;
11
- now: () => Date;
12
13
  logger: Logger;
13
14
  }
14
15
  export declare const emberChatRoutes: FastifyPluginAsync<EmberChatRoutesOptions>;
@@ -1 +1 @@
1
- {"version":3,"file":"emberChat.routes.d.ts","sourceRoot":"","sources":["../../../../../../src/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oEAAoE,CAAC;AAC/G,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACzG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0EAA0E,CAAC;AAInH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,eAAe,EAAE,kBAAkB,CAAC,sBAAsB,CAmEtE,CAAC"}
1
+ {"version":3,"file":"emberChat.routes.d.ts","sourceRoot":"","sources":["../../../../../../src/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAInC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2EAA2E,CAAC;AAC7H,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACzG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kEAAkE,CAAC;AAC3G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0EAA0E,CAAC;AAInH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,2BAA2B,CAAC;IACvC,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,eAAe,EAAE,kBAAkB,CAAC,sBAAsB,CA2EtE,CAAC"}
@@ -1,8 +1,13 @@
1
1
  import { emberMessageGuard } from '../../../../../modules/ember-chat/entities/emberMessage/emberMessage.guard.js';
2
2
  import { askEmber } from '../../../../../modules/ember-chat/usecases/askEmber/askEmber.usecase.js';
3
+ import { clearEmberMemory } from '../../../../../modules/ember-chat/usecases/clearEmberMemory/clearEmberMemory.usecase.js';
3
4
  const UNAVAILABLE_MESSAGE = '// EMBER INDISPONIBLE — réessayer';
4
5
  export const emberChatRoutes = async (fastify, options) => {
5
- const { registry, environment, readData, projectPath, now, logger } = options;
6
+ const { transport, environment, readData, memory, projectPath, logger } = options;
7
+ fastify.post('/api/ember/memory/clear', async (_request, reply) => {
8
+ await clearEmberMemory({ memory, projectPath });
9
+ reply.code(200).send({ status: 'cleared' });
10
+ });
6
11
  fastify.post('/api/ember/ask', async (request, reply) => {
7
12
  const parsed = emberMessageGuard.safeParse(request.body);
8
13
  if (!parsed.success) {
@@ -10,11 +15,11 @@ export const emberChatRoutes = async (fastify, options) => {
10
15
  return;
11
16
  }
12
17
  const result = await askEmber(parsed.data, {
13
- registry,
18
+ transport,
14
19
  environment,
15
20
  readData,
21
+ memory,
16
22
  projectPath,
17
- now,
18
23
  });
19
24
  reply.hijack();
20
25
  reply.raw.writeHead(200, {
@@ -54,7 +59,10 @@ export const emberChatRoutes = async (fastify, options) => {
54
59
  },
55
60
  onDone: finish,
56
61
  });
57
- request.raw.on('close', finish);
62
+ request.raw.on('close', () => {
63
+ result.cancel();
64
+ finish();
65
+ });
58
66
  });
59
67
  });
60
68
  };
@@ -1 +1 @@
1
- {"version":3,"file":"emberChat.routes.js","sourceRoot":"","sources":["../../../../../../src/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"emberChat.routes.js","sourceRoot":"","sources":["../../../../../../src/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { ClaudeSessionGateway } from '../../../../modules/claude-invocation/entities/claudeSession/claudeSession.gateway.js';
2
+ import type { EmberAnswerStartOptions, EmberAnswerStartResult, EmberAnswerSubscriber, EmberAnswerTransportGateway } from '../../../../modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js';
3
+ /**
4
+ * HUMBLE GLUE — NOT unit-tested. This is the single unverified mechanism in
5
+ * SPEC-190 (plan §OPEN RISKS 1-2). Every layer above it (askEmber usecase,
6
+ * relay, presenter, routes, client) is unit-tested against
7
+ * StubEmberAnswerTransportGateway; this file is the swappable real
8
+ * implementation, validated by acceptance/manual only.
9
+ *
10
+ * Transport: ONE `claude --bg` dispatch per question (subscription / OAuth
11
+ * billing, the same path reviews use — NEVER `--print`/headless, which switches
12
+ * to API billing on 2026-06-15). After dispatch, tail the session transcript
13
+ * JSONL, emitting onChunk per new assistant text segment and onDone on the
14
+ * turn-complete marker, then stop the (persistent) background session.
15
+ *
16
+ * Read-only is enforced structurally: read-only tools (Read,Glob,Grep), with
17
+ * Edit/Write/Bash/Task in disallowedTools and no MCP servers. `--permission-mode
18
+ * auto` matches the proven reviews path (`plan` would risk the agent emitting a
19
+ * plan instead of an answer).
20
+ *
21
+ * Verified against claude 2.1.154 (`claude --bg --permission-mode auto`):
22
+ * - The transcript file is named with the FULL session UUID, while `backgrounded
23
+ * · <id>` only yields the short prefix — so the file is resolved by prefix glob
24
+ * (<shortId>*.jsonl) in the project dir, NOT by exact name.
25
+ * - There is NO `result`/`message_stop` line. Turn completion is signalled by an
26
+ * `assistant` message with stop_reason `end_turn` and a `system` line with
27
+ * subtype `turn_duration` (both handled by isTurnComplete).
28
+ * - A `--bg` session is persistent: after answering it goes `idle` (not a
29
+ * terminal status), so a listAgents() poll cannot detect "done" — completion
30
+ * relies on the transcript marker; the session is then stopped here.
31
+ * - Assistant text is carried under message.content[].text (what extractText
32
+ * reads); chunks are whole-message granularity (coarse progressive), not deltas.
33
+ *
34
+ * STILL TO VERIFY MANUALLY: drive the chat end-to-end in a browser.
35
+ */
36
+ export interface EmberAnswerTransportClaudeGatewayOptions {
37
+ homeDir: string;
38
+ pollIntervalMs?: number;
39
+ }
40
+ export declare class EmberAnswerTransportClaudeGateway implements EmberAnswerTransportGateway {
41
+ private readonly sessionGateway;
42
+ private readonly options;
43
+ constructor(sessionGateway: ClaudeSessionGateway, options: EmberAnswerTransportClaudeGatewayOptions);
44
+ start(options: EmberAnswerStartOptions, subscriber: EmberAnswerSubscriber): EmberAnswerStartResult;
45
+ }
46
+ //# sourceMappingURL=emberAnswerTransport.claude.gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberAnswerTransport.claude.gateway.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6EAA6E,CAAC;AAOxH,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,2BAA2B,EAC5B,MAAM,2EAA2E,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,MAAM,WAAW,wCAAwC;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAID,qBAAa,iCAAkC,YAAW,2BAA2B;IAEjF,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO;gBADP,cAAc,EAAE,oBAAoB,EACpC,OAAO,EAAE,wCAAwC;IAGpE,KAAK,CACH,OAAO,EAAE,uBAAuB,EAChC,UAAU,EAAE,qBAAqB,GAChC,sBAAsB;CAW1B"}
@@ -0,0 +1,176 @@
1
+ import { readFileSync, existsSync, readdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { parseStreamJsonEvent, extractText, isTurnComplete, } from '../../../../modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js';
4
+ const DEFAULT_POLL_INTERVAL_MS = 750;
5
+ export class EmberAnswerTransportClaudeGateway {
6
+ sessionGateway;
7
+ options;
8
+ constructor(sessionGateway, options) {
9
+ this.sessionGateway = sessionGateway;
10
+ this.options = options;
11
+ }
12
+ start(options, subscriber) {
13
+ const run = new EmberAnswerRunner(this.sessionGateway, this.options.homeDir, this.options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS, options, subscriber);
14
+ run.begin();
15
+ return { status: 'started', run };
16
+ }
17
+ }
18
+ const MAX_TAIL_ATTEMPTS = 240;
19
+ class EmberAnswerRunner {
20
+ sessionGateway;
21
+ homeDir;
22
+ pollIntervalMs;
23
+ options;
24
+ subscriber;
25
+ cancelled = false;
26
+ timer = null;
27
+ byteOffset = 0;
28
+ pendingLine = '';
29
+ transcriptPath = null;
30
+ projectDir = null;
31
+ shortSessionId = null;
32
+ attempts = 0;
33
+ stopped = false;
34
+ constructor(sessionGateway, homeDir, pollIntervalMs, options, subscriber) {
35
+ this.sessionGateway = sessionGateway;
36
+ this.homeDir = homeDir;
37
+ this.pollIntervalMs = pollIntervalMs;
38
+ this.options = options;
39
+ this.subscriber = subscriber;
40
+ }
41
+ begin() {
42
+ void this.dispatchThenTail();
43
+ }
44
+ cancel() {
45
+ this.cancelled = true;
46
+ this.stopTimer();
47
+ this.stopSession();
48
+ }
49
+ async dispatchThenTail() {
50
+ const dispatch = await this.sessionGateway.dispatch({
51
+ prompt: this.options.question,
52
+ flags: {
53
+ model: 'sonnet',
54
+ permissionMode: 'auto',
55
+ systemPrompt: this.options.systemPrompt,
56
+ mcpConfigJson: '{"mcpServers":{}}',
57
+ allowedTools: 'Read,Glob,Grep',
58
+ disallowedTools: 'Edit,Write,Bash,Task',
59
+ },
60
+ localPath: this.options.projectPath,
61
+ jobId: `ember-${Date.now()}`,
62
+ jobType: 'ember-chat',
63
+ });
64
+ if (dispatch.status !== 'dispatched') {
65
+ this.fail('ember-answer-dispatch-failed');
66
+ return;
67
+ }
68
+ const slug = this.options.projectPath.replace(/\//g, '-');
69
+ this.projectDir = join(this.homeDir, '.claude', 'projects', slug);
70
+ this.shortSessionId = dispatch.sessionId;
71
+ this.scheduleTail();
72
+ }
73
+ scheduleTail() {
74
+ if (this.cancelled) {
75
+ return;
76
+ }
77
+ this.timer = setTimeout(() => {
78
+ this.tailOnce();
79
+ }, this.pollIntervalMs);
80
+ }
81
+ tailOnce() {
82
+ if (this.cancelled) {
83
+ return;
84
+ }
85
+ this.attempts += 1;
86
+ this.resolveTranscript();
87
+ const completed = this.readNewLines();
88
+ if (completed) {
89
+ this.finish();
90
+ return;
91
+ }
92
+ if (this.attempts >= MAX_TAIL_ATTEMPTS) {
93
+ this.fail('ember-answer-timeout');
94
+ return;
95
+ }
96
+ this.scheduleTail();
97
+ }
98
+ resolveTranscript() {
99
+ if (this.transcriptPath !== null || this.projectDir === null || this.shortSessionId === null) {
100
+ return;
101
+ }
102
+ if (!existsSync(this.projectDir)) {
103
+ return;
104
+ }
105
+ const match = readdirSync(this.projectDir).find((name) => name.startsWith(this.shortSessionId ?? '') && name.endsWith('.jsonl'));
106
+ if (match !== undefined) {
107
+ this.transcriptPath = join(this.projectDir, match);
108
+ }
109
+ }
110
+ readNewLines() {
111
+ if (this.transcriptPath === null || !existsSync(this.transcriptPath)) {
112
+ return false;
113
+ }
114
+ let raw;
115
+ try {
116
+ raw = readFileSync(this.transcriptPath, 'utf-8');
117
+ }
118
+ catch {
119
+ this.fail('ember-answer-transcript-unreadable');
120
+ return false;
121
+ }
122
+ const fresh = raw.slice(this.byteOffset);
123
+ this.byteOffset = raw.length;
124
+ this.pendingLine += fresh;
125
+ const lines = this.pendingLine.split('\n');
126
+ this.pendingLine = lines.pop() ?? '';
127
+ let terminal = false;
128
+ for (const line of lines) {
129
+ if (line.trim().length === 0) {
130
+ continue;
131
+ }
132
+ const event = parseStreamJsonEvent(line);
133
+ if (event === null) {
134
+ continue;
135
+ }
136
+ const text = extractText(event);
137
+ if (text !== null) {
138
+ this.subscriber.onChunk(text);
139
+ }
140
+ if (isTurnComplete(event)) {
141
+ terminal = true;
142
+ }
143
+ }
144
+ return terminal;
145
+ }
146
+ finish() {
147
+ if (this.cancelled) {
148
+ return;
149
+ }
150
+ this.readNewLines();
151
+ this.stopTimer();
152
+ this.stopSession();
153
+ this.subscriber.onDone();
154
+ }
155
+ fail(message) {
156
+ if (this.cancelled) {
157
+ return;
158
+ }
159
+ this.cancel();
160
+ this.subscriber.onError(message);
161
+ }
162
+ stopSession() {
163
+ if (this.stopped || this.shortSessionId === null) {
164
+ return;
165
+ }
166
+ this.stopped = true;
167
+ void this.sessionGateway.stop(this.shortSessionId);
168
+ }
169
+ stopTimer() {
170
+ if (this.timer !== null) {
171
+ clearTimeout(this.timer);
172
+ this.timer = null;
173
+ }
174
+ }
175
+ }
176
+ //# sourceMappingURL=emberAnswerTransport.claude.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberAnswerTransport.claude.gateway.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
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
+ export interface EmberMemoryFileSystemGatewayOptions {
4
+ homeDir: string;
5
+ }
6
+ /**
7
+ * Ember's private per-project notebook. One file per project under
8
+ * ~/.claude-review/ember-memory/<slug>.json — never inside the reviewed repo and
9
+ * never a write to project state (reviews, threads, config). A corrupted or
10
+ * unreadable notebook resolves to null so it can never block an answer.
11
+ */
12
+ export declare class EmberMemoryFileSystemGateway implements EmberMemoryGateway {
13
+ private readonly directory;
14
+ constructor(options: EmberMemoryFileSystemGatewayOptions);
15
+ load(projectPath: string): Promise<EmberMemory | null>;
16
+ appendTurn(projectPath: string, turn: EmberMemoryTurn): Promise<void>;
17
+ appendInsight(projectPath: string, insight: EmberRecurringInsight): Promise<void>;
18
+ clear(projectPath: string): Promise<void>;
19
+ private write;
20
+ private notebookFor;
21
+ }
22
+ //# sourceMappingURL=emberMemory.fileSystem.gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberMemory.fileSystem.gateway.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kEAAkE,CAAC;AAC3G,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,qBAAqB,EACtB,MAAM,iEAAiE,CAAC;AAGzE,MAAM,WAAW,mCAAmC;IAClD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,4BAA6B,YAAW,kBAAkB;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,OAAO,EAAE,mCAAmC;IAIlD,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAetD,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrE,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjF,KAAK,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/C,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,WAAW;CAIpB"}
@@ -0,0 +1,55 @@
1
+ import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { emberMemoryGuard } from '../../../../modules/ember-chat/entities/emberMemory/emberMemory.guard.js';
4
+ /**
5
+ * Ember's private per-project notebook. One file per project under
6
+ * ~/.claude-review/ember-memory/<slug>.json — never inside the reviewed repo and
7
+ * never a write to project state (reviews, threads, config). A corrupted or
8
+ * unreadable notebook resolves to null so it can never block an answer.
9
+ */
10
+ export class EmberMemoryFileSystemGateway {
11
+ directory;
12
+ constructor(options) {
13
+ this.directory = join(options.homeDir, '.claude-review', 'ember-memory');
14
+ }
15
+ async load(projectPath) {
16
+ const path = this.notebookFor(projectPath);
17
+ if (!existsSync(path)) {
18
+ return null;
19
+ }
20
+ try {
21
+ const raw = readFileSync(path, 'utf-8');
22
+ const parsed = JSON.parse(raw);
23
+ const result = emberMemoryGuard.safeParse(parsed);
24
+ return result.success ? result.data : null;
25
+ }
26
+ catch {
27
+ return null;
28
+ }
29
+ }
30
+ async appendTurn(projectPath, turn) {
31
+ const current = (await this.load(projectPath)) ?? { turns: [], insights: [] };
32
+ this.write(projectPath, { turns: [...current.turns, turn], insights: current.insights });
33
+ }
34
+ async appendInsight(projectPath, insight) {
35
+ const current = (await this.load(projectPath)) ?? { turns: [], insights: [] };
36
+ this.write(projectPath, { turns: current.turns, insights: [...current.insights, insight] });
37
+ }
38
+ async clear(projectPath) {
39
+ const path = this.notebookFor(projectPath);
40
+ if (existsSync(path)) {
41
+ unlinkSync(path);
42
+ }
43
+ }
44
+ write(projectPath, memory) {
45
+ if (!existsSync(this.directory)) {
46
+ mkdirSync(this.directory, { recursive: true });
47
+ }
48
+ writeFileSync(this.notebookFor(projectPath), JSON.stringify(memory), 'utf-8');
49
+ }
50
+ notebookFor(projectPath) {
51
+ const slug = projectPath.replace(/\//g, '-');
52
+ return join(this.directory, `${slug}.json`);
53
+ }
54
+ }
55
+ //# sourceMappingURL=emberMemory.fileSystem.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emberMemory.fileSystem.gateway.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberMemory.fileSystem.gateway.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,8 @@ export interface StreamJsonEvent {
9
9
  content?: Array<{
10
10
  type?: string;
11
11
  text?: string;
12
- }>;
12
+ }> | string;
13
+ stop_reason?: string | null;
13
14
  };
14
15
  }
15
16
  export declare function parseStreamJsonEvent(line: string): StreamJsonEvent | null;
@@ -1 +1 @@
1
- {"version":3,"file":"emberStreamJson.parser.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;CACjE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAUzE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAgBjE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAE9D"}
1
+ {"version":3,"file":"emberStreamJson.parser.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,OAAO,CAAC,EAAE;QACR,OAAO,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,GAAG,MAAM,CAAC;QAC3D,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;KAC7B,CAAC;CACH;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAUzE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAgBjE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAQ9D"}
@@ -18,7 +18,7 @@ export function extractText(event) {
18
18
  return event.delta.text;
19
19
  }
20
20
  const content = event.message?.content;
21
- if (content !== undefined) {
21
+ if (Array.isArray(content)) {
22
22
  const text = content
23
23
  .filter((part) => part.type === 'text' && typeof part.text === 'string')
24
24
  .map((part) => part.text ?? '')
@@ -28,6 +28,12 @@ export function extractText(event) {
28
28
  return null;
29
29
  }
30
30
  export function isTurnComplete(event) {
31
- return event.type === 'result' || event.type === 'message_stop';
31
+ if (event.type === 'result' || event.type === 'message_stop') {
32
+ return true;
33
+ }
34
+ if (event.type === 'system' && event.subtype === 'turn_duration') {
35
+ return true;
36
+ }
37
+ return event.type === 'assistant' && event.message?.stop_reason === 'end_turn';
32
38
  }
33
39
  //# sourceMappingURL=emberStreamJson.parser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"emberStreamJson.parser.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAsB;IAChD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;IAC1B,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;IACvC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,OAAO;aACjB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC;aACvE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;aAC9B,IAAI,CAAC,EAAE,CAAC,CAAC;QACZ,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAsB;IACnD,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"emberStreamJson.parser.js","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.ts"],"names":[],"mappings":"AAWA,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAsB;IAChD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtE,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC;IAC1B,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC;IACvC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,OAAO;aACjB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC;aACvE,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;aAC9B,IAAI,CAAC,EAAE,CAAC,CAAC;QACZ,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAsB;IACnD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,KAAK,eAAe,EAAE,CAAC;QACjE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,OAAO,EAAE,WAAW,KAAK,UAAU,CAAC;AACjF,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { EmberStatus } from '../../../../modules/ember-chat/usecases/emberSession/emberSessionRegistry.js';
1
+ import type { EmberStatus } from '../../../../modules/ember-chat/usecases/askEmber/emberStream.js';
2
2
  export type EmberAvatarState = 'idle' | 'working' | 'error';
3
3
  export type EmberStatusEvent = {
4
4
  kind: 'status';
@@ -1 +1 @@
1
- {"version":3,"file":"emberStatus.presenter.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oEAAoE,CAAC;AAEtG,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAID,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,EAAE,gBAAgB,GAAG,oBAAoB;CA2BvD"}
1
+ {"version":3,"file":"emberStatus.presenter.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uDAAuD,CAAC;AAEzF,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACvC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,gBAAgB,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAID,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,KAAK,EAAE,gBAAgB,GAAG,oBAAoB;CA2BvD"}