task-o-matic 0.0.12 → 0.0.14

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 (150) hide show
  1. package/dist/commands/init.js +41 -8
  2. package/dist/commands/tasks/create.d.ts.map +1 -1
  3. package/dist/commands/tasks/create.js +6 -13
  4. package/dist/commands/tasks/document/add.d.ts +3 -0
  5. package/dist/commands/tasks/document/add.d.ts.map +1 -0
  6. package/dist/commands/tasks/document/add.js +35 -0
  7. package/dist/commands/tasks/document/analyze.d.ts +3 -0
  8. package/dist/commands/tasks/document/analyze.d.ts.map +1 -0
  9. package/dist/commands/tasks/document/analyze.js +49 -0
  10. package/dist/commands/tasks/document/get.d.ts +3 -0
  11. package/dist/commands/tasks/document/get.d.ts.map +1 -0
  12. package/dist/commands/tasks/document/get.js +29 -0
  13. package/dist/commands/tasks/document/index.d.ts +8 -0
  14. package/dist/commands/tasks/document/index.d.ts.map +1 -0
  15. package/dist/commands/tasks/document/index.js +13 -0
  16. package/dist/commands/tasks/enhance.d.ts.map +1 -1
  17. package/dist/commands/tasks/enhance.js +64 -61
  18. package/dist/commands/tasks/execute-loop.d.ts.map +1 -1
  19. package/dist/commands/tasks/execute-loop.js +64 -90
  20. package/dist/commands/tasks/execute.d.ts.map +1 -1
  21. package/dist/commands/tasks/execute.js +52 -16
  22. package/dist/commands/tasks/list.js +2 -2
  23. package/dist/commands/tasks/next.js +4 -4
  24. package/dist/commands/tasks/plan/create.d.ts +3 -0
  25. package/dist/commands/tasks/plan/create.d.ts.map +1 -0
  26. package/dist/commands/tasks/plan/create.js +37 -0
  27. package/dist/commands/tasks/plan/delete.d.ts +3 -0
  28. package/dist/commands/tasks/plan/delete.d.ts.map +1 -0
  29. package/dist/commands/tasks/plan/delete.js +14 -0
  30. package/dist/commands/tasks/plan/get.d.ts +3 -0
  31. package/dist/commands/tasks/plan/get.d.ts.map +1 -0
  32. package/dist/commands/tasks/plan/get.js +24 -0
  33. package/dist/commands/tasks/plan/index.d.ts +10 -0
  34. package/dist/commands/tasks/plan/index.d.ts.map +1 -0
  35. package/dist/commands/tasks/plan/index.js +17 -0
  36. package/dist/commands/tasks/plan/list.d.ts +3 -0
  37. package/dist/commands/tasks/plan/list.d.ts.map +1 -0
  38. package/dist/commands/tasks/plan/list.js +21 -0
  39. package/dist/commands/tasks/plan/set.d.ts +3 -0
  40. package/dist/commands/tasks/plan/set.d.ts.map +1 -0
  41. package/dist/commands/tasks/plan/set.js +33 -0
  42. package/dist/commands/tasks/split.d.ts.map +1 -1
  43. package/dist/commands/tasks/split.js +65 -60
  44. package/dist/commands/tasks/status.js +2 -2
  45. package/dist/lib/ai-service/ai-operations.d.ts +1 -1
  46. package/dist/lib/ai-service/ai-operations.d.ts.map +1 -1
  47. package/dist/lib/ai-service/base-operations.d.ts +22 -0
  48. package/dist/lib/ai-service/base-operations.d.ts.map +1 -1
  49. package/dist/lib/ai-service/base-operations.js +29 -1
  50. package/dist/lib/ai-service/task-operations.d.ts +1 -1
  51. package/dist/lib/ai-service/task-operations.d.ts.map +1 -1
  52. package/dist/lib/better-t-stack-cli.d.ts +36 -21
  53. package/dist/lib/better-t-stack-cli.d.ts.map +1 -1
  54. package/dist/lib/better-t-stack-cli.js +212 -33
  55. package/dist/lib/bootstrap/cli-bootstrap.d.ts +14 -0
  56. package/dist/lib/bootstrap/cli-bootstrap.d.ts.map +1 -0
  57. package/dist/lib/bootstrap/cli-bootstrap.js +325 -0
  58. package/dist/lib/bootstrap/index.d.ts +4 -0
  59. package/dist/lib/bootstrap/index.d.ts.map +1 -0
  60. package/dist/lib/bootstrap/index.js +19 -0
  61. package/dist/lib/bootstrap/medusa-bootstrap.d.ts +14 -0
  62. package/dist/lib/bootstrap/medusa-bootstrap.d.ts.map +1 -0
  63. package/dist/lib/bootstrap/medusa-bootstrap.js +218 -0
  64. package/dist/lib/bootstrap/opentui-bootstrap.d.ts +11 -0
  65. package/dist/lib/bootstrap/opentui-bootstrap.d.ts.map +1 -0
  66. package/dist/lib/bootstrap/opentui-bootstrap.js +342 -0
  67. package/dist/lib/config.d.ts +14 -0
  68. package/dist/lib/config.d.ts.map +1 -1
  69. package/dist/lib/config.js +18 -0
  70. package/dist/lib/git-utils.d.ts +45 -0
  71. package/dist/lib/git-utils.d.ts.map +1 -0
  72. package/dist/lib/git-utils.js +160 -0
  73. package/dist/lib/task-execution-core.d.ts +7 -0
  74. package/dist/lib/task-execution-core.d.ts.map +1 -0
  75. package/dist/lib/task-execution-core.js +360 -0
  76. package/dist/lib/task-execution.d.ts +4 -0
  77. package/dist/lib/task-execution.d.ts.map +1 -1
  78. package/dist/lib/task-execution.js +31 -149
  79. package/dist/lib/task-loop-execution.d.ts +1 -19
  80. package/dist/lib/task-loop-execution.d.ts.map +1 -1
  81. package/dist/lib/task-loop-execution.js +50 -585
  82. package/dist/lib/task-planning.d.ts +28 -0
  83. package/dist/lib/task-planning.d.ts.map +1 -0
  84. package/dist/lib/task-planning.js +109 -0
  85. package/dist/lib/task-review.d.ts +27 -0
  86. package/dist/lib/task-review.d.ts.map +1 -0
  87. package/dist/lib/task-review.js +106 -0
  88. package/dist/lib/validation.d.ts +20 -3
  89. package/dist/lib/validation.d.ts.map +1 -1
  90. package/dist/lib/validation.js +39 -10
  91. package/dist/services/prd.d.ts.map +1 -1
  92. package/dist/services/prd.js +18 -45
  93. package/dist/services/tasks.d.ts +2 -2
  94. package/dist/services/tasks.d.ts.map +1 -1
  95. package/dist/services/tasks.js +55 -85
  96. package/dist/test/task-loop-git.test.js +6 -6
  97. package/dist/types/cli-options.d.ts +138 -0
  98. package/dist/types/cli-options.d.ts.map +1 -0
  99. package/dist/types/cli-options.js +6 -0
  100. package/dist/types/index.d.ts +74 -1
  101. package/dist/types/index.d.ts.map +1 -1
  102. package/dist/types/results.d.ts +60 -6
  103. package/dist/types/results.d.ts.map +1 -1
  104. package/dist/utils/bulk-operations.d.ts +51 -0
  105. package/dist/utils/bulk-operations.d.ts.map +1 -0
  106. package/dist/utils/bulk-operations.js +68 -0
  107. package/dist/utils/cli-validators.d.ts +54 -0
  108. package/dist/utils/cli-validators.d.ts.map +1 -0
  109. package/dist/utils/cli-validators.js +75 -0
  110. package/dist/utils/command-error-handler.d.ts +32 -0
  111. package/dist/utils/command-error-handler.d.ts.map +1 -0
  112. package/dist/utils/command-error-handler.js +52 -0
  113. package/dist/utils/confirmation.d.ts +19 -0
  114. package/dist/utils/confirmation.d.ts.map +1 -0
  115. package/dist/utils/confirmation.js +39 -0
  116. package/dist/utils/display-helpers.d.ts +81 -0
  117. package/dist/utils/display-helpers.d.ts.map +1 -0
  118. package/dist/utils/display-helpers.js +109 -0
  119. package/dist/utils/error-utils.d.ts +70 -0
  120. package/dist/utils/error-utils.d.ts.map +1 -0
  121. package/dist/utils/error-utils.js +103 -0
  122. package/dist/utils/file-utils.d.ts +49 -0
  123. package/dist/utils/file-utils.d.ts.map +1 -0
  124. package/dist/utils/file-utils.js +77 -0
  125. package/dist/utils/id-generator.d.ts +92 -0
  126. package/dist/utils/id-generator.d.ts.map +1 -0
  127. package/dist/utils/id-generator.js +140 -0
  128. package/dist/utils/model-executor-parser.d.ts +38 -0
  129. package/dist/utils/model-executor-parser.d.ts.map +1 -0
  130. package/dist/utils/model-executor-parser.js +67 -0
  131. package/dist/utils/progress-tracking.d.ts +28 -0
  132. package/dist/utils/progress-tracking.d.ts.map +1 -0
  133. package/dist/utils/progress-tracking.js +43 -0
  134. package/dist/utils/stack-formatter.d.ts +2 -1
  135. package/dist/utils/stack-formatter.d.ts.map +1 -1
  136. package/dist/utils/stack-formatter.js +8 -2
  137. package/dist/utils/storage-utils.d.ts +49 -0
  138. package/dist/utils/storage-utils.d.ts.map +1 -0
  139. package/dist/utils/storage-utils.js +79 -0
  140. package/dist/utils/streaming-utils.d.ts +38 -0
  141. package/dist/utils/streaming-utils.d.ts.map +1 -0
  142. package/dist/utils/streaming-utils.js +56 -0
  143. package/docs/agents/cli.md +58 -149
  144. package/package.json +1 -1
  145. package/dist/commands/tasks/document.d.ts +0 -5
  146. package/dist/commands/tasks/document.d.ts.map +0 -1
  147. package/dist/commands/tasks/document.js +0 -118
  148. package/dist/commands/tasks/plan.d.ts +0 -7
  149. package/dist/commands/tasks/plan.d.ts.map +0 -1
  150. package/dist/commands/tasks/plan.js +0 -131
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-executor-parser.d.ts","sourceRoot":"","sources":["../../src/utils/model-executor-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE5D;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,YAAY,EAKzC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAAE,CA2BlE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,QAAQ,IAAI,YAAY,CAE3E"}
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VALID_EXECUTORS = void 0;
4
+ exports.parseTryModels = parseTryModels;
5
+ exports.validateExecutor = validateExecutor;
6
+ /**
7
+ * Valid executor tools
8
+ */
9
+ exports.VALID_EXECUTORS = [
10
+ "opencode",
11
+ "claude",
12
+ "gemini",
13
+ "codex",
14
+ ];
15
+ /**
16
+ * Parse --try-models option into ModelAttemptConfig array
17
+ * Supports formats:
18
+ * - "model1,model2,model3" - just models (uses default executor)
19
+ * - "opencode:gpt-4o,claude:sonnet-4" - executor:model format
20
+ * - Mixed: "gpt-4o,claude:sonnet-4,gemini:gemini-2.0"
21
+ *
22
+ * @param value - Comma-separated model/executor specifications
23
+ * @returns Array of model attempt configurations
24
+ * @throws Error if an invalid executor is specified
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * parseTryModels("gpt-4o-mini,gpt-4o"); // [{ model: "gpt-4o-mini" }, { model: "gpt-4o" }]
29
+ * parseTryModels("opencode:gpt-4o,claude:sonnet-4"); // [{ executor: "opencode", model: "gpt-4o" }, ...]
30
+ * ```
31
+ */
32
+ function parseTryModels(value) {
33
+ return value.split(",").map((item) => {
34
+ const trimmed = item.trim();
35
+ // Check if it includes executor specification (executor:model format)
36
+ if (trimmed.includes(":")) {
37
+ const [executor, model] = trimmed.split(":");
38
+ if (!exports.VALID_EXECUTORS.includes(executor)) {
39
+ throw new Error(`Invalid executor "${executor}" in --try-models. Must be one of: ${exports.VALID_EXECUTORS.join(", ")}`);
40
+ }
41
+ return {
42
+ executor: executor,
43
+ model: model.trim(),
44
+ };
45
+ }
46
+ // Just a model name - use default executor
47
+ return {
48
+ model: trimmed,
49
+ };
50
+ });
51
+ }
52
+ /**
53
+ * Validate that an executor name is valid
54
+ *
55
+ * @param executor - Executor name to validate
56
+ * @returns Type guard confirming executor is valid
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * if (validateExecutor(options.tool)) {
61
+ * // TypeScript knows options.tool is ExecutorTool
62
+ * }
63
+ * ```
64
+ */
65
+ function validateExecutor(executor) {
66
+ return exports.VALID_EXECUTORS.includes(executor);
67
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Progress event payload from AI operations
3
+ */
4
+ export interface ProgressEvent {
5
+ taskId?: string;
6
+ operation?: string;
7
+ step?: string;
8
+ progress?: number;
9
+ message?: string;
10
+ phase?: string;
11
+ [key: string]: any;
12
+ }
13
+ /**
14
+ * Execute an async function with automatic progress tracking
15
+ * Registers a progress handler, executes the function, and cleans up
16
+ *
17
+ * @param fn - The async function to execute with progress tracking
18
+ * @returns The result of the function
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const result = await withProgressTracking(async () => {
23
+ * return await taskService.enhanceTask(taskId);
24
+ * });
25
+ * ```
26
+ */
27
+ export declare function withProgressTracking<T>(fn: () => Promise<T>): Promise<T>;
28
+ //# sourceMappingURL=progress-tracking.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progress-tracking.d.ts","sourceRoot":"","sources":["../../src/utils/progress-tracking.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAiBD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,EAC1C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CASZ"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withProgressTracking = withProgressTracking;
4
+ const hooks_1 = require("../lib/hooks");
5
+ /**
6
+ * Display progress information to the console
7
+ */
8
+ function displayProgress(payload) {
9
+ const { operation, step, message, phase } = payload;
10
+ if (phase) {
11
+ console.log(`[${phase}]`, message || step || operation || "");
12
+ }
13
+ else if (operation && step) {
14
+ console.log(`${operation}: ${step}`);
15
+ }
16
+ else if (message) {
17
+ console.log(message);
18
+ }
19
+ }
20
+ /**
21
+ * Execute an async function with automatic progress tracking
22
+ * Registers a progress handler, executes the function, and cleans up
23
+ *
24
+ * @param fn - The async function to execute with progress tracking
25
+ * @returns The result of the function
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const result = await withProgressTracking(async () => {
30
+ * return await taskService.enhanceTask(taskId);
31
+ * });
32
+ * ```
33
+ */
34
+ async function withProgressTracking(fn) {
35
+ const progressHandler = (payload) => displayProgress(payload);
36
+ hooks_1.hooks.on("task:progress", progressHandler);
37
+ try {
38
+ return await fn();
39
+ }
40
+ finally {
41
+ hooks_1.hooks.off("task:progress", progressHandler);
42
+ }
43
+ }
@@ -1,5 +1,6 @@
1
+ import type { BTSFrontend } from "../types/index.js";
1
2
  export interface StackInfo {
2
- frontend: string;
3
+ frontend: BTSFrontend | BTSFrontend[];
3
4
  backend: string;
4
5
  database: string;
5
6
  orm: string;
@@ -1 +1 @@
1
- {"version":3,"file":"stack-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/stack-formatter.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAyB3E;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAMjF"}
1
+ {"version":3,"file":"stack-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/stack-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,WAAW,GAAG,WAAW,EAAE,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CA6B3E;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAUjF"}
@@ -6,8 +6,11 @@ function formatStackInfo(stack) {
6
6
  if (!stack) {
7
7
  return "Not detected";
8
8
  }
9
+ const frontendStr = Array.isArray(stack.frontend)
10
+ ? stack.frontend.join(", ")
11
+ : stack.frontend;
9
12
  const parts = [
10
- `Frontend: ${stack.frontend}`,
13
+ `Frontend: ${frontendStr}`,
11
14
  `Backend: ${stack.backend}`
12
15
  ];
13
16
  if (stack.database !== 'none') {
@@ -26,5 +29,8 @@ function formatStackForContext(stack) {
26
29
  if (!stack) {
27
30
  return "";
28
31
  }
29
- return `Technology Stack: ${stack.frontend} + ${stack.backend} + ${stack.database}`;
32
+ const frontendStr = Array.isArray(stack.frontend)
33
+ ? stack.frontend.join(" + ")
34
+ : stack.frontend;
35
+ return `Technology Stack: ${frontendStr} + ${stack.backend} + ${stack.database}`;
30
36
  }
@@ -0,0 +1,49 @@
1
+ import { Task } from "../types/index.js";
2
+ /**
3
+ * Ensures a task is not null, throwing an error if it is.
4
+ * Useful for enforcing null checks after storage operations.
5
+ *
6
+ * @param task - Task that may be null
7
+ * @param taskId - ID of the task for error message
8
+ * @returns The task if not null
9
+ * @throws Error if task is null
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const task = await storage.getTask(taskId);
14
+ * const validTask = requireTask(task, taskId);
15
+ * console.log(validTask.title); // Safe - never null
16
+ * ```
17
+ */
18
+ export declare function requireTask(task: Task | null, taskId: string): Task;
19
+ /**
20
+ * Ensures multiple tasks are not null, throwing an error if any is null.
21
+ *
22
+ * @param tasks - Array of tasks that may contain nulls
23
+ * @param context - Context for error message (e.g., "subtasks", "dependencies")
24
+ * @returns Array of tasks with nulls filtered out
25
+ * @throws Error if any task is null
26
+ */
27
+ export declare function requireTasks(tasks: (Task | null)[], context?: string): Task[];
28
+ /**
29
+ * Filters out null tasks from an array, with type narrowing.
30
+ *
31
+ * @param tasks - Array of tasks that may contain nulls
32
+ * @returns Array of tasks with nulls removed
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const tasks = await Promise.all(ids.map(id => storage.getTask(id)));
37
+ * const validTasks = filterNullTasks(tasks);
38
+ * // validTasks has type Task[] (no null)
39
+ * ```
40
+ */
41
+ export declare function filterNullTasks(tasks: (Task | null)[]): Task[];
42
+ /**
43
+ * Validates that a task ID is a non-empty string.
44
+ *
45
+ * @param taskId - Task ID to validate
46
+ * @throws Error if task ID is invalid
47
+ */
48
+ export declare function validateTaskId(taskId: string): void;
49
+ //# sourceMappingURL=storage-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-utils.d.ts","sourceRoot":"","sources":["../../src/utils/storage-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAKnE;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,EACtB,OAAO,GAAE,MAAgB,GACxB,IAAI,EAAE,CAiBR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAInD"}
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requireTask = requireTask;
4
+ exports.requireTasks = requireTasks;
5
+ exports.filterNullTasks = filterNullTasks;
6
+ exports.validateTaskId = validateTaskId;
7
+ /**
8
+ * Ensures a task is not null, throwing an error if it is.
9
+ * Useful for enforcing null checks after storage operations.
10
+ *
11
+ * @param task - Task that may be null
12
+ * @param taskId - ID of the task for error message
13
+ * @returns The task if not null
14
+ * @throws Error if task is null
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const task = await storage.getTask(taskId);
19
+ * const validTask = requireTask(task, taskId);
20
+ * console.log(validTask.title); // Safe - never null
21
+ * ```
22
+ */
23
+ function requireTask(task, taskId) {
24
+ if (!task) {
25
+ throw new Error(`Task not found: ${taskId}`);
26
+ }
27
+ return task;
28
+ }
29
+ /**
30
+ * Ensures multiple tasks are not null, throwing an error if any is null.
31
+ *
32
+ * @param tasks - Array of tasks that may contain nulls
33
+ * @param context - Context for error message (e.g., "subtasks", "dependencies")
34
+ * @returns Array of tasks with nulls filtered out
35
+ * @throws Error if any task is null
36
+ */
37
+ function requireTasks(tasks, context = "tasks") {
38
+ const validTasks = [];
39
+ const missingIds = [];
40
+ tasks.forEach((task, index) => {
41
+ if (!task) {
42
+ missingIds.push(`index ${index}`);
43
+ }
44
+ else {
45
+ validTasks.push(task);
46
+ }
47
+ });
48
+ if (missingIds.length > 0) {
49
+ throw new Error(`Missing ${context}: ${missingIds.join(", ")}`);
50
+ }
51
+ return validTasks;
52
+ }
53
+ /**
54
+ * Filters out null tasks from an array, with type narrowing.
55
+ *
56
+ * @param tasks - Array of tasks that may contain nulls
57
+ * @returns Array of tasks with nulls removed
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const tasks = await Promise.all(ids.map(id => storage.getTask(id)));
62
+ * const validTasks = filterNullTasks(tasks);
63
+ * // validTasks has type Task[] (no null)
64
+ * ```
65
+ */
66
+ function filterNullTasks(tasks) {
67
+ return tasks.filter((task) => task !== null);
68
+ }
69
+ /**
70
+ * Validates that a task ID is a non-empty string.
71
+ *
72
+ * @param taskId - Task ID to validate
73
+ * @throws Error if task ID is invalid
74
+ */
75
+ function validateTaskId(taskId) {
76
+ if (!taskId || typeof taskId !== "string" || !taskId.trim()) {
77
+ throw new Error("Invalid task ID: must be a non-empty string");
78
+ }
79
+ }
@@ -0,0 +1,38 @@
1
+ import { StreamingOptions } from "../types/index.js";
2
+ /**
3
+ * Token usage metrics from AI operations
4
+ */
5
+ export interface TokenUsage {
6
+ prompt: number;
7
+ completion: number;
8
+ total: number;
9
+ }
10
+ export interface MetricsTracker {
11
+ tokenUsage: TokenUsage;
12
+ timeToFirstToken: number | undefined;
13
+ }
14
+ export interface MetricsStreamingResult {
15
+ options: StreamingOptions;
16
+ getMetrics: () => MetricsTracker;
17
+ }
18
+ /**
19
+ * Creates streaming options with automatic metrics tracking.
20
+ * Wraps provided streaming callbacks to capture token usage and timing metrics.
21
+ *
22
+ * @param streamingOptions - Optional base streaming options to wrap
23
+ * @param aiStartTime - Optional timestamp when AI operation started (for measuring time to first token)
24
+ * @returns Object containing wrapped streaming options and metrics getter
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const aiStartTime = Date.now();
29
+ * const { options, getMetrics } = createMetricsStreamingOptions(userCallbacks, aiStartTime);
30
+ *
31
+ * await generateText({ model, prompt, ...options });
32
+ *
33
+ * const { tokenUsage, timeToFirstToken } = getMetrics();
34
+ * console.log(`Used ${tokenUsage.total} tokens in ${timeToFirstToken}ms`);
35
+ * ```
36
+ */
37
+ export declare function createMetricsStreamingOptions(streamingOptions?: StreamingOptions, aiStartTime?: number): MetricsStreamingResult;
38
+ //# sourceMappingURL=streaming-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streaming-utils.d.ts","sourceRoot":"","sources":["../../src/utils/streaming-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,UAAU,CAAC;IACvB,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,UAAU,EAAE,MAAM,cAAc,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,6BAA6B,CAC3C,gBAAgB,CAAC,EAAE,gBAAgB,EACnC,WAAW,CAAC,EAAE,MAAM,GACnB,sBAAsB,CAsCxB"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createMetricsStreamingOptions = createMetricsStreamingOptions;
4
+ /**
5
+ * Creates streaming options with automatic metrics tracking.
6
+ * Wraps provided streaming callbacks to capture token usage and timing metrics.
7
+ *
8
+ * @param streamingOptions - Optional base streaming options to wrap
9
+ * @param aiStartTime - Optional timestamp when AI operation started (for measuring time to first token)
10
+ * @returns Object containing wrapped streaming options and metrics getter
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const aiStartTime = Date.now();
15
+ * const { options, getMetrics } = createMetricsStreamingOptions(userCallbacks, aiStartTime);
16
+ *
17
+ * await generateText({ model, prompt, ...options });
18
+ *
19
+ * const { tokenUsage, timeToFirstToken } = getMetrics();
20
+ * console.log(`Used ${tokenUsage.total} tokens in ${timeToFirstToken}ms`);
21
+ * ```
22
+ */
23
+ function createMetricsStreamingOptions(streamingOptions, aiStartTime) {
24
+ let tokenUsage = { prompt: 0, completion: 0, total: 0 };
25
+ let timeToFirstToken = undefined;
26
+ const wrappedOptions = {
27
+ onFinish: async (result) => {
28
+ // Extract token usage from result
29
+ if (result.usage) {
30
+ tokenUsage = {
31
+ prompt: result.usage.inputTokens || result.usage.promptTokens || 0,
32
+ completion: result.usage.outputTokens || result.usage.completionTokens || 0,
33
+ total: result.usage.totalTokens || 0,
34
+ };
35
+ }
36
+ // Call original onFinish callback if provided
37
+ await streamingOptions?.onFinish?.(result);
38
+ },
39
+ onChunk: (chunk) => {
40
+ // Measure time to first token (ignore empty/whitespace chunks)
41
+ if (chunk && chunk.trim() && !timeToFirstToken && aiStartTime) {
42
+ timeToFirstToken = Date.now() - aiStartTime;
43
+ }
44
+ // Call original onChunk callback if provided
45
+ streamingOptions?.onChunk?.(chunk);
46
+ },
47
+ onError: (error) => {
48
+ // Pass through error callback
49
+ streamingOptions?.onError?.(error);
50
+ },
51
+ };
52
+ return {
53
+ options: wrappedOptions,
54
+ getMetrics: () => ({ tokenUsage, timeToFirstToken }),
55
+ };
56
+ }