agentfootprint 9.128.1 → 9.131.0
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/CAPABILITIES.md +13 -1
- package/dist/adapters/llm/AnthropicProvider.js +10 -111
- package/dist/adapters/llm/AnthropicProvider.js.map +1 -1
- package/dist/adapters/llm/BedrockProvider.js +11 -4
- package/dist/adapters/llm/BedrockProvider.js.map +1 -1
- package/dist/adapters/llm/InvokeModelGatewayProvider.js +167 -35
- package/dist/adapters/llm/InvokeModelGatewayProvider.js.map +1 -1
- package/dist/adapters/llm/OpenAIProvider.js +5 -0
- package/dist/adapters/llm/OpenAIProvider.js.map +1 -1
- package/dist/adapters/llm/anthropicMessagesWire.js +20 -6
- package/dist/adapters/llm/anthropicMessagesWire.js.map +1 -1
- package/dist/adapters/llm/retryAfter.js +61 -0
- package/dist/adapters/llm/retryAfter.js.map +1 -0
- package/dist/adapters/types.js.map +1 -1
- package/dist/artifacts/datasetResult.js +2 -2
- package/dist/artifacts/datasetResult.js.map +1 -1
- package/dist/artifacts/index.js +10 -8
- package/dist/artifacts/index.js.map +1 -1
- package/dist/artifacts/minting.js +2 -2
- package/dist/artifacts/minting.js.map +1 -1
- package/dist/core/Agent.js +229 -5
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +75 -1
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/arguments/ask.js +356 -14
- package/dist/core/agent/arguments/ask.js.map +1 -1
- package/dist/core/agent/arguments/declare.js +260 -45
- package/dist/core/agent/arguments/declare.js.map +1 -1
- package/dist/core/agent/arguments/dispatch.js +25 -1
- package/dist/core/agent/arguments/dispatch.js.map +1 -1
- package/dist/core/agent/arguments/resolve.js +239 -6
- package/dist/core/agent/arguments/resolve.js.map +1 -1
- package/dist/core/agent/arguments/rows.js +37 -2
- package/dist/core/agent/arguments/rows.js.map +1 -1
- package/dist/core/agent/arguments/serve.js +332 -4
- package/dist/core/agent/arguments/serve.js.map +1 -1
- package/dist/core/agent/arguments/subflow.js +46 -7
- package/dist/core/agent/arguments/subflow.js.map +1 -1
- package/dist/core/agent/assessment/assess.js +45 -6
- package/dist/core/agent/assessment/assess.js.map +1 -1
- package/dist/core/agent/assessment/compose.js +3 -0
- package/dist/core/agent/assessment/compose.js.map +1 -1
- package/dist/core/agent/assessment/reasons.js +18 -0
- package/dist/core/agent/assessment/reasons.js.map +1 -1
- package/dist/core/agent/buildAgentChart.js +31 -1
- package/dist/core/agent/buildAgentChart.js.map +1 -1
- package/dist/core/agent/buildDynamicAgentChart.js +9 -0
- package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/core/agent/coverage/answer.js +24 -7
- package/dist/core/agent/coverage/answer.js.map +1 -1
- package/dist/core/agent/coverage/period.js +110 -69
- package/dist/core/agent/coverage/period.js.map +1 -1
- package/dist/core/agent/coverage/timeLimitFacts.js +70 -0
- package/dist/core/agent/coverage/timeLimitFacts.js.map +1 -0
- package/dist/core/agent/coverage/timeLimits.js +72 -0
- package/dist/core/agent/coverage/timeLimits.js.map +1 -0
- package/dist/core/agent/evidence/evidenceIndex.js +48 -7
- package/dist/core/agent/evidence/evidenceIndex.js.map +1 -1
- package/dist/core/agent/evidence/gate.js +9 -4
- package/dist/core/agent/evidence/gate.js.map +1 -1
- package/dist/core/agent/evidence/normalize.js +1 -105
- package/dist/core/agent/evidence/normalize.js.map +1 -1
- package/dist/core/agent/findings/ledger.js +14 -0
- package/dist/core/agent/findings/ledger.js.map +1 -1
- package/dist/core/agent/findings/types.js.map +1 -1
- package/dist/core/agent/honesty/mounts.js +105 -4
- package/dist/core/agent/honesty/mounts.js.map +1 -1
- package/dist/core/agent/results/subflow.js +43 -11
- package/dist/core/agent/results/subflow.js.map +1 -1
- package/dist/core/agent/stages/argumentAsk.js +85 -6
- package/dist/core/agent/stages/argumentAsk.js.map +1 -1
- package/dist/core/agent/stages/callLLM.js +16 -0
- package/dist/core/agent/stages/callLLM.js.map +1 -1
- package/dist/core/agent/stages/prepareFinal.js +61 -8
- package/dist/core/agent/stages/prepareFinal.js.map +1 -1
- package/dist/core/agent/stages/route.js +64 -6
- package/dist/core/agent/stages/route.js.map +1 -1
- package/dist/core/agent/stages/seed.js +29 -6
- package/dist/core/agent/stages/seed.js.map +1 -1
- package/dist/core/agent/stages/timeLayer.js +201 -0
- package/dist/core/agent/stages/timeLayer.js.map +1 -0
- package/dist/core/agent/stages/timeLineage.js +61 -0
- package/dist/core/agent/stages/timeLineage.js.map +1 -0
- package/dist/core/agent/stages/toolCalls.js +70 -0
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/inputRequest.js +132 -5
- package/dist/core/inputRequest.js.map +1 -1
- package/dist/core/messageFrom.js +5 -2
- package/dist/core/messageFrom.js.map +1 -1
- package/dist/core/runCheckpoint.js +17 -2
- package/dist/core/runCheckpoint.js.map +1 -1
- package/dist/core/slots/buildToolsSlot.js +30 -2
- package/dist/core/slots/buildToolsSlot.js.map +1 -1
- package/dist/core/time/ask.js +239 -0
- package/dist/core/time/ask.js.map +1 -0
- package/dist/core/time/axis.js +469 -0
- package/dist/core/time/axis.js.map +1 -0
- package/dist/core/time/bind.js +235 -0
- package/dist/core/time/bind.js.map +1 -0
- package/dist/core/time/check.js +261 -0
- package/dist/core/time/check.js.map +1 -0
- package/dist/core/time/checkRecord.js +97 -0
- package/dist/core/time/checkRecord.js.map +1 -0
- package/dist/core/time/clock.js +260 -0
- package/dist/core/time/clock.js.map +1 -0
- package/dist/core/time/convert.js +634 -0
- package/dist/core/time/convert.js.map +1 -0
- package/dist/core/time/drift.js +96 -0
- package/dist/core/time/drift.js.map +1 -0
- package/dist/core/time/duration.js +125 -0
- package/dist/core/time/duration.js.map +1 -0
- package/dist/core/time/forms.js +273 -0
- package/dist/core/time/forms.js.map +1 -0
- package/dist/core/time/instant.js +141 -0
- package/dist/core/time/instant.js.map +1 -0
- package/dist/core/time/periodForm.js +392 -0
- package/dist/core/time/periodForm.js.map +1 -0
- package/dist/core/time/present.js +312 -0
- package/dist/core/time/present.js.map +1 -0
- package/dist/core/time/range.js +267 -0
- package/dist/core/time/range.js.map +1 -0
- package/dist/core/time/reader.js +209 -0
- package/dist/core/time/reader.js.map +1 -0
- package/dist/core/time/readers/english.js +576 -0
- package/dist/core/time/readers/english.js.map +1 -0
- package/dist/core/time/readingAsk.js +94 -0
- package/dist/core/time/readingAsk.js.map +1 -0
- package/dist/core/time/resolve.js +694 -0
- package/dist/core/time/resolve.js.map +1 -0
- package/dist/core/time/resolveRecord.js +164 -0
- package/dist/core/time/resolveRecord.js.map +1 -0
- package/dist/core/time/rows.js +412 -0
- package/dist/core/time/rows.js.map +1 -0
- package/dist/core/time/rowsBuild.js +193 -0
- package/dist/core/time/rowsBuild.js.map +1 -0
- package/dist/core/time/textForms.js +133 -0
- package/dist/core/time/textForms.js.map +1 -0
- package/dist/core/time/windows.js +172 -0
- package/dist/core/time/windows.js.map +1 -0
- package/dist/core/time/wire.js +86 -0
- package/dist/core/time/wire.js.map +1 -0
- package/dist/core/time/zone.js +253 -0
- package/dist/core/time/zone.js.map +1 -0
- package/dist/core/tools.js.map +1 -1
- package/dist/esm/adapters/llm/AnthropicProvider.js +8 -109
- package/dist/esm/adapters/llm/AnthropicProvider.js.map +1 -1
- package/dist/esm/adapters/llm/BedrockProvider.js +11 -4
- package/dist/esm/adapters/llm/BedrockProvider.js.map +1 -1
- package/dist/esm/adapters/llm/InvokeModelGatewayProvider.d.ts +38 -4
- package/dist/esm/adapters/llm/InvokeModelGatewayProvider.js +167 -35
- package/dist/esm/adapters/llm/InvokeModelGatewayProvider.js.map +1 -1
- package/dist/esm/adapters/llm/OpenAIProvider.js +5 -0
- package/dist/esm/adapters/llm/OpenAIProvider.js.map +1 -1
- package/dist/esm/adapters/llm/anthropicMessagesWire.d.ts +6 -1
- package/dist/esm/adapters/llm/anthropicMessagesWire.js +20 -6
- package/dist/esm/adapters/llm/anthropicMessagesWire.js.map +1 -1
- package/dist/esm/adapters/llm/retryAfter.d.ts +27 -0
- package/dist/esm/adapters/llm/retryAfter.js +56 -0
- package/dist/esm/adapters/llm/retryAfter.js.map +1 -0
- package/dist/esm/adapters/types.d.ts +9 -0
- package/dist/esm/adapters/types.js.map +1 -1
- package/dist/esm/artifacts/datasetResult.js +1 -1
- package/dist/esm/artifacts/datasetResult.js.map +1 -1
- package/dist/esm/artifacts/index.d.ts +1 -1
- package/dist/esm/artifacts/index.js +3 -2
- package/dist/esm/artifacts/index.js.map +1 -1
- package/dist/esm/artifacts/minting.js +1 -1
- package/dist/esm/artifacts/minting.js.map +1 -1
- package/dist/esm/artifacts/types.d.ts +2 -2
- package/dist/esm/core/Agent.d.ts +64 -0
- package/dist/esm/core/Agent.js +230 -6
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.d.ts +60 -0
- package/dist/esm/core/agent/AgentBuilder.js +75 -1
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/arguments/ask.d.ts +88 -5
- package/dist/esm/core/agent/arguments/ask.js +349 -8
- package/dist/esm/core/agent/arguments/ask.js.map +1 -1
- package/dist/esm/core/agent/arguments/checks.d.ts +1 -1
- package/dist/esm/core/agent/arguments/declare.d.ts +76 -15
- package/dist/esm/core/agent/arguments/declare.js +255 -44
- package/dist/esm/core/agent/arguments/declare.js.map +1 -1
- package/dist/esm/core/agent/arguments/dispatch.js +25 -1
- package/dist/esm/core/agent/arguments/dispatch.js.map +1 -1
- package/dist/esm/core/agent/arguments/resolve.d.ts +77 -7
- package/dist/esm/core/agent/arguments/resolve.js +239 -8
- package/dist/esm/core/agent/arguments/resolve.js.map +1 -1
- package/dist/esm/core/agent/arguments/rows.d.ts +31 -2
- package/dist/esm/core/agent/arguments/rows.js +35 -1
- package/dist/esm/core/agent/arguments/rows.js.map +1 -1
- package/dist/esm/core/agent/arguments/serve.d.ts +133 -4
- package/dist/esm/core/agent/arguments/serve.js +328 -4
- package/dist/esm/core/agent/arguments/serve.js.map +1 -1
- package/dist/esm/core/agent/arguments/subflow.d.ts +28 -0
- package/dist/esm/core/agent/arguments/subflow.js +47 -8
- package/dist/esm/core/agent/arguments/subflow.js.map +1 -1
- package/dist/esm/core/agent/assessment/assess.js +45 -6
- package/dist/esm/core/agent/assessment/assess.js.map +1 -1
- package/dist/esm/core/agent/assessment/compose.js +3 -0
- package/dist/esm/core/agent/assessment/compose.js.map +1 -1
- package/dist/esm/core/agent/assessment/reasons.js +18 -0
- package/dist/esm/core/agent/assessment/reasons.js.map +1 -1
- package/dist/esm/core/agent/assessment/types.d.ts +15 -1
- package/dist/esm/core/agent/buildAgentChart.d.ts +41 -0
- package/dist/esm/core/agent/buildAgentChart.js +28 -0
- package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
- package/dist/esm/core/agent/buildDynamicAgentChart.d.ts +1 -1
- package/dist/esm/core/agent/buildDynamicAgentChart.js +9 -0
- package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
- package/dist/esm/core/agent/coverage/answer.d.ts +20 -1
- package/dist/esm/core/agent/coverage/answer.js +23 -6
- package/dist/esm/core/agent/coverage/answer.js.map +1 -1
- package/dist/esm/core/agent/coverage/period.d.ts +49 -3
- package/dist/esm/core/agent/coverage/period.js +107 -68
- package/dist/esm/core/agent/coverage/period.js.map +1 -1
- package/dist/esm/core/agent/coverage/timeLimitFacts.d.ts +56 -0
- package/dist/esm/core/agent/coverage/timeLimitFacts.js +65 -0
- package/dist/esm/core/agent/coverage/timeLimitFacts.js.map +1 -0
- package/dist/esm/core/agent/coverage/timeLimits.d.ts +46 -0
- package/dist/esm/core/agent/coverage/timeLimits.js +67 -0
- package/dist/esm/core/agent/coverage/timeLimits.js.map +1 -0
- package/dist/esm/core/agent/evidence/evidenceIndex.d.ts +25 -2
- package/dist/esm/core/agent/evidence/evidenceIndex.js +47 -7
- package/dist/esm/core/agent/evidence/evidenceIndex.js.map +1 -1
- package/dist/esm/core/agent/evidence/gate.d.ts +7 -0
- package/dist/esm/core/agent/evidence/gate.js +9 -4
- package/dist/esm/core/agent/evidence/gate.js.map +1 -1
- package/dist/esm/core/agent/evidence/normalize.d.ts +0 -34
- package/dist/esm/core/agent/evidence/normalize.js +0 -103
- package/dist/esm/core/agent/evidence/normalize.js.map +1 -1
- package/dist/esm/core/agent/evidence/types.d.ts +12 -1
- package/dist/esm/core/agent/findings/ledger.js +14 -0
- package/dist/esm/core/agent/findings/ledger.js.map +1 -1
- package/dist/esm/core/agent/findings/types.d.ts +2 -1
- package/dist/esm/core/agent/findings/types.js.map +1 -1
- package/dist/esm/core/agent/honesty/mounts.d.ts +25 -0
- package/dist/esm/core/agent/honesty/mounts.js +104 -4
- package/dist/esm/core/agent/honesty/mounts.js.map +1 -1
- package/dist/esm/core/agent/results/subflow.d.ts +34 -2
- package/dist/esm/core/agent/results/subflow.js +43 -11
- package/dist/esm/core/agent/results/subflow.js.map +1 -1
- package/dist/esm/core/agent/stages/argumentAsk.d.ts +19 -0
- package/dist/esm/core/agent/stages/argumentAsk.js +85 -6
- package/dist/esm/core/agent/stages/argumentAsk.js.map +1 -1
- package/dist/esm/core/agent/stages/callLLM.d.ts +6 -0
- package/dist/esm/core/agent/stages/callLLM.js +16 -0
- package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
- package/dist/esm/core/agent/stages/prepareFinal.d.ts +13 -1
- package/dist/esm/core/agent/stages/prepareFinal.js +59 -7
- package/dist/esm/core/agent/stages/prepareFinal.js.map +1 -1
- package/dist/esm/core/agent/stages/route.d.ts +29 -1
- package/dist/esm/core/agent/stages/route.js +64 -7
- package/dist/esm/core/agent/stages/route.js.map +1 -1
- package/dist/esm/core/agent/stages/seed.d.ts +23 -0
- package/dist/esm/core/agent/stages/seed.js +29 -6
- package/dist/esm/core/agent/stages/seed.js.map +1 -1
- package/dist/esm/core/agent/stages/timeLayer.d.ts +94 -0
- package/dist/esm/core/agent/stages/timeLayer.js +193 -0
- package/dist/esm/core/agent/stages/timeLayer.js.map +1 -0
- package/dist/esm/core/agent/stages/timeLineage.d.ts +31 -0
- package/dist/esm/core/agent/stages/timeLineage.js +57 -0
- package/dist/esm/core/agent/stages/timeLineage.js.map +1 -0
- package/dist/esm/core/agent/stages/toolCalls.d.ts +32 -0
- package/dist/esm/core/agent/stages/toolCalls.js +70 -0
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +37 -0
- package/dist/esm/core/inputRequest.d.ts +50 -6
- package/dist/esm/core/inputRequest.js +132 -5
- package/dist/esm/core/inputRequest.js.map +1 -1
- package/dist/esm/core/messageFrom.d.ts +5 -2
- package/dist/esm/core/messageFrom.js +5 -2
- package/dist/esm/core/messageFrom.js.map +1 -1
- package/dist/esm/core/runCheckpoint.js +17 -2
- package/dist/esm/core/runCheckpoint.js.map +1 -1
- package/dist/esm/core/slots/buildToolsSlot.d.ts +29 -0
- package/dist/esm/core/slots/buildToolsSlot.js +30 -2
- package/dist/esm/core/slots/buildToolsSlot.js.map +1 -1
- package/dist/esm/core/time/ask.d.ts +126 -0
- package/dist/esm/core/time/ask.js +230 -0
- package/dist/esm/core/time/ask.js.map +1 -0
- package/dist/esm/core/time/axis.d.ts +224 -0
- package/dist/esm/core/time/axis.js +462 -0
- package/dist/esm/core/time/axis.js.map +1 -0
- package/dist/esm/core/time/bind.d.ts +143 -0
- package/dist/esm/core/time/bind.js +227 -0
- package/dist/esm/core/time/bind.js.map +1 -0
- package/dist/esm/core/time/check.d.ts +113 -0
- package/dist/esm/core/time/check.js +252 -0
- package/dist/esm/core/time/check.js.map +1 -0
- package/dist/esm/core/time/checkRecord.d.ts +74 -0
- package/dist/esm/core/time/checkRecord.js +90 -0
- package/dist/esm/core/time/checkRecord.js.map +1 -0
- package/dist/esm/core/time/clock.d.ts +183 -0
- package/dist/esm/core/time/clock.js +252 -0
- package/dist/esm/core/time/clock.js.map +1 -0
- package/dist/esm/core/time/convert.d.ts +178 -0
- package/dist/esm/core/time/convert.js +609 -0
- package/dist/esm/core/time/convert.js.map +1 -0
- package/dist/esm/core/time/drift.d.ts +85 -0
- package/dist/esm/core/time/drift.js +91 -0
- package/dist/esm/core/time/drift.js.map +1 -0
- package/dist/esm/core/time/duration.d.ts +71 -0
- package/dist/esm/core/time/duration.js +117 -0
- package/dist/esm/core/time/duration.js.map +1 -0
- package/dist/esm/core/time/forms.d.ts +84 -0
- package/dist/esm/core/time/forms.js +268 -0
- package/dist/esm/core/time/forms.js.map +1 -0
- package/dist/esm/core/time/instant.d.ts +75 -0
- package/dist/esm/core/time/instant.js +131 -0
- package/dist/esm/core/time/instant.js.map +1 -0
- package/dist/esm/core/time/periodForm.d.ts +184 -0
- package/dist/esm/core/time/periodForm.js +376 -0
- package/dist/esm/core/time/periodForm.js.map +1 -0
- package/dist/esm/core/time/present.d.ts +107 -0
- package/dist/esm/core/time/present.js +305 -0
- package/dist/esm/core/time/present.js.map +1 -0
- package/dist/esm/core/time/range.d.ts +127 -0
- package/dist/esm/core/time/range.js +249 -0
- package/dist/esm/core/time/range.js.map +1 -0
- package/dist/esm/core/time/reader.d.ts +162 -0
- package/dist/esm/core/time/reader.js +203 -0
- package/dist/esm/core/time/reader.js.map +1 -0
- package/dist/esm/core/time/readers/english.d.ts +99 -0
- package/dist/esm/core/time/readers/english.js +572 -0
- package/dist/esm/core/time/readers/english.js.map +1 -0
- package/dist/esm/core/time/readingAsk.d.ts +45 -0
- package/dist/esm/core/time/readingAsk.js +90 -0
- package/dist/esm/core/time/readingAsk.js.map +1 -0
- package/dist/esm/core/time/resolve.d.ts +103 -0
- package/dist/esm/core/time/resolve.js +684 -0
- package/dist/esm/core/time/resolve.js.map +1 -0
- package/dist/esm/core/time/resolveRecord.d.ts +160 -0
- package/dist/esm/core/time/resolveRecord.js +158 -0
- package/dist/esm/core/time/resolveRecord.js.map +1 -0
- package/dist/esm/core/time/rows.d.ts +297 -0
- package/dist/esm/core/time/rows.js +397 -0
- package/dist/esm/core/time/rows.js.map +1 -0
- package/dist/esm/core/time/rowsBuild.d.ts +82 -0
- package/dist/esm/core/time/rowsBuild.js +185 -0
- package/dist/esm/core/time/rowsBuild.js.map +1 -0
- package/dist/esm/core/time/textForms.d.ts +53 -0
- package/dist/esm/core/time/textForms.js +126 -0
- package/dist/esm/core/time/textForms.js.map +1 -0
- package/dist/esm/core/time/windows.d.ts +113 -0
- package/dist/esm/core/time/windows.js +166 -0
- package/dist/esm/core/time/windows.js.map +1 -0
- package/dist/esm/core/time/wire.d.ts +63 -0
- package/dist/esm/core/time/wire.js +81 -0
- package/dist/esm/core/time/wire.js.map +1 -0
- package/dist/esm/core/time/zone.d.ts +115 -0
- package/dist/esm/core/time/zone.js +242 -0
- package/dist/esm/core/time/zone.js.map +1 -0
- package/dist/esm/core/tools.d.ts +26 -4
- package/dist/esm/core/tools.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +16 -2
- package/dist/esm/index.d.ts +13 -1
- package/dist/esm/index.js +6 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/answer-account/facts/howSure.js +7 -0
- package/dist/esm/lib/answer-account/facts/howSure.js.map +1 -1
- package/dist/esm/lib/answer-account/templates.d.ts +3 -0
- package/dist/esm/lib/answer-account/templates.js +4 -0
- package/dist/esm/lib/answer-account/templates.js.map +1 -1
- package/dist/esm/lib/mcp/elicitation.d.ts +84 -0
- package/dist/esm/lib/mcp/elicitation.js +181 -0
- package/dist/esm/lib/mcp/elicitation.js.map +1 -0
- package/dist/esm/lib/mcp/mcpClient.js +9 -3
- package/dist/esm/lib/mcp/mcpClient.js.map +1 -1
- package/dist/esm/lib/mcp/mcpServe.js +6 -2
- package/dist/esm/lib/mcp/mcpServe.js.map +1 -1
- package/dist/esm/lib/mcp/mockMcpClient.d.ts +9 -1
- package/dist/esm/lib/mcp/mockMcpClient.js +5 -3
- package/dist/esm/lib/mcp/mockMcpClient.js.map +1 -1
- package/dist/esm/lib/mcp/toolExtras.d.ts +21 -2
- package/dist/esm/lib/mcp/toolExtras.js +22 -0
- package/dist/esm/lib/mcp/toolExtras.js.map +1 -1
- package/dist/esm/lib/mcp/types.d.ts +8 -0
- package/dist/esm/lib/time-travel/receipt.d.ts +1 -1
- package/dist/esm/lib/time-travel/servedView.d.ts +1 -1
- package/dist/esm/lib/time-travel/servedView.js +9 -0
- package/dist/esm/lib/time-travel/servedView.js.map +1 -1
- package/dist/esm/locales/index.d.ts +6 -0
- package/dist/esm/locales/index.js +6 -0
- package/dist/esm/locales/index.js.map +1 -1
- package/dist/esm/locales/timeAsk.d.ts +29 -0
- package/dist/esm/locales/timeAsk.js +44 -0
- package/dist/esm/locales/timeAsk.js.map +1 -0
- package/dist/esm/recorders/core/resilienceHooks.js +1 -0
- package/dist/esm/recorders/core/resilienceHooks.js.map +1 -1
- package/dist/esm/resilience/statedWait.d.ts +22 -0
- package/dist/esm/resilience/statedWait.js +35 -0
- package/dist/esm/resilience/statedWait.js.map +1 -0
- package/dist/esm/resilience/withRetry.d.ts +13 -2
- package/dist/esm/resilience/withRetry.js +16 -1
- package/dist/esm/resilience/withRetry.js.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/answer-account/facts/howSure.js +7 -0
- package/dist/lib/answer-account/facts/howSure.js.map +1 -1
- package/dist/lib/answer-account/templates.js +4 -0
- package/dist/lib/answer-account/templates.js.map +1 -1
- package/dist/lib/mcp/elicitation.js +186 -0
- package/dist/lib/mcp/elicitation.js.map +1 -0
- package/dist/lib/mcp/mcpClient.js +8 -2
- package/dist/lib/mcp/mcpClient.js.map +1 -1
- package/dist/lib/mcp/mcpServe.js +5 -1
- package/dist/lib/mcp/mcpServe.js.map +1 -1
- package/dist/lib/mcp/mockMcpClient.js +4 -2
- package/dist/lib/mcp/mockMcpClient.js.map +1 -1
- package/dist/lib/mcp/toolExtras.js +25 -1
- package/dist/lib/mcp/toolExtras.js.map +1 -1
- package/dist/lib/time-travel/servedView.js +9 -0
- package/dist/lib/time-travel/servedView.js.map +1 -1
- package/dist/locales/index.js +8 -1
- package/dist/locales/index.js.map +1 -1
- package/dist/locales/timeAsk.js +47 -0
- package/dist/locales/timeAsk.js.map +1 -0
- package/dist/recorders/core/resilienceHooks.js +1 -0
- package/dist/recorders/core/resilienceHooks.js.map +1 -1
- package/dist/resilience/statedWait.js +39 -0
- package/dist/resilience/statedWait.js.map +1 -0
- package/dist/resilience/withRetry.js +16 -1
- package/dist/resilience/withRetry.js.map +1 -1
- package/dist/types/adapters/llm/AnthropicProvider.d.ts.map +1 -1
- package/dist/types/adapters/llm/BedrockProvider.d.ts.map +1 -1
- package/dist/types/adapters/llm/InvokeModelGatewayProvider.d.ts +38 -4
- package/dist/types/adapters/llm/InvokeModelGatewayProvider.d.ts.map +1 -1
- package/dist/types/adapters/llm/OpenAIProvider.d.ts.map +1 -1
- package/dist/types/adapters/llm/anthropicMessagesWire.d.ts +6 -1
- package/dist/types/adapters/llm/anthropicMessagesWire.d.ts.map +1 -1
- package/dist/types/adapters/llm/retryAfter.d.ts +28 -0
- package/dist/types/adapters/llm/retryAfter.d.ts.map +1 -0
- package/dist/types/adapters/types.d.ts +9 -0
- package/dist/types/adapters/types.d.ts.map +1 -1
- package/dist/types/artifacts/index.d.ts +1 -1
- package/dist/types/artifacts/index.d.ts.map +1 -1
- package/dist/types/artifacts/types.d.ts +2 -2
- package/dist/types/artifacts/types.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts +64 -0
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts +60 -0
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/arguments/ask.d.ts +88 -5
- package/dist/types/core/agent/arguments/ask.d.ts.map +1 -1
- package/dist/types/core/agent/arguments/checks.d.ts +1 -1
- package/dist/types/core/agent/arguments/checks.d.ts.map +1 -1
- package/dist/types/core/agent/arguments/declare.d.ts +76 -15
- package/dist/types/core/agent/arguments/declare.d.ts.map +1 -1
- package/dist/types/core/agent/arguments/dispatch.d.ts.map +1 -1
- package/dist/types/core/agent/arguments/resolve.d.ts +77 -7
- package/dist/types/core/agent/arguments/resolve.d.ts.map +1 -1
- package/dist/types/core/agent/arguments/rows.d.ts +31 -2
- package/dist/types/core/agent/arguments/rows.d.ts.map +1 -1
- package/dist/types/core/agent/arguments/serve.d.ts +133 -4
- package/dist/types/core/agent/arguments/serve.d.ts.map +1 -1
- package/dist/types/core/agent/arguments/subflow.d.ts +28 -0
- package/dist/types/core/agent/arguments/subflow.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/assess.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/compose.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/reasons.d.ts.map +1 -1
- package/dist/types/core/agent/assessment/types.d.ts +15 -1
- package/dist/types/core/agent/assessment/types.d.ts.map +1 -1
- package/dist/types/core/agent/buildAgentChart.d.ts +41 -0
- package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts +1 -1
- package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/answer.d.ts +20 -1
- package/dist/types/core/agent/coverage/answer.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/period.d.ts +49 -3
- package/dist/types/core/agent/coverage/period.d.ts.map +1 -1
- package/dist/types/core/agent/coverage/timeLimitFacts.d.ts +57 -0
- package/dist/types/core/agent/coverage/timeLimitFacts.d.ts.map +1 -0
- package/dist/types/core/agent/coverage/timeLimits.d.ts +47 -0
- package/dist/types/core/agent/coverage/timeLimits.d.ts.map +1 -0
- package/dist/types/core/agent/evidence/evidenceIndex.d.ts +25 -2
- package/dist/types/core/agent/evidence/evidenceIndex.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/gate.d.ts +7 -0
- package/dist/types/core/agent/evidence/gate.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/normalize.d.ts +0 -34
- package/dist/types/core/agent/evidence/normalize.d.ts.map +1 -1
- package/dist/types/core/agent/evidence/types.d.ts +12 -1
- package/dist/types/core/agent/evidence/types.d.ts.map +1 -1
- package/dist/types/core/agent/findings/ledger.d.ts.map +1 -1
- package/dist/types/core/agent/findings/types.d.ts +2 -1
- package/dist/types/core/agent/findings/types.d.ts.map +1 -1
- package/dist/types/core/agent/honesty/mounts.d.ts +25 -0
- package/dist/types/core/agent/honesty/mounts.d.ts.map +1 -1
- package/dist/types/core/agent/results/subflow.d.ts +34 -2
- package/dist/types/core/agent/results/subflow.d.ts.map +1 -1
- package/dist/types/core/agent/stages/argumentAsk.d.ts +19 -0
- package/dist/types/core/agent/stages/argumentAsk.d.ts.map +1 -1
- package/dist/types/core/agent/stages/callLLM.d.ts +6 -0
- package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
- package/dist/types/core/agent/stages/prepareFinal.d.ts +13 -1
- package/dist/types/core/agent/stages/prepareFinal.d.ts.map +1 -1
- package/dist/types/core/agent/stages/route.d.ts +29 -1
- package/dist/types/core/agent/stages/route.d.ts.map +1 -1
- package/dist/types/core/agent/stages/seed.d.ts +23 -0
- package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
- package/dist/types/core/agent/stages/timeLayer.d.ts +95 -0
- package/dist/types/core/agent/stages/timeLayer.d.ts.map +1 -0
- package/dist/types/core/agent/stages/timeLineage.d.ts +32 -0
- package/dist/types/core/agent/stages/timeLineage.d.ts.map +1 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts +32 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +37 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/inputRequest.d.ts +50 -6
- package/dist/types/core/inputRequest.d.ts.map +1 -1
- package/dist/types/core/messageFrom.d.ts +5 -2
- package/dist/types/core/messageFrom.d.ts.map +1 -1
- package/dist/types/core/runCheckpoint.d.ts.map +1 -1
- package/dist/types/core/slots/buildToolsSlot.d.ts +29 -0
- package/dist/types/core/slots/buildToolsSlot.d.ts.map +1 -1
- package/dist/types/core/time/ask.d.ts +127 -0
- package/dist/types/core/time/ask.d.ts.map +1 -0
- package/dist/types/core/time/axis.d.ts +225 -0
- package/dist/types/core/time/axis.d.ts.map +1 -0
- package/dist/types/core/time/bind.d.ts +144 -0
- package/dist/types/core/time/bind.d.ts.map +1 -0
- package/dist/types/core/time/check.d.ts +114 -0
- package/dist/types/core/time/check.d.ts.map +1 -0
- package/dist/types/core/time/checkRecord.d.ts +75 -0
- package/dist/types/core/time/checkRecord.d.ts.map +1 -0
- package/dist/types/core/time/clock.d.ts +184 -0
- package/dist/types/core/time/clock.d.ts.map +1 -0
- package/dist/types/core/time/convert.d.ts +179 -0
- package/dist/types/core/time/convert.d.ts.map +1 -0
- package/dist/types/core/time/drift.d.ts +86 -0
- package/dist/types/core/time/drift.d.ts.map +1 -0
- package/dist/types/core/time/duration.d.ts +72 -0
- package/dist/types/core/time/duration.d.ts.map +1 -0
- package/dist/types/core/time/forms.d.ts +85 -0
- package/dist/types/core/time/forms.d.ts.map +1 -0
- package/dist/types/core/time/instant.d.ts +76 -0
- package/dist/types/core/time/instant.d.ts.map +1 -0
- package/dist/types/core/time/periodForm.d.ts +185 -0
- package/dist/types/core/time/periodForm.d.ts.map +1 -0
- package/dist/types/core/time/present.d.ts +108 -0
- package/dist/types/core/time/present.d.ts.map +1 -0
- package/dist/types/core/time/range.d.ts +128 -0
- package/dist/types/core/time/range.d.ts.map +1 -0
- package/dist/types/core/time/reader.d.ts +163 -0
- package/dist/types/core/time/reader.d.ts.map +1 -0
- package/dist/types/core/time/readers/english.d.ts +100 -0
- package/dist/types/core/time/readers/english.d.ts.map +1 -0
- package/dist/types/core/time/readingAsk.d.ts +46 -0
- package/dist/types/core/time/readingAsk.d.ts.map +1 -0
- package/dist/types/core/time/resolve.d.ts +104 -0
- package/dist/types/core/time/resolve.d.ts.map +1 -0
- package/dist/types/core/time/resolveRecord.d.ts +161 -0
- package/dist/types/core/time/resolveRecord.d.ts.map +1 -0
- package/dist/types/core/time/rows.d.ts +298 -0
- package/dist/types/core/time/rows.d.ts.map +1 -0
- package/dist/types/core/time/rowsBuild.d.ts +83 -0
- package/dist/types/core/time/rowsBuild.d.ts.map +1 -0
- package/dist/types/core/time/textForms.d.ts +54 -0
- package/dist/types/core/time/textForms.d.ts.map +1 -0
- package/dist/types/core/time/windows.d.ts +114 -0
- package/dist/types/core/time/windows.d.ts.map +1 -0
- package/dist/types/core/time/wire.d.ts +64 -0
- package/dist/types/core/time/wire.d.ts.map +1 -0
- package/dist/types/core/time/zone.d.ts +116 -0
- package/dist/types/core/time/zone.d.ts.map +1 -0
- package/dist/types/core/tools.d.ts +26 -4
- package/dist/types/core/tools.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +16 -2
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/index.d.ts +13 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/answer-account/facts/howSure.d.ts.map +1 -1
- package/dist/types/lib/answer-account/templates.d.ts +3 -0
- package/dist/types/lib/answer-account/templates.d.ts.map +1 -1
- package/dist/types/lib/mcp/elicitation.d.ts +85 -0
- package/dist/types/lib/mcp/elicitation.d.ts.map +1 -0
- package/dist/types/lib/mcp/mcpServe.d.ts.map +1 -1
- package/dist/types/lib/mcp/mockMcpClient.d.ts +9 -1
- package/dist/types/lib/mcp/mockMcpClient.d.ts.map +1 -1
- package/dist/types/lib/mcp/toolExtras.d.ts +21 -2
- package/dist/types/lib/mcp/toolExtras.d.ts.map +1 -1
- package/dist/types/lib/mcp/types.d.ts +8 -0
- package/dist/types/lib/mcp/types.d.ts.map +1 -1
- package/dist/types/lib/time-travel/receipt.d.ts +1 -1
- package/dist/types/lib/time-travel/receipt.d.ts.map +1 -1
- package/dist/types/lib/time-travel/servedView.d.ts +1 -1
- package/dist/types/lib/time-travel/servedView.d.ts.map +1 -1
- package/dist/types/locales/index.d.ts +6 -0
- package/dist/types/locales/index.d.ts.map +1 -1
- package/dist/types/locales/timeAsk.d.ts +30 -0
- package/dist/types/locales/timeAsk.d.ts.map +1 -0
- package/dist/types/recorders/core/resilienceHooks.d.ts.map +1 -1
- package/dist/types/resilience/statedWait.d.ts +23 -0
- package/dist/types/resilience/statedWait.d.ts.map +1 -0
- package/dist/types/resilience/withRetry.d.ts +13 -2
- package/dist/types/resilience/withRetry.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/artifacts/timeAxis.js +0 -218
- package/dist/artifacts/timeAxis.js.map +0 -1
- package/dist/esm/artifacts/timeAxis.d.ts +0 -114
- package/dist/esm/artifacts/timeAxis.js +0 -212
- package/dist/esm/artifacts/timeAxis.js.map +0 -1
- package/dist/types/artifacts/timeAxis.d.ts +0 -115
- package/dist/types/artifacts/timeAxis.d.ts.map +0 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/time/readers/english — the library's careful English reader (time
|
|
3
|
+
* design § 5.3): a tokenizer over a small, closed set of phrases, and
|
|
4
|
+
* "unreadable" for every other time phrase it recognises.
|
|
5
|
+
*
|
|
6
|
+
* Pattern: Strategy behind the `TimeReader` port (`../reader.ts`). It
|
|
7
|
+
* TOKENIZES only: it returns the parts it sees and the verbatim
|
|
8
|
+
* quote. It never resolves an instant, never applies a date order,
|
|
9
|
+
* never maps a zone abbreviation and never refuses a future date —
|
|
10
|
+
* all of that is `resolve.ts`'s, the policy's or the ask's.
|
|
11
|
+
* Role: core/ leaf (the time layer). Imports only the port's types. Armed
|
|
12
|
+
* by the app: `.time({ reader: englishTimeReader() })` — there is no
|
|
13
|
+
* default reader.
|
|
14
|
+
* Emits: N/A.
|
|
15
|
+
*
|
|
16
|
+
* ## What it reads (the v1 rows of § 5.3)
|
|
17
|
+
*
|
|
18
|
+
* | Phrase | Example | Parts |
|
|
19
|
+
* |--------|---------|-------|
|
|
20
|
+
* | an ISO date or instant | `2026-10-09`, `2026-10-09T08:00-07:00` | `date: fixed`, `wall`, `zoneToken` |
|
|
21
|
+
* | a numeric date | `10/09/26`, `10/9` | `date: numeric` — the ORDER is not decided here |
|
|
22
|
+
* | a clock time | `8 AM`, `8:40`, `20:40`, `8:40 p.m.` | `wall` (a bare `8` is a time only as a range's first side: `8 to 9 AM`) |
|
|
23
|
+
* | a range between two of the above | `8 AM to 8:40 AM`, `08:00–08:40`, `between 8 and 9 AM` | `rangeOf` (a day or zone said once for both sides is the whole mention's) |
|
|
24
|
+
* | a zone after a time or date | `America/Los_Angeles`, `UTC-07:00`, `PST` | `zoneToken`, as written (an abbreviation is ASKED — v1 ships no map) |
|
|
25
|
+
* | a day word | today, yesterday, tomorrow | `relative: { unit: 'day', offset }` |
|
|
26
|
+
* | a relative span from now | last 40 minutes, past 2 hours, the last hour, the past week | `relative: { unit, count }` — a look-back in minutes, hours, days or weeks |
|
|
27
|
+
*
|
|
28
|
+
* ## What it says "unreadable" for — never a partial reading
|
|
29
|
+
*
|
|
30
|
+
* Parts of the day (`yesterday morning`, `tonight`, `noon`), calendar spans
|
|
31
|
+
* (`last week`, `this month`), week days and named months (`Friday`,
|
|
32
|
+
* `Oct 9`), `N hours ago`, spans in words (`last two hours`), in a unit it
|
|
33
|
+
* does not read (`last 30 seconds`, `last 3 months`) or said with `previous`
|
|
34
|
+
* (`previous 7 days` — often relative to another window), a look-ahead (`next 2 hours`), an
|
|
35
|
+
* ordinal day (`the 9th`), `8 o'clock`, and any v1 phrase a modifier changes
|
|
36
|
+
* (`since 8 AM`, `before yesterday`, `around 8:40`, `earlier today`,
|
|
37
|
+
* `8 AM to now`, `past 8 PM`, `8 AM-ish`, `from 3 PM yesterday` with no `to`) and
|
|
38
|
+
* a meridiem the number contradicts (`13:00 PM`). Such a phrase is ONE mention
|
|
39
|
+
* with `problem: 'unreadable'`, quoting the whole phrase: reading `yesterday`
|
|
40
|
+
* out of `yesterday morning` would silently widen what the person said.
|
|
41
|
+
*
|
|
42
|
+
* ## It only PROPOSES — the person confirms (the owner's decision "Always confirm")
|
|
43
|
+
*
|
|
44
|
+
* Nothing this reader reads is ever filed as the person's words. Seven review
|
|
45
|
+
* rounds each found the next English spelling a word list, an allow-list or a
|
|
46
|
+
* position rule missed (a zone named in words, a look-back tied to an event,
|
|
47
|
+
* an open end, a half-read range), so the owner decided (2026-09-30, time
|
|
48
|
+
* design TQ29): every reading of a chat message is a PROPOSAL, offered
|
|
49
|
+
* through the time ask pre-filled and editable, with its window AND its zone
|
|
50
|
+
* ("I read “last 2 hours” as … in America/Los_Angeles — is that right?").
|
|
51
|
+
* Only what the person picks or types in that form is theirs. The library
|
|
52
|
+
* owns the law (`../rowsBuild.ts` · `timeReadingRows`), so this reader returns
|
|
53
|
+
* parts and quotes only — no confirm flag, no leftover list, no allow-list.
|
|
54
|
+
* A form may later skip the click only when a registered benchmark shows it
|
|
55
|
+
* is always read right (TQ29's growth rule).
|
|
56
|
+
*
|
|
57
|
+
* A numeric date the tokens could split two ways stays ONE parse — `10/09/26`
|
|
58
|
+
* is three numbers; which is the month is the policy's or the person's.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* const reader = englishTimeReader();
|
|
63
|
+
* reader.read('errors on 10/09/26 8 AM to 8:40 AM PST', { locale: 'en-US' });
|
|
64
|
+
* // { mentions: [{ quote: '10/09/26 8 AM to 8:40 AM PST', parses: [{
|
|
65
|
+
* // date: { kind: 'numeric', fields: [10, 9, 26], yearDigits: 2 }, zoneToken: 'PST',
|
|
66
|
+
* // rangeOf: [{ wall: { h: 8, meridiem: 'am' } }, { wall: { h: 8, m: 40, meridiem: 'am' } }] }] }] }
|
|
67
|
+
* reader.read('errors in the last 2 hours', { locale: 'en-US' });
|
|
68
|
+
* // { mentions: [{ quote: 'last 2 hours', parses: [{ relative: { unit: 'hour', count: 2 } }] }] }
|
|
69
|
+
* reader.read('what failed yesterday morning?', { locale: 'en-US' });
|
|
70
|
+
* // { mentions: [{ quote: 'yesterday morning', parses: [], problem: 'unreadable' }] }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
import { type TimeReader } from '../reader.js';
|
|
74
|
+
/** The reader's recorded identity — on every `time-reading` row with its version. */
|
|
75
|
+
export declare const ENGLISH_TIME_READER_ID = "agentfootprint/english";
|
|
76
|
+
/** Raised whenever what the reader returns for some text changes. */
|
|
77
|
+
export declare const ENGLISH_TIME_READER_VERSION = "1.0.0";
|
|
78
|
+
/** Options for {@link englishTimeReader}. */
|
|
79
|
+
export interface EnglishTimeReaderOptions {
|
|
80
|
+
/**
|
|
81
|
+
* The language tag the time ask's labels are rendered in (`present.ts`),
|
|
82
|
+
* e.g. `'en-GB'`. Default `'en-US'`. It never decides a date order — that is
|
|
83
|
+
* the policy's (`dateOrder`) or the person's.
|
|
84
|
+
*/
|
|
85
|
+
readonly locale?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The library's careful English reader: a `kind: 'rule'` tokenizer over the
|
|
89
|
+
* v1 phrases of the time design's § 5.3, "unreadable" for every other time
|
|
90
|
+
* phrase it recognises. No dependency; deterministic over the text.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```ts
|
|
94
|
+
* Agent.create({ provider, model })
|
|
95
|
+
* .time({ zone: 'America/Los_Angeles', reader: englishTimeReader() })
|
|
96
|
+
* .build();
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export declare function englishTimeReader(options?: EnglishTimeReaderOptions): TimeReader;
|
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/time/readers/english — the library's careful English reader (time
|
|
3
|
+
* design § 5.3): a tokenizer over a small, closed set of phrases, and
|
|
4
|
+
* "unreadable" for every other time phrase it recognises.
|
|
5
|
+
*
|
|
6
|
+
* Pattern: Strategy behind the `TimeReader` port (`../reader.ts`). It
|
|
7
|
+
* TOKENIZES only: it returns the parts it sees and the verbatim
|
|
8
|
+
* quote. It never resolves an instant, never applies a date order,
|
|
9
|
+
* never maps a zone abbreviation and never refuses a future date —
|
|
10
|
+
* all of that is `resolve.ts`'s, the policy's or the ask's.
|
|
11
|
+
* Role: core/ leaf (the time layer). Imports only the port's types. Armed
|
|
12
|
+
* by the app: `.time({ reader: englishTimeReader() })` — there is no
|
|
13
|
+
* default reader.
|
|
14
|
+
* Emits: N/A.
|
|
15
|
+
*
|
|
16
|
+
* ## What it reads (the v1 rows of § 5.3)
|
|
17
|
+
*
|
|
18
|
+
* | Phrase | Example | Parts |
|
|
19
|
+
* |--------|---------|-------|
|
|
20
|
+
* | an ISO date or instant | `2026-10-09`, `2026-10-09T08:00-07:00` | `date: fixed`, `wall`, `zoneToken` |
|
|
21
|
+
* | a numeric date | `10/09/26`, `10/9` | `date: numeric` — the ORDER is not decided here |
|
|
22
|
+
* | a clock time | `8 AM`, `8:40`, `20:40`, `8:40 p.m.` | `wall` (a bare `8` is a time only as a range's first side: `8 to 9 AM`) |
|
|
23
|
+
* | a range between two of the above | `8 AM to 8:40 AM`, `08:00–08:40`, `between 8 and 9 AM` | `rangeOf` (a day or zone said once for both sides is the whole mention's) |
|
|
24
|
+
* | a zone after a time or date | `America/Los_Angeles`, `UTC-07:00`, `PST` | `zoneToken`, as written (an abbreviation is ASKED — v1 ships no map) |
|
|
25
|
+
* | a day word | today, yesterday, tomorrow | `relative: { unit: 'day', offset }` |
|
|
26
|
+
* | a relative span from now | last 40 minutes, past 2 hours, the last hour, the past week | `relative: { unit, count }` — a look-back in minutes, hours, days or weeks |
|
|
27
|
+
*
|
|
28
|
+
* ## What it says "unreadable" for — never a partial reading
|
|
29
|
+
*
|
|
30
|
+
* Parts of the day (`yesterday morning`, `tonight`, `noon`), calendar spans
|
|
31
|
+
* (`last week`, `this month`), week days and named months (`Friday`,
|
|
32
|
+
* `Oct 9`), `N hours ago`, spans in words (`last two hours`), in a unit it
|
|
33
|
+
* does not read (`last 30 seconds`, `last 3 months`) or said with `previous`
|
|
34
|
+
* (`previous 7 days` — often relative to another window), a look-ahead (`next 2 hours`), an
|
|
35
|
+
* ordinal day (`the 9th`), `8 o'clock`, and any v1 phrase a modifier changes
|
|
36
|
+
* (`since 8 AM`, `before yesterday`, `around 8:40`, `earlier today`,
|
|
37
|
+
* `8 AM to now`, `past 8 PM`, `8 AM-ish`, `from 3 PM yesterday` with no `to`) and
|
|
38
|
+
* a meridiem the number contradicts (`13:00 PM`). Such a phrase is ONE mention
|
|
39
|
+
* with `problem: 'unreadable'`, quoting the whole phrase: reading `yesterday`
|
|
40
|
+
* out of `yesterday morning` would silently widen what the person said.
|
|
41
|
+
*
|
|
42
|
+
* ## It only PROPOSES — the person confirms (the owner's decision "Always confirm")
|
|
43
|
+
*
|
|
44
|
+
* Nothing this reader reads is ever filed as the person's words. Seven review
|
|
45
|
+
* rounds each found the next English spelling a word list, an allow-list or a
|
|
46
|
+
* position rule missed (a zone named in words, a look-back tied to an event,
|
|
47
|
+
* an open end, a half-read range), so the owner decided (2026-09-30, time
|
|
48
|
+
* design TQ29): every reading of a chat message is a PROPOSAL, offered
|
|
49
|
+
* through the time ask pre-filled and editable, with its window AND its zone
|
|
50
|
+
* ("I read “last 2 hours” as … in America/Los_Angeles — is that right?").
|
|
51
|
+
* Only what the person picks or types in that form is theirs. The library
|
|
52
|
+
* owns the law (`../rowsBuild.ts` · `timeReadingRows`), so this reader returns
|
|
53
|
+
* parts and quotes only — no confirm flag, no leftover list, no allow-list.
|
|
54
|
+
* A form may later skip the click only when a registered benchmark shows it
|
|
55
|
+
* is always read right (TQ29's growth rule).
|
|
56
|
+
*
|
|
57
|
+
* A numeric date the tokens could split two ways stays ONE parse — `10/09/26`
|
|
58
|
+
* is three numbers; which is the month is the policy's or the person's.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* const reader = englishTimeReader();
|
|
63
|
+
* reader.read('errors on 10/09/26 8 AM to 8:40 AM PST', { locale: 'en-US' });
|
|
64
|
+
* // { mentions: [{ quote: '10/09/26 8 AM to 8:40 AM PST', parses: [{
|
|
65
|
+
* // date: { kind: 'numeric', fields: [10, 9, 26], yearDigits: 2 }, zoneToken: 'PST',
|
|
66
|
+
* // rangeOf: [{ wall: { h: 8, meridiem: 'am' } }, { wall: { h: 8, m: 40, meridiem: 'am' } }] }] }] }
|
|
67
|
+
* reader.read('errors in the last 2 hours', { locale: 'en-US' });
|
|
68
|
+
* // { mentions: [{ quote: 'last 2 hours', parses: [{ relative: { unit: 'hour', count: 2 } }] }] }
|
|
69
|
+
* reader.read('what failed yesterday morning?', { locale: 'en-US' });
|
|
70
|
+
* // { mentions: [{ quote: 'yesterday morning', parses: [], problem: 'unreadable' }] }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
import { isTimeParts, MAX_MENTIONS, } from '../reader.js';
|
|
74
|
+
// ─── The words (data) ────────────────────────────────────────────────────
|
|
75
|
+
/** The reader's recorded identity — on every `time-reading` row with its version. */
|
|
76
|
+
export const ENGLISH_TIME_READER_ID = 'agentfootprint/english';
|
|
77
|
+
/** Raised whenever what the reader returns for some text changes. */
|
|
78
|
+
export const ENGLISH_TIME_READER_VERSION = '1.0.0';
|
|
79
|
+
const DAY_WORDS = { today: 0, yesterday: -1, tomorrow: 1 };
|
|
80
|
+
/** The units a look-back is read in: minutes, hours, days, weeks. */
|
|
81
|
+
const SPAN_UNITS = {
|
|
82
|
+
minute: 'minute',
|
|
83
|
+
min: 'minute',
|
|
84
|
+
hour: 'hour',
|
|
85
|
+
hr: 'hour',
|
|
86
|
+
day: 'day',
|
|
87
|
+
week: 'week',
|
|
88
|
+
};
|
|
89
|
+
/** Zone abbreviations the reader TOKENIZES after a time or a date — never maps (§ 5.3). */
|
|
90
|
+
const ZONE_ABBREVIATIONS = [
|
|
91
|
+
'UTC', 'GMT', 'PST', 'PDT', 'PT', 'MST', 'MDT', 'MT', 'CST', 'CDT', 'CT', 'EST', 'EDT', 'ET',
|
|
92
|
+
'AKST', 'AKDT', 'HST', 'AST', 'ADT', 'NST', 'NDT', 'BST', 'IST', 'CET', 'CEST', 'EET', 'EEST',
|
|
93
|
+
'WET', 'WEST', 'MSK', 'JST', 'KST', 'HKT', 'SGT', 'AEST', 'AEDT', 'ACST', 'ACDT', 'AWST',
|
|
94
|
+
'NZST', 'NZDT', 'SAST',
|
|
95
|
+
]; // prettier-ignore
|
|
96
|
+
const IANA_AREAS = 'Africa|America|Antarctica|Arctic|Asia|Atlantic|Australia|Europe|Indian|Pacific|Etc';
|
|
97
|
+
const UNIT_WORDS = 'seconds?|secs?|minutes?|mins?|hours?|hrs?|days?|weeks?|months?|years?|quarters?';
|
|
98
|
+
const NUMBER_WORDS = 'an?|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve|fifteen|twenty|thirty|' +
|
|
99
|
+
'forty|fifty|sixty|ninety|few|several|couple(?:\\s+of)?';
|
|
100
|
+
const MONTHS = 'jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may|june?|july?|aug(?:ust)?|' +
|
|
101
|
+
'sep(?:t(?:ember)?)?|oct(?:ober)?|nov(?:ember)?|dec(?:ember)?';
|
|
102
|
+
/**
|
|
103
|
+
* Time phrases v1 does not read (§ 5.3's "later" rows and everything past
|
|
104
|
+
* them). Each forms an `unreadable` mention on its own, and taints any v1
|
|
105
|
+
* phrase it touches.
|
|
106
|
+
*/
|
|
107
|
+
const NOT_READ = [
|
|
108
|
+
/\b(?:(?:this|last|early|late|mid)\s+)?(?:morning|afternoon|evening|night|tonight|overnight|noon|midday|midnight|lunchtime|dawn|dusk)s?\b/gi,
|
|
109
|
+
/\b(?:last|this|next|past|previous|coming|current)\s+(?:week|month|year|quarter|weekend|hour|minute|second|day|night|decade|fortnight|shift)\b/gi,
|
|
110
|
+
/\bweekends?\b/gi,
|
|
111
|
+
/\b(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday)s?\b/gi,
|
|
112
|
+
new RegExp(`\\b(?:${MONTHS})\\.?\\s+\\d{1,2}(?:st|nd|rd|th)?\\b(?:,?\\s+\\d{4}\\b)?`, 'gi'),
|
|
113
|
+
new RegExp(`\\b\\d{1,2}(?:st|nd|rd|th)?\\s+(?:of\\s+)?(?:${MONTHS})\\b\\.?(?:,?\\s+\\d{4}\\b)?`, 'gi'),
|
|
114
|
+
/\b(?:january|february|july|september|october|november|december)\b/gi,
|
|
115
|
+
new RegExp(`\\b(?:\\d+|${NUMBER_WORDS})\\s+(?:${UNIT_WORDS})\\s+ago\\b`, 'gi'),
|
|
116
|
+
new RegExp(`\\b(?:last|past|previous|next|coming|upcoming|following)\\s+` +
|
|
117
|
+
`(?:(?:${NUMBER_WORDS}|\\d+)\\s+)?(?:${UNIT_WORDS})\\b`, 'gi'),
|
|
118
|
+
/\b(?:the\s+)?day\s+(?:before\s+yesterday|after\s+tomorrow)\b/gi,
|
|
119
|
+
/\bon\s+the\s+\d{1,2}(?:st|nd|rd|th)\b/gi,
|
|
120
|
+
/\bthe\s+\d{1,2}(?:st|nd|rd|th)\s+of\b/gi,
|
|
121
|
+
/\b\d{1,2}\s*o['’]?\s?clock\b/gi,
|
|
122
|
+
// A meridiem on a number that is no 12-hour time (`13:00 PM`, `0 AM`): the words contradict.
|
|
123
|
+
/(?<![\w:.+/])\d{1,2}(?::\d{2}){0,2}\s?(?:am|pm|a\.m\.|p\.m\.)(?![a-z])/gi,
|
|
124
|
+
];
|
|
125
|
+
// ─── The range grammar (one owner) ──────────────────────────────────────
|
|
126
|
+
//
|
|
127
|
+
// The connectors a v1 range is READ with — the grammar's own list: the joins
|
|
128
|
+
// (`joins`), the bare hour's lookahead (`BARE_HOUR`) and `… to now`
|
|
129
|
+
// (`MODIFIER_AFTER`) all build from it. What the reader did not read is not
|
|
130
|
+
// its question any more: every reading is a proposal the person confirms
|
|
131
|
+
// (the owner's decision "Always confirm", time design TQ29).
|
|
132
|
+
const RANGE_WORDS = 'to|until|till|through|thru';
|
|
133
|
+
/** A range connector the grammar reads: a word, or a hyphen, en dash or em dash. */
|
|
134
|
+
const RANGE_CONNECTOR = `(?:(?:${RANGE_WORDS})(?![a-z])|[–—-])`;
|
|
135
|
+
/** A word right before a phrase that changes what it means: the phrase is not read. */
|
|
136
|
+
const MODIFIER_BEFORE = new RegExp('(?:^|[^\\w])(since|before|after|by|around|circa|approx(?:imately)?|until|till|earlier|later|' +
|
|
137
|
+
'early|late|within|past|beyond|prior\\s+to|up\\s+to|no\\s+(?:later|earlier|sooner)\\s+than|' +
|
|
138
|
+
'as\\s+of|(?:starting|beginning)(?:\\s+(?:at|from|on))?|~)\\s*$', 'i');
|
|
139
|
+
/** `from` with no `to`: a time after it is where a window STARTS (`from 3 PM yesterday`), not an hour. */
|
|
140
|
+
const FROM_BEFORE = /(?:^|[^\w])(from)\s*$/i;
|
|
141
|
+
/** …and right after it. */
|
|
142
|
+
const MODIFIER_AFTER = new RegExp('^(?:\\s*-?\\s*ish\\b|\\s*(?:ago\\b|onwards?\\b|or\\s+so\\b|(?:or|and)\\s+(?:later|earlier|after|before)\\b|' +
|
|
143
|
+
`at\\s+the\\s+(?:latest|earliest)\\b|${RANGE_CONNECTOR}\\s*now\\b))`, 'i');
|
|
144
|
+
/** Text not preceded by something that would make these digits part of a larger token. */
|
|
145
|
+
const NOT_AFTER = '(?<![\\w:./-])';
|
|
146
|
+
/**
|
|
147
|
+
* The same for a clock time — which may follow a range's hyphen (`8:00-8:40`)
|
|
148
|
+
* or `..` (`2026-09-26 08:00..08:40`), never an offset's sign or one dot.
|
|
149
|
+
*/
|
|
150
|
+
const TIME_NOT_AFTER = '(?<![\\w:+/])(?<!(?:^|[^.])\\.)';
|
|
151
|
+
const ISO = new RegExp(
|
|
152
|
+
// An ISO interval's second end follows its first's `/` (`…08:00Z/2026-…`) or `..`; a path's `/` does not count.
|
|
153
|
+
`(?<![\\w:-])(?<!(?:^|[^.])\\.)(?<![^\\dZ]/)(?<!^/)(\\d{4})-(\\d{2})-(\\d{2})` +
|
|
154
|
+
'(?:[Tt ](\\d{2}):(\\d{2})(?::(\\d{2}))?(Z|[+-]\\d{2}(?::?\\d{2})?)?)?' +
|
|
155
|
+
'(?![\\w:]|[.-]\\d)', 'g');
|
|
156
|
+
const NUMERIC = new RegExp(
|
|
157
|
+
// A hyphen may join two dates (`10/01/26-10/09/26`).
|
|
158
|
+
`(?<![\\w:./])(\\d{1,4})/(\\d{1,2})(?:/(\\d{4}|\\d{2}))?(?![\\w/:]|\\.\\d)`, 'g');
|
|
159
|
+
const WALL_MERIDIEM = new RegExp(`${TIME_NOT_AFTER}(\\d{1,2})(?::(\\d{2})(?::(\\d{2}))?)?\\s?(am|pm|a\\.m\\.|p\\.m\\.)(?![a-z])`, 'gi');
|
|
160
|
+
const WALL_COLON = new RegExp(
|
|
161
|
+
// A meridiem after it is `WALL_MERIDIEM`'s — or, when that refuses it (`13:00 PM`), unreadable.
|
|
162
|
+
`${TIME_NOT_AFTER}(\\d{1,2}):(\\d{2})(?::(\\d{2}))?(?![\\d:])(?!\\s?(?:am|pm|a\\.m\\.|p\\.m\\.)(?![a-z]))`, 'gi');
|
|
163
|
+
/** A bare hour — a time only as a range's first side whose second side carries a meridiem. */
|
|
164
|
+
const BARE_HOUR = new RegExp(`${NOT_AFTER}(\\d{1,2})(?=\\s*(?:${RANGE_CONNECTOR}|and)\\s*` +
|
|
165
|
+
'\\d{1,2}(?::\\d{2})?\\s?(?:am|pm|a\\.m\\.|p\\.m\\.)(?![a-z]))', 'gi');
|
|
166
|
+
const DAY_WORD = /\b(today|yesterday|tomorrow)\b/gi;
|
|
167
|
+
const SPAN = /\b(?:last|past)\s+(\d{1,6})\s*(minutes?|mins?|hours?|hrs?|days?|weeks?)\b/gi;
|
|
168
|
+
/** `the last hour`, `the past week` — a look-back of one unit; without `the`, `last week` is a calendar week (not read). */
|
|
169
|
+
const ONE_SPAN = /\bthe\s+(?:last|past)\s+(hour|day|week)\b/gi;
|
|
170
|
+
/** A zone right after a phrase: optional `(`, or `in`, then the token (and a closing `)`). */
|
|
171
|
+
const ZONE_AFTER = new RegExp('^(\\s*\\(?\\s*|\\s+in\\s+)' +
|
|
172
|
+
`(?:(${IANA_AREAS})/[A-Za-z0-9_+-]+(?:/[A-Za-z0-9_+-]+)?` +
|
|
173
|
+
'|(?:UTC|GMT)\\s?([+-]\\d{1,2}(?::?\\d{2})?)' +
|
|
174
|
+
`|(${ZONE_ABBREVIATIONS.join('|')}))(?![A-Za-z0-9_/])(\\s*\\))?`);
|
|
175
|
+
const num = (text) => text === undefined ? undefined : Number(text);
|
|
176
|
+
function wallOf(h, m, s, meridiem) {
|
|
177
|
+
if (!Number.isInteger(h) || h > 23)
|
|
178
|
+
return undefined;
|
|
179
|
+
if (m !== undefined && m > 59)
|
|
180
|
+
return undefined;
|
|
181
|
+
if (s !== undefined && s > 59)
|
|
182
|
+
return undefined;
|
|
183
|
+
if (meridiem !== undefined && (h < 1 || h > 12))
|
|
184
|
+
return undefined;
|
|
185
|
+
return {
|
|
186
|
+
h,
|
|
187
|
+
...(m !== undefined && { m }),
|
|
188
|
+
...(s !== undefined && { s }),
|
|
189
|
+
...(meridiem !== undefined && { meridiem }),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function* matches(re, text) {
|
|
193
|
+
re.lastIndex = 0;
|
|
194
|
+
for (let m = re.exec(text); m !== null; m = re.exec(text)) {
|
|
195
|
+
yield m;
|
|
196
|
+
if (m[0].length === 0)
|
|
197
|
+
re.lastIndex++;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
function isoAtoms(text) {
|
|
201
|
+
const out = [];
|
|
202
|
+
for (const m of matches(ISO, text)) {
|
|
203
|
+
const [, y, mo, d, h, mi, s, zone] = m;
|
|
204
|
+
const date = { kind: 'fixed', year: Number(y), month: Number(mo), day: Number(d) };
|
|
205
|
+
const wall = h === undefined ? undefined : wallOf(Number(h), Number(mi), num(s));
|
|
206
|
+
if (h !== undefined && wall === undefined)
|
|
207
|
+
continue;
|
|
208
|
+
out.push({
|
|
209
|
+
start: m.index,
|
|
210
|
+
end: m.index + m[0].length,
|
|
211
|
+
kind: 'instant',
|
|
212
|
+
date,
|
|
213
|
+
...(wall !== undefined && { wall }),
|
|
214
|
+
...(zone !== undefined && { zoneToken: zone }),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
function numericAtoms(text) {
|
|
220
|
+
const out = [];
|
|
221
|
+
for (const m of matches(NUMERIC, text)) {
|
|
222
|
+
const [, a, b, c] = m;
|
|
223
|
+
if (a.length === 3 || (a.length === 4 && c === undefined))
|
|
224
|
+
continue;
|
|
225
|
+
const fields = [Number(a), Number(b), ...(c !== undefined ? [Number(c)] : [])];
|
|
226
|
+
const yearDigits = c === undefined ? undefined : a.length === 4 ? 4 : c.length;
|
|
227
|
+
out.push({
|
|
228
|
+
start: m.index,
|
|
229
|
+
end: m.index + m[0].length,
|
|
230
|
+
kind: 'date',
|
|
231
|
+
date: { kind: 'numeric', fields, ...(yearDigits !== undefined && { yearDigits }) },
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
return out;
|
|
235
|
+
}
|
|
236
|
+
function wallAtoms(text) {
|
|
237
|
+
const out = [];
|
|
238
|
+
for (const m of matches(WALL_MERIDIEM, text)) {
|
|
239
|
+
const meridiem = m[4].toLowerCase().startsWith('a') ? 'am' : 'pm';
|
|
240
|
+
const wall = wallOf(Number(m[1]), num(m[2]), num(m[3]), meridiem);
|
|
241
|
+
if (wall !== undefined) {
|
|
242
|
+
out.push({ start: m.index, end: m.index + m[0].length, kind: 'wall', wall });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
for (const m of matches(WALL_COLON, text)) {
|
|
246
|
+
const wall = wallOf(Number(m[1]), Number(m[2]), num(m[3]));
|
|
247
|
+
if (wall !== undefined) {
|
|
248
|
+
out.push({ start: m.index, end: m.index + m[0].length, kind: 'wall', wall });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
for (const m of matches(BARE_HOUR, text)) {
|
|
252
|
+
const wall = wallOf(Number(m[1]));
|
|
253
|
+
if (wall !== undefined) {
|
|
254
|
+
out.push({ start: m.index, end: m.index + m[0].length, kind: 'bare', wall });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return out;
|
|
258
|
+
}
|
|
259
|
+
function wordAtoms(text) {
|
|
260
|
+
const out = [];
|
|
261
|
+
for (const m of matches(DAY_WORD, text)) {
|
|
262
|
+
const offset = DAY_WORDS[m[1].toLowerCase()];
|
|
263
|
+
out.push({
|
|
264
|
+
start: m.index,
|
|
265
|
+
end: m.index + m[0].length,
|
|
266
|
+
kind: 'day',
|
|
267
|
+
relative: { unit: 'day', offset },
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
for (const m of matches(SPAN, text)) {
|
|
271
|
+
const count = Number(m[1]);
|
|
272
|
+
const unit = SPAN_UNITS[m[2].toLowerCase().replace(/s$/, '')];
|
|
273
|
+
if (unit === undefined || count < 1 || count > 100_000)
|
|
274
|
+
continue;
|
|
275
|
+
out.push({
|
|
276
|
+
start: m.index,
|
|
277
|
+
end: m.index + m[0].length,
|
|
278
|
+
kind: 'span',
|
|
279
|
+
relative: { unit, count },
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
for (const m of matches(ONE_SPAN, text)) {
|
|
283
|
+
const unit = SPAN_UNITS[m[1].toLowerCase()];
|
|
284
|
+
out.push({
|
|
285
|
+
start: m.index,
|
|
286
|
+
end: m.index + m[0].length,
|
|
287
|
+
kind: 'span',
|
|
288
|
+
relative: { unit, count: 1 },
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
return out;
|
|
292
|
+
}
|
|
293
|
+
/** The v1 phrases, overlaps settled: the earlier, then the longer, wins. */
|
|
294
|
+
function atomsOf(text) {
|
|
295
|
+
const all = [...isoAtoms(text), ...numericAtoms(text), ...wallAtoms(text), ...wordAtoms(text)];
|
|
296
|
+
all.sort((a, b) => a.start - b.start || b.end - b.start - (a.end - a.start));
|
|
297
|
+
const kept = [];
|
|
298
|
+
for (const atom of all) {
|
|
299
|
+
const last = kept[kept.length - 1];
|
|
300
|
+
if (last !== undefined && atom.start < last.end)
|
|
301
|
+
continue;
|
|
302
|
+
kept.push({ ...atom });
|
|
303
|
+
}
|
|
304
|
+
for (const atom of kept)
|
|
305
|
+
attachZone(text, atom);
|
|
306
|
+
// A zone written after a phrase may cover a phrase found on its own (`UTC-07:00` holds `07:00`).
|
|
307
|
+
const out = [];
|
|
308
|
+
for (const atom of kept) {
|
|
309
|
+
const last = out[out.length - 1];
|
|
310
|
+
if (last === undefined || atom.start >= last.end)
|
|
311
|
+
out.push(atom);
|
|
312
|
+
}
|
|
313
|
+
return out;
|
|
314
|
+
}
|
|
315
|
+
/** A zone written right after a date or a time joins that phrase, as written. */
|
|
316
|
+
function attachZone(text, atom) {
|
|
317
|
+
if (atom.kind === 'day' || atom.kind === 'span' || atom.kind === 'bare')
|
|
318
|
+
return;
|
|
319
|
+
if (atom.zoneToken !== undefined)
|
|
320
|
+
return;
|
|
321
|
+
const m = ZONE_AFTER.exec(text.slice(atom.end));
|
|
322
|
+
if (m === null)
|
|
323
|
+
return;
|
|
324
|
+
const lead = m[1];
|
|
325
|
+
const opened = lead.includes('(');
|
|
326
|
+
const closed = m[5] !== undefined;
|
|
327
|
+
if (opened !== closed)
|
|
328
|
+
return;
|
|
329
|
+
// The IANA name, else the offset after `UTC` / `GMT`, else the abbreviation — each verbatim.
|
|
330
|
+
const whole = m[0].slice(lead.length).replace(/\s*\)$/, '');
|
|
331
|
+
const token = m[2] !== undefined ? whole : m[3] !== undefined ? m[3] : m[4];
|
|
332
|
+
atom.zoneToken = token;
|
|
333
|
+
atom.end += m[0].length;
|
|
334
|
+
}
|
|
335
|
+
function notReadSpans(text, atoms) {
|
|
336
|
+
const out = [];
|
|
337
|
+
for (const re of NOT_READ) {
|
|
338
|
+
for (const m of matches(re, text)) {
|
|
339
|
+
const span = { start: m.index, end: m.index + m[0].length };
|
|
340
|
+
// A span a v1 phrase covers whole is that phrase (`last 40 minutes`), not a later row.
|
|
341
|
+
if (atoms.some((a) => a.start <= span.start && span.end <= a.end))
|
|
342
|
+
continue;
|
|
343
|
+
out.push(span);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
return out;
|
|
347
|
+
}
|
|
348
|
+
// ─── Mentions ────────────────────────────────────────────────────────────
|
|
349
|
+
/** A gap token that is one of the grammar's range connectors. */
|
|
350
|
+
const CONNECTOR = new RegExp(`^${RANGE_CONNECTOR}$`, 'i');
|
|
351
|
+
const GLUE = /^(?:,|at|on|in|of|the|@|from|between)$/i;
|
|
352
|
+
/** The words and marks between two phrases. */
|
|
353
|
+
const gapTokens = (gap) => gap.match(/\.\.|[–—\-/,@()]|[A-Za-z]+|\d+|\S/g) ?? [];
|
|
354
|
+
/** Whether the text between two phrases only joins them — and whether it says "range". */
|
|
355
|
+
function joins(gap, between, left, right) {
|
|
356
|
+
if (gap.replace(/[\s\w,@()./–—-]/g, '') !== '')
|
|
357
|
+
return undefined;
|
|
358
|
+
const tokens = gapTokens(gap);
|
|
359
|
+
let range = false;
|
|
360
|
+
for (const t of tokens) {
|
|
361
|
+
const instants = left.atom?.kind === 'instant' && right.atom?.kind === 'instant';
|
|
362
|
+
if (CONNECTOR.test(t) || t === '..' || (instants && t === '/')) {
|
|
363
|
+
if (range)
|
|
364
|
+
return undefined;
|
|
365
|
+
range = true;
|
|
366
|
+
}
|
|
367
|
+
else if (t.toLowerCase() === 'and' && between) {
|
|
368
|
+
if (range)
|
|
369
|
+
return undefined;
|
|
370
|
+
range = true;
|
|
371
|
+
}
|
|
372
|
+
else if (!GLUE.test(t)) {
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return range ? 'range' : 'glue';
|
|
377
|
+
}
|
|
378
|
+
function groupsOf(text, atoms, notRead) {
|
|
379
|
+
const items = [
|
|
380
|
+
...atoms.map((atom) => ({ start: atom.start, end: atom.end, atom })),
|
|
381
|
+
...notRead.map((s) => ({ start: s.start, end: s.end })),
|
|
382
|
+
].sort((a, b) => a.start - b.start || b.end - a.end);
|
|
383
|
+
const groups = [];
|
|
384
|
+
for (const item of items) {
|
|
385
|
+
const group = groups[groups.length - 1];
|
|
386
|
+
const last = group?.items[group.items.length - 1];
|
|
387
|
+
if (group !== undefined && last !== undefined) {
|
|
388
|
+
if (item.start < group.end) {
|
|
389
|
+
group.items.push(item);
|
|
390
|
+
group.end = Math.max(group.end, item.end);
|
|
391
|
+
group.unreadable = true;
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
const between = /\bbetween\s+$/i.test(text.slice(0, group.start));
|
|
395
|
+
const joined = joins(text.slice(group.end, item.start), between, last, item);
|
|
396
|
+
if (joined !== undefined) {
|
|
397
|
+
if (joined === 'range') {
|
|
398
|
+
if (group.rangeAt !== undefined)
|
|
399
|
+
group.unreadable = true;
|
|
400
|
+
group.rangeAt = group.items.length;
|
|
401
|
+
}
|
|
402
|
+
group.items.push(item);
|
|
403
|
+
group.end = item.end;
|
|
404
|
+
if (item.atom === undefined)
|
|
405
|
+
group.unreadable = true;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
groups.push({
|
|
410
|
+
start: item.start,
|
|
411
|
+
end: item.end,
|
|
412
|
+
items: [item],
|
|
413
|
+
unreadable: item.atom === undefined,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
for (const group of groups)
|
|
417
|
+
widenForModifiers(text, group);
|
|
418
|
+
return mergeOverlaps(groups).filter((g) => g.unreadable || g.items.some((i) => i.atom?.kind !== 'bare'));
|
|
419
|
+
}
|
|
420
|
+
/** Groups a widening made overlap are one phrase (`8 and 9 AM` held the bare `8` on its own). */
|
|
421
|
+
function mergeOverlaps(groups) {
|
|
422
|
+
const out = [];
|
|
423
|
+
for (const group of [...groups].sort((a, b) => a.start - b.start)) {
|
|
424
|
+
const last = out[out.length - 1];
|
|
425
|
+
if (last !== undefined && group.start < last.end) {
|
|
426
|
+
last.items.push(...group.items);
|
|
427
|
+
last.end = Math.max(last.end, group.end);
|
|
428
|
+
last.unreadable = true;
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
out.push(group);
|
|
432
|
+
}
|
|
433
|
+
return out;
|
|
434
|
+
}
|
|
435
|
+
/** A modifier before or after a v1 phrase changes it: the whole phrase is not read. */
|
|
436
|
+
function widenForModifiers(text, group) {
|
|
437
|
+
const head = text.slice(0, group.start);
|
|
438
|
+
const clock = group.items.some((i) => i.atom?.wall !== undefined);
|
|
439
|
+
const before = MODIFIER_BEFORE.exec(head) ??
|
|
440
|
+
(group.rangeAt === undefined && clock ? FROM_BEFORE.exec(head) : null);
|
|
441
|
+
if (before !== null) {
|
|
442
|
+
group.start = before.index + before[0].lastIndexOf(before[1]);
|
|
443
|
+
group.unreadable = true;
|
|
444
|
+
}
|
|
445
|
+
const after = MODIFIER_AFTER.exec(text.slice(group.end));
|
|
446
|
+
if (after !== null) {
|
|
447
|
+
group.end += after[0].length;
|
|
448
|
+
group.unreadable = true;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
/** One side's parts from its phrases — `undefined` when two phrases say the same part. */
|
|
452
|
+
function sideOf(atoms) {
|
|
453
|
+
const side = {};
|
|
454
|
+
for (const a of atoms) {
|
|
455
|
+
if (a.date !== undefined || a.kind === 'day') {
|
|
456
|
+
if (side.date !== undefined || side.relative !== undefined)
|
|
457
|
+
return undefined;
|
|
458
|
+
if (a.date !== undefined)
|
|
459
|
+
side.date = a.date;
|
|
460
|
+
if (a.kind === 'day')
|
|
461
|
+
side.relative = a.relative;
|
|
462
|
+
side.dayFirst = side.wall === undefined;
|
|
463
|
+
}
|
|
464
|
+
if (a.kind === 'span') {
|
|
465
|
+
if (side.relative !== undefined)
|
|
466
|
+
return undefined;
|
|
467
|
+
side.relative = a.relative;
|
|
468
|
+
side.span = true;
|
|
469
|
+
}
|
|
470
|
+
if (a.wall !== undefined) {
|
|
471
|
+
if (side.wall !== undefined)
|
|
472
|
+
return undefined;
|
|
473
|
+
side.wall = a.wall;
|
|
474
|
+
if (a.kind === 'bare')
|
|
475
|
+
side.bare = true;
|
|
476
|
+
}
|
|
477
|
+
if (a.zoneToken !== undefined) {
|
|
478
|
+
if (side.zoneToken !== undefined)
|
|
479
|
+
return undefined;
|
|
480
|
+
side.zoneToken = a.zoneToken;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (side.span === true && (side.date !== undefined || side.wall !== undefined))
|
|
484
|
+
return undefined;
|
|
485
|
+
return side;
|
|
486
|
+
}
|
|
487
|
+
const partsOfSide = (side) => ({
|
|
488
|
+
...(side.date !== undefined && { date: side.date }),
|
|
489
|
+
...(side.wall !== undefined && { wall: side.wall }),
|
|
490
|
+
...(side.zoneToken !== undefined && { zoneToken: side.zoneToken }),
|
|
491
|
+
...(side.relative !== undefined && { relative: side.relative }),
|
|
492
|
+
});
|
|
493
|
+
/** The parts a group says, or `undefined` when they are not a v1 phrase. */
|
|
494
|
+
function partsOf(group) {
|
|
495
|
+
const atoms = group.items.map((i) => i.atom);
|
|
496
|
+
if (group.rangeAt === undefined) {
|
|
497
|
+
const side = sideOf(atoms);
|
|
498
|
+
if (side === undefined || side.bare === true)
|
|
499
|
+
return undefined;
|
|
500
|
+
const parts = partsOfSide(side);
|
|
501
|
+
return isTimeParts(parts) ? parts : undefined;
|
|
502
|
+
}
|
|
503
|
+
const left = sideOf(atoms.slice(0, group.rangeAt));
|
|
504
|
+
const right = sideOf(atoms.slice(group.rangeAt));
|
|
505
|
+
if (left === undefined || right === undefined)
|
|
506
|
+
return undefined;
|
|
507
|
+
if (left.span === true || right.span === true || right.bare === true)
|
|
508
|
+
return undefined;
|
|
509
|
+
if (left.bare === true && right.wall?.meridiem === undefined)
|
|
510
|
+
return undefined;
|
|
511
|
+
const outer = {};
|
|
512
|
+
// A day said before the first side's time, and not again, is the whole mention's…
|
|
513
|
+
const leftDay = left.date !== undefined || left.relative !== undefined;
|
|
514
|
+
const rightDay = right.date !== undefined || right.relative !== undefined;
|
|
515
|
+
if (leftDay && !rightDay && left.dayFirst === true && left.wall !== undefined) {
|
|
516
|
+
if (left.date !== undefined)
|
|
517
|
+
outer.date = left.date;
|
|
518
|
+
if (left.relative !== undefined)
|
|
519
|
+
outer.relative = left.relative;
|
|
520
|
+
delete left.date;
|
|
521
|
+
delete left.relative;
|
|
522
|
+
}
|
|
523
|
+
// …and so is a zone said after the second side, and not on the first.
|
|
524
|
+
if (right.zoneToken !== undefined && left.zoneToken === undefined) {
|
|
525
|
+
outer.zoneToken = right.zoneToken;
|
|
526
|
+
delete right.zoneToken;
|
|
527
|
+
}
|
|
528
|
+
const l = partsOfSide(left);
|
|
529
|
+
const r = partsOfSide(right);
|
|
530
|
+
if (Object.keys(l).length === 0 || Object.keys(r).length === 0)
|
|
531
|
+
return undefined;
|
|
532
|
+
const parts = { ...outer, rangeOf: [l, r] };
|
|
533
|
+
return isTimeParts(parts) ? parts : undefined;
|
|
534
|
+
}
|
|
535
|
+
/** The text's mentions, in the order written — at most `MAX_MENTIONS`, the port's bound. */
|
|
536
|
+
function mentionsOf(text) {
|
|
537
|
+
const atoms = atomsOf(text);
|
|
538
|
+
const groups = groupsOf(text, atoms, notReadSpans(text, atoms));
|
|
539
|
+
const mentions = [];
|
|
540
|
+
for (const group of groups) {
|
|
541
|
+
const quote = text.slice(group.start, group.end);
|
|
542
|
+
if (quote.trim() === '')
|
|
543
|
+
continue;
|
|
544
|
+
const parts = group.unreadable ? undefined : partsOf(group);
|
|
545
|
+
mentions.push(parts === undefined
|
|
546
|
+
? { quote, parses: [], problem: 'unreadable' }
|
|
547
|
+
: { quote, parses: [parts] });
|
|
548
|
+
}
|
|
549
|
+
return mentions.slice(0, MAX_MENTIONS);
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* The library's careful English reader: a `kind: 'rule'` tokenizer over the
|
|
553
|
+
* v1 phrases of the time design's § 5.3, "unreadable" for every other time
|
|
554
|
+
* phrase it recognises. No dependency; deterministic over the text.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```ts
|
|
558
|
+
* Agent.create({ provider, model })
|
|
559
|
+
* .time({ zone: 'America/Los_Angeles', reader: englishTimeReader() })
|
|
560
|
+
* .build();
|
|
561
|
+
* ```
|
|
562
|
+
*/
|
|
563
|
+
export function englishTimeReader(options = {}) {
|
|
564
|
+
return Object.freeze({
|
|
565
|
+
id: ENGLISH_TIME_READER_ID,
|
|
566
|
+
version: ENGLISH_TIME_READER_VERSION,
|
|
567
|
+
locale: options.locale ?? 'en-US',
|
|
568
|
+
kind: 'rule',
|
|
569
|
+
read: (text) => ({ mentions: mentionsOf(text) }),
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
//# sourceMappingURL=english.js.map
|