task.test.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import { describe, expect, test } from 'bun:test';
  2. import {
  3. parseContextSummaryFromTaskOutput,
  4. parseTaskIdFromTaskOutput,
  5. stripContextSummaryFromTaskOutput,
  6. } from './task';
  7. describe('parseTaskIdFromTaskOutput', () => {
  8. test('parses task_id line from successful task tool output', () => {
  9. const output = [
  10. 'task_id: session-abc-123 (for resuming to continue this task if needed)',
  11. '',
  12. '<task_result>',
  13. 'done',
  14. '</task_result>',
  15. ].join('\n');
  16. expect(parseTaskIdFromTaskOutput(output)).toBe('session-abc-123');
  17. });
  18. test('returns undefined when task_id is absent', () => {
  19. const output = ['<task_result>', 'no task id here', '</task_result>'].join(
  20. '\n',
  21. );
  22. expect(parseTaskIdFromTaskOutput(output)).toBeUndefined();
  23. });
  24. });
  25. describe('parseContextSummaryFromTaskOutput', () => {
  26. test('parses and normalizes the final context summary block', () => {
  27. const output = [
  28. '<context_summary>old summary</context_summary>',
  29. '<task_result>',
  30. 'done',
  31. '</task_result>',
  32. '<context_summary>',
  33. ' Reviewed session management\n and found implementation points. ',
  34. '</context_summary>',
  35. ].join('\n');
  36. expect(parseContextSummaryFromTaskOutput(output)).toBe(
  37. 'Reviewed session management and found implementation points.',
  38. );
  39. });
  40. test('ignores context summary mentions that are not final metadata', () => {
  41. const output = [
  42. '<task_result>',
  43. '<results>',
  44. '<answer>Discusses <context_summary> syntax only.</answer>',
  45. '</results>',
  46. '</task_result>',
  47. ].join('\n');
  48. expect(parseContextSummaryFromTaskOutput(output)).toBeUndefined();
  49. });
  50. test('ignores context summary blocks nested inside task results', () => {
  51. const output = [
  52. '<task_result>',
  53. '<results>',
  54. '<answer>done</answer>',
  55. '<context_summary>Nested summary should not parse.</context_summary>',
  56. '</results>',
  57. '</task_result>',
  58. ].join('\n');
  59. expect(parseContextSummaryFromTaskOutput(output)).toBeUndefined();
  60. });
  61. test('returns undefined when context block is absent or empty', () => {
  62. expect(parseContextSummaryFromTaskOutput('plain output')).toBeUndefined();
  63. expect(
  64. parseContextSummaryFromTaskOutput(
  65. '<context_summary> \n </context_summary>',
  66. ),
  67. ).toBeUndefined();
  68. });
  69. test('parses malformed final context summary blocks', () => {
  70. const output = [
  71. '<task_result>',
  72. '<results>',
  73. '<answer>done</answer>',
  74. '</task_result>',
  75. '<context_summary>Remember inspected session code.',
  76. ].join('\n');
  77. expect(parseContextSummaryFromTaskOutput(output)).toBe(
  78. 'Remember inspected session code.',
  79. );
  80. });
  81. test('truncates long context summaries', () => {
  82. const longSummary = 'a'.repeat(320);
  83. expect(
  84. parseContextSummaryFromTaskOutput(
  85. `<context_summary>${longSummary}</context_summary>`,
  86. ),
  87. ).toHaveLength(280);
  88. });
  89. });
  90. describe('stripContextSummaryFromTaskOutput', () => {
  91. test('removes context summary metadata blocks', () => {
  92. const output = [
  93. 'task_id: session-abc-123',
  94. '',
  95. '<task_result>',
  96. 'done',
  97. '</task_result>',
  98. '<context_summary>metadata only</context_summary>',
  99. ].join('\n');
  100. expect(stripContextSummaryFromTaskOutput(output)).toBe(
  101. [
  102. 'task_id: session-abc-123',
  103. '',
  104. '<task_result>',
  105. 'done',
  106. '</task_result>',
  107. ].join('\n'),
  108. );
  109. });
  110. test('does not remove context summary mentions inside task results', () => {
  111. const output = [
  112. '<task_result>',
  113. '<results>',
  114. '<answer>Discusses <context_summary> syntax only.</answer>',
  115. '</results>',
  116. '</task_result>',
  117. ].join('\n');
  118. expect(stripContextSummaryFromTaskOutput(output)).toBe(output);
  119. });
  120. test('removes malformed final context summary metadata blocks', () => {
  121. const output = [
  122. 'task_id: session-abc-123',
  123. '<task_result>',
  124. '<results>',
  125. '<answer>done</answer>',
  126. '</task_result>',
  127. '<context_summary>metadata only',
  128. ].join('\n');
  129. expect(stripContextSummaryFromTaskOutput(output)).toBe(
  130. [
  131. 'task_id: session-abc-123',
  132. '<task_result>',
  133. '<results>',
  134. '<answer>done</answer>',
  135. '</task_result>',
  136. ].join('\n'),
  137. );
  138. });
  139. });