reviewflow 3.29.0 → 3.31.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 (115) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/dashboard/index.html +54 -26
  3. package/dist/dashboard/modules/emberAvatar.d.ts +134 -0
  4. package/dist/dashboard/modules/emberAvatar.d.ts.map +1 -0
  5. package/dist/dashboard/modules/emberAvatar.js +192 -0
  6. package/dist/dashboard/modules/emberAvatar.js.map +1 -0
  7. package/dist/dashboard/modules/emberAvatarRenderer.d.ts +42 -0
  8. package/dist/dashboard/modules/emberAvatarRenderer.d.ts.map +1 -0
  9. package/dist/dashboard/modules/emberAvatarRenderer.js +119 -0
  10. package/dist/dashboard/modules/emberAvatarRenderer.js.map +1 -0
  11. package/dist/dashboard/styles.css +183 -8
  12. package/dist/frameworks/claude/claudeInvoker.d.ts +7 -0
  13. package/dist/frameworks/claude/claudeInvoker.d.ts.map +1 -1
  14. package/dist/frameworks/claude/claudeInvoker.js +1 -1
  15. package/dist/frameworks/claude/claudeInvoker.js.map +1 -1
  16. package/dist/main/routes.d.ts.map +1 -1
  17. package/dist/main/routes.js +6 -16
  18. package/dist/main/routes.js.map +1 -1
  19. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.gateway.d.ts +1 -1
  20. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.gateway.d.ts.map +1 -1
  21. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.guard.d.ts +1 -1
  22. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.d.ts +2 -0
  23. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.d.ts.map +1 -1
  24. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.js +1 -1
  25. package/dist/modules/claude-invocation/entities/claudeSession/claudeSession.schema.js.map +1 -1
  26. package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.d.ts +24 -0
  27. package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.d.ts.map +1 -0
  28. package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js +2 -0
  29. package/dist/modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js.map +1 -0
  30. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.d.ts +2 -3
  31. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.d.ts.map +1 -1
  32. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js +6 -4
  33. package/dist/modules/ember-chat/interface-adapters/controllers/http/emberChat.routes.js.map +1 -1
  34. package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.d.ts +46 -0
  35. package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.d.ts.map +1 -0
  36. package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.js +176 -0
  37. package/dist/modules/ember-chat/interface-adapters/gateways/emberAnswerTransport.claude.gateway.js.map +1 -0
  38. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.d.ts +2 -1
  39. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.d.ts.map +1 -1
  40. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js +8 -2
  41. package/dist/modules/ember-chat/interface-adapters/gateways/emberStreamJson.parser.js.map +1 -1
  42. package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.d.ts +1 -1
  43. package/dist/modules/ember-chat/interface-adapters/presenters/emberStatus.presenter.d.ts.map +1 -1
  44. package/dist/modules/ember-chat/services/emberSystemPrompt.d.ts.map +1 -1
  45. package/dist/modules/ember-chat/services/emberSystemPrompt.js +47 -4
  46. package/dist/modules/ember-chat/services/emberSystemPrompt.js.map +1 -1
  47. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.d.ts +5 -4
  48. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.d.ts.map +1 -1
  49. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.js +61 -9
  50. package/dist/modules/ember-chat/usecases/askEmber/askEmber.usecase.js.map +1 -1
  51. package/dist/modules/ember-chat/usecases/askEmber/emberStream.d.ts +8 -0
  52. package/dist/modules/ember-chat/usecases/askEmber/emberStream.d.ts.map +1 -0
  53. package/dist/modules/ember-chat/usecases/askEmber/emberStream.js +2 -0
  54. package/dist/modules/ember-chat/usecases/askEmber/emberStream.js.map +1 -0
  55. package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.d.ts +2 -0
  56. package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.d.ts.map +1 -0
  57. package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.js +158 -0
  58. package/dist/tests/acceptance/190-ember-live-answers-subscription.acceptance.test.js.map +1 -0
  59. package/dist/tests/stubs/emberAnswerTransport.stub.d.ts +21 -0
  60. package/dist/tests/stubs/emberAnswerTransport.stub.d.ts.map +1 -0
  61. package/dist/tests/stubs/emberAnswerTransport.stub.js +54 -0
  62. package/dist/tests/stubs/emberAnswerTransport.stub.js.map +1 -0
  63. package/dist/tests/units/dashboard/modules/emberAvatar.test.d.ts +2 -0
  64. package/dist/tests/units/dashboard/modules/emberAvatar.test.d.ts.map +1 -0
  65. package/dist/tests/units/dashboard/modules/emberAvatar.test.js +74 -0
  66. package/dist/tests/units/dashboard/modules/emberAvatar.test.js.map +1 -0
  67. package/dist/tests/units/dashboard/modules/emberAvatarRenderer.test.d.ts +2 -0
  68. package/dist/tests/units/dashboard/modules/emberAvatarRenderer.test.d.ts.map +1 -0
  69. package/dist/tests/units/dashboard/modules/emberAvatarRenderer.test.js +44 -0
  70. package/dist/tests/units/dashboard/modules/emberAvatarRenderer.test.js.map +1 -0
  71. package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.js +21 -14
  72. package/dist/tests/units/modules/ember-chat/controllers/emberChat.routes.test.js.map +1 -1
  73. package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.js +13 -0
  74. package/dist/tests/units/modules/ember-chat/gateways/emberStreamJson.parser.test.js.map +1 -1
  75. package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.js +19 -0
  76. package/dist/tests/units/modules/ember-chat/services/emberSystemPrompt.test.js.map +1 -1
  77. package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.js +53 -20
  78. package/dist/tests/units/modules/ember-chat/usecases/askEmber.usecase.test.js.map +1 -1
  79. package/package.json +1 -1
  80. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.d.ts +0 -7
  81. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.d.ts.map +0 -1
  82. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.js +0 -3
  83. package/dist/modules/ember-chat/entities/emberSession/emberSession.schema.js.map +0 -1
  84. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.d.ts +0 -13
  85. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.d.ts.map +0 -1
  86. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.js +0 -35
  87. package/dist/modules/ember-chat/entities/emberSession/emberSessionState.js.map +0 -1
  88. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.d.ts +0 -26
  89. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.d.ts.map +0 -1
  90. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js +0 -2
  91. package/dist/modules/ember-chat/entities/emberSession/emberSessionTransport.gateway.js.map +0 -1
  92. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.d.ts +0 -13
  93. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.d.ts.map +0 -1
  94. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.js +0 -130
  95. package/dist/modules/ember-chat/interface-adapters/gateways/emberSessionTransport.claude.gateway.js.map +0 -1
  96. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.d.ts +0 -36
  97. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.d.ts.map +0 -1
  98. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.js +0 -59
  99. package/dist/modules/ember-chat/usecases/emberSession/emberSessionRegistry.js.map +0 -1
  100. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.d.ts +0 -2
  101. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.d.ts.map +0 -1
  102. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.js +0 -124
  103. package/dist/tests/acceptance/189-ember-readonly-review-chat.acceptance.test.js.map +0 -1
  104. package/dist/tests/stubs/emberSessionTransport.stub.d.ts +0 -18
  105. package/dist/tests/stubs/emberSessionTransport.stub.d.ts.map +0 -1
  106. package/dist/tests/stubs/emberSessionTransport.stub.js +0 -75
  107. package/dist/tests/stubs/emberSessionTransport.stub.js.map +0 -1
  108. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.d.ts +0 -2
  109. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.d.ts.map +0 -1
  110. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.js +0 -42
  111. package/dist/tests/units/modules/ember-chat/entities/emberSessionState.test.js.map +0 -1
  112. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.d.ts +0 -2
  113. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.d.ts.map +0 -1
  114. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.js +0 -88
  115. package/dist/tests/units/modules/ember-chat/usecases/emberSessionRegistry.test.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  export declare const claudeSessionGuard: import("../../../../shared/foundation/guard.base.js").Guard<{
2
2
  sessionId: string & import("zod").$brand<"SessionId">;
3
3
  jobId: string;
4
- jobType: "review" | "followup";
4
+ jobType: "review" | "followup" | "ember-chat";
5
5
  localPath: string;
6
6
  mergeRequestId: string;
7
7
  dispatchedAt: Date;
@@ -12,6 +12,7 @@ export declare const claudeSessionStatusSchema: z.ZodEnum<{
12
12
  export declare const claudeSessionJobTypeSchema: z.ZodEnum<{
13
13
  review: "review";
14
14
  followup: "followup";
15
+ "ember-chat": "ember-chat";
15
16
  }>;
16
17
  export declare const claudeSessionSchema: z.ZodObject<{
17
18
  sessionId: z.core.$ZodBranded<z.ZodString, "SessionId", "out">;
@@ -19,6 +20,7 @@ export declare const claudeSessionSchema: z.ZodObject<{
19
20
  jobType: z.ZodEnum<{
20
21
  review: "review";
21
22
  followup: "followup";
23
+ "ember-chat": "ember-chat";
22
24
  }>;
23
25
  localPath: z.ZodString;
24
26
  mergeRequestId: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"claudeSession.schema.d.ts","sourceRoot":"","sources":["../../../../../src/modules/claude-invocation/entities/claudeSession/claudeSession.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,eAAe,qDAGL,CAAC;AAExB,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAEvD;AAED,eAAO,MAAM,yBAAyB;;;;;;EAMpC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;EAAiC,CAAC;AAEzE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;iBAS9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC5E,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
1
+ {"version":3,"file":"claudeSession.schema.d.ts","sourceRoot":"","sources":["../../../../../src/modules/claude-invocation/entities/claudeSession/claudeSession.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,eAAe,qDAGL,CAAC;AAExB,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAEvD;AAED,eAAO,MAAM,yBAAyB;;;;;;EAMpC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;EAA+C,CAAC;AAEvF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;iBAS9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC5E,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC"}
@@ -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":""}
@@ -1,14 +1,13 @@
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
5
  import type { EnvironmentGateway } from '../../../../../modules/claude-invocation/entities/billingState/environment.gateway.js';
6
6
  export interface EmberChatRoutesOptions {
7
- registry: EmberSessionRegistry;
7
+ transport: EmberAnswerTransportGateway;
8
8
  environment: EnvironmentGateway;
9
9
  readData: EmberReadDataGateway;
10
10
  projectPath: string;
11
- now: () => Date;
12
11
  logger: Logger;
13
12
  }
14
13
  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;AAGnC,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2EAA2E,CAAC;AAC7H,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACzG,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,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,eAAe,EAAE,kBAAkB,CAAC,sBAAsB,CAqEtE,CAAC"}
@@ -2,7 +2,7 @@ import { emberMessageGuard } from '../../../../../modules/ember-chat/entities/em
2
2
  import { askEmber } from '../../../../../modules/ember-chat/usecases/askEmber/askEmber.usecase.js';
3
3
  const UNAVAILABLE_MESSAGE = '// EMBER INDISPONIBLE — réessayer';
4
4
  export const emberChatRoutes = async (fastify, options) => {
5
- const { registry, environment, readData, projectPath, now, logger } = options;
5
+ const { transport, environment, readData, projectPath, logger } = options;
6
6
  fastify.post('/api/ember/ask', async (request, reply) => {
7
7
  const parsed = emberMessageGuard.safeParse(request.body);
8
8
  if (!parsed.success) {
@@ -10,11 +10,10 @@ export const emberChatRoutes = async (fastify, options) => {
10
10
  return;
11
11
  }
12
12
  const result = await askEmber(parsed.data, {
13
- registry,
13
+ transport,
14
14
  environment,
15
15
  readData,
16
16
  projectPath,
17
- now,
18
17
  });
19
18
  reply.hijack();
20
19
  reply.raw.writeHead(200, {
@@ -54,7 +53,10 @@ export const emberChatRoutes = async (fastify, options) => {
54
53
  },
55
54
  onDone: finish,
56
55
  });
57
- request.raw.on('close', finish);
56
+ request.raw.on('close', () => {
57
+ result.cancel();
58
+ finish();
59
+ });
58
60
  });
59
61
  });
60
62
  };
@@ -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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"}
@@ -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"}
@@ -1 +1 @@
1
- {"version":3,"file":"emberSystemPrompt.d.ts","sourceRoot":"","sources":["../../../../src/modules/ember-chat/services/emberSystemPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;AACjG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yEAAyE,CAAC;AACrH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oEAAoE,CAAC;AAExG,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACvC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CA2BxE"}
1
+ {"version":3,"file":"emberSystemPrompt.d.ts","sourceRoot":"","sources":["../../../../src/modules/ember-chat/services/emberSystemPrompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAC;AACjG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yEAAyE,CAAC;AACrH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wDAAwD,CAAC;AAC7F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oEAAoE,CAAC;AAExG,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACvC,UAAU,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAgDD,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CA8BxE"}
@@ -1,4 +1,46 @@
1
+ const MAX_RECENT_REVIEWS = 20;
2
+ const MAX_RECENT_MRS = 20;
3
+ const MAX_DEVELOPERS = 10;
4
+ const MAX_DEVELOPER_RECENT_REVIEWS = 5;
5
+ const MAX_WORKTREES = 20;
6
+ function boundReviewScores(stats) {
7
+ if (stats === null) {
8
+ return null;
9
+ }
10
+ return { ...stats, reviews: mostRecent(stats.reviews, MAX_RECENT_REVIEWS) };
11
+ }
12
+ function boundJobHistory(jobHistory) {
13
+ if (jobHistory === null) {
14
+ return null;
15
+ }
16
+ return { ...jobHistory, mrs: mostRecent(jobHistory.mrs, MAX_RECENT_MRS) };
17
+ }
18
+ function boundInsights(insights) {
19
+ if (insights === null) {
20
+ return null;
21
+ }
22
+ return {
23
+ ...insights,
24
+ developers: mostRecent(insights.developers, MAX_DEVELOPERS).map((developer) => ({
25
+ ...developer,
26
+ recentReviews: mostRecent(developer.recentReviews, MAX_DEVELOPER_RECENT_REVIEWS),
27
+ })),
28
+ processedReviewIds: mostRecent(insights.processedReviewIds, MAX_RECENT_REVIEWS),
29
+ };
30
+ }
31
+ function mostRecent(items, limit) {
32
+ return items.slice(Math.max(0, items.length - limit));
33
+ }
34
+ function reviewCountSummary(stats) {
35
+ if (stats === null || stats.reviews.length <= MAX_RECENT_REVIEWS) {
36
+ return '';
37
+ }
38
+ const olderCount = stats.reviews.length - MAX_RECENT_REVIEWS;
39
+ return `… et ${olderCount} reviews plus anciennes (résumé agrégé seulement).`;
40
+ }
1
41
  export function buildEmberSystemPrompt(grounding) {
42
+ const reviewScores = boundReviewScores(grounding.reviewScores);
43
+ const olderReviewsNote = reviewCountSummary(grounding.reviewScores);
2
44
  return [
3
45
  "Tu es Ember, l'assistant conversationnel du tableau de bord ReviewFlow.",
4
46
  '',
@@ -6,16 +48,17 @@ export function buildEmberSystemPrompt(grounding) {
6
48
  "Tu n'as aucun autre accès : ni système de fichiers, ni outil, ni réseau.",
7
49
  '',
8
50
  'reviewScores (scores et statistiques de review) :',
9
- JSON.stringify(grounding.reviewScores),
51
+ JSON.stringify(reviewScores),
52
+ olderReviewsNote,
10
53
  '',
11
54
  'insights (insights développeur et équipe) :',
12
- JSON.stringify(grounding.insights),
55
+ JSON.stringify(boundInsights(grounding.insights)),
13
56
  '',
14
57
  'jobHistory (historique des jobs de review) :',
15
- JSON.stringify(grounding.jobHistory),
58
+ JSON.stringify(boundJobHistory(grounding.jobHistory)),
16
59
  '',
17
60
  'worktrees (état des worktrees) :',
18
- JSON.stringify(grounding.worktrees),
61
+ JSON.stringify(mostRecent(grounding.worktrees, MAX_WORKTREES)),
19
62
  '',
20
63
  'GROUNDING : réponds uniquement à partir de ces données de review.',
21
64
  "Si la question sort de ces données, dis que tu ne sais répondre qu'à propos des reviews",
@@ -1 +1 @@
1
- {"version":3,"file":"emberSystemPrompt.js","sourceRoot":"","sources":["../../../../src/modules/ember-chat/services/emberSystemPrompt.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,sBAAsB,CAAC,SAAyB;IAC9D,OAAO;QACL,yEAAyE;QACzE,EAAE;QACF,0FAA0F;QAC1F,0EAA0E;QAC1E,EAAE;QACF,mDAAmD;QACnD,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,YAAY,CAAC;QACtC,EAAE;QACF,6CAA6C;QAC7C,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC;QAClC,EAAE;QACF,8CAA8C;QAC9C,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU,CAAC;QACpC,EAAE;QACF,kCAAkC;QAClC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC;QACnC,EAAE;QACF,mEAAmE;QACnE,yFAAyF;QACzF,sDAAsD;QACtD,EAAE;QACF,iFAAiF;QACjF,gFAAgF;QAChF,sEAAsE;KACvE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"emberSystemPrompt.js","sourceRoot":"","sources":["../../../../src/modules/ember-chat/services/emberSystemPrompt.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,19 @@
1
1
  import type { EnvironmentGateway } from '../../../../modules/claude-invocation/entities/billingState/environment.gateway.js';
2
2
  import type { EmberMessage } from '../../../../modules/ember-chat/entities/emberMessage/emberMessage.schema.js';
3
3
  import type { EmberReadDataGateway } from '../../../../modules/ember-chat/entities/emberTool/emberTool.gateway.js';
4
- import type { EmberSessionRegistry, EmberStreamSubscriber } from '../../../../modules/ember-chat/usecases/emberSession/emberSessionRegistry.js';
5
- export type { EmberStreamSubscriber } from '../../../../modules/ember-chat/usecases/emberSession/emberSessionRegistry.js';
4
+ import type { EmberAnswerTransportGateway } from '../../../../modules/ember-chat/entities/emberAnswer/emberAnswerTransport.gateway.js';
5
+ import type { EmberStreamSubscriber } from '../../../../modules/ember-chat/usecases/askEmber/emberStream.js';
6
+ export type { EmberStatus, EmberStreamSubscriber } from '../../../../modules/ember-chat/usecases/askEmber/emberStream.js';
6
7
  export interface AskEmberDependencies {
7
- registry: EmberSessionRegistry;
8
+ transport: EmberAnswerTransportGateway;
8
9
  environment: EnvironmentGateway;
9
10
  readData: EmberReadDataGateway;
10
11
  projectPath: string;
11
- now: () => Date;
12
12
  }
13
13
  export type AskEmberResult = {
14
14
  status: 'streaming';
15
15
  subscribe: (subscriber: EmberStreamSubscriber) => void;
16
+ cancel: () => void;
16
17
  } | {
17
18
  status: 'unavailable';
18
19
  reason: string;
@@ -1 +1 @@
1
- {"version":3,"file":"askEmber.usecase.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/usecases/askEmber/askEmber.usecase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0EAA0E,CAAC;AACnH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mEAAmE,CAAC;AACtG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACzG,OAAO,KAAK,EACV,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,oEAAoE,CAAC;AAG5E,YAAY,EAAE,qBAAqB,EAAE,MAAM,oEAAoE,CAAC;AAEhH,MAAM,WAAW,oBAAoB;IACnC,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;CACjB;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,CAAC,UAAU,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAAE,GAC/E;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,8BAA8B,CAAA;CAAE,CAAC;AAE/C,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,YAAY,EACrB,YAAY,EAAE,oBAAoB,GACjC,OAAO,CAAC,cAAc,CAAC,CAwBzB"}
1
+ {"version":3,"file":"askEmber.usecase.d.ts","sourceRoot":"","sources":["../../../../../src/modules/ember-chat/usecases/askEmber/askEmber.usecase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0EAA0E,CAAC;AACnH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mEAAmE,CAAC;AACtG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAC;AACzG,OAAO,KAAK,EAEV,2BAA2B,EAC5B,MAAM,2EAA2E,CAAC;AACnF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uDAAuD,CAAC;AAGnG,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,uDAAuD,CAAC;AAEhH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,2BAA2B,CAAC;IACvC,WAAW,EAAE,kBAAkB,CAAC;IAChC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,GACtB;IACE,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,CAAC,UAAU,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACvD,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,GACD;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,8BAA8B,CAAA;CAAE,CAAC;AA2D/C,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,YAAY,EACrB,YAAY,EAAE,oBAAoB,GACjC,OAAO,CAAC,cAAc,CAAC,CA4BzB"}