@task-mcp/shared 1.0.6 → 1.0.8

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 (41) hide show
  1. package/dist/schemas/inbox.d.ts +49 -18
  2. package/dist/schemas/inbox.d.ts.map +1 -1
  3. package/dist/schemas/inbox.js +16 -16
  4. package/dist/schemas/inbox.js.map +1 -1
  5. package/dist/schemas/index.d.ts +2 -1
  6. package/dist/schemas/index.d.ts.map +1 -1
  7. package/dist/schemas/index.js +2 -0
  8. package/dist/schemas/index.js.map +1 -1
  9. package/dist/schemas/project.d.ts +164 -42
  10. package/dist/schemas/project.d.ts.map +1 -1
  11. package/dist/schemas/project.js +41 -33
  12. package/dist/schemas/project.js.map +1 -1
  13. package/dist/schemas/response-format.d.ts +76 -2
  14. package/dist/schemas/response-format.d.ts.map +1 -1
  15. package/dist/schemas/response-format.js +3 -2
  16. package/dist/schemas/response-format.js.map +1 -1
  17. package/dist/schemas/response-schema.d.ts +307 -0
  18. package/dist/schemas/response-schema.d.ts.map +1 -0
  19. package/dist/schemas/response-schema.js +75 -0
  20. package/dist/schemas/response-schema.js.map +1 -0
  21. package/dist/schemas/response-schema.test.d.ts +2 -0
  22. package/dist/schemas/response-schema.test.d.ts.map +1 -0
  23. package/dist/schemas/response-schema.test.js +256 -0
  24. package/dist/schemas/response-schema.test.js.map +1 -0
  25. package/dist/schemas/task.d.ts +588 -147
  26. package/dist/schemas/task.d.ts.map +1 -1
  27. package/dist/schemas/task.js +114 -88
  28. package/dist/schemas/task.js.map +1 -1
  29. package/dist/schemas/view.d.ts +128 -37
  30. package/dist/schemas/view.d.ts.map +1 -1
  31. package/dist/schemas/view.js +38 -24
  32. package/dist/schemas/view.js.map +1 -1
  33. package/package.json +2 -2
  34. package/src/schemas/inbox.ts +20 -20
  35. package/src/schemas/index.ts +23 -0
  36. package/src/schemas/project.ts +46 -40
  37. package/src/schemas/response-format.ts +99 -3
  38. package/src/schemas/response-schema.test.ts +314 -0
  39. package/src/schemas/response-schema.ts +92 -0
  40. package/src/schemas/task.ts +128 -110
  41. package/src/schemas/view.ts +43 -33
@@ -1,32 +1,32 @@
1
- import { type } from "arktype";
1
+ import { z } from "zod";
2
2
 
3
3
  // Inbox item status
4
- export const InboxStatus = type("'pending' | 'promoted' | 'discarded'");
5
- export type InboxStatus = typeof InboxStatus.infer;
4
+ export const InboxStatus = z.enum(["pending", "promoted", "discarded"]);
5
+ export type InboxStatus = z.infer<typeof InboxStatus>;
6
6
 
7
7
  // Inbox item schema - lightweight idea/memo capture
8
- export const InboxItem = type({
9
- id: "string",
10
- content: "string", // The memo/idea content
11
- capturedAt: "string", // ISO timestamp
12
- "source?": "string", // Origin: 'cli', 'mcp', 'api', etc.
13
- "tags?": "string[]", // Simple tags for organization
14
- "promotedToTaskId?": "string", // Task ID if promoted
8
+ export const InboxItem = z.object({
9
+ id: z.string(),
10
+ content: z.string(), // The memo/idea content
11
+ capturedAt: z.string(), // ISO timestamp
12
+ source: z.string().optional(), // Origin: 'cli', 'mcp', 'api', etc.
13
+ tags: z.array(z.string()).optional(), // Simple tags for organization
14
+ promotedToTaskId: z.string().optional(), // Task ID if promoted
15
15
  status: InboxStatus,
16
16
  });
17
- export type InboxItem = typeof InboxItem.infer;
17
+ export type InboxItem = z.infer<typeof InboxItem>;
18
18
 
19
19
  // Inbox item creation input (minimal)
20
- export const InboxCreateInput = type({
21
- content: "string",
22
- "source?": "string",
23
- "tags?": "string[]",
20
+ export const InboxCreateInput = z.object({
21
+ content: z.string(),
22
+ source: z.string().optional(),
23
+ tags: z.array(z.string()).optional(),
24
24
  });
25
- export type InboxCreateInput = typeof InboxCreateInput.infer;
25
+ export type InboxCreateInput = z.infer<typeof InboxCreateInput>;
26
26
 
27
27
  // Inbox item update input
28
- export const InboxUpdateInput = type({
29
- "content?": "string",
30
- "tags?": "string[]",
28
+ export const InboxUpdateInput = z.object({
29
+ content: z.string().optional(),
30
+ tags: z.array(z.string()).optional(),
31
31
  });
32
- export type InboxUpdateInput = typeof InboxUpdateInput.infer;
32
+ export type InboxUpdateInput = z.infer<typeof InboxUpdateInput>;
@@ -58,4 +58,27 @@ export {
58
58
  type InboxPreview,
59
59
  type CriticalPathSummary,
60
60
  type BottleneckSummary,
61
+ // Dashboard types
62
+ type DashboardProgress,
63
+ type DashboardPriorityBreakdown,
64
+ type DashboardDependencyMetrics,
65
+ type DashboardNextTask,
66
+ type DashboardCriticalPath,
67
+ type DashboardStatusBreakdown,
68
+ type DashboardSubtaskProgress,
69
+ type DashboardDependencyStats,
70
+ type DashboardConcise,
71
+ type DashboardStandard,
61
72
  } from "./response-format.js";
73
+
74
+ // Response schema (agent interaction)
75
+ export {
76
+ ResponseType,
77
+ ResponsePriority,
78
+ ResponseOption,
79
+ QuestionResponse,
80
+ SuggestionResponse,
81
+ ConfirmationResponse,
82
+ AgentResponse,
83
+ GenerateResponseInput,
84
+ } from "./response-schema.js";
@@ -1,62 +1,68 @@
1
- import { type } from "arktype";
1
+ import { z } from "zod";
2
2
  import { Priority } from "./task.js";
3
3
 
4
4
  // Project status
5
- export const ProjectStatus = type(
6
- "'active' | 'on_hold' | 'completed' | 'archived'"
7
- );
8
- export type ProjectStatus = typeof ProjectStatus.infer;
5
+ export const ProjectStatus = z.enum([
6
+ "active",
7
+ "on_hold",
8
+ "completed",
9
+ "archived",
10
+ ]);
11
+ export type ProjectStatus = z.infer<typeof ProjectStatus>;
9
12
 
10
13
  // Context definition
11
- export const Context = type({
12
- name: "string",
13
- "color?": "string", // hex color
14
- "description?": "string",
14
+ export const Context = z.object({
15
+ name: z.string(),
16
+ color: z.string().optional(), // hex color
17
+ description: z.string().optional(),
15
18
  });
16
- export type Context = typeof Context.infer;
19
+ export type Context = z.infer<typeof Context>;
17
20
 
18
21
  // Project schema
19
- export const Project = type({
20
- id: "string",
21
- name: "string",
22
- "description?": "string",
22
+ export const Project = z.object({
23
+ id: z.string(),
24
+ name: z.string(),
25
+ description: z.string().optional(),
23
26
  status: ProjectStatus,
24
27
 
25
28
  // Project-level settings
26
- "defaultPriority?": Priority,
27
- "contexts?": Context.array(),
29
+ defaultPriority: Priority.optional(),
30
+ contexts: z.array(Context).optional(),
28
31
 
29
32
  // Metadata
30
- createdAt: "string",
31
- updatedAt: "string",
32
- "targetDate?": "string",
33
+ createdAt: z.string(),
34
+ updatedAt: z.string(),
35
+ targetDate: z.string().optional(),
36
+ sortOrder: z.number().optional(), // User-defined display order (auto-assigned if not specified)
33
37
 
34
38
  // Computed stats
35
- "completionPercentage?": "number",
36
- "criticalPathLength?": "number", // Total minutes on critical path
37
- "blockedTaskCount?": "number",
38
- "totalTasks?": "number",
39
- "completedTasks?": "number",
39
+ completionPercentage: z.number().optional(),
40
+ criticalPathLength: z.number().optional(), // Total minutes on critical path
41
+ blockedTaskCount: z.number().optional(),
42
+ totalTasks: z.number().optional(),
43
+ completedTasks: z.number().optional(),
40
44
  });
41
- export type Project = typeof Project.infer;
45
+ export type Project = z.infer<typeof Project>;
42
46
 
43
47
  // Project creation input
44
- export const ProjectCreateInput = type({
45
- name: "string",
46
- "description?": "string",
47
- "defaultPriority?": Priority,
48
- "contexts?": Context.array(),
49
- "targetDate?": "string",
48
+ export const ProjectCreateInput = z.object({
49
+ name: z.string(),
50
+ description: z.string().optional(),
51
+ defaultPriority: Priority.optional(),
52
+ contexts: z.array(Context).optional(),
53
+ targetDate: z.string().optional(),
54
+ sortOrder: z.number().optional(), // Auto-assigned if not specified
50
55
  });
51
- export type ProjectCreateInput = typeof ProjectCreateInput.infer;
56
+ export type ProjectCreateInput = z.infer<typeof ProjectCreateInput>;
52
57
 
53
58
  // Project update input
54
- export const ProjectUpdateInput = type({
55
- "name?": "string",
56
- "description?": "string",
57
- "status?": ProjectStatus,
58
- "defaultPriority?": Priority,
59
- "contexts?": Context.array(),
60
- "targetDate?": "string",
59
+ export const ProjectUpdateInput = z.object({
60
+ name: z.string().optional(),
61
+ description: z.string().optional(),
62
+ status: ProjectStatus.optional(),
63
+ defaultPriority: Priority.optional(),
64
+ contexts: z.array(Context).optional(),
65
+ targetDate: z.string().optional(),
66
+ sortOrder: z.number().optional(),
61
67
  });
62
- export type ProjectUpdateInput = typeof ProjectUpdateInput.infer;
68
+ export type ProjectUpdateInput = z.infer<typeof ProjectUpdateInput>;
@@ -1,4 +1,4 @@
1
- import { type } from "arktype";
1
+ import { z } from "zod";
2
2
 
3
3
  /**
4
4
  * Response Format Schema
@@ -12,8 +12,8 @@ import { type } from "arktype";
12
12
  */
13
13
 
14
14
  // Response format options
15
- export const ResponseFormat = type("'concise' | 'standard' | 'detailed'");
16
- export type ResponseFormat = typeof ResponseFormat.infer;
15
+ export const ResponseFormat = z.enum(["concise", "standard", "detailed"]);
16
+ export type ResponseFormat = z.infer<typeof ResponseFormat>;
17
17
 
18
18
  // Default limits for pagination
19
19
  export const DEFAULT_LIMIT = 20;
@@ -106,3 +106,99 @@ export interface BottleneckSummary {
106
106
  title: string;
107
107
  blockedCount: number;
108
108
  }
109
+
110
+ /**
111
+ * Dashboard response types - project_dashboard tool
112
+ *
113
+ * Provides unified project overview with progress, priority breakdown,
114
+ * dependency metrics, and next task recommendation.
115
+ */
116
+
117
+ // Progress metrics
118
+ export interface DashboardProgress {
119
+ completed: number;
120
+ total: number;
121
+ pct: number; // 0-100
122
+ }
123
+
124
+ // Priority breakdown
125
+ export interface DashboardPriorityBreakdown {
126
+ critical: number;
127
+ high: number;
128
+ medium: number;
129
+ low: number;
130
+ }
131
+
132
+ // Dependency metrics
133
+ export interface DashboardDependencyMetrics {
134
+ ready: number; // No dependencies or all satisfied
135
+ blocked: number; // Has unsatisfied dependencies
136
+ noDeps: number; // Tasks with no dependencies
137
+ }
138
+
139
+ // Next task recommendation
140
+ export interface DashboardNextTask {
141
+ id: string;
142
+ title: string;
143
+ priority: string;
144
+ reason: string; // Why this task is recommended
145
+ }
146
+
147
+ // Critical path info
148
+ export interface DashboardCriticalPath {
149
+ length: number; // Total duration in minutes
150
+ taskCount: number; // Number of tasks on critical path
151
+ }
152
+
153
+ // Status breakdown (TaskMaster-style)
154
+ export interface DashboardStatusBreakdown {
155
+ done: number;
156
+ inProgress: number;
157
+ pending: number;
158
+ blocked: number;
159
+ deferred: number;
160
+ cancelled: number;
161
+ }
162
+
163
+ // Subtask progress metrics (TaskMaster-style)
164
+ export interface DashboardSubtaskProgress {
165
+ completed: number;
166
+ total: number;
167
+ pct: number; // 0-100
168
+ inProgress: number;
169
+ pending: number;
170
+ blocked: number;
171
+ }
172
+
173
+ // Dependency statistics (TaskMaster-style)
174
+ export interface DashboardDependencyStats {
175
+ mostDependedOn?: {
176
+ taskId: string;
177
+ title: string;
178
+ dependentCount: number; // How many tasks depend on this
179
+ };
180
+ avgDepsPerTask: number; // Average number of dependencies per task
181
+ }
182
+
183
+ // Concise format (~100 tokens) - essential metrics only
184
+ export interface DashboardConcise {
185
+ id: string;
186
+ name: string;
187
+ progress: DashboardProgress;
188
+ statusBreakdown: DashboardStatusBreakdown;
189
+ subtaskProgress?: DashboardSubtaskProgress;
190
+ priority: DashboardPriorityBreakdown;
191
+ dependency: DashboardDependencyMetrics;
192
+ dependencyStats: DashboardDependencyStats;
193
+ nextTask?: DashboardNextTask;
194
+ }
195
+
196
+ // Standard format (~300 tokens) - includes tasks and critical path
197
+ export interface DashboardStandard extends DashboardConcise {
198
+ projectStatus: string;
199
+ targetDate?: string;
200
+ criticalPath?: DashboardCriticalPath;
201
+ tasks: TaskSummary[];
202
+ }
203
+
204
+ // Detailed format - human-readable markdown (use string output)
@@ -0,0 +1,314 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import {
3
+ ResponseType,
4
+ ResponsePriority,
5
+ ResponseOption,
6
+ QuestionResponse,
7
+ SuggestionResponse,
8
+ ConfirmationResponse,
9
+ GenerateResponseInput,
10
+ } from "./response-schema.js";
11
+
12
+ describe("Response Schema", () => {
13
+ describe("ResponseType", () => {
14
+ it("should accept valid response types", () => {
15
+ expect(() => ResponseType.parse("question")).not.toThrow();
16
+ expect(() => ResponseType.parse("suggestion")).not.toThrow();
17
+ expect(() => ResponseType.parse("confirmation")).not.toThrow();
18
+ });
19
+
20
+ it("should reject invalid response types", () => {
21
+ expect(() => ResponseType.parse("invalid")).toThrow();
22
+ expect(() => ResponseType.parse("ask")).toThrow();
23
+ });
24
+ });
25
+
26
+ describe("ResponsePriority", () => {
27
+ it("should accept valid priority levels", () => {
28
+ expect(() => ResponsePriority.parse("low")).not.toThrow();
29
+ expect(() => ResponsePriority.parse("medium")).not.toThrow();
30
+ expect(() => ResponsePriority.parse("high")).not.toThrow();
31
+ expect(() => ResponsePriority.parse("critical")).not.toThrow();
32
+ });
33
+
34
+ it("should reject invalid priority levels", () => {
35
+ expect(() => ResponsePriority.parse("urgent")).toThrow();
36
+ expect(() => ResponsePriority.parse("normal")).toThrow();
37
+ });
38
+ });
39
+
40
+ describe("ResponseOption", () => {
41
+ it("should validate option with all fields", () => {
42
+ const option = {
43
+ label: "High Priority",
44
+ value: "high",
45
+ description: "For urgent tasks",
46
+ };
47
+
48
+ expect(() => ResponseOption.parse(option)).not.toThrow();
49
+ const parsed = ResponseOption.parse(option);
50
+ expect(parsed.label).toBe("High Priority");
51
+ expect(parsed.value).toBe("high");
52
+ expect(parsed.description).toBe("For urgent tasks");
53
+ });
54
+
55
+ it("should validate option without description", () => {
56
+ const option = {
57
+ label: "Low Priority",
58
+ value: "low",
59
+ };
60
+
61
+ expect(() => ResponseOption.parse(option)).not.toThrow();
62
+ const parsed = ResponseOption.parse(option);
63
+ expect(parsed.label).toBe("Low Priority");
64
+ expect(parsed.value).toBe("low");
65
+ expect(parsed.description).toBeUndefined();
66
+ });
67
+
68
+ it("should reject option without required fields", () => {
69
+ expect(() => ResponseOption.parse({ label: "Test" })).toThrow();
70
+ expect(() => ResponseOption.parse({ value: "test" })).toThrow();
71
+ expect(() => ResponseOption.parse({})).toThrow();
72
+ });
73
+ });
74
+
75
+ describe("QuestionResponse", () => {
76
+ it("should validate question with all fields", () => {
77
+ const question = {
78
+ type: "question" as const,
79
+ message: "What should we do?",
80
+ context: "Need clarification on approach",
81
+ priority: "high" as const,
82
+ options: [
83
+ { label: "Option A", value: "a" },
84
+ { label: "Option B", value: "b" },
85
+ ],
86
+ defaultOption: "a",
87
+ };
88
+
89
+ expect(() => QuestionResponse.parse(question)).not.toThrow();
90
+ const parsed = QuestionResponse.parse(question);
91
+ expect(parsed.type).toBe("question");
92
+ expect(parsed.message).toBe("What should we do?");
93
+ expect(parsed.options).toHaveLength(2);
94
+ expect(parsed.defaultOption).toBe("a");
95
+ });
96
+
97
+ it("should validate question with minimal fields", () => {
98
+ const question = {
99
+ type: "question" as const,
100
+ message: "Proceed?",
101
+ };
102
+
103
+ expect(() => QuestionResponse.parse(question)).not.toThrow();
104
+ const parsed = QuestionResponse.parse(question);
105
+ expect(parsed.type).toBe("question");
106
+ expect(parsed.message).toBe("Proceed?");
107
+ expect(parsed.context).toBeUndefined();
108
+ expect(parsed.options).toBeUndefined();
109
+ });
110
+
111
+ it("should reject question without message", () => {
112
+ expect(() => QuestionResponse.parse({ type: "question" })).toThrow();
113
+ });
114
+
115
+ it("should reject question with wrong type", () => {
116
+ expect(() =>
117
+ QuestionResponse.parse({
118
+ type: "suggestion",
119
+ message: "Test",
120
+ })
121
+ ).toThrow();
122
+ });
123
+ });
124
+
125
+ describe("SuggestionResponse", () => {
126
+ it("should validate suggestion with all fields", () => {
127
+ const suggestion = {
128
+ type: "suggestion" as const,
129
+ message: "Consider breaking down this task",
130
+ context: "Task is complex",
131
+ priority: "medium" as const,
132
+ options: [
133
+ { label: "3 subtasks", value: "sub_3" },
134
+ { label: "5 subtasks", value: "sub_5" },
135
+ ],
136
+ reasoning: "Based on complexity analysis",
137
+ };
138
+
139
+ expect(() => SuggestionResponse.parse(suggestion)).not.toThrow();
140
+ const parsed = SuggestionResponse.parse(suggestion);
141
+ expect(parsed.type).toBe("suggestion");
142
+ expect(parsed.options).toHaveLength(2);
143
+ expect(parsed.reasoning).toBe("Based on complexity analysis");
144
+ });
145
+
146
+ it("should validate suggestion with minimal fields", () => {
147
+ const suggestion = {
148
+ type: "suggestion" as const,
149
+ message: "Try this",
150
+ options: [{ label: "Do it", value: "yes" }],
151
+ };
152
+
153
+ expect(() => SuggestionResponse.parse(suggestion)).not.toThrow();
154
+ const parsed = SuggestionResponse.parse(suggestion);
155
+ expect(parsed.options).toHaveLength(1);
156
+ });
157
+
158
+ it("should reject suggestion without options", () => {
159
+ expect(() =>
160
+ SuggestionResponse.parse({
161
+ type: "suggestion",
162
+ message: "Test",
163
+ })
164
+ ).toThrow();
165
+ });
166
+
167
+ it("should reject suggestion with empty options array", () => {
168
+ expect(() =>
169
+ SuggestionResponse.parse({
170
+ type: "suggestion",
171
+ message: "Test",
172
+ options: [],
173
+ })
174
+ ).toThrow();
175
+ });
176
+ });
177
+
178
+ describe("ConfirmationResponse", () => {
179
+ it("should validate confirmation with all fields", () => {
180
+ const confirmation = {
181
+ type: "confirmation" as const,
182
+ message: "Are you sure?",
183
+ action: "Delete all completed tasks",
184
+ context: "This operation is irreversible",
185
+ priority: "critical" as const,
186
+ consequences: ["10 tasks will be removed", "Cannot be undone"],
187
+ defaultConfirm: false,
188
+ };
189
+
190
+ expect(() => ConfirmationResponse.parse(confirmation)).not.toThrow();
191
+ const parsed = ConfirmationResponse.parse(confirmation);
192
+ expect(parsed.type).toBe("confirmation");
193
+ expect(parsed.action).toBe("Delete all completed tasks");
194
+ expect(parsed.consequences).toHaveLength(2);
195
+ expect(parsed.defaultConfirm).toBe(false);
196
+ });
197
+
198
+ it("should validate confirmation with minimal fields", () => {
199
+ const confirmation = {
200
+ type: "confirmation" as const,
201
+ message: "Delete this?",
202
+ action: "Delete task",
203
+ };
204
+
205
+ expect(() => ConfirmationResponse.parse(confirmation)).not.toThrow();
206
+ const parsed = ConfirmationResponse.parse(confirmation);
207
+ expect(parsed.action).toBe("Delete task");
208
+ expect(parsed.consequences).toBeUndefined();
209
+ });
210
+
211
+ it("should reject confirmation without action", () => {
212
+ expect(() =>
213
+ ConfirmationResponse.parse({
214
+ type: "confirmation",
215
+ message: "Confirm?",
216
+ })
217
+ ).toThrow();
218
+ });
219
+
220
+ it("should reject confirmation without message", () => {
221
+ expect(() =>
222
+ ConfirmationResponse.parse({
223
+ type: "confirmation",
224
+ action: "Do something",
225
+ })
226
+ ).toThrow();
227
+ });
228
+ });
229
+
230
+ describe("GenerateResponseInput", () => {
231
+ it("should validate input for question type", () => {
232
+ const input = {
233
+ type: "question" as const,
234
+ message: "What to do?",
235
+ options: [{ label: "Yes", value: "yes" }],
236
+ defaultOption: "yes",
237
+ };
238
+
239
+ expect(() => GenerateResponseInput.parse(input)).not.toThrow();
240
+ const parsed = GenerateResponseInput.parse(input);
241
+ expect(parsed.type).toBe("question");
242
+ });
243
+
244
+ it("should validate input for suggestion type", () => {
245
+ const input = {
246
+ type: "suggestion" as const,
247
+ message: "Try this",
248
+ options: [{ label: "Option", value: "opt" }],
249
+ reasoning: "Because reasons",
250
+ };
251
+
252
+ expect(() => GenerateResponseInput.parse(input)).not.toThrow();
253
+ });
254
+
255
+ it("should validate input for confirmation type", () => {
256
+ const input = {
257
+ type: "confirmation" as const,
258
+ message: "Sure?",
259
+ action: "Delete",
260
+ consequences: ["Gone forever"],
261
+ defaultConfirm: false,
262
+ };
263
+
264
+ expect(() => GenerateResponseInput.parse(input)).not.toThrow();
265
+ });
266
+
267
+ it("should use default priority of medium", () => {
268
+ const input = {
269
+ type: "question" as const,
270
+ message: "Test?",
271
+ };
272
+
273
+ const parsed = GenerateResponseInput.parse(input);
274
+ expect(parsed.priority).toBe("medium");
275
+ });
276
+
277
+ it("should allow custom priority", () => {
278
+ const input = {
279
+ type: "question" as const,
280
+ message: "Test?",
281
+ priority: "critical" as const,
282
+ };
283
+
284
+ const parsed = GenerateResponseInput.parse(input);
285
+ expect(parsed.priority).toBe("critical");
286
+ });
287
+ });
288
+
289
+ describe("Type discrimination", () => {
290
+ it("should differentiate response types at compile time", () => {
291
+ const question: QuestionResponse = {
292
+ type: "question",
293
+ message: "Test",
294
+ };
295
+
296
+ const suggestion: SuggestionResponse = {
297
+ type: "suggestion",
298
+ message: "Test",
299
+ options: [{ label: "A", value: "a" }],
300
+ };
301
+
302
+ const confirmation: ConfirmationResponse = {
303
+ type: "confirmation",
304
+ message: "Test",
305
+ action: "Do it",
306
+ };
307
+
308
+ // TypeScript should allow this
309
+ expect(question.type).toBe("question");
310
+ expect(suggestion.type).toBe("suggestion");
311
+ expect(confirmation.type).toBe("confirmation");
312
+ });
313
+ });
314
+ });