@taico/taico 0.8.0 → 0.8.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 (90) hide show
  1. package/README.md +1 -1
  2. package/dist/ai-providers/enums/ai-model-job.enum.d.ts +2 -1
  3. package/dist/ai-providers/enums/ai-model-job.enum.js +5 -2
  4. package/dist/ai-providers/enums/ai-model-job.enum.js.map +1 -1
  5. package/dist/ai-providers/errors/ai-providers.errors.js +10 -4
  6. package/dist/ai-providers/errors/ai-providers.errors.js.map +1 -1
  7. package/dist/app.module.js +4 -0
  8. package/dist/app.module.js.map +1 -1
  9. package/dist/migrations/1761700000000-SplitSmallTasksSelection.d.ts +6 -0
  10. package/dist/migrations/1761700000000-SplitSmallTasksSelection.js +32 -0
  11. package/dist/migrations/1761700000000-SplitSmallTasksSelection.js.map +1 -0
  12. package/dist/migrations/1761800000000-ThreadTimers.d.ts +6 -0
  13. package/dist/migrations/1761800000000-ThreadTimers.js +22 -0
  14. package/dist/migrations/1761800000000-ThreadTimers.js.map +1 -0
  15. package/dist/threads/agent/chat-model.factory.js +3 -1
  16. package/dist/threads/agent/chat-model.factory.js.map +1 -1
  17. package/dist/threads/agent/chat-model.factory.spec.js +49 -4
  18. package/dist/threads/agent/chat-model.factory.spec.js.map +1 -1
  19. package/dist/threads/agent/thread-agent-log.service.d.ts +10 -0
  20. package/dist/threads/agent/thread-agent-log.service.js +57 -1
  21. package/dist/threads/agent/thread-agent-log.service.js.map +1 -1
  22. package/dist/threads/agent/thread-agent-tools.factory.d.ts +3 -1
  23. package/dist/threads/agent/thread-agent-tools.factory.js +195 -3
  24. package/dist/threads/agent/thread-agent-tools.factory.js.map +1 -1
  25. package/dist/threads/agent/thread-agent.prompts.d.ts +15 -0
  26. package/dist/threads/agent/thread-agent.prompts.js +29 -1
  27. package/dist/threads/agent/thread-agent.prompts.js.map +1 -1
  28. package/dist/threads/agent/thread-agent.service.js +9 -3
  29. package/dist/threads/agent/thread-agent.service.js.map +1 -1
  30. package/dist/threads/agent/thread-agent.service.spec.js +23 -0
  31. package/dist/threads/agent/thread-agent.service.spec.js.map +1 -1
  32. package/dist/threads/chat.service.d.ts +10 -1
  33. package/dist/threads/chat.service.js +41 -13
  34. package/dist/threads/chat.service.js.map +1 -1
  35. package/dist/threads/chat.service.spec.d.ts +1 -0
  36. package/dist/threads/chat.service.spec.js +150 -0
  37. package/dist/threads/chat.service.spec.js.map +1 -0
  38. package/dist/threads/dto/service/threads.service.types.d.ts +12 -0
  39. package/dist/threads/dto/thread-response.dto.d.ts +2 -0
  40. package/dist/threads/dto/thread-response.dto.js +10 -0
  41. package/dist/threads/dto/thread-response.dto.js.map +1 -1
  42. package/dist/threads/dto/thread-task-subscription-params.dto.d.ts +4 -0
  43. package/dist/threads/dto/thread-task-subscription-params.dto.js +28 -0
  44. package/dist/threads/dto/thread-task-subscription-params.dto.js.map +1 -0
  45. package/dist/threads/dto/thread-timer-params.dto.d.ts +4 -0
  46. package/dist/threads/dto/thread-timer-params.dto.js +28 -0
  47. package/dist/threads/dto/thread-timer-params.dto.js.map +1 -0
  48. package/dist/threads/dto/thread-timer-response.dto.d.ts +13 -0
  49. package/dist/threads/dto/thread-timer-response.dto.js +92 -0
  50. package/dist/threads/dto/thread-timer-response.dto.js.map +1 -0
  51. package/dist/threads/task-subscriptions/thread-task-subscriptions.service.d.ts +8 -0
  52. package/dist/threads/task-subscriptions/thread-task-subscriptions.service.js +14 -0
  53. package/dist/threads/task-subscriptions/thread-task-subscriptions.service.js.map +1 -1
  54. package/dist/threads/thread-title.service.d.ts +8 -2
  55. package/dist/threads/thread-title.service.js +18 -3
  56. package/dist/threads/thread-title.service.js.map +1 -1
  57. package/dist/threads/thread-title.service.spec.d.ts +1 -0
  58. package/dist/threads/thread-title.service.spec.js +59 -0
  59. package/dist/threads/thread-title.service.spec.js.map +1 -0
  60. package/dist/threads/threads.controller.d.ts +4 -0
  61. package/dist/threads/threads.controller.js +40 -0
  62. package/dist/threads/threads.controller.js.map +1 -1
  63. package/dist/threads/threads.module.js +8 -0
  64. package/dist/threads/threads.module.js.map +1 -1
  65. package/dist/threads/threads.service.d.ts +8 -1
  66. package/dist/threads/threads.service.js +39 -10
  67. package/dist/threads/threads.service.js.map +1 -1
  68. package/dist/threads/timers/thread-timer-firing.entity.d.ts +9 -0
  69. package/dist/threads/timers/thread-timer-firing.entity.js +54 -0
  70. package/dist/threads/timers/thread-timer-firing.entity.js.map +1 -0
  71. package/dist/threads/timers/thread-timer-sweeper.service.d.ts +11 -0
  72. package/dist/threads/timers/thread-timer-sweeper.service.js +62 -0
  73. package/dist/threads/timers/thread-timer-sweeper.service.js.map +1 -0
  74. package/dist/threads/timers/thread-timer.entity.d.ts +17 -0
  75. package/dist/threads/timers/thread-timer.entity.js +87 -0
  76. package/dist/threads/timers/thread-timer.entity.js.map +1 -0
  77. package/dist/threads/timers/thread-timer.enums.d.ts +4 -0
  78. package/dist/threads/timers/thread-timer.enums.js +9 -0
  79. package/dist/threads/timers/thread-timer.enums.js.map +1 -0
  80. package/dist/threads/timers/thread-timers.service.d.ts +26 -0
  81. package/dist/threads/timers/thread-timers.service.js +130 -0
  82. package/dist/threads/timers/thread-timers.service.js.map +1 -0
  83. package/dist/threads/timers/timer-input.d.ts +13 -0
  84. package/dist/threads/timers/timer-input.js +159 -0
  85. package/dist/threads/timers/timer-input.js.map +1 -0
  86. package/dist/threads/timers/timer-input.spec.d.ts +1 -0
  87. package/dist/threads/timers/timer-input.spec.js +92 -0
  88. package/dist/threads/timers/timer-input.spec.js.map +1 -0
  89. package/dist/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +5 -5
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_ITERATIONS = exports.MAX_DURATION_SECONDS = void 0;
4
+ exports.parseDuration = parseDuration;
5
+ exports.parseMaxIterations = parseMaxIterations;
6
+ exports.describeDuration = describeDuration;
7
+ exports.parseInstant = parseInstant;
8
+ exports.MAX_DURATION_SECONDS = 366 * 24 * 60 * 60;
9
+ exports.MAX_ITERATIONS = 10;
10
+ const UNIT_SECONDS = { s: 1, m: 60, h: 3600 };
11
+ const UNIT_NAMES = { s: 'second', m: 'minute', h: 'hour' };
12
+ function parseDuration(input) {
13
+ const match = /^([1-9]\d*)([smh])$/.exec(input.trim());
14
+ if (!match) {
15
+ return {
16
+ ok: false,
17
+ error: `Invalid duration "${input}". Use a positive whole number followed by one unit: s, m or h (for example "30s", "5m", "2h"). Compound values such as "1h30m" are not supported; use "90m".`,
18
+ };
19
+ }
20
+ const seconds = Number(match[1]) * UNIT_SECONDS[match[2]];
21
+ if (seconds > exports.MAX_DURATION_SECONDS) {
22
+ return { ok: false, error: `Duration "${input}" is too long. The longest supported is 366 days.` };
23
+ }
24
+ return { ok: true, value: seconds };
25
+ }
26
+ function parseMaxIterations(input) {
27
+ if (typeof input !== 'number' || !Number.isInteger(input) || input < 1) {
28
+ return { ok: false, error: 'maxIterations must be a positive whole number.' };
29
+ }
30
+ if (input > exports.MAX_ITERATIONS) {
31
+ return { ok: false, error: `maxIterations can be at most ${exports.MAX_ITERATIONS}.` };
32
+ }
33
+ return { ok: true, value: input };
34
+ }
35
+ function describeDuration(seconds) {
36
+ for (const unit of ['h', 'm', 's']) {
37
+ if (seconds % UNIT_SECONDS[unit] === 0) {
38
+ const count = seconds / UNIT_SECONDS[unit];
39
+ return `${count} ${UNIT_NAMES[unit]}${count === 1 ? '' : 's'}`;
40
+ }
41
+ }
42
+ return `${seconds} seconds`;
43
+ }
44
+ const DATETIME_PATTERN = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?(?:\.\d+)?(Z|[+-]\d{2}:\d{2})?$/;
45
+ function parseInstant(at, timezone) {
46
+ const match = DATETIME_PATTERN.exec(at.trim());
47
+ if (!match) {
48
+ return {
49
+ ok: false,
50
+ error: `Invalid datetime "${at}". Use ISO 8601, for example "2026-10-15T12:00:00Z", "2026-10-15T12:00:00+11:00", or "2026-10-15T12:00:00" with a timezone such as "Australia/Sydney".`,
51
+ };
52
+ }
53
+ const [, year, month, day, hour, minute, second = '0', offset] = match;
54
+ const fields = {
55
+ year: Number(year),
56
+ month: Number(month),
57
+ day: Number(day),
58
+ hour: Number(hour),
59
+ minute: Number(minute),
60
+ second: Number(second),
61
+ };
62
+ const asUtc = Date.UTC(fields.year, fields.month - 1, fields.day, fields.hour, fields.minute, fields.second);
63
+ const check = new Date(asUtc);
64
+ if (check.getUTCFullYear() !== fields.year ||
65
+ check.getUTCMonth() !== fields.month - 1 ||
66
+ check.getUTCDate() !== fields.day ||
67
+ check.getUTCHours() !== fields.hour ||
68
+ check.getUTCMinutes() !== fields.minute ||
69
+ check.getUTCSeconds() !== fields.second) {
70
+ return { ok: false, error: `"${at}" is not a real date and time.` };
71
+ }
72
+ const zone = timezone?.trim() || undefined;
73
+ if (zone && !isValidTimeZone(zone)) {
74
+ return { ok: false, error: `Unknown timezone "${timezone}". Use an IANA name such as "Australia/Sydney" or "UTC".` };
75
+ }
76
+ if (offset) {
77
+ const offsetMinutes = offset === 'Z' ? 0 : parseOffset(offset);
78
+ if (offsetMinutes === null) {
79
+ return {
80
+ ok: false,
81
+ error: `"${at}" has offset ${offset}, which is not a real UTC offset. Offsets run from -12:00 to +14:00 with minutes 00-59.`,
82
+ };
83
+ }
84
+ const instant = new Date(asUtc - offsetMinutes * 60_000);
85
+ if (zone && zoneOffsetMinutes(zone, instant) !== offsetMinutes) {
86
+ return {
87
+ ok: false,
88
+ error: `"${at}" has offset ${offset}, which does not match timezone "${zone}" at that time. Give either the offset or the timezone, not conflicting ones.`,
89
+ };
90
+ }
91
+ return { ok: true, value: instant };
92
+ }
93
+ if (!zone) {
94
+ return {
95
+ ok: false,
96
+ error: `"${at}" has no offset. Add one ("Z" for UTC, or "+10:00") or pass a timezone such as "Australia/Sydney".`,
97
+ };
98
+ }
99
+ const candidateOffsets = new Set([-86_400_000, 0, 86_400_000].map((shift) => zoneOffsetMinutes(zone, new Date(asUtc + shift))));
100
+ const instants = [...candidateOffsets]
101
+ .map((offsetMinutes) => new Date(asUtc - offsetMinutes * 60_000))
102
+ .filter((instant) => zoneOffsetMinutes(zone, instant) * 60_000 === asUtc - instant.getTime());
103
+ const unique = [...new Set(instants.map((instant) => instant.getTime()))];
104
+ if (unique.length === 0) {
105
+ return { ok: false, error: `${at} does not exist in ${zone}: the clocks skip it for daylight saving. Pick another time.` };
106
+ }
107
+ if (unique.length > 1) {
108
+ return {
109
+ ok: false,
110
+ error: `${at} happens twice in ${zone} because of daylight saving. Give an offset to say which one (for example "${at}${formatOffset(zoneOffsetMinutes(zone, new Date(Math.min(...unique))))}").`,
111
+ };
112
+ }
113
+ return { ok: true, value: new Date(unique[0]) };
114
+ }
115
+ function isValidTimeZone(zone) {
116
+ try {
117
+ new Intl.DateTimeFormat('en-US', { timeZone: zone });
118
+ return true;
119
+ }
120
+ catch {
121
+ return false;
122
+ }
123
+ }
124
+ const MIN_OFFSET_MINUTES = -12 * 60;
125
+ const MAX_OFFSET_MINUTES = 14 * 60;
126
+ function parseOffset(offset) {
127
+ const sign = offset.startsWith('-') ? -1 : 1;
128
+ const [hours, minutes] = offset.slice(1).split(':').map(Number);
129
+ if (minutes > 59) {
130
+ return null;
131
+ }
132
+ const total = sign * (hours * 60 + minutes);
133
+ if (total < MIN_OFFSET_MINUTES || total > MAX_OFFSET_MINUTES) {
134
+ return null;
135
+ }
136
+ return total;
137
+ }
138
+ function formatOffset(minutes) {
139
+ const sign = minutes < 0 ? '-' : '+';
140
+ const abs = Math.abs(minutes);
141
+ return `${sign}${String(Math.floor(abs / 60)).padStart(2, '0')}:${String(abs % 60).padStart(2, '0')}`;
142
+ }
143
+ function zoneOffsetMinutes(zone, instant) {
144
+ const parts = new Intl.DateTimeFormat('en-US', {
145
+ timeZone: zone,
146
+ hourCycle: 'h23',
147
+ year: 'numeric',
148
+ month: '2-digit',
149
+ day: '2-digit',
150
+ hour: '2-digit',
151
+ minute: '2-digit',
152
+ second: '2-digit',
153
+ }).formatToParts(instant);
154
+ const get = (type) => Number(parts.find((part) => part.type === type)?.value);
155
+ const wallAsUtc = Date.UTC(get('year'), get('month') - 1, get('day'), get('hour'), get('minute'), get('second'));
156
+ const wholeSeconds = Math.floor(instant.getTime() / 1000) * 1000;
157
+ return Math.round((wallAsUtc - wholeSeconds) / 60_000);
158
+ }
159
+ //# sourceMappingURL=timer-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer-input.js","sourceRoot":"","sources":["../../../src/threads/timers/timer-input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const timer_input_1 = require("./timer-input");
4
+ describe('timer input', () => {
5
+ describe('parseDuration', () => {
6
+ it.each([
7
+ ['5s', 5],
8
+ ['5m', 300],
9
+ ['2h', 7200],
10
+ [' 90m ', 5400],
11
+ ])('reads %p as %p seconds', (input, seconds) => {
12
+ expect((0, timer_input_1.parseDuration)(input)).toEqual({ ok: true, value: seconds });
13
+ });
14
+ it.each(['1h30m', '0m', '-5m', '5', 'm', '5d', '1.5h', '05m', ''])('rejects %p', (input) => {
15
+ expect((0, timer_input_1.parseDuration)(input).ok).toBe(false);
16
+ });
17
+ it('rejects durations longer than a year', () => {
18
+ expect((0, timer_input_1.parseDuration)('9000h').ok).toBe(false);
19
+ });
20
+ });
21
+ describe('parseMaxIterations', () => {
22
+ it('accepts positive whole numbers', () => {
23
+ expect((0, timer_input_1.parseMaxIterations)(5)).toEqual({ ok: true, value: 5 });
24
+ });
25
+ it('accepts up to 10', () => {
26
+ expect((0, timer_input_1.parseMaxIterations)(10)).toEqual({ ok: true, value: 10 });
27
+ });
28
+ it.each([0, -1, 1.5, '5', undefined, 11])('rejects %p', (input) => {
29
+ expect((0, timer_input_1.parseMaxIterations)(input).ok).toBe(false);
30
+ });
31
+ });
32
+ describe('describeDuration', () => {
33
+ it.each([
34
+ [300, '5 minutes'],
35
+ [3600, '1 hour'],
36
+ [90, '90 seconds'],
37
+ [5400, '90 minutes'],
38
+ ])('describes %p seconds as %p', (seconds, text) => {
39
+ expect((0, timer_input_1.describeDuration)(seconds)).toBe(text);
40
+ });
41
+ });
42
+ describe('parseInstant', () => {
43
+ const iso = (at, timezone) => {
44
+ const result = (0, timer_input_1.parseInstant)(at, timezone);
45
+ return result.ok ? result.value.toISOString() : result.error;
46
+ };
47
+ it('reads UTC and offset timestamps', () => {
48
+ expect(iso('2026-10-15T12:00:00Z')).toBe('2026-10-15T12:00:00.000Z');
49
+ expect(iso('2026-10-15T12:00:00+11:00')).toBe('2026-10-15T01:00:00.000Z');
50
+ expect(iso('2026-10-15T12:00-03:30')).toBe('2026-10-15T15:30:00.000Z');
51
+ });
52
+ it('reads a local time in a timezone', () => {
53
+ expect(iso('2026-10-15T12:00:00', 'Australia/Sydney')).toBe('2026-10-15T01:00:00.000Z');
54
+ expect(iso('2026-07-15T12:00:00', 'Australia/Sydney')).toBe('2026-07-15T02:00:00.000Z');
55
+ });
56
+ it('accepts an offset that agrees with the timezone', () => {
57
+ expect(iso('2026-10-15T12:00:00+11:00', 'Australia/Sydney')).toBe('2026-10-15T01:00:00.000Z');
58
+ });
59
+ it('rejects an offset that conflicts with the timezone', () => {
60
+ expect((0, timer_input_1.parseInstant)('2026-10-15T12:00:00+10:00', 'Australia/Sydney').ok).toBe(false);
61
+ });
62
+ it('rejects a local time with no timezone', () => {
63
+ expect((0, timer_input_1.parseInstant)('2026-10-15T12:00:00').ok).toBe(false);
64
+ });
65
+ it('rejects a local time that daylight saving skips', () => {
66
+ const result = (0, timer_input_1.parseInstant)('2026-10-04T02:30:00', 'Australia/Sydney');
67
+ expect(result.ok).toBe(false);
68
+ expect(!result.ok && result.error).toContain('does not exist');
69
+ });
70
+ it('rejects a local time that daylight saving repeats', () => {
71
+ const result = (0, timer_input_1.parseInstant)('2026-04-05T02:30:00', 'Australia/Sydney');
72
+ expect(result.ok).toBe(false);
73
+ expect(!result.ok && result.error).toContain('happens twice');
74
+ });
75
+ it('accepts the extreme real offsets', () => {
76
+ expect(iso('2026-10-15T12:00:00+14:00')).toBe('2026-10-14T22:00:00.000Z');
77
+ expect(iso('2026-10-15T12:00:00-12:00')).toBe('2026-10-16T00:00:00.000Z');
78
+ expect(iso('2026-10-15T12:00:00+05:45')).toBe('2026-10-15T06:15:00.000Z');
79
+ });
80
+ it.each(['+24:00', '+11:60', '-13:00', '+14:01', '+99:99'])('rejects the invalid offset %p', (offset) => {
81
+ const result = (0, timer_input_1.parseInstant)(`2026-10-15T12:00:00${offset}`);
82
+ expect(result.ok).toBe(false);
83
+ expect(!result.ok && result.error).toContain('not a real UTC offset');
84
+ });
85
+ it('rejects unknown timezones, impossible dates and other formats', () => {
86
+ expect((0, timer_input_1.parseInstant)('2026-10-15T12:00:00', 'Mars/Olympus').ok).toBe(false);
87
+ expect((0, timer_input_1.parseInstant)('2026-02-30T12:00:00Z').ok).toBe(false);
88
+ expect((0, timer_input_1.parseInstant)('tomorrow at noon').ok).toBe(false);
89
+ });
90
+ });
91
+ });
92
+ //# sourceMappingURL=timer-input.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer-input.spec.js","sourceRoot":"","sources":["../../../src/threads/timers/timer-input.spec.ts"],"names":[],"mappings":"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"}