@webex/contact-center 3.12.0-next.9 → 3.12.0-task-refactor.1

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 (200) hide show
  1. package/AGENTS.md +438 -0
  2. package/ai-docs/README.md +131 -0
  3. package/ai-docs/RULES.md +455 -0
  4. package/ai-docs/patterns/event-driven-patterns.md +485 -0
  5. package/ai-docs/patterns/testing-patterns.md +480 -0
  6. package/ai-docs/patterns/typescript-patterns.md +365 -0
  7. package/ai-docs/templates/README.md +102 -0
  8. package/ai-docs/templates/documentation/create-agents-md.md +240 -0
  9. package/ai-docs/templates/documentation/create-architecture-md.md +295 -0
  10. package/ai-docs/templates/existing-service/bug-fix.md +254 -0
  11. package/ai-docs/templates/existing-service/feature-enhancement.md +450 -0
  12. package/ai-docs/templates/new-method/00-master.md +80 -0
  13. package/ai-docs/templates/new-method/01-requirements.md +232 -0
  14. package/ai-docs/templates/new-method/02-implementation.md +295 -0
  15. package/ai-docs/templates/new-method/03-tests.md +201 -0
  16. package/ai-docs/templates/new-method/04-validation.md +141 -0
  17. package/ai-docs/templates/new-service/00-master.md +109 -0
  18. package/ai-docs/templates/new-service/01-pre-questions.md +159 -0
  19. package/ai-docs/templates/new-service/02-code-generation.md +346 -0
  20. package/ai-docs/templates/new-service/03-integration.md +178 -0
  21. package/ai-docs/templates/new-service/04-test-generation.md +205 -0
  22. package/ai-docs/templates/new-service/05-validation.md +145 -0
  23. package/dist/cc.js +65 -123
  24. package/dist/cc.js.map +1 -1
  25. package/dist/constants.js +13 -2
  26. package/dist/constants.js.map +1 -1
  27. package/dist/index.js +13 -5
  28. package/dist/index.js.map +1 -1
  29. package/dist/metrics/behavioral-events.js +26 -13
  30. package/dist/metrics/behavioral-events.js.map +1 -1
  31. package/dist/metrics/constants.js +7 -6
  32. package/dist/metrics/constants.js.map +1 -1
  33. package/dist/services/ApiAiAssistant.js +0 -3
  34. package/dist/services/ApiAiAssistant.js.map +1 -1
  35. package/dist/services/config/Util.js +2 -3
  36. package/dist/services/config/Util.js.map +1 -1
  37. package/dist/services/config/types.js +16 -14
  38. package/dist/services/config/types.js.map +1 -1
  39. package/dist/services/constants.js +0 -1
  40. package/dist/services/constants.js.map +1 -1
  41. package/dist/services/core/Err.js.map +1 -1
  42. package/dist/services/core/Utils.js +79 -55
  43. package/dist/services/core/Utils.js.map +1 -1
  44. package/dist/services/core/aqm-reqs.js +17 -92
  45. package/dist/services/core/aqm-reqs.js.map +1 -1
  46. package/dist/services/core/websocket/WebSocketManager.js +5 -25
  47. package/dist/services/core/websocket/WebSocketManager.js.map +1 -1
  48. package/dist/services/core/websocket/types.js.map +1 -1
  49. package/dist/services/index.js +1 -2
  50. package/dist/services/index.js.map +1 -1
  51. package/dist/services/task/Task.js +644 -0
  52. package/dist/services/task/Task.js.map +1 -0
  53. package/dist/services/task/TaskFactory.js +45 -0
  54. package/dist/services/task/TaskFactory.js.map +1 -0
  55. package/dist/services/task/TaskManager.js +556 -532
  56. package/dist/services/task/TaskManager.js.map +1 -1
  57. package/dist/services/task/TaskUtils.js +132 -28
  58. package/dist/services/task/TaskUtils.js.map +1 -1
  59. package/dist/services/task/constants.js +7 -6
  60. package/dist/services/task/constants.js.map +1 -1
  61. package/dist/services/task/dialer.js +0 -51
  62. package/dist/services/task/dialer.js.map +1 -1
  63. package/dist/services/task/digital/Digital.js +77 -0
  64. package/dist/services/task/digital/Digital.js.map +1 -0
  65. package/dist/services/task/state-machine/TaskStateMachine.js +634 -0
  66. package/dist/services/task/state-machine/TaskStateMachine.js.map +1 -0
  67. package/dist/services/task/state-machine/actions.js +366 -0
  68. package/dist/services/task/state-machine/actions.js.map +1 -0
  69. package/dist/services/task/state-machine/constants.js +139 -0
  70. package/dist/services/task/state-machine/constants.js.map +1 -0
  71. package/dist/services/task/state-machine/guards.js +256 -0
  72. package/dist/services/task/state-machine/guards.js.map +1 -0
  73. package/dist/services/task/state-machine/index.js +53 -0
  74. package/dist/services/task/state-machine/index.js.map +1 -0
  75. package/dist/services/task/state-machine/types.js +54 -0
  76. package/dist/services/task/state-machine/types.js.map +1 -0
  77. package/dist/services/task/state-machine/uiControlsComputer.js +369 -0
  78. package/dist/services/task/state-machine/uiControlsComputer.js.map +1 -0
  79. package/dist/services/task/taskDataNormalizer.js +99 -0
  80. package/dist/services/task/taskDataNormalizer.js.map +1 -0
  81. package/dist/services/task/types.js +157 -18
  82. package/dist/services/task/types.js.map +1 -1
  83. package/dist/services/task/voice/Voice.js +1031 -0
  84. package/dist/services/task/voice/Voice.js.map +1 -0
  85. package/dist/services/task/voice/WebRTC.js +149 -0
  86. package/dist/services/task/voice/WebRTC.js.map +1 -0
  87. package/dist/types/cc.d.ts +4 -33
  88. package/dist/types/constants.d.ts +13 -2
  89. package/dist/types/index.d.ts +11 -5
  90. package/dist/types/metrics/constants.d.ts +5 -3
  91. package/dist/types/services/ApiAiAssistant.d.ts +1 -1
  92. package/dist/types/services/config/types.d.ts +97 -25
  93. package/dist/types/services/core/Err.d.ts +0 -2
  94. package/dist/types/services/core/Utils.d.ts +25 -23
  95. package/dist/types/services/core/aqm-reqs.d.ts +0 -49
  96. package/dist/types/services/core/websocket/WebSocketManager.d.ts +1 -1
  97. package/dist/types/services/core/websocket/connection-service.d.ts +0 -1
  98. package/dist/types/services/core/websocket/types.d.ts +1 -1
  99. package/dist/types/services/index.d.ts +1 -1
  100. package/dist/types/services/task/Task.d.ts +146 -0
  101. package/dist/types/services/task/TaskFactory.d.ts +12 -0
  102. package/dist/types/services/task/TaskUtils.d.ts +39 -8
  103. package/dist/types/services/task/constants.d.ts +5 -4
  104. package/dist/types/services/task/dialer.d.ts +0 -15
  105. package/dist/types/services/task/digital/Digital.d.ts +22 -0
  106. package/dist/types/services/task/state-machine/TaskStateMachine.d.ts +906 -0
  107. package/dist/types/services/task/state-machine/actions.d.ts +8 -0
  108. package/dist/types/services/task/state-machine/constants.d.ts +91 -0
  109. package/dist/types/services/task/state-machine/guards.d.ts +78 -0
  110. package/dist/types/services/task/state-machine/index.d.ts +13 -0
  111. package/dist/types/services/task/state-machine/types.d.ts +256 -0
  112. package/dist/types/services/task/state-machine/uiControlsComputer.d.ts +9 -0
  113. package/dist/types/services/task/taskDataNormalizer.d.ts +10 -0
  114. package/dist/types/services/task/types.d.ts +539 -88
  115. package/dist/types/services/task/voice/Voice.d.ts +183 -0
  116. package/dist/types/services/task/voice/WebRTC.d.ts +53 -0
  117. package/dist/types/types.d.ts +68 -0
  118. package/dist/types/webex.d.ts +1 -0
  119. package/dist/types.js +70 -0
  120. package/dist/types.js.map +1 -1
  121. package/dist/webex.js +14 -2
  122. package/dist/webex.js.map +1 -1
  123. package/package.json +14 -11
  124. package/src/cc.ts +91 -177
  125. package/src/constants.ts +13 -2
  126. package/src/index.ts +14 -5
  127. package/src/metrics/ai-docs/AGENTS.md +348 -0
  128. package/src/metrics/ai-docs/ARCHITECTURE.md +336 -0
  129. package/src/metrics/behavioral-events.ts +28 -14
  130. package/src/metrics/constants.ts +7 -8
  131. package/src/services/ApiAiAssistant.ts +2 -4
  132. package/src/services/agent/ai-docs/AGENTS.md +238 -0
  133. package/src/services/agent/ai-docs/ARCHITECTURE.md +302 -0
  134. package/src/services/ai-docs/AGENTS.md +384 -0
  135. package/src/services/config/Util.ts +2 -3
  136. package/src/services/config/ai-docs/AGENTS.md +253 -0
  137. package/src/services/config/ai-docs/ARCHITECTURE.md +424 -0
  138. package/src/services/config/types.ts +108 -20
  139. package/src/services/constants.ts +0 -1
  140. package/src/services/core/Err.ts +0 -1
  141. package/src/services/core/Utils.ts +90 -67
  142. package/src/services/core/ai-docs/AGENTS.md +379 -0
  143. package/src/services/core/ai-docs/ARCHITECTURE.md +696 -0
  144. package/src/services/core/aqm-reqs.ts +22 -100
  145. package/src/services/core/websocket/WebSocketManager.ts +4 -23
  146. package/src/services/core/websocket/types.ts +1 -1
  147. package/src/services/index.ts +1 -2
  148. package/src/services/task/Task.ts +785 -0
  149. package/src/services/task/TaskFactory.ts +55 -0
  150. package/src/services/task/TaskManager.ts +567 -633
  151. package/src/services/task/TaskUtils.ts +175 -31
  152. package/src/services/task/ai-docs/AGENTS.md +448 -0
  153. package/src/services/task/ai-docs/ARCHITECTURE.md +573 -0
  154. package/src/services/task/constants.ts +5 -4
  155. package/src/services/task/dialer.ts +1 -56
  156. package/src/services/task/digital/Digital.ts +95 -0
  157. package/src/services/task/state-machine/TaskStateMachine.ts +793 -0
  158. package/src/services/task/state-machine/actions.ts +409 -0
  159. package/src/services/task/state-machine/ai-docs/AGENTS.md +495 -0
  160. package/src/services/task/state-machine/ai-docs/ARCHITECTURE.md +1135 -0
  161. package/src/services/task/state-machine/constants.ts +150 -0
  162. package/src/services/task/state-machine/guards.ts +295 -0
  163. package/src/services/task/state-machine/index.ts +28 -0
  164. package/src/services/task/state-machine/types.ts +228 -0
  165. package/src/services/task/state-machine/uiControlsComputer.ts +529 -0
  166. package/src/services/task/taskDataNormalizer.ts +137 -0
  167. package/src/services/task/types.ts +641 -95
  168. package/src/services/task/voice/Voice.ts +1255 -0
  169. package/src/services/task/voice/WebRTC.ts +187 -0
  170. package/src/types.ts +88 -5
  171. package/src/utils/AGENTS.md +276 -0
  172. package/src/webex.js +2 -0
  173. package/test/unit/spec/cc.ts +59 -142
  174. package/test/unit/spec/logger-proxy.ts +70 -0
  175. package/test/unit/spec/services/ApiAiAssistant.ts +17 -0
  176. package/test/unit/spec/services/config/index.ts +26 -55
  177. package/test/unit/spec/services/core/Utils.ts +103 -52
  178. package/test/unit/spec/services/core/websocket/WebSocketManager.ts +48 -112
  179. package/test/unit/spec/services/core/websocket/connection-service.ts +5 -4
  180. package/test/unit/spec/services/task/AutoWrapup.ts +63 -0
  181. package/test/unit/spec/services/task/Task.ts +416 -0
  182. package/test/unit/spec/services/task/TaskFactory.ts +62 -0
  183. package/test/unit/spec/services/task/TaskManager.ts +781 -1735
  184. package/test/unit/spec/services/task/TaskUtils.ts +125 -0
  185. package/test/unit/spec/services/task/dialer.ts +112 -198
  186. package/test/unit/spec/services/task/digital/Digital.ts +105 -0
  187. package/test/unit/spec/services/task/state-machine/TaskStateMachine.ts +473 -0
  188. package/test/unit/spec/services/task/state-machine/guards.ts +288 -0
  189. package/test/unit/spec/services/task/state-machine/types.ts +18 -0
  190. package/test/unit/spec/services/task/state-machine/uiControlsComputer.ts +147 -0
  191. package/test/unit/spec/services/task/taskTestUtils.ts +87 -0
  192. package/test/unit/spec/services/task/voice/Voice.ts +587 -0
  193. package/test/unit/spec/services/task/voice/WebRTC.ts +242 -0
  194. package/umd/contact-center.min.js +2 -2
  195. package/umd/contact-center.min.js.map +1 -1
  196. package/dist/services/task/index.js +0 -1525
  197. package/dist/services/task/index.js.map +0 -1
  198. package/dist/types/services/task/index.d.ts +0 -650
  199. package/src/services/task/index.ts +0 -1801
  200. package/test/unit/spec/services/task/index.ts +0 -2184
@@ -0,0 +1,201 @@
1
+ # New Method - Tests
2
+
3
+ > **Purpose**: Create unit tests for the new method.
4
+
5
+ ---
6
+
7
+ ## Test Location
8
+
9
+ Add tests to the existing test file that corresponds to the source file:
10
+ - For `cc.ts` methods: `test/unit/spec/cc.ts`
11
+ - For service methods: `test/unit/spec/services/[service]/index.ts`
12
+ - For non-service files: `test/unit/spec/[filename].ts`
13
+
14
+ > **Convention**: The test file path mirrors the source file path under `test/unit/spec/`. For example:
15
+ > - `src/cc.ts` → `test/unit/spec/cc.ts`
16
+ > - `src/logger-proxy.ts` → `test/unit/spec/logger-proxy.ts`
17
+ > - `src/metrics/MetricsManager.ts` → `test/unit/spec/metrics/MetricsManager.ts`
18
+ > - `src/services/agent/index.ts` → `test/unit/spec/services/agent/index.ts`
19
+ > - `src/services/task/Task.ts` → `test/unit/spec/services/task/Task.ts`
20
+ > - `src/services/WebCallingService.ts` → `test/unit/spec/services/WebCallingService.ts`
21
+
22
+ ---
23
+
24
+ ## Test Template
25
+
26
+ ```typescript
27
+ describe('cc.methodName', () => {
28
+ // Mock data
29
+ const mockParams = {
30
+ requiredField: 'test-value',
31
+ };
32
+
33
+ const mockSuccessResponse = {
34
+ data: {
35
+ field: 'value',
36
+ },
37
+ trackingId: 'track-123',
38
+ };
39
+
40
+ const mockError = new Error('Operation failed');
41
+ mockError.details = {
42
+ type: 'OperationFailed',
43
+ data: { reason: 'INVALID_INPUT' },
44
+ trackingId: 'track-456',
45
+ };
46
+
47
+ beforeEach(() => {
48
+ // Reset mocks
49
+ jest.clearAllMocks();
50
+
51
+ // Setup default mock behavior
52
+ mockServicesInstance.someService.method.mockResolvedValue(mockSuccessResponse);
53
+ });
54
+
55
+ describe('success scenarios', () => {
56
+ it('should complete operation successfully', async () => {
57
+ // Act
58
+ const result = await webex.cc.methodName(mockParams);
59
+
60
+ // Assert
61
+ expect(result).toEqual(mockSuccessResponse);
62
+ expect(mockServicesInstance.someService.method).toHaveBeenCalledWith({
63
+ data: {
64
+ requiredField: 'test-value',
65
+ agentId: 'mock-agent-id',
66
+ },
67
+ });
68
+ });
69
+
70
+ it('should track success metrics', async () => {
71
+ // Act
72
+ await webex.cc.methodName(mockParams);
73
+
74
+ // Assert
75
+ expect(mockMetricsManager.timeEvent).toHaveBeenCalledWith([
76
+ METRIC_EVENT_NAMES.OPERATION_SUCCESS,
77
+ METRIC_EVENT_NAMES.OPERATION_FAILED,
78
+ ]);
79
+ expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
80
+ METRIC_EVENT_NAMES.OPERATION_SUCCESS,
81
+ {
82
+ ...mockCommonTrackingFields,
83
+ customField: 'test-value',
84
+ },
85
+ ['behavioral', 'operational']
86
+ );
87
+ });
88
+
89
+ it('should log operation start and completion', async () => {
90
+ // Act
91
+ await webex.cc.methodName(mockParams);
92
+
93
+ // Assert
94
+ expect(LoggerProxy.info).toHaveBeenCalledWith(
95
+ 'Starting operation',
96
+ {
97
+ module: CC_FILE,
98
+ method: METHODS.METHOD_NAME,
99
+ }
100
+ );
101
+ expect(LoggerProxy.log).toHaveBeenCalledWith(
102
+ 'Operation completed successfully',
103
+ {
104
+ module: CC_FILE,
105
+ method: METHODS.METHOD_NAME,
106
+ trackingId: 'track-123',
107
+ }
108
+ );
109
+ });
110
+ });
111
+
112
+ describe('error scenarios', () => {
113
+ it('should throw error on service failure', async () => {
114
+ // Arrange
115
+ mockServicesInstance.someService.method.mockRejectedValue(mockError);
116
+
117
+ // Act & Assert
118
+ await expect(webex.cc.methodName(mockParams)).rejects.toThrow();
119
+ });
120
+
121
+ it('should track failure metrics on error', async () => {
122
+ // Arrange
123
+ mockServicesInstance.someService.method.mockRejectedValue(mockError);
124
+
125
+ // Act
126
+ await expect(webex.cc.methodName(mockParams)).rejects.toThrow();
127
+
128
+ // Assert
129
+ expect(mockMetricsManager.trackEvent).toHaveBeenCalledWith(
130
+ METRIC_EVENT_NAMES.OPERATION_FAILED,
131
+ {
132
+ ...mockCommonFailedTrackingFields,
133
+ customField: 'test-value',
134
+ },
135
+ ['behavioral', 'operational']
136
+ );
137
+ });
138
+
139
+ it('should call getErrorDetails on failure', async () => {
140
+ // Arrange
141
+ mockServicesInstance.someService.method.mockRejectedValue(mockError);
142
+
143
+ // Act
144
+ await expect(webex.cc.methodName(mockParams)).rejects.toThrow();
145
+
146
+ // Assert
147
+ expect(getErrorDetailsSpy).toHaveBeenCalledWith(
148
+ mockError,
149
+ METHODS.METHOD_NAME,
150
+ CC_FILE
151
+ );
152
+ });
153
+ });
154
+
155
+ describe('input validation', () => {
156
+ it('should handle optional parameters', async () => {
157
+ // Arrange
158
+ const paramsWithOptional = {
159
+ ...mockParams,
160
+ optionalField: 42,
161
+ };
162
+
163
+ // Act
164
+ await webex.cc.methodName(paramsWithOptional);
165
+
166
+ // Assert
167
+ expect(mockServicesInstance.someService.method).toHaveBeenCalledWith({
168
+ data: {
169
+ requiredField: 'test-value',
170
+ optionalField: 42,
171
+ agentId: 'mock-agent-id',
172
+ },
173
+ });
174
+ });
175
+ });
176
+ });
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Test Assertion Guidelines
182
+
183
+ > **Team standard: Use exact matches, not partial matchers.** Always use `expect(result).toEqual(expectedValue)` with the full expected object. Avoid `expect.objectContaining()` or `expect.arrayContaining()` unless there is a specific reason (e.g., dynamic fields like timestamps). Exact assertions catch unintended payload changes early.
184
+
185
+ ---
186
+
187
+ ## Running Tests
188
+
189
+ ```bash
190
+ # Run specific test file
191
+ yarn workspace @webex/contact-center test:unit -- <path_to_specific_file>
192
+
193
+ # Run with coverage
194
+ yarn workspace @webex/contact-center test:unit --coverage
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Next Step
200
+
201
+ Proceed to: [`04-validation.md`](04-validation.md)
@@ -0,0 +1,141 @@
1
+ # New Method - Validation Checklist
2
+
3
+ > **Purpose**: Final quality check before completing method addition.
4
+
5
+ ---
6
+
7
+ ## Code Quality Checklist
8
+
9
+ ### Method Implementation
10
+ - [ ] Method added with correct signature
11
+ - [ ] JSDoc with `@param`, `@returns`, `@throws`, `@example`
12
+ - [ ] `@public` tag for public API methods
13
+ - [ ] LoggerProxy.info at method start
14
+ - [ ] LoggerProxy.log on success
15
+ - [ ] LoggerProxy.error on failure (via getErrorDetails)
16
+ - [ ] MetricsManager.timeEvent at start
17
+ - [ ] MetricsManager.trackEvent on success
18
+ - [ ] MetricsManager.trackEvent on failure
19
+ - [ ] Error handling uses `getErrorDetails` pattern
20
+ - [ ] Failure cast: `const failure = error.details as Failure`
21
+
22
+ ### Constants
23
+ - [ ] Method name added to `METHODS` constant
24
+ - [ ] Metric events added to `METRIC_EVENT_NAMES`
25
+
26
+ ### Types
27
+ - [ ] Parameter type defined with JSDoc
28
+ - [ ] Return type defined with JSDoc
29
+ - [ ] Types exported from `src/types.ts`
30
+
31
+ ### Tests
32
+ - [ ] Success case tested
33
+ - [ ] Error case tested
34
+ - [ ] Metrics tracking verified
35
+ - [ ] Logging verified
36
+ - [ ] Optional parameters tested
37
+
38
+ ---
39
+
40
+ ## Pattern Verification
41
+
42
+ ### Correct Logging Pattern
43
+ ```typescript
44
+ // ✅ At start
45
+ LoggerProxy.info('Starting operation', {
46
+ module: CC_FILE,
47
+ method: METHODS.METHOD_NAME,
48
+ });
49
+
50
+ // ✅ On success
51
+ LoggerProxy.log('Operation completed successfully', {
52
+ module: CC_FILE,
53
+ method: METHODS.METHOD_NAME,
54
+ trackingId: result.trackingId,
55
+ });
56
+ ```
57
+
58
+ ### Error Logging — `error` vs `warn`
59
+
60
+ | Level | When to Use | Stack Trace Included? |
61
+ |---|---|---|
62
+ | `LoggerProxy.error()` | Operation failures, API errors, exceptions in catch blocks | **Yes** — full stack trace is appended automatically |
63
+ | `LoggerProxy.warn()` | Non-critical issues that don't break flow (e.g., deprecation notices, fallback behavior) | **No** — only the message is logged |
64
+
65
+ > **Current codebase convention**: `LoggerProxy.error()` is used extensively across the SDK. `LoggerProxy.warn()` is not currently used in any source file. Default to `error` for catch blocks and failure paths.
66
+
67
+ ```typescript
68
+ // ✅ Error — in catch blocks and failure paths (includes stack trace)
69
+ LoggerProxy.error(`${methodName} failed with reason: ${reason}`, {
70
+ module: moduleName,
71
+ method: methodName,
72
+ trackingId: failure?.trackingId,
73
+ });
74
+
75
+ // ✅ Error — via getErrorDetails (logs error + uploads logs automatically)
76
+ // Most methods use this pattern instead of calling LoggerProxy.error() directly
77
+ const {error: detailedError} = getErrorDetails(error, METHODS.METHOD_NAME, CC_FILE);
78
+
79
+ // ⚠️ Warn — for non-critical issues only (no stack trace)
80
+ LoggerProxy.warn('Falling back to default configuration', {
81
+ module: CC_FILE,
82
+ method: METHODS.METHOD_NAME,
83
+ });
84
+ ```
85
+
86
+ > **Note**: `getErrorDetails()` (in `src/services/core/Utils.ts`) already calls `LoggerProxy.error()` internally and uploads logs via `WebexRequest.uploadLogs()`. Do not double-log errors when using `getErrorDetails`.
87
+
88
+ ### Correct Metrics Pattern
89
+ ```typescript
90
+ // ✅ Start timing
91
+ this.metricsManager.timeEvent([
92
+ METRIC_EVENT_NAMES.SUCCESS,
93
+ METRIC_EVENT_NAMES.FAILED,
94
+ ]);
95
+
96
+ // ✅ Track success
97
+ this.metricsManager.trackEvent(
98
+ METRIC_EVENT_NAMES.SUCCESS,
99
+ {...MetricsManager.getCommonTrackingFieldForAQMResponse(result)},
100
+ ['behavioral', 'operational']
101
+ );
102
+
103
+ // ✅ Track failure
104
+ this.metricsManager.trackEvent(
105
+ METRIC_EVENT_NAMES.FAILED,
106
+ {...MetricsManager.getCommonTrackingFieldForAQMResponseFailed(failure)},
107
+ ['behavioral', 'operational']
108
+ );
109
+ ```
110
+
111
+ ### Correct Error Pattern
112
+ ```typescript
113
+ // ✅
114
+ const failure = error.details as Failure;
115
+ this.metricsManager.trackEvent(FAILED_EVENT, {...}, [...]);
116
+ const {error: detailedError} = getErrorDetails(error, METHOD, MODULE);
117
+ throw detailedError;
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Build & Test Verification
123
+
124
+ ```bash
125
+ # Lint
126
+ yarn workspace @webex/contact-center test:styles
127
+
128
+ # Test unit tests
129
+ yarn workspace @webex/contact-center test:unit
130
+
131
+ # Build
132
+ yarn workspace @webex/contact-center build:src
133
+ ```
134
+
135
+ All should pass without errors.
136
+
137
+ ---
138
+
139
+ ## Complete!
140
+
141
+ Method addition is complete when all checkboxes are checked.
@@ -0,0 +1,109 @@
1
+ # New Service Creation - Master Template
2
+
3
+ > **Purpose**: Orchestrator for creating new services or modules within the Contact Center SDK — whether top-level (e.g., AddressBook, EntryPoint, Queue), a sub-module under an existing service (e.g., a new module under `task/`), or an internal-only utility service.
4
+
5
+ ---
6
+
7
+ ## Entry Paths
8
+
9
+ You can land on this template from:
10
+ - direct "create new service" requests
11
+ - "add feature" requests after feature triage determines the feature should be a standalone service/module
12
+
13
+ If coming from feature triage, include:
14
+ - feature placement rationale
15
+ - desired service/module name
16
+ - expected public API surface
17
+
18
+ ---
19
+
20
+ ## Prerequisites
21
+
22
+ Before starting, ensure you have:
23
+ - Clear understanding of what the service will do
24
+ - Complete API signature details (payload, response, HTTP method, endpoint)
25
+ - Event contract details when feature uses events (listener object, payload shape, emission source)
26
+ - Understanding of data structures involved
27
+
28
+ ---
29
+
30
+ ## Workflow Overview
31
+
32
+ ```
33
+ Step 1: Requirements → Step 2: Code Generation → Step 3: Integration → Step 4: Tests → Step 5: Validation
34
+ ```
35
+
36
+ ---
37
+
38
+ ## Step-by-Step Process
39
+
40
+ ### Step 1: Gather Requirements
41
+ **Template**: [`01-pre-questions.md`](01-pre-questions.md)
42
+
43
+ Answer these questions:
44
+ - What is the service name?
45
+ - What API endpoints will it call?
46
+ - What data will it manage?
47
+ - Will it be exposed on `cc.serviceName`?
48
+
49
+ ### Step 2: Generate Code
50
+ **Template**: [`02-code-generation.md`](02-code-generation.md)
51
+
52
+ Create:
53
+ - Service class file (placement determined by pre-questions — see Step 1)
54
+ - Type definitions (location depends on placement — service folder's `types.ts` or root `src/types.ts`)
55
+ - Constants if needed (service folder's `constants.ts` or shared `src/services/constants.ts`)
56
+
57
+ ### Step 3: Integration
58
+ **Template**: [`03-integration.md`](03-integration.md)
59
+
60
+ Integrate:
61
+ - Initialize the service (location depends on placement — `cc.ts` for top-level, parent service for sub-modules)
62
+ - Expose via `cc.serviceName` if developer confirmed public in pre-questions Q7
63
+ - Export types from `src/types.ts` (for public services only)
64
+
65
+ ### Step 4: Generate Tests
66
+ **Template**: [`04-test-generation.md`](04-test-generation.md)
67
+
68
+ Create:
69
+ - Unit test file
70
+ - Mock service methods
71
+ - Test success and error cases
72
+
73
+ ### Step 5: Validation
74
+ **Template**: [`05-validation.md`](05-validation.md)
75
+
76
+ Verify:
77
+ - All patterns followed
78
+ - Tests pass
79
+ - Types exported
80
+ - Documentation updated
81
+
82
+ ---
83
+
84
+ ## Patterns to Load
85
+
86
+ Before generating code, read:
87
+ 1. [`../../patterns/typescript-patterns.md`](../../patterns/typescript-patterns.md) - Type conventions
88
+ 2. [`../../patterns/event-driven-patterns.md`](../../patterns/event-driven-patterns.md) - Event and WebSocket patterns
89
+ 3. [`../../patterns/testing-patterns.md`](../../patterns/testing-patterns.md) - Test patterns
90
+
91
+ ---
92
+
93
+ ## Reference Implementation
94
+
95
+ Study existing service: `src/services/AddressBook.ts` or `src/services/EntryPoint.ts`
96
+
97
+ ---
98
+
99
+ ## Quick Checklist
100
+
101
+ - [ ] Service class created with WebexSDK injection
102
+ - [ ] LoggerProxy used for all logging
103
+ - [ ] Metrics tracked for all operations (success + failure)
104
+ - [ ] Error handling follows `getErrorDetails` pattern
105
+ - [ ] Types defined and placed correctly (folder `types.ts` or root `src/types.ts`)
106
+ - [ ] Constants placed correctly (folder `constants.ts` or shared `src/services/constants.ts`)
107
+ - [ ] Initialized and integrated (in `cc.ts` for top-level, or parent service for sub-modules)
108
+ - [ ] Unit tests created
109
+ - [ ] JSDoc added for public methods
@@ -0,0 +1,159 @@
1
+ # New Service - Pre-Questions
2
+
3
+ > **Purpose**: Gather requirements from the developer before generating service code.
4
+
5
+ ---
6
+
7
+ ## STOP — Ask These Questions First
8
+
9
+ **You MUST present the following questions to the developer and wait for their answers before proceeding.** Do not infer answers from the developer's initial request. Do not fill in fields yourself. Do not read code or load patterns yet.
10
+
11
+ Present questions grouped by section. If the developer cannot answer a MANDATORY question, ask follow-up questions to help them clarify. Only proceed to code generation when all MANDATORY fields have explicit developer-provided answers.
12
+
13
+ ---
14
+
15
+ ## 1. Service Identity (MANDATORY)
16
+
17
+ Ask the developer:
18
+
19
+ 1. **"What should the service be named?"**
20
+ - Must be PascalCase (e.g., "AddressBook", "Queue", "EntryPoint")
21
+
22
+ 2. **"What problem does this service solve? What data does it manage?"**
23
+ - Need a one-sentence purpose description.
24
+
25
+ 3. **"Where should this service live?"**
26
+ - **Folder-based service**: `src/services/ServiceName/` — complex service with its own folder, `index.ts`, `types.ts`, and optionally `constants.ts` (e.g., `agent/`, `config/`, `task/`)
27
+ - **Single-file service**: `src/services/ServiceName.ts` — lightweight service as a single file; types go in `src/types.ts`, constants go in `src/services/constants.ts` (e.g., `AddressBook.ts`, `EntryPoint.ts`, `Queue.ts`)
28
+ - **Sub-module under existing service**: a file within an existing service folder (e.g., `task/Voice.ts`, `task/Digital.ts`)
29
+
30
+ This determines the file structure and where types/constants are placed.
31
+
32
+ ---
33
+
34
+ ## 2. API Contract (MANDATORY)
35
+
36
+ Ask the developer to provide the complete API signature for **each** API the service will use:
37
+
38
+ 4. **"What API endpoint(s) will this service call? For each, provide:"**
39
+
40
+ | Field | What to Ask |
41
+ |---|---|
42
+ | API Name | "What should the method be called?" (e.g., `getEntries`, `createItem`) |
43
+ | HTTP Method | "Is this a GET, POST, PUT, or DELETE?" |
44
+ | Endpoint | "What is the full endpoint path?" (e.g., `/v1/address-books/{id}/entries`) |
45
+ | Request Payload | "What fields does the request body contain? Which are required vs optional?" |
46
+ | Response Structure | "What does the response look like? What fields does `data` contain?" |
47
+ | Error Shape | "What error reason codes can this return?" |
48
+
49
+ **If any API field is unknown, STOP and ask the developer before proceeding. Do not guess endpoint structures or payload shapes.**
50
+
51
+ ---
52
+
53
+ ## 3. Event Contract (MANDATORY if the service uses events, otherwise skip)
54
+
55
+ Ask the developer:
56
+
57
+ 5. **"Does this service listen to or emit any events?"**
58
+ - If YES, for each event ask:
59
+
60
+ | Field | What to Ask |
61
+ |---|---|
62
+ | Event Name | "What is the event name?" |
63
+ | Direction | "Is this incoming (received from WebSocket) or outgoing (emitted by SDK)?" |
64
+ | Source | "Is this a WebSocket event, or an internal EventEmitter event?" |
65
+ | Listen/Emit Object | "Where do consumers subscribe to this event?" (`cc`, `task`, `taskManager`, service) |
66
+ | Payload Type/Shape | "What data does the event carry? What are the field names and types?" |
67
+ | Emitted From | "Which class/file/method emits this event?" |
68
+ | Emission Trigger | "What causes this event to fire?" |
69
+
70
+ - If any events come from WebSocket: "How should these WebSocket events map to service behavior?"
71
+ - If NO events at all, skip to section 4.
72
+
73
+ ---
74
+
75
+ ## 4. Dependencies & Exposure (MANDATORY)
76
+
77
+ Ask the developer:
78
+
79
+ 6. **"Does this service need any data from the agent profile?"**
80
+ - If YES: "Which specific fields?" (e.g., `addressBookId`, `teamIds`)
81
+ - If NO: note "No profile dependency"
82
+
83
+ 7. **"Should this service be accessible as `cc.serviceName` (public API), or is it internal only?"**
84
+ - If public: it will be exposed on the `cc` object and types will be re-exported from `src/types.ts`
85
+ - If internal: it will only be used by other services within the SDK
86
+
87
+ 8. **"What methods should be exposed? For each method, what is the expected behavior?"**
88
+ - e.g., `getEntries(params)` — Fetch paginated list
89
+ - e.g., `getEntryById(id)` — Fetch single item
90
+
91
+ ---
92
+
93
+ ## 6. Caching (OPTIONAL)
94
+
95
+ Ask the developer:
96
+
97
+ 9. **"Should responses be cached in memory, or should every call fetch fresh data?"**
98
+ - If caching: "What is the cache invalidation strategy?"
99
+
100
+ ---
101
+
102
+ ## Completion Gate
103
+
104
+ **Before proceeding, verify:**
105
+
106
+ - [ ] Service name provided by developer
107
+ - [ ] Service purpose described by developer
108
+ - [ ] Service placement decided (top-level, sub-module, or single file)
109
+ - [ ] At least one API endpoint fully specified (method, path, request, response, errors)
110
+ - [ ] Event contract captured (or developer confirmed no events)
111
+ - [ ] Dependencies identified (or developer confirmed none)
112
+ - [ ] Exposure decision made (public vs internal)
113
+ - [ ] Methods to expose listed
114
+
115
+ **If any MANDATORY field above is missing an explicit developer answer, ask a targeted follow-up question. Do not proceed.**
116
+
117
+ ---
118
+
119
+ ## Spec Summary
120
+
121
+ Once all questions are answered, present this summary to the developer for approval before proceeding to code generation:
122
+
123
+ ```
124
+ ## Spec Summary — New Service
125
+
126
+ **Service Name**: [from Q1]
127
+ **Purpose**: [from Q2]
128
+ **Placement**: [from Q3 — folder-based / single-file / sub-module under {parent}]
129
+ **Target location**: [derived from Q3, e.g., `src/services/ServiceName/` or `src/services/ServiceName.ts` or `src/services/{parent}/ServiceName.ts`]
130
+
131
+ ### API Contract:
132
+ | Method | HTTP | Endpoint | Request | Response |
133
+ |---|---|---|---|---|
134
+ | [method] | [GET/POST/...] | [path] | [payload] | [response] |
135
+
136
+ ### Events:
137
+ [event table or "None"]
138
+
139
+ ### Dependencies:
140
+ - Profile fields: [list or "None"]
141
+
142
+ ### Exposure:
143
+ - Public API: [Yes/No] — `cc.[serviceName]`
144
+ - Methods: [list]
145
+
146
+ ### Caching: [Yes/No]
147
+
148
+ ---
149
+ Does this match your intent? (Yes / No / Adjust)
150
+ ```
151
+
152
+ **Wait for developer approval. Do not proceed to [`02-code-generation.md`](02-code-generation.md) until confirmed.**
153
+
154
+ ---
155
+
156
+ ## Next Step
157
+
158
+ Once the developer approves the spec summary, proceed to:
159
+ [`02-code-generation.md`](02-code-generation.md)