@nhtio/adk 0.1.0-master-f0aa531d
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.
- package/LICENSE.md +9 -0
- package/README.md +3 -0
- package/batteries/index.d.ts +28 -0
- package/batteries/llm/index.d.ts +11 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs +916 -0
- package/batteries/llm/openai_chat_completions/adapter.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/adapter.d.ts +101 -0
- package/batteries/llm/openai_chat_completions/adapter.mjs +914 -0
- package/batteries/llm/openai_chat_completions/adapter.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/exceptions.cjs +89 -0
- package/batteries/llm/openai_chat_completions/exceptions.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/exceptions.d.ts +97 -0
- package/batteries/llm/openai_chat_completions/exceptions.mjs +81 -0
- package/batteries/llm/openai_chat_completions/exceptions.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/helpers.cjs +819 -0
- package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/helpers.d.ts +233 -0
- package/batteries/llm/openai_chat_completions/helpers.mjs +783 -0
- package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions/index.d.ts +27 -0
- package/batteries/llm/openai_chat_completions/types.cjs +1 -0
- package/batteries/llm/openai_chat_completions/types.d.ts +524 -0
- package/batteries/llm/openai_chat_completions/types.mjs +0 -0
- package/batteries/llm/openai_chat_completions/validation.cjs +190 -0
- package/batteries/llm/openai_chat_completions/validation.cjs.map +1 -0
- package/batteries/llm/openai_chat_completions/validation.d.ts +31 -0
- package/batteries/llm/openai_chat_completions/validation.mjs +187 -0
- package/batteries/llm/openai_chat_completions/validation.mjs.map +1 -0
- package/batteries/llm/openai_chat_completions.cjs +51 -0
- package/batteries/llm/openai_chat_completions.mjs +5 -0
- package/batteries/llm/webllm_chat_completions/adapter.cjs +658 -0
- package/batteries/llm/webllm_chat_completions/adapter.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/adapter.d.ts +103 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs +656 -0
- package/batteries/llm/webllm_chat_completions/adapter.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/exceptions.cjs +70 -0
- package/batteries/llm/webllm_chat_completions/exceptions.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/exceptions.d.ts +74 -0
- package/batteries/llm/webllm_chat_completions/exceptions.mjs +65 -0
- package/batteries/llm/webllm_chat_completions/exceptions.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/helpers.cjs +38 -0
- package/batteries/llm/webllm_chat_completions/helpers.d.ts +6 -0
- package/batteries/llm/webllm_chat_completions/helpers.mjs +2 -0
- package/batteries/llm/webllm_chat_completions/index.d.ts +25 -0
- package/batteries/llm/webllm_chat_completions/types.d.ts +31 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs +115 -0
- package/batteries/llm/webllm_chat_completions/validation.cjs.map +1 -0
- package/batteries/llm/webllm_chat_completions/validation.d.ts +8 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs +112 -0
- package/batteries/llm/webllm_chat_completions/validation.mjs.map +1 -0
- package/batteries/llm/webllm_chat_completions.cjs +50 -0
- package/batteries/llm/webllm_chat_completions.mjs +6 -0
- package/batteries/llm.cjs +63 -0
- package/batteries/llm.mjs +10 -0
- package/batteries/storage/flydrive/index.d.ts +167 -0
- package/batteries/storage/flydrive.cjs +249 -0
- package/batteries/storage/flydrive.cjs.map +1 -0
- package/batteries/storage/flydrive.mjs +249 -0
- package/batteries/storage/flydrive.mjs.map +1 -0
- package/batteries/storage/in_memory/index.d.ts +106 -0
- package/batteries/storage/in_memory.cjs +121 -0
- package/batteries/storage/in_memory.cjs.map +1 -0
- package/batteries/storage/in_memory.mjs +119 -0
- package/batteries/storage/in_memory.mjs.map +1 -0
- package/batteries/storage/index.d.ts +18 -0
- package/batteries/storage/opfs/index.d.ts +299 -0
- package/batteries/storage/opfs.cjs +368 -0
- package/batteries/storage/opfs.cjs.map +1 -0
- package/batteries/storage/opfs.mjs +366 -0
- package/batteries/storage/opfs.mjs.map +1 -0
- package/batteries/storage.cjs +4 -0
- package/batteries/storage.mjs +2 -0
- package/batteries/tools/color/index.d.ts +37 -0
- package/batteries/tools/color.cjs +659 -0
- package/batteries/tools/color.cjs.map +1 -0
- package/batteries/tools/color.mjs +655 -0
- package/batteries/tools/color.mjs.map +1 -0
- package/batteries/tools/comparison/index.d.ts +29 -0
- package/batteries/tools/comparison.cjs +171 -0
- package/batteries/tools/comparison.cjs.map +1 -0
- package/batteries/tools/comparison.mjs +168 -0
- package/batteries/tools/comparison.mjs.map +1 -0
- package/batteries/tools/data_structure/index.d.ts +30 -0
- package/batteries/tools/data_structure.cjs +270 -0
- package/batteries/tools/data_structure.cjs.map +1 -0
- package/batteries/tools/data_structure.mjs +267 -0
- package/batteries/tools/data_structure.mjs.map +1 -0
- package/batteries/tools/datetime_extended/index.d.ts +51 -0
- package/batteries/tools/datetime_extended.cjs +309 -0
- package/batteries/tools/datetime_extended.cjs.map +1 -0
- package/batteries/tools/datetime_extended.mjs +302 -0
- package/batteries/tools/datetime_extended.mjs.map +1 -0
- package/batteries/tools/datetime_math/index.d.ts +36 -0
- package/batteries/tools/datetime_math.cjs +175 -0
- package/batteries/tools/datetime_math.cjs.map +1 -0
- package/batteries/tools/datetime_math.mjs +171 -0
- package/batteries/tools/datetime_math.mjs.map +1 -0
- package/batteries/tools/encoding/index.d.ts +36 -0
- package/batteries/tools/encoding.cjs +156 -0
- package/batteries/tools/encoding.cjs.map +1 -0
- package/batteries/tools/encoding.mjs +152 -0
- package/batteries/tools/encoding.mjs.map +1 -0
- package/batteries/tools/formatting/index.d.ts +28 -0
- package/batteries/tools/formatting.cjs +120 -0
- package/batteries/tools/formatting.cjs.map +1 -0
- package/batteries/tools/formatting.mjs +117 -0
- package/batteries/tools/formatting.mjs.map +1 -0
- package/batteries/tools/geo_basics/index.d.ts +33 -0
- package/batteries/tools/geo_basics.cjs +136 -0
- package/batteries/tools/geo_basics.cjs.map +1 -0
- package/batteries/tools/geo_basics.mjs +132 -0
- package/batteries/tools/geo_basics.mjs.map +1 -0
- package/batteries/tools/index.d.ts +32 -0
- package/batteries/tools/math/index.d.ts +37 -0
- package/batteries/tools/math.cjs +136 -0
- package/batteries/tools/math.cjs.map +1 -0
- package/batteries/tools/math.mjs +133 -0
- package/batteries/tools/math.mjs.map +1 -0
- package/batteries/tools/memory/index.d.ts +73 -0
- package/batteries/tools/memory.cjs +193 -0
- package/batteries/tools/memory.cjs.map +1 -0
- package/batteries/tools/memory.mjs +187 -0
- package/batteries/tools/memory.mjs.map +1 -0
- package/batteries/tools/parsing/index.d.ts +47 -0
- package/batteries/tools/parsing.cjs +191 -0
- package/batteries/tools/parsing.cjs.map +1 -0
- package/batteries/tools/parsing.mjs +185 -0
- package/batteries/tools/parsing.mjs.map +1 -0
- package/batteries/tools/retrievables/index.d.ts +81 -0
- package/batteries/tools/retrievables.cjs +215 -0
- package/batteries/tools/retrievables.cjs.map +1 -0
- package/batteries/tools/retrievables.mjs +209 -0
- package/batteries/tools/retrievables.mjs.map +1 -0
- package/batteries/tools/standing_instructions/index.d.ts +64 -0
- package/batteries/tools/standing_instructions.cjs +126 -0
- package/batteries/tools/standing_instructions.cjs.map +1 -0
- package/batteries/tools/standing_instructions.mjs +121 -0
- package/batteries/tools/standing_instructions.mjs.map +1 -0
- package/batteries/tools/statistics/index.d.ts +46 -0
- package/batteries/tools/statistics.cjs +253 -0
- package/batteries/tools/statistics.cjs.map +1 -0
- package/batteries/tools/statistics.mjs +248 -0
- package/batteries/tools/statistics.mjs.map +1 -0
- package/batteries/tools/string_processing/index.d.ts +29 -0
- package/batteries/tools/string_processing.cjs +154 -0
- package/batteries/tools/string_processing.cjs.map +1 -0
- package/batteries/tools/string_processing.mjs +151 -0
- package/batteries/tools/string_processing.mjs.map +1 -0
- package/batteries/tools/structured_data/index.d.ts +34 -0
- package/batteries/tools/structured_data.cjs +189 -0
- package/batteries/tools/structured_data.cjs.map +1 -0
- package/batteries/tools/structured_data.mjs +185 -0
- package/batteries/tools/structured_data.mjs.map +1 -0
- package/batteries/tools/text_analysis/index.d.ts +31 -0
- package/batteries/tools/text_analysis.cjs +120 -0
- package/batteries/tools/text_analysis.cjs.map +1 -0
- package/batteries/tools/text_analysis.mjs +117 -0
- package/batteries/tools/text_analysis.mjs.map +1 -0
- package/batteries/tools/text_comparison/index.d.ts +28 -0
- package/batteries/tools/text_comparison.cjs +96 -0
- package/batteries/tools/text_comparison.cjs.map +1 -0
- package/batteries/tools/text_comparison.mjs +93 -0
- package/batteries/tools/text_comparison.mjs.map +1 -0
- package/batteries/tools/time/index.d.ts +27 -0
- package/batteries/tools/time.cjs +63 -0
- package/batteries/tools/time.cjs.map +1 -0
- package/batteries/tools/time.mjs +60 -0
- package/batteries/tools/time.mjs.map +1 -0
- package/batteries/tools/unit_conversion/index.d.ts +19 -0
- package/batteries/tools/unit_conversion.cjs +452 -0
- package/batteries/tools/unit_conversion.cjs.map +1 -0
- package/batteries/tools/unit_conversion.mjs +450 -0
- package/batteries/tools/unit_conversion.mjs.map +1 -0
- package/batteries/tools.cjs +80 -0
- package/batteries/tools.mjs +21 -0
- package/batteries.cjs +142 -0
- package/batteries.mjs +30 -0
- package/chunk-KmRHZBOW.js +35 -0
- package/common-DeZaonK1.mjs +208 -0
- package/common-DeZaonK1.mjs.map +1 -0
- package/common-Od8edUXU.js +232 -0
- package/common-Od8edUXU.js.map +1 -0
- package/common.cjs +31 -0
- package/common.d.ts +108 -0
- package/common.mjs +8 -0
- package/dispatch_runner-9j6bXHL3.mjs +1609 -0
- package/dispatch_runner-9j6bXHL3.mjs.map +1 -0
- package/dispatch_runner-CsoH0nld.js +1627 -0
- package/dispatch_runner-CsoH0nld.js.map +1 -0
- package/dispatch_runner.cjs +3 -0
- package/dispatch_runner.d.ts +17 -0
- package/dispatch_runner.mjs +2 -0
- package/exceptions-D5YrO9Vm.js +280 -0
- package/exceptions-D5YrO9Vm.js.map +1 -0
- package/exceptions-NrzIHw_R.mjs +244 -0
- package/exceptions-NrzIHw_R.mjs.map +1 -0
- package/exceptions.cjs +33 -0
- package/exceptions.d.ts +52 -0
- package/exceptions.mjs +3 -0
- package/factories.cjs +4 -0
- package/factories.d.ts +39 -0
- package/factories.mjs +2 -0
- package/forge.cjs +9 -0
- package/forge.d.ts +49 -0
- package/forge.mjs +5 -0
- package/guards.cjs +96 -0
- package/guards.cjs.map +1 -0
- package/guards.d.ts +83 -0
- package/guards.mjs +72 -0
- package/guards.mjs.map +1 -0
- package/index.cjs +107 -0
- package/index.cjs.map +1 -0
- package/index.d.ts +18 -0
- package/index.mjs +31 -0
- package/index.mjs.map +1 -0
- package/lib/classes/artifact_tool.d.ts +129 -0
- package/lib/classes/base_exception.d.ts +83 -0
- package/lib/classes/identity.d.ts +71 -0
- package/lib/classes/media.d.ts +326 -0
- package/lib/classes/memory.d.ts +72 -0
- package/lib/classes/message.d.ts +137 -0
- package/lib/classes/registry.d.ts +79 -0
- package/lib/classes/retrievable.d.ts +100 -0
- package/lib/classes/spooled_artifact.d.ts +296 -0
- package/lib/classes/spooled_json_artifact.d.ts +158 -0
- package/lib/classes/spooled_markdown_artifact.d.ts +202 -0
- package/lib/classes/thought.d.ts +142 -0
- package/lib/classes/tokenizable.d.ts +124 -0
- package/lib/classes/tool.d.ts +228 -0
- package/lib/classes/tool_call.d.ts +190 -0
- package/lib/classes/tool_registry.d.ts +159 -0
- package/lib/classes/turn_gate.d.ts +109 -0
- package/lib/contracts/dispatch_context.d.ts +345 -0
- package/lib/contracts/media_reader.d.ts +60 -0
- package/lib/contracts/spool_reader.d.ts +80 -0
- package/lib/contracts/spooled_artifact_constructor.d.ts +38 -0
- package/lib/contracts/turn_runner_config.d.ts +101 -0
- package/lib/contracts/turn_runner_context.d.ts +267 -0
- package/lib/dispatch_runner.d.ts +98 -0
- package/lib/exceptions/runtime.d.ts +370 -0
- package/lib/helpers/media_readers.d.ts +39 -0
- package/lib/turn_runner.d.ts +144 -0
- package/lib/types/dispatch_context.d.ts +233 -0
- package/lib/types/dispatch_runner.d.ts +387 -0
- package/lib/types/turn_runner.d.ts +322 -0
- package/lib/utils/canonical_json.d.ts +18 -0
- package/lib/utils/exceptions.d.ts +78 -0
- package/lib/utils/guards.d.ts +32 -0
- package/lib/utils/validation.d.ts +77 -0
- package/package.json +334 -0
- package/runtime-BJVkrGQe.js +519 -0
- package/runtime-BJVkrGQe.js.map +1 -0
- package/runtime-CrEPIFgr.mjs +346 -0
- package/runtime-CrEPIFgr.mjs.map +1 -0
- package/skills/adk-assembly/SKILL.md +109 -0
- package/skills/adk-assembly/references/assembly-contract.md +66 -0
- package/skills/adk-assembly/references/executors-tools-pipelines-events.md +113 -0
- package/skills/adk-assembly/references/first-integration.md +93 -0
- package/skills/adk-assembly/references/storage-and-context.md +102 -0
- package/spooled_artifact-C5ZtGxuJ.mjs +544 -0
- package/spooled_artifact-C5ZtGxuJ.mjs.map +1 -0
- package/spooled_artifact-Cm9Te22K.js +568 -0
- package/spooled_artifact-Cm9Te22K.js.map +1 -0
- package/spooled_artifact.cjs +7 -0
- package/spooled_artifact.d.ts +40 -0
- package/spooled_artifact.mjs +3 -0
- package/spooled_markdown_artifact-BpUJol0W.mjs +771 -0
- package/spooled_markdown_artifact-BpUJol0W.mjs.map +1 -0
- package/spooled_markdown_artifact-RRB113sy.js +786 -0
- package/spooled_markdown_artifact-RRB113sy.js.map +1 -0
- package/thought-CDb457b4.mjs +470 -0
- package/thought-CDb457b4.mjs.map +1 -0
- package/thought-DuN2PgdO.js +494 -0
- package/thought-DuN2PgdO.js.map +1 -0
- package/tool-COSeH8I6.js +302 -0
- package/tool-COSeH8I6.js.map +1 -0
- package/tool-D2WB1EA1.mjs +296 -0
- package/tool-D2WB1EA1.mjs.map +1 -0
- package/tool_call-BKyyxGaZ.mjs +578 -0
- package/tool_call-BKyyxGaZ.mjs.map +1 -0
- package/tool_call-DFgzcVcU.js +608 -0
- package/tool_call-DFgzcVcU.js.map +1 -0
- package/tool_registry-Dkfprsck.js +641 -0
- package/tool_registry-Dkfprsck.js.map +1 -0
- package/tool_registry-DqLOyGyG.mjs +592 -0
- package/tool_registry-DqLOyGyG.mjs.map +1 -0
- package/turn_runner-CMm2BHdX.js +615 -0
- package/turn_runner-CMm2BHdX.js.map +1 -0
- package/turn_runner-y7eyEcJH.mjs +603 -0
- package/turn_runner-y7eyEcJH.mjs.map +1 -0
- package/turn_runner.cjs +3 -0
- package/turn_runner.d.ts +21 -0
- package/turn_runner.mjs +2 -0
- package/types.cjs +1 -0
- package/types.d.ts +56 -0
- package/types.mjs +0 -0
- package/vite-env.d.ts +23 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import "../../common-DeZaonK1.mjs";
|
|
2
|
+
import { t as Tool } from "../../tool-D2WB1EA1.mjs";
|
|
3
|
+
import { validator } from "@nhtio/validation";
|
|
4
|
+
import { DateTime, IANAZone } from "luxon";
|
|
5
|
+
import * as chrono from "chrono-node";
|
|
6
|
+
//#region src/batteries/tools/datetime_extended/index.ts
|
|
7
|
+
/**
|
|
8
|
+
* Pre-constructed tools for parsing natural-language dates and business-calendar calculations.
|
|
9
|
+
*
|
|
10
|
+
* @module @nhtio/adk/batteries/tools/datetime_extended
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* Pre-constructed bundled tools for the `datetime_extended` category. Import individually, the whole
|
|
14
|
+
* category, or import every tool via `@nhtio/adk/batteries`.
|
|
15
|
+
*/
|
|
16
|
+
function resolveZone(timezone) {
|
|
17
|
+
if (!timezone) return { zone: "UTC" };
|
|
18
|
+
if (!IANAZone.isValidZone(timezone)) return {
|
|
19
|
+
zone: "",
|
|
20
|
+
error: `Invalid timezone "${timezone}".`
|
|
21
|
+
};
|
|
22
|
+
return { zone: timezone };
|
|
23
|
+
}
|
|
24
|
+
function countBusinessDays(from, to) {
|
|
25
|
+
const forward = to >= from;
|
|
26
|
+
const start = forward ? from.startOf("day") : to.startOf("day");
|
|
27
|
+
const end = forward ? to.startOf("day") : from.startOf("day");
|
|
28
|
+
const totalDays = Math.round(end.diff(start, "days").days);
|
|
29
|
+
const fullWeeks = Math.floor(totalDays / 7);
|
|
30
|
+
let bdays = fullWeeks * 5;
|
|
31
|
+
let cursor = start.plus({ days: fullWeeks * 7 });
|
|
32
|
+
while (cursor < end) {
|
|
33
|
+
cursor = cursor.plus({ days: 1 });
|
|
34
|
+
if (cursor.weekday <= 5) bdays++;
|
|
35
|
+
}
|
|
36
|
+
return forward ? bdays : -bdays;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Find the Nth occurrence of a weekday in a given month.
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* Examples: "2nd Friday of March 2026", "last Monday of January 2025". Accepts 1st–5th and
|
|
43
|
+
* `last`. Returns an error if the month does not contain that many occurrences of the weekday.
|
|
44
|
+
*/
|
|
45
|
+
var dateNthWeekdayTool = new Tool({
|
|
46
|
+
name: "date_nth_weekday",
|
|
47
|
+
description: "Find the Nth occurrence of a weekday in a given month (e.g., \"2nd Friday of March 2026\", \"last Monday of next month\"). Supports 1st–5th and \"last\".",
|
|
48
|
+
inputSchema: validator.object({
|
|
49
|
+
nth: validator.string().required().description("Which occurrence: \"1st\", \"2nd\", \"3rd\", \"4th\", \"5th\", or \"last\"."),
|
|
50
|
+
weekday: validator.string().valid("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday").required().description("Day of the week."),
|
|
51
|
+
month: validator.number().required().description("Month number (1–12)."),
|
|
52
|
+
year: validator.number().optional().description("Year (defaults to current year)."),
|
|
53
|
+
timezone: validator.string().optional().description("IANA timezone (optional, defaults UTC).")
|
|
54
|
+
}),
|
|
55
|
+
handler: async (args) => {
|
|
56
|
+
const { nth, weekday, month: rawMonth, year: rawYear, timezone } = args;
|
|
57
|
+
const { zone, error: zoneError } = resolveZone(timezone);
|
|
58
|
+
if (zoneError) return `Error: ${zoneError}`;
|
|
59
|
+
const targetWeekday = {
|
|
60
|
+
monday: 1,
|
|
61
|
+
tuesday: 2,
|
|
62
|
+
wednesday: 3,
|
|
63
|
+
thursday: 4,
|
|
64
|
+
friday: 5,
|
|
65
|
+
saturday: 6,
|
|
66
|
+
sunday: 7
|
|
67
|
+
}[weekday.toLowerCase()];
|
|
68
|
+
const month = Math.floor(rawMonth);
|
|
69
|
+
if (month < 1 || month > 12) return `Error: Month must be 1–12, got ${rawMonth}.`;
|
|
70
|
+
const year = Math.floor(rawYear ?? DateTime.now().setZone(zone).year);
|
|
71
|
+
const nthRaw = nth.toLowerCase().replace(/\s/g, "");
|
|
72
|
+
const firstOfMonth = DateTime.fromObject({
|
|
73
|
+
year,
|
|
74
|
+
month,
|
|
75
|
+
day: 1
|
|
76
|
+
}, { zone });
|
|
77
|
+
if (!firstOfMonth.isValid) return `Error: Invalid date for ${year}-${month}.`;
|
|
78
|
+
const occurrences = [];
|
|
79
|
+
let cursor = firstOfMonth;
|
|
80
|
+
while (cursor.weekday !== targetWeekday) cursor = cursor.plus({ days: 1 });
|
|
81
|
+
while (cursor.month === month) {
|
|
82
|
+
occurrences.push(cursor);
|
|
83
|
+
cursor = cursor.plus({ weeks: 1 });
|
|
84
|
+
}
|
|
85
|
+
let result;
|
|
86
|
+
if (nthRaw === "last") result = occurrences[occurrences.length - 1];
|
|
87
|
+
else {
|
|
88
|
+
const n = {
|
|
89
|
+
"1st": 1,
|
|
90
|
+
"1": 1,
|
|
91
|
+
"first": 1,
|
|
92
|
+
"2nd": 2,
|
|
93
|
+
"2": 2,
|
|
94
|
+
"second": 2,
|
|
95
|
+
"3rd": 3,
|
|
96
|
+
"3": 3,
|
|
97
|
+
"third": 3,
|
|
98
|
+
"4th": 4,
|
|
99
|
+
"4": 4,
|
|
100
|
+
"fourth": 4,
|
|
101
|
+
"5th": 5,
|
|
102
|
+
"5": 5,
|
|
103
|
+
"fifth": 5
|
|
104
|
+
}[nthRaw];
|
|
105
|
+
if (!n) return `Error: Invalid nth value "${nth}". Use 1st–5th or "last".`;
|
|
106
|
+
if (n > occurrences.length) return `Error: There is no ${nth} ${weekday} in ${firstOfMonth.toFormat("LLLL yyyy")} (only ${occurrences.length} occurrence${occurrences.length !== 1 ? "s" : ""}).`;
|
|
107
|
+
result = occurrences[n - 1];
|
|
108
|
+
}
|
|
109
|
+
if (!result) return "Error: Could not compute the date.";
|
|
110
|
+
return `${nth} ${weekday} of ${result.toFormat("LLLL yyyy")}: ${result.toISODate()}\nFormatted: ${result.toFormat("cccc, LLLL d, yyyy")}`;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
/**
|
|
114
|
+
* Get calendar metadata for a date.
|
|
115
|
+
*
|
|
116
|
+
* @remarks
|
|
117
|
+
* Reports ISO week number, day of year, calendar quarter, fiscal quarter/year (configurable via
|
|
118
|
+
* `fiscal_year_start_month`), week of month, and whether the date is a weekend. Accepts ISO
|
|
119
|
+
* dates, natural-language ("next Tuesday"), and `now`.
|
|
120
|
+
*/
|
|
121
|
+
var dateCalendarInfoTool = new Tool({
|
|
122
|
+
name: "date_calendar_info",
|
|
123
|
+
description: "Get calendar metadata for a date: ISO week number, day of year, calendar quarter, fiscal quarter/year, week of month, and whether it is a weekend or weekday.",
|
|
124
|
+
inputSchema: validator.object({
|
|
125
|
+
date: validator.string().required().description("ISO 8601 date, natural language date, or \"now\"."),
|
|
126
|
+
timezone: validator.string().optional().description("IANA timezone (optional, defaults UTC)."),
|
|
127
|
+
fiscal_year_start_month: validator.number().default(1).description("Month when fiscal year starts (1–12, default: 1 = calendar year).")
|
|
128
|
+
}),
|
|
129
|
+
handler: async (args) => {
|
|
130
|
+
const { date: dateStr, timezone, fiscal_year_start_month: rawFyStart } = args;
|
|
131
|
+
const { zone, error: zoneError } = resolveZone(timezone);
|
|
132
|
+
if (zoneError) return `Error: ${zoneError}`;
|
|
133
|
+
let dt;
|
|
134
|
+
if (dateStr.toLowerCase() === "now") dt = DateTime.now().setZone(zone);
|
|
135
|
+
else {
|
|
136
|
+
dt = DateTime.fromISO(dateStr, { zone });
|
|
137
|
+
if (!dt.isValid) {
|
|
138
|
+
const parsed = chrono.parseDate(dateStr, /* @__PURE__ */ new Date());
|
|
139
|
+
if (!parsed) return `Error: Could not parse date "${dateStr}".`;
|
|
140
|
+
dt = DateTime.fromJSDate(parsed).setZone(zone);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)));
|
|
144
|
+
const calendarQuarter = Math.ceil(dt.month / 3);
|
|
145
|
+
const monthInFY = (dt.month - fyStart + 12) % 12;
|
|
146
|
+
const fiscalQuarter = Math.floor(monthInFY / 3) + 1;
|
|
147
|
+
const fiscalYear = dt.month >= fyStart ? dt.year : dt.year - 1;
|
|
148
|
+
const firstOfMonth = dt.startOf("month");
|
|
149
|
+
const weekOfMonth = Math.ceil((dt.day + firstOfMonth.weekday - 1) / 7);
|
|
150
|
+
const dayOfYear = Math.floor(dt.diff(dt.startOf("year"), "days").days) + 1;
|
|
151
|
+
const isWeekend = dt.weekday >= 6;
|
|
152
|
+
return [
|
|
153
|
+
`Date: ${dt.toISODate()} (${dt.toFormat("cccc, LLLL d, yyyy")})`,
|
|
154
|
+
"",
|
|
155
|
+
`ISO week number: ${dt.weekNumber} (ISO year: ${dt.weekYear})`,
|
|
156
|
+
`Day of year: ${dayOfYear} / ${dt.daysInYear}`,
|
|
157
|
+
`Day of week: ${dt.weekday} (${dt.toFormat("cccc")})`,
|
|
158
|
+
`Week of month: ${weekOfMonth}`,
|
|
159
|
+
`Weekend: ${isWeekend ? "Yes" : "No"}`,
|
|
160
|
+
"",
|
|
161
|
+
`Calendar quarter: Q${calendarQuarter}`,
|
|
162
|
+
`Fiscal quarter: FQ${fiscalQuarter} (FY${fiscalYear}${fyStart !== 1 ? `, starts month ${fyStart}` : ""})`
|
|
163
|
+
].join("\n");
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
/**
|
|
167
|
+
* Parse a date/time expression from natural language or common formats.
|
|
168
|
+
*
|
|
169
|
+
* @remarks
|
|
170
|
+
* Examples: `"next Monday"`, `"March 5th"`, `"in 2 weeks"`, `"yesterday"`. Uses chrono-node for
|
|
171
|
+
* relative parsing. `reference_date` overrides the "now" anchor.
|
|
172
|
+
*/
|
|
173
|
+
var dateParseTool = new Tool({
|
|
174
|
+
name: "date_parse",
|
|
175
|
+
description: "Parse a date/time string from natural language or common formats (\"next Monday\", \"March 5th\", \"in 2 weeks\", \"yesterday\"). Returns an ISO 8601 date.",
|
|
176
|
+
inputSchema: validator.object({
|
|
177
|
+
text: validator.string().required().description("Date/time expression to parse (natural language or structured)"),
|
|
178
|
+
reference_date: validator.string().optional().description("ISO date to treat as \"now\" for relative expressions (default: current time)"),
|
|
179
|
+
timezone: validator.string().optional().description("IANA timezone for the result (optional, defaults UTC)")
|
|
180
|
+
}),
|
|
181
|
+
handler: async (args) => {
|
|
182
|
+
const { text, reference_date: referenceDate, timezone } = args;
|
|
183
|
+
const { zone, error: zoneError } = resolveZone(timezone);
|
|
184
|
+
if (zoneError) return `Error: ${zoneError}`;
|
|
185
|
+
let refDate = /* @__PURE__ */ new Date();
|
|
186
|
+
if (referenceDate) {
|
|
187
|
+
refDate = new Date(referenceDate);
|
|
188
|
+
if (Number.isNaN(refDate.getTime())) return `Error: Invalid reference_date "${referenceDate}".`;
|
|
189
|
+
}
|
|
190
|
+
const parsed = chrono.parseDate(text, refDate);
|
|
191
|
+
if (!parsed) return `Error: Could not parse a date from "${text}".`;
|
|
192
|
+
const dt = DateTime.fromJSDate(parsed).setZone(zone);
|
|
193
|
+
return `ISO: ${dt.toISO()}\nFormatted: ${dt.toFormat("cccc, LLLL d, yyyy h:mm a ZZZZ")}`;
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
/**
|
|
197
|
+
* Get the start or end of a time period containing a given date.
|
|
198
|
+
*
|
|
199
|
+
* @remarks
|
|
200
|
+
* Periods: `day`, `week`, `isoweek` (Monday-start), `month`, `quarter`, `year`. Quarter and year
|
|
201
|
+
* honour `fiscal_year_start_month` for fiscal calendars (default: 1 = calendar year).
|
|
202
|
+
*/
|
|
203
|
+
var datePeriodTool = new Tool({
|
|
204
|
+
name: "date_period",
|
|
205
|
+
description: "Get the start or end of a time period (day, week, month, quarter, year) containing a given date. Supports fiscal year offsets.",
|
|
206
|
+
inputSchema: validator.object({
|
|
207
|
+
date: validator.string().required().description("ISO 8601 date or \"now\""),
|
|
208
|
+
period: validator.string().valid("day", "week", "isoweek", "month", "quarter", "year").required().description("Time period (isoweek = Monday-start week)"),
|
|
209
|
+
boundary: validator.string().valid("start", "end").required().description("\"start\" for the first moment, \"end\" for the last moment of the period"),
|
|
210
|
+
timezone: validator.string().optional().description("IANA timezone (optional, defaults UTC)"),
|
|
211
|
+
fiscal_year_start_month: validator.number().default(1).description("For quarter/year: month number when the fiscal year starts (1–12, default: 1 = calendar year)")
|
|
212
|
+
}),
|
|
213
|
+
handler: async (args) => {
|
|
214
|
+
const { date: dateStr, period, boundary, timezone, fiscal_year_start_month: rawFyStart } = args;
|
|
215
|
+
const { zone, error: zoneError } = resolveZone(timezone);
|
|
216
|
+
if (zoneError) return `Error: ${zoneError}`;
|
|
217
|
+
const dt = dateStr.toLowerCase() === "now" ? DateTime.now().setZone(zone) : DateTime.fromISO(dateStr, { zone });
|
|
218
|
+
if (!dt.isValid) return `Error: Invalid date "${dateStr}".`;
|
|
219
|
+
const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)));
|
|
220
|
+
let result;
|
|
221
|
+
switch (period) {
|
|
222
|
+
case "day":
|
|
223
|
+
result = boundary === "start" ? dt.startOf("day") : dt.endOf("day");
|
|
224
|
+
break;
|
|
225
|
+
case "week":
|
|
226
|
+
result = boundary === "start" ? dt.startOf("week") : dt.endOf("week");
|
|
227
|
+
break;
|
|
228
|
+
case "isoweek":
|
|
229
|
+
result = boundary === "start" ? dt.startOf("week").set({ weekday: 1 }) : dt.startOf("week").set({ weekday: 7 }).endOf("day");
|
|
230
|
+
break;
|
|
231
|
+
case "month":
|
|
232
|
+
result = boundary === "start" ? dt.startOf("month") : dt.endOf("month");
|
|
233
|
+
break;
|
|
234
|
+
case "quarter": {
|
|
235
|
+
const monthInFY = (dt.month - fyStart + 12) % 12;
|
|
236
|
+
const qStartMonth = (Math.floor(monthInFY / 3) * 3 + fyStart - 1) % 12 + 1;
|
|
237
|
+
const qStart = dt.set({
|
|
238
|
+
month: qStartMonth,
|
|
239
|
+
day: 1
|
|
240
|
+
}).startOf("day");
|
|
241
|
+
const adjusted = qStart > dt ? qStart.minus({ months: 3 }) : qStart;
|
|
242
|
+
result = boundary === "start" ? adjusted : adjusted.plus({ months: 3 }).minus({ days: 1 }).endOf("day");
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
case "year":
|
|
246
|
+
if (fyStart === 1) result = boundary === "start" ? dt.startOf("year") : dt.endOf("year");
|
|
247
|
+
else {
|
|
248
|
+
const fyStartThis = dt.set({
|
|
249
|
+
month: fyStart,
|
|
250
|
+
day: 1
|
|
251
|
+
}).startOf("day");
|
|
252
|
+
const fyBase = dt >= fyStartThis ? fyStartThis : fyStartThis.minus({ years: 1 });
|
|
253
|
+
result = boundary === "start" ? fyBase : fyBase.plus({ years: 1 }).minus({ days: 1 }).endOf("day");
|
|
254
|
+
}
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
return `${boundary === "start" ? "Start" : "End"} of ${period} containing ${dateStr}: ${result.toISO()}\nFormatted: ${result.toFormat("cccc, LLLL d, yyyy h:mm:ss a ZZZZ")}`;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
/**
|
|
261
|
+
* Count business days between two dates, or compute the date N business days away.
|
|
262
|
+
*
|
|
263
|
+
* @remarks
|
|
264
|
+
* Monday–Friday only; no holiday calendar awareness. Provide either `to` (count between) or
|
|
265
|
+
* `add_days` (compute target date). Negative `add_days` walks backwards.
|
|
266
|
+
*/
|
|
267
|
+
var dateBusinessDaysTool = new Tool({
|
|
268
|
+
name: "date_business_days",
|
|
269
|
+
description: "Count business days (Mon–Fri, no holiday awareness) between two dates, or calculate the date that is N business days from a start date.",
|
|
270
|
+
inputSchema: validator.object({
|
|
271
|
+
from: validator.string().required().description("Start date (ISO 8601 or \"now\")"),
|
|
272
|
+
to: validator.string().optional().description("End date (ISO 8601 or \"now\") — for counting business days between two dates"),
|
|
273
|
+
add_days: validator.number().optional().description("Instead of \"to\": number of business days to add (negative to subtract)"),
|
|
274
|
+
timezone: validator.string().optional().description("IANA timezone (optional, defaults UTC)")
|
|
275
|
+
}),
|
|
276
|
+
handler: async (args) => {
|
|
277
|
+
const { from: fromStr, to: toStr, add_days: addDays, timezone } = args;
|
|
278
|
+
const { zone, error: zoneError } = resolveZone(timezone);
|
|
279
|
+
if (zoneError) return `Error: ${zoneError}`;
|
|
280
|
+
const fromDt = (fromStr.toLowerCase() === "now" ? DateTime.now() : DateTime.fromISO(fromStr)).setZone(zone);
|
|
281
|
+
if (!fromDt.isValid) return `Error: Invalid from date "${fromStr}".`;
|
|
282
|
+
if (addDays !== void 0) {
|
|
283
|
+
const n = Math.floor(addDays);
|
|
284
|
+
let cursor = fromDt.startOf("day");
|
|
285
|
+
let remaining = Math.abs(n);
|
|
286
|
+
const dir = n >= 0 ? 1 : -1;
|
|
287
|
+
while (remaining > 0) {
|
|
288
|
+
cursor = cursor.plus({ days: dir });
|
|
289
|
+
if (cursor.weekday <= 5) remaining--;
|
|
290
|
+
}
|
|
291
|
+
return `${n >= 0 ? "+" : ""}${n} business day${Math.abs(n) !== 1 ? "s" : ""} from ${fromStr}: ${cursor.toISODate()}\nFormatted: ${cursor.toFormat("cccc, LLLL d, yyyy")}`;
|
|
292
|
+
}
|
|
293
|
+
if (!toStr) return "Error: Provide either \"to\" date or \"add_days\".";
|
|
294
|
+
const toDt = (toStr.toLowerCase() === "now" ? DateTime.now() : DateTime.fromISO(toStr)).setZone(zone);
|
|
295
|
+
if (!toDt.isValid) return `Error: Invalid to date "${toStr}".`;
|
|
296
|
+
return `Business days from ${fromStr} to ${toStr}: ${countBusinessDays(fromDt, toDt)}`;
|
|
297
|
+
}
|
|
298
|
+
});
|
|
299
|
+
//#endregion
|
|
300
|
+
export { dateBusinessDaysTool, dateCalendarInfoTool, dateNthWeekdayTool, dateParseTool, datePeriodTool };
|
|
301
|
+
|
|
302
|
+
//# sourceMappingURL=datetime_extended.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datetime_extended.mjs","names":[],"sources":["../../../src/batteries/tools/datetime_extended/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for parsing natural-language dates and business-calendar calculations.\n *\n * @module @nhtio/adk/batteries/tools/datetime_extended\n *\n * @remarks\n * Pre-constructed bundled tools for the `datetime_extended` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport * as chrono from 'chrono-node'\nimport { Tool } from '@nhtio/adk/common'\nimport { DateTime, IANAZone } from 'luxon'\nimport { validator } from '@nhtio/validation'\n\nfunction resolveZone(timezone: string | undefined): { zone: string; error?: string } {\n if (!timezone) return { zone: 'UTC' }\n if (!IANAZone.isValidZone(timezone)) return { zone: '', error: `Invalid timezone \"${timezone}\".` }\n return { zone: timezone }\n}\n\nfunction countBusinessDays(from: DateTime, to: DateTime): number {\n const forward = to >= from\n const start = forward ? from.startOf('day') : to.startOf('day')\n const end = forward ? to.startOf('day') : from.startOf('day')\n\n const totalDays = Math.round(end.diff(start, 'days').days)\n const fullWeeks = Math.floor(totalDays / 7)\n let bdays = fullWeeks * 5\n\n let cursor = start.plus({ days: fullWeeks * 7 })\n while (cursor < end) {\n cursor = cursor.plus({ days: 1 })\n if (cursor.weekday <= 5) bdays++\n }\n\n return forward ? bdays : -bdays\n}\n\n/**\n * Find the Nth occurrence of a weekday in a given month.\n *\n * @remarks\n * Examples: \"2nd Friday of March 2026\", \"last Monday of January 2025\". Accepts 1st–5th and\n * `last`. Returns an error if the month does not contain that many occurrences of the weekday.\n */\nexport const dateNthWeekdayTool = new Tool({\n name: 'date_nth_weekday',\n description:\n 'Find the Nth occurrence of a weekday in a given month (e.g., \"2nd Friday of March 2026\", \"last Monday of next month\"). Supports 1st–5th and \"last\".',\n inputSchema: validator.object({\n nth: validator\n .string()\n .required()\n .description('Which occurrence: \"1st\", \"2nd\", \"3rd\", \"4th\", \"5th\", or \"last\".'),\n weekday: validator\n .string()\n .valid('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday')\n .required()\n .description('Day of the week.'),\n month: validator.number().required().description('Month number (1–12).'),\n year: validator.number().optional().description('Year (defaults to current year).'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n }),\n handler: async (args) => {\n const {\n nth,\n weekday,\n month: rawMonth,\n year: rawYear,\n timezone,\n } = args as {\n nth: string\n weekday: string\n month: number\n year?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const weekdayNames: Record<string, number> = {\n monday: 1,\n tuesday: 2,\n wednesday: 3,\n thursday: 4,\n friday: 5,\n saturday: 6,\n sunday: 7,\n }\n\n const targetWeekday = weekdayNames[weekday.toLowerCase()]\n const month = Math.floor(rawMonth)\n if (month < 1 || month > 12) return `Error: Month must be 1–12, got ${rawMonth}.`\n\n const year = Math.floor(rawYear ?? DateTime.now().setZone(zone).year)\n const nthRaw = nth.toLowerCase().replace(/\\s/g, '')\n\n const firstOfMonth = DateTime.fromObject({ year, month, day: 1 }, { zone })\n if (!firstOfMonth.isValid) return `Error: Invalid date for ${year}-${month}.`\n\n const occurrences: DateTime[] = []\n let cursor = firstOfMonth\n while (cursor.weekday !== targetWeekday) {\n cursor = cursor.plus({ days: 1 })\n }\n while (cursor.month === month) {\n occurrences.push(cursor)\n cursor = cursor.plus({ weeks: 1 })\n }\n\n let result: DateTime | undefined\n\n if (nthRaw === 'last') {\n result = occurrences[occurrences.length - 1]\n } else {\n const nthMap: Record<string, number> = {\n '1st': 1,\n '1': 1,\n 'first': 1,\n '2nd': 2,\n '2': 2,\n 'second': 2,\n '3rd': 3,\n '3': 3,\n 'third': 3,\n '4th': 4,\n '4': 4,\n 'fourth': 4,\n '5th': 5,\n '5': 5,\n 'fifth': 5,\n }\n const n = nthMap[nthRaw]\n if (!n) return `Error: Invalid nth value \"${nth}\". Use 1st–5th or \"last\".`\n if (n > occurrences.length) {\n return `Error: There is no ${nth} ${weekday} in ${firstOfMonth.toFormat('LLLL yyyy')} (only ${occurrences.length} occurrence${occurrences.length !== 1 ? 's' : ''}).`\n }\n result = occurrences[n - 1]\n }\n\n if (!result) return 'Error: Could not compute the date.'\n\n return `${nth} ${weekday} of ${result.toFormat('LLLL yyyy')}: ${result.toISODate()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy')}`\n },\n})\n\n/**\n * Get calendar metadata for a date.\n *\n * @remarks\n * Reports ISO week number, day of year, calendar quarter, fiscal quarter/year (configurable via\n * `fiscal_year_start_month`), week of month, and whether the date is a weekend. Accepts ISO\n * dates, natural-language (\"next Tuesday\"), and `now`.\n */\nexport const dateCalendarInfoTool = new Tool({\n name: 'date_calendar_info',\n description:\n 'Get calendar metadata for a date: ISO week number, day of year, calendar quarter, fiscal quarter/year, week of month, and whether it is a weekend or weekday.',\n inputSchema: validator.object({\n date: validator\n .string()\n .required()\n .description('ISO 8601 date, natural language date, or \"now\".'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC).'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description('Month when fiscal year starts (1–12, default: 1 = calendar year).'),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let dt: DateTime\n\n if (dateStr.toLowerCase() === 'now') {\n dt = DateTime.now().setZone(zone)\n } else {\n dt = DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) {\n const parsed = chrono.parseDate(dateStr, new Date())\n if (!parsed) return `Error: Could not parse date \"${dateStr}\".`\n dt = DateTime.fromJSDate(parsed).setZone(zone)\n }\n }\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n const calendarQuarter = Math.ceil(dt.month / 3)\n\n const monthInFY = (dt.month - fyStart + 12) % 12\n const fiscalQuarter = Math.floor(monthInFY / 3) + 1\n const fiscalYear = dt.month >= fyStart ? dt.year : dt.year - 1\n\n const firstOfMonth = dt.startOf('month')\n const weekOfMonth = Math.ceil((dt.day + firstOfMonth.weekday - 1) / 7)\n\n const dayOfYear = Math.floor(dt.diff(dt.startOf('year'), 'days').days) + 1\n\n const isWeekend = dt.weekday >= 6\n\n const lines = [\n `Date: ${dt.toISODate()} (${dt.toFormat('cccc, LLLL d, yyyy')})`,\n '',\n `ISO week number: ${dt.weekNumber} (ISO year: ${dt.weekYear})`,\n `Day of year: ${dayOfYear} / ${dt.daysInYear}`,\n `Day of week: ${dt.weekday} (${dt.toFormat('cccc')})`,\n `Week of month: ${weekOfMonth}`,\n `Weekend: ${isWeekend ? 'Yes' : 'No'}`,\n '',\n `Calendar quarter: Q${calendarQuarter}`,\n `Fiscal quarter: FQ${fiscalQuarter} (FY${fiscalYear}${fyStart !== 1 ? `, starts month ${fyStart}` : ''})`,\n ]\n\n return lines.join('\\n')\n },\n})\n\n/**\n * Parse a date/time expression from natural language or common formats.\n *\n * @remarks\n * Examples: `\"next Monday\"`, `\"March 5th\"`, `\"in 2 weeks\"`, `\"yesterday\"`. Uses chrono-node for\n * relative parsing. `reference_date` overrides the \"now\" anchor.\n */\nexport const dateParseTool = new Tool({\n name: 'date_parse',\n description:\n 'Parse a date/time string from natural language or common formats (\"next Monday\", \"March 5th\", \"in 2 weeks\", \"yesterday\"). Returns an ISO 8601 date.',\n inputSchema: validator.object({\n text: validator\n .string()\n .required()\n .description('Date/time expression to parse (natural language or structured)'),\n reference_date: validator\n .string()\n .optional()\n .description('ISO date to treat as \"now\" for relative expressions (default: current time)'),\n timezone: validator\n .string()\n .optional()\n .description('IANA timezone for the result (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n text,\n reference_date: referenceDate,\n timezone,\n } = args as {\n text: string\n reference_date?: string\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n let refDate = new Date()\n if (referenceDate) {\n refDate = new Date(referenceDate)\n if (Number.isNaN(refDate.getTime()))\n return `Error: Invalid reference_date \"${referenceDate}\".`\n }\n\n const parsed = chrono.parseDate(text, refDate)\n if (!parsed) return `Error: Could not parse a date from \"${text}\".`\n\n const dt = DateTime.fromJSDate(parsed).setZone(zone)\n return `ISO: ${dt.toISO()}\\nFormatted: ${dt.toFormat('cccc, LLLL d, yyyy h:mm a ZZZZ')}`\n },\n})\n\n/**\n * Get the start or end of a time period containing a given date.\n *\n * @remarks\n * Periods: `day`, `week`, `isoweek` (Monday-start), `month`, `quarter`, `year`. Quarter and year\n * honour `fiscal_year_start_month` for fiscal calendars (default: 1 = calendar year).\n */\nexport const datePeriodTool = new Tool({\n name: 'date_period',\n description:\n 'Get the start or end of a time period (day, week, month, quarter, year) containing a given date. Supports fiscal year offsets.',\n inputSchema: validator.object({\n date: validator.string().required().description('ISO 8601 date or \"now\"'),\n period: validator\n .string()\n .valid('day', 'week', 'isoweek', 'month', 'quarter', 'year')\n .required()\n .description('Time period (isoweek = Monday-start week)'),\n boundary: validator\n .string()\n .valid('start', 'end')\n .required()\n .description('\"start\" for the first moment, \"end\" for the last moment of the period'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n fiscal_year_start_month: validator\n .number()\n .default(1)\n .description(\n 'For quarter/year: month number when the fiscal year starts (1–12, default: 1 = calendar year)'\n ),\n }),\n handler: async (args) => {\n const {\n date: dateStr,\n period,\n boundary,\n timezone,\n fiscal_year_start_month: rawFyStart,\n } = args as {\n date: string\n period: 'day' | 'week' | 'isoweek' | 'month' | 'quarter' | 'year'\n boundary: 'start' | 'end'\n timezone?: string\n fiscal_year_start_month: number\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const dt =\n dateStr.toLowerCase() === 'now'\n ? DateTime.now().setZone(zone)\n : DateTime.fromISO(dateStr, { zone })\n if (!dt.isValid) return `Error: Invalid date \"${dateStr}\".`\n\n const fyStart = Math.max(1, Math.min(12, Math.floor(rawFyStart)))\n\n let result: DateTime\n\n switch (period) {\n case 'day':\n result = boundary === 'start' ? dt.startOf('day') : dt.endOf('day')\n break\n case 'week':\n result = boundary === 'start' ? dt.startOf('week') : dt.endOf('week')\n break\n case 'isoweek':\n result =\n boundary === 'start'\n ? dt.startOf('week').set({ weekday: 1 })\n : dt.startOf('week').set({ weekday: 7 }).endOf('day')\n break\n case 'month':\n result = boundary === 'start' ? dt.startOf('month') : dt.endOf('month')\n break\n case 'quarter': {\n const monthInFY = (dt.month - fyStart + 12) % 12\n const qIndex = Math.floor(monthInFY / 3)\n const qStartMonth = ((qIndex * 3 + fyStart - 1) % 12) + 1\n const qStart = dt.set({ month: qStartMonth, day: 1 }).startOf('day')\n const adjusted = qStart > dt ? qStart.minus({ months: 3 }) : qStart\n result =\n boundary === 'start'\n ? adjusted\n : adjusted.plus({ months: 3 }).minus({ days: 1 }).endOf('day')\n break\n }\n case 'year':\n if (fyStart === 1) {\n result = boundary === 'start' ? dt.startOf('year') : dt.endOf('year')\n } else {\n const fyStartThis = dt.set({ month: fyStart, day: 1 }).startOf('day')\n const fyBase = dt >= fyStartThis ? fyStartThis : fyStartThis.minus({ years: 1 })\n result =\n boundary === 'start'\n ? fyBase\n : fyBase.plus({ years: 1 }).minus({ days: 1 }).endOf('day')\n }\n break\n }\n\n return `${boundary === 'start' ? 'Start' : 'End'} of ${period} containing ${dateStr}: ${result.toISO()}\\nFormatted: ${result.toFormat('cccc, LLLL d, yyyy h:mm:ss a ZZZZ')}`\n },\n})\n\n/**\n * Count business days between two dates, or compute the date N business days away.\n *\n * @remarks\n * Monday–Friday only; no holiday calendar awareness. Provide either `to` (count between) or\n * `add_days` (compute target date). Negative `add_days` walks backwards.\n */\nexport const dateBusinessDaysTool = new Tool({\n name: 'date_business_days',\n description:\n 'Count business days (Mon–Fri, no holiday awareness) between two dates, or calculate the date that is N business days from a start date.',\n inputSchema: validator.object({\n from: validator.string().required().description('Start date (ISO 8601 or \"now\")'),\n to: validator\n .string()\n .optional()\n .description('End date (ISO 8601 or \"now\") — for counting business days between two dates'),\n add_days: validator\n .number()\n .optional()\n .description('Instead of \"to\": number of business days to add (negative to subtract)'),\n timezone: validator.string().optional().description('IANA timezone (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const {\n from: fromStr,\n to: toStr,\n add_days: addDays,\n timezone,\n } = args as {\n from: string\n to?: string\n add_days?: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const fromDt = (\n fromStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(fromStr)\n ).setZone(zone)\n if (!fromDt.isValid) return `Error: Invalid from date \"${fromStr}\".`\n\n if (addDays !== undefined) {\n const n = Math.floor(addDays)\n let cursor = fromDt.startOf('day')\n let remaining = Math.abs(n)\n const dir = n >= 0 ? 1 : -1\n while (remaining > 0) {\n cursor = cursor.plus({ days: dir })\n if (cursor.weekday <= 5) remaining--\n }\n return `${n >= 0 ? '+' : ''}${n} business day${Math.abs(n) !== 1 ? 's' : ''} from ${fromStr}: ${cursor.toISODate()}\\nFormatted: ${cursor.toFormat('cccc, LLLL d, yyyy')}`\n }\n\n if (!toStr) return 'Error: Provide either \"to\" date or \"add_days\".'\n\n const toDt = (toStr.toLowerCase() === 'now' ? DateTime.now() : DateTime.fromISO(toStr)).setZone(\n zone\n )\n if (!toDt.isValid) return `Error: Invalid to date \"${toStr}\".`\n\n const count = countBusinessDays(fromDt, toDt)\n return `Business days from ${fromStr} to ${toStr}: ${count}`\n },\n})\n"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pre-constructed tools for ISO datetime arithmetic, differences, and timezone-aware formatting.
|
|
3
|
+
*
|
|
4
|
+
* @module @nhtio/adk/batteries/tools/datetime_math
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Pre-constructed bundled tools for the `datetime_math` category. Import individually, the whole
|
|
8
|
+
* category, or import every tool via `@nhtio/adk/batteries`.
|
|
9
|
+
*/
|
|
10
|
+
import { Tool } from "../../../common";
|
|
11
|
+
/**
|
|
12
|
+
* Add or subtract a duration from a date/time.
|
|
13
|
+
*
|
|
14
|
+
* @remarks
|
|
15
|
+
* All duration components (years/months/weeks/days/hours/minutes/seconds) are optional and
|
|
16
|
+
* combined into a single Duration. Output formatting includes a time component when the input
|
|
17
|
+
* itself has one or when any sub-day component is non-zero.
|
|
18
|
+
*/
|
|
19
|
+
export declare const dateAddTool: Tool<import("../../../common").SpooledArtifact>;
|
|
20
|
+
/**
|
|
21
|
+
* Calculate the difference between two dates/times in a chosen unit.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* Result is signed — positive when `to` is after `from`, negative otherwise — but rendered as
|
|
25
|
+
* `|value| <unit> after/before` for readability. Uses luxon's `diff().as(unit)` which respects
|
|
26
|
+
* calendar arithmetic for months/years.
|
|
27
|
+
*/
|
|
28
|
+
export declare const dateDiffTool: Tool<import("../../../common").SpooledArtifact>;
|
|
29
|
+
/**
|
|
30
|
+
* Convert total seconds into a human-readable duration string.
|
|
31
|
+
*
|
|
32
|
+
* @remarks
|
|
33
|
+
* Examples: `3725` → `1 hour, 2 minutes and 5 seconds`. Negative inputs are prefixed with `-`.
|
|
34
|
+
* Zero seconds returns the literal `0 seconds`.
|
|
35
|
+
*/
|
|
36
|
+
export declare const durationFormatTool: Tool<import("../../../common").SpooledArtifact>;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("../../chunk-KmRHZBOW.js");
|
|
3
|
+
require("../../common-Od8edUXU.js");
|
|
4
|
+
const require_tool = require("../../tool-COSeH8I6.js");
|
|
5
|
+
let _nhtio_validation = require("@nhtio/validation");
|
|
6
|
+
let luxon = require("luxon");
|
|
7
|
+
//#region src/batteries/tools/datetime_math/index.ts
|
|
8
|
+
/**
|
|
9
|
+
* Pre-constructed tools for ISO datetime arithmetic, differences, and timezone-aware formatting.
|
|
10
|
+
*
|
|
11
|
+
* @module @nhtio/adk/batteries/tools/datetime_math
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* Pre-constructed bundled tools for the `datetime_math` category. Import individually, the whole
|
|
15
|
+
* category, or import every tool via `@nhtio/adk/batteries`.
|
|
16
|
+
*/
|
|
17
|
+
function resolveZone(timezone) {
|
|
18
|
+
if (!timezone) return { zone: "UTC" };
|
|
19
|
+
if (!luxon.IANAZone.isValidZone(timezone)) return {
|
|
20
|
+
zone: "",
|
|
21
|
+
error: `Invalid timezone "${timezone}".`
|
|
22
|
+
};
|
|
23
|
+
return { zone: timezone };
|
|
24
|
+
}
|
|
25
|
+
function parseDate(input, zone) {
|
|
26
|
+
if (input.toLowerCase() === "now") return luxon.DateTime.now().setZone(zone);
|
|
27
|
+
const dt = luxon.DateTime.fromISO(input, { zone });
|
|
28
|
+
if (!dt.isValid) return { error: `Invalid date "${input}". Use ISO 8601 format (e.g. "2025-06-15" or "2025-06-15T14:30:00") or "now".` };
|
|
29
|
+
return dt;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Add or subtract a duration from a date/time.
|
|
33
|
+
*
|
|
34
|
+
* @remarks
|
|
35
|
+
* All duration components (years/months/weeks/days/hours/minutes/seconds) are optional and
|
|
36
|
+
* combined into a single Duration. Output formatting includes a time component when the input
|
|
37
|
+
* itself has one or when any sub-day component is non-zero.
|
|
38
|
+
*/
|
|
39
|
+
var dateAddTool = new require_tool.Tool({
|
|
40
|
+
name: "date_add",
|
|
41
|
+
description: "Add or subtract a duration from a date/time. Useful for \"what date is 90 days from now?\" or \"when was 6 months before X?\"",
|
|
42
|
+
inputSchema: _nhtio_validation.validator.object({
|
|
43
|
+
date: _nhtio_validation.validator.string().required().description("ISO 8601 date/datetime string or \"now\""),
|
|
44
|
+
direction: _nhtio_validation.validator.string().valid("add", "subtract").required().description("\"add\" to move forward in time, \"subtract\" to move backward"),
|
|
45
|
+
years: _nhtio_validation.validator.number().default(0).description("Years component (optional)"),
|
|
46
|
+
months: _nhtio_validation.validator.number().default(0).description("Months component (optional)"),
|
|
47
|
+
weeks: _nhtio_validation.validator.number().default(0).description("Weeks component (optional)"),
|
|
48
|
+
days: _nhtio_validation.validator.number().default(0).description("Days component (optional)"),
|
|
49
|
+
hours: _nhtio_validation.validator.number().default(0).description("Hours component (optional)"),
|
|
50
|
+
minutes: _nhtio_validation.validator.number().default(0).description("Minutes component (optional)"),
|
|
51
|
+
seconds: _nhtio_validation.validator.number().default(0).description("Seconds component (optional)"),
|
|
52
|
+
timezone: _nhtio_validation.validator.string().optional().description("IANA timezone for interpreting the date (optional, defaults UTC)")
|
|
53
|
+
}),
|
|
54
|
+
handler: async (args) => {
|
|
55
|
+
const { date, direction, years, months, weeks, days, hours, minutes, seconds, timezone } = args;
|
|
56
|
+
const { zone, error: zoneError } = resolveZone(timezone);
|
|
57
|
+
if (zoneError) return `Error: ${zoneError}`;
|
|
58
|
+
const parsed = parseDate(date, zone);
|
|
59
|
+
if ("error" in parsed) return `Error: ${parsed.error}`;
|
|
60
|
+
const durObj = {
|
|
61
|
+
years,
|
|
62
|
+
months,
|
|
63
|
+
weeks,
|
|
64
|
+
days,
|
|
65
|
+
hours,
|
|
66
|
+
minutes,
|
|
67
|
+
seconds
|
|
68
|
+
};
|
|
69
|
+
const dur = luxon.Duration.fromObject(durObj);
|
|
70
|
+
const result = direction === "subtract" ? parsed.minus(dur) : parsed.plus(dur);
|
|
71
|
+
const inputHasTime = date.includes("T") || date.toLowerCase() === "now";
|
|
72
|
+
const durationHasTime = durObj.hours !== 0 || durObj.minutes !== 0 || durObj.seconds !== 0;
|
|
73
|
+
const formatted = inputHasTime || durationHasTime ? result.toFormat("cccc, LLLL d, yyyy 'at' h:mm:ss a ZZZZ") : result.toFormat("cccc, LLLL d, yyyy");
|
|
74
|
+
const durParts = Object.entries(durObj).filter(([, v]) => v !== 0).map(([k, v]) => `${v} ${k}`).join(", ");
|
|
75
|
+
return `${direction === "subtract" ? "Subtracting" : "Adding"} ${durParts || "0"} ${direction === "subtract" ? "from" : "to"} ${date}: ${formatted}`;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
/**
|
|
79
|
+
* Calculate the difference between two dates/times in a chosen unit.
|
|
80
|
+
*
|
|
81
|
+
* @remarks
|
|
82
|
+
* Result is signed — positive when `to` is after `from`, negative otherwise — but rendered as
|
|
83
|
+
* `|value| <unit> after/before` for readability. Uses luxon's `diff().as(unit)` which respects
|
|
84
|
+
* calendar arithmetic for months/years.
|
|
85
|
+
*/
|
|
86
|
+
var dateDiffTool = new require_tool.Tool({
|
|
87
|
+
name: "date_diff",
|
|
88
|
+
description: "Calculate the difference between two dates/times in a specified unit. Useful for \"how many days until X?\" or \"how long ago was Y?\"",
|
|
89
|
+
inputSchema: _nhtio_validation.validator.object({
|
|
90
|
+
from: _nhtio_validation.validator.string().required().description("Start date (ISO 8601 or \"now\")"),
|
|
91
|
+
to: _nhtio_validation.validator.string().required().description("End date (ISO 8601 or \"now\")"),
|
|
92
|
+
unit: _nhtio_validation.validator.string().valid("years", "months", "weeks", "days", "hours", "minutes", "seconds").required().description("Unit to express the difference in"),
|
|
93
|
+
timezone: _nhtio_validation.validator.string().optional().description("IANA timezone for interpreting dates (optional, defaults UTC)")
|
|
94
|
+
}),
|
|
95
|
+
handler: async (args) => {
|
|
96
|
+
const { from, to, unit, timezone } = args;
|
|
97
|
+
const { zone, error: zoneError } = resolveZone(timezone);
|
|
98
|
+
if (zoneError) return `Error: ${zoneError}`;
|
|
99
|
+
const fromParsed = parseDate(from, zone);
|
|
100
|
+
if ("error" in fromParsed) return `Error: ${fromParsed.error}`;
|
|
101
|
+
const toParsed = parseDate(to, zone);
|
|
102
|
+
if ("error" in toParsed) return `Error: ${toParsed.error}`;
|
|
103
|
+
const value = toParsed.diff(fromParsed, unit).as(unit);
|
|
104
|
+
const rounded = Number.parseFloat(value.toFixed(4));
|
|
105
|
+
return `${to} is ${Math.abs(rounded)} ${unit} ${value >= 0 ? "after" : "before"} ${from}`;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
/**
|
|
109
|
+
* Convert total seconds into a human-readable duration string.
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
* Examples: `3725` → `1 hour, 2 minutes and 5 seconds`. Negative inputs are prefixed with `-`.
|
|
113
|
+
* Zero seconds returns the literal `0 seconds`.
|
|
114
|
+
*/
|
|
115
|
+
var durationFormatTool = new require_tool.Tool({
|
|
116
|
+
name: "duration_format",
|
|
117
|
+
description: "Convert a total number of seconds into a human-readable duration breakdown (e.g. \"2 hours, 15 minutes and 30 seconds\").",
|
|
118
|
+
inputSchema: _nhtio_validation.validator.object({ seconds: _nhtio_validation.validator.number().required().description("Total number of seconds (may be negative)") }),
|
|
119
|
+
handler: async (args) => {
|
|
120
|
+
const { seconds: totalSeconds } = args;
|
|
121
|
+
const sign = totalSeconds < 0 ? "-" : "";
|
|
122
|
+
const absSeconds = Math.abs(totalSeconds);
|
|
123
|
+
const obj = luxon.Duration.fromObject({ seconds: absSeconds }).shiftTo("years", "months", "weeks", "days", "hours", "minutes", "seconds").toObject();
|
|
124
|
+
const units = [
|
|
125
|
+
[
|
|
126
|
+
"years",
|
|
127
|
+
"year",
|
|
128
|
+
"years"
|
|
129
|
+
],
|
|
130
|
+
[
|
|
131
|
+
"months",
|
|
132
|
+
"month",
|
|
133
|
+
"months"
|
|
134
|
+
],
|
|
135
|
+
[
|
|
136
|
+
"weeks",
|
|
137
|
+
"week",
|
|
138
|
+
"weeks"
|
|
139
|
+
],
|
|
140
|
+
[
|
|
141
|
+
"days",
|
|
142
|
+
"day",
|
|
143
|
+
"days"
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
"hours",
|
|
147
|
+
"hour",
|
|
148
|
+
"hours"
|
|
149
|
+
],
|
|
150
|
+
[
|
|
151
|
+
"minutes",
|
|
152
|
+
"minute",
|
|
153
|
+
"minutes"
|
|
154
|
+
],
|
|
155
|
+
[
|
|
156
|
+
"seconds",
|
|
157
|
+
"second",
|
|
158
|
+
"seconds"
|
|
159
|
+
]
|
|
160
|
+
];
|
|
161
|
+
const parts = [];
|
|
162
|
+
for (const [key, singular, plural] of units) {
|
|
163
|
+
const v = Math.floor(obj[key] ?? 0);
|
|
164
|
+
if (v > 0) parts.push(`${v} ${v === 1 ? singular : plural}`);
|
|
165
|
+
}
|
|
166
|
+
if (parts.length === 0) return "0 seconds";
|
|
167
|
+
return `${sign}${parts.length === 1 ? parts[0] : parts.slice(0, -1).join(", ") + " and " + parts[parts.length - 1]}`;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
//#endregion
|
|
171
|
+
exports.dateAddTool = dateAddTool;
|
|
172
|
+
exports.dateDiffTool = dateDiffTool;
|
|
173
|
+
exports.durationFormatTool = durationFormatTool;
|
|
174
|
+
|
|
175
|
+
//# sourceMappingURL=datetime_math.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"datetime_math.cjs","names":[],"sources":["../../../src/batteries/tools/datetime_math/index.ts"],"sourcesContent":["/**\n * Pre-constructed tools for ISO datetime arithmetic, differences, and timezone-aware formatting.\n *\n * @module @nhtio/adk/batteries/tools/datetime_math\n *\n * @remarks\n * Pre-constructed bundled tools for the `datetime_math` category. Import individually, the whole\n * category, or import every tool via `@nhtio/adk/batteries`.\n */\n\nimport { Tool } from '@nhtio/adk/common'\nimport { validator } from '@nhtio/validation'\nimport { DateTime, Duration, IANAZone } from 'luxon'\n\nfunction resolveZone(timezone: string | undefined): { zone: string; error?: string } {\n if (!timezone) return { zone: 'UTC' }\n if (!IANAZone.isValidZone(timezone)) return { zone: '', error: `Invalid timezone \"${timezone}\".` }\n return { zone: timezone }\n}\n\nfunction parseDate(input: string, zone: string): DateTime | { error: string } {\n if (input.toLowerCase() === 'now') return DateTime.now().setZone(zone)\n const dt = DateTime.fromISO(input, { zone })\n if (!dt.isValid)\n return {\n error: `Invalid date \"${input}\". Use ISO 8601 format (e.g. \"2025-06-15\" or \"2025-06-15T14:30:00\") or \"now\".`,\n }\n return dt\n}\n\n/**\n * Add or subtract a duration from a date/time.\n *\n * @remarks\n * All duration components (years/months/weeks/days/hours/minutes/seconds) are optional and\n * combined into a single Duration. Output formatting includes a time component when the input\n * itself has one or when any sub-day component is non-zero.\n */\nexport const dateAddTool = new Tool({\n name: 'date_add',\n description:\n 'Add or subtract a duration from a date/time. Useful for \"what date is 90 days from now?\" or \"when was 6 months before X?\"',\n inputSchema: validator.object({\n date: validator.string().required().description('ISO 8601 date/datetime string or \"now\"'),\n direction: validator\n .string()\n .valid('add', 'subtract')\n .required()\n .description('\"add\" to move forward in time, \"subtract\" to move backward'),\n years: validator.number().default(0).description('Years component (optional)'),\n months: validator.number().default(0).description('Months component (optional)'),\n weeks: validator.number().default(0).description('Weeks component (optional)'),\n days: validator.number().default(0).description('Days component (optional)'),\n hours: validator.number().default(0).description('Hours component (optional)'),\n minutes: validator.number().default(0).description('Minutes component (optional)'),\n seconds: validator.number().default(0).description('Seconds component (optional)'),\n timezone: validator\n .string()\n .optional()\n .description('IANA timezone for interpreting the date (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const { date, direction, years, months, weeks, days, hours, minutes, seconds, timezone } =\n args as {\n date: string\n direction: 'add' | 'subtract'\n years: number\n months: number\n weeks: number\n days: number\n hours: number\n minutes: number\n seconds: number\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const parsed = parseDate(date, zone)\n if ('error' in parsed) return `Error: ${parsed.error}`\n\n const durObj = { years, months, weeks, days, hours, minutes, seconds }\n const dur = Duration.fromObject(durObj)\n const result = direction === 'subtract' ? parsed.minus(dur) : parsed.plus(dur)\n\n const inputHasTime = date.includes('T') || date.toLowerCase() === 'now'\n const durationHasTime = durObj.hours !== 0 || durObj.minutes !== 0 || durObj.seconds !== 0\n const showTime = inputHasTime || durationHasTime\n\n const formatted = showTime\n ? result.toFormat(\"cccc, LLLL d, yyyy 'at' h:mm:ss a ZZZZ\")\n : result.toFormat('cccc, LLLL d, yyyy')\n\n const durParts = Object.entries(durObj)\n .filter(([, v]) => v !== 0)\n .map(([k, v]) => `${v} ${k}`)\n .join(', ')\n\n const verb = direction === 'subtract' ? 'Subtracting' : 'Adding'\n const prep = direction === 'subtract' ? 'from' : 'to'\n return `${verb} ${durParts || '0'} ${prep} ${date}: ${formatted}`\n },\n})\n\n/**\n * Calculate the difference between two dates/times in a chosen unit.\n *\n * @remarks\n * Result is signed — positive when `to` is after `from`, negative otherwise — but rendered as\n * `|value| <unit> after/before` for readability. Uses luxon's `diff().as(unit)` which respects\n * calendar arithmetic for months/years.\n */\nexport const dateDiffTool = new Tool({\n name: 'date_diff',\n description:\n 'Calculate the difference between two dates/times in a specified unit. Useful for \"how many days until X?\" or \"how long ago was Y?\"',\n inputSchema: validator.object({\n from: validator.string().required().description('Start date (ISO 8601 or \"now\")'),\n to: validator.string().required().description('End date (ISO 8601 or \"now\")'),\n unit: validator\n .string()\n .valid('years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds')\n .required()\n .description('Unit to express the difference in'),\n timezone: validator\n .string()\n .optional()\n .description('IANA timezone for interpreting dates (optional, defaults UTC)'),\n }),\n handler: async (args) => {\n const { from, to, unit, timezone } = args as {\n from: string\n to: string\n unit: 'years' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds'\n timezone?: string\n }\n const { zone, error: zoneError } = resolveZone(timezone)\n if (zoneError) return `Error: ${zoneError}`\n\n const fromParsed = parseDate(from, zone)\n if ('error' in fromParsed) return `Error: ${fromParsed.error}`\n\n const toParsed = parseDate(to, zone)\n if ('error' in toParsed) return `Error: ${toParsed.error}`\n\n const diff = toParsed.diff(fromParsed, unit)\n const value = diff.as(unit)\n const rounded = Number.parseFloat(value.toFixed(4))\n const abs = Math.abs(rounded)\n const direction = value >= 0 ? 'after' : 'before'\n\n return `${to} is ${abs} ${unit} ${direction} ${from}`\n },\n})\n\n/**\n * Convert total seconds into a human-readable duration string.\n *\n * @remarks\n * Examples: `3725` → `1 hour, 2 minutes and 5 seconds`. Negative inputs are prefixed with `-`.\n * Zero seconds returns the literal `0 seconds`.\n */\nexport const durationFormatTool = new Tool({\n name: 'duration_format',\n description:\n 'Convert a total number of seconds into a human-readable duration breakdown (e.g. \"2 hours, 15 minutes and 30 seconds\").',\n inputSchema: validator.object({\n seconds: validator.number().required().description('Total number of seconds (may be negative)'),\n }),\n handler: async (args) => {\n const { seconds: totalSeconds } = args as { seconds: number }\n const sign = totalSeconds < 0 ? '-' : ''\n const absSeconds = Math.abs(totalSeconds)\n\n const dur = Duration.fromObject({ seconds: absSeconds }).shiftTo(\n 'years',\n 'months',\n 'weeks',\n 'days',\n 'hours',\n 'minutes',\n 'seconds'\n )\n const obj = dur.toObject()\n\n const units: Array<[keyof typeof obj, string, string]> = [\n ['years', 'year', 'years'],\n ['months', 'month', 'months'],\n ['weeks', 'week', 'weeks'],\n ['days', 'day', 'days'],\n ['hours', 'hour', 'hours'],\n ['minutes', 'minute', 'minutes'],\n ['seconds', 'second', 'seconds'],\n ]\n\n const parts: string[] = []\n for (const [key, singular, plural] of units) {\n const v = Math.floor(obj[key] ?? 0)\n if (v > 0) parts.push(`${v} ${v === 1 ? singular : plural}`)\n }\n\n if (parts.length === 0) return '0 seconds'\n const formatted =\n parts.length === 1\n ? parts[0]\n : parts.slice(0, -1).join(', ') + ' and ' + parts[parts.length - 1]\n return `${sign}${formatted}`\n },\n})\n"],"mappings":"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"}
|