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,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/time/axis — a dataset's TIME AXIS: the declaration, its one judge, and
|
|
3
|
+
* the read-side view that turns the declared column into comparable instants.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: declared, never guessed; judged at mint, never repaired; values
|
|
6
|
+
* read through ONE view ({@link normaliseInstants}) that never
|
|
7
|
+
* touches the stored rows. Moved here from `artifacts/timeAxis.ts`
|
|
8
|
+
* (which `artifacts/index.ts` still re-exports), so the axis speaks
|
|
9
|
+
* the time layer's one grammar: `interval` is a `duration.ts`
|
|
10
|
+
* duration under {@link AXIS_UNITS}, `zone` is a `zone.ts` zone name.
|
|
11
|
+
* Role: core/ leaf (the time layer's one owner). Imports `instant.ts`,
|
|
12
|
+
* `duration.ts` and `zone.ts`. Asked by `artifacts/minting.ts` ·
|
|
13
|
+
* `prepareArtifact` and `artifacts/datasetResult.ts` ·
|
|
14
|
+
* `stageDatasetArtifacts` (the judge), and by any consumer that
|
|
15
|
+
* compares a dataset's times (the view).
|
|
16
|
+
* Emits: N/A.
|
|
17
|
+
*
|
|
18
|
+
* ## Why a producer declares it
|
|
19
|
+
*
|
|
20
|
+
* A table of rows is a time series only when one column IS time, and the
|
|
21
|
+
* reader of the rows cannot know that honestly: `ts` holding 1726000000 is
|
|
22
|
+
* epoch SECONDS to the tool that wrote it and a large integer to everything
|
|
23
|
+
* else; `'2026-09-14T10:00:00'` is UTC or the collector's wall clock. So the
|
|
24
|
+
* producer SAYS it, on the ticket (`PutArtifactInput.timeAxis`, carried on
|
|
25
|
+
* `ArtifactMeta.timeAxis`). A malformed declaration is REFUSED at mint
|
|
26
|
+
* ({@link timeAxisIssues}) — never trimmed or defaulted — and the shape is
|
|
27
|
+
* CLOSED: a misspelt `agg` is refused by name, never dropped.
|
|
28
|
+
*
|
|
29
|
+
* ## The view — values, not the declaration
|
|
30
|
+
*
|
|
31
|
+
* The judge never reads a value; {@link normaliseInstants} does, at read time.
|
|
32
|
+
* It turns the declared column into UTC `Z` instants spelled at ONE precision,
|
|
33
|
+
* so a lexicographic compare downstream is chronological, and it is honest
|
|
34
|
+
* about every value it could not place:
|
|
35
|
+
*
|
|
36
|
+
* | Value | Under | Read as |
|
|
37
|
+
* |-------|-------|---------|
|
|
38
|
+
* | a number | `epoch-s` / `epoch-ms` | that instant, exactly as written (no float rounding) |
|
|
39
|
+
* | ISO with `Z` or `±HH:MM` | `iso`, any zone | that instant (the lenient profile — a producer's spelling) |
|
|
40
|
+
* | ISO with NO offset | `iso`, no `zone` | **naive** — counted, never read as UTC; `status: 'naive-values'`, or refused under `naive: 'refuse'` |
|
|
41
|
+
* | ISO with no offset | `iso` + `zone` | a wall time in that zone; one instant, or — in a fall-back overlap — the row-order rule below; in a spring-forward gap, counted `dstGap` |
|
|
42
|
+
* | anything else | — | counted `unreadable` (`missing` when the row lacks the column) |
|
|
43
|
+
*
|
|
44
|
+
* **The fall-back rule.** In the hour the clocks go back, one wall time names
|
|
45
|
+
* two instants. Read in the rows' order, the values before the wall clock
|
|
46
|
+
* steps back take the earlier offset and those from the step on the later
|
|
47
|
+
* (a note `{ kind: 'dst-overlap', resolvedBy: 'row-order' }` per value). When
|
|
48
|
+
* the order cannot tell — a lone `01:30`, no step back, two steps back, or a
|
|
49
|
+
* column whose wall times are not in order anywhere — the value is counted
|
|
50
|
+
* `dstAmbiguous` and handled like a naive one. Nothing is picked silently.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* timeAxisIssues({ column: 'ts', unit: 'epoch-s', zone: 'UTC' }); // ['timeAxis.zone is for wall-clock ISO values; …']
|
|
55
|
+
* normaliseInstants([{ ts: 1726300800 }, { ts: 1726304400.5 }], { column: 'ts', unit: 'epoch-s' });
|
|
56
|
+
* // { status: 'instants', precision: 'millisecond',
|
|
57
|
+
* // points: [{ row: 0, at: '2024-09-14T08:00:00.000Z' }, { row: 1, at: '2024-09-14T09:00:00.500Z' }], … }
|
|
58
|
+
* normaliseInstants([{ t: '2026-09-14T10:00:00' }], { column: 't', unit: 'iso' });
|
|
59
|
+
* // { status: 'naive-values', count: 1, points: [], … } — never read as UTC
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
import { type InstantText } from './instant.js';
|
|
63
|
+
/** How the time column's values are written. */
|
|
64
|
+
export type TimeAxisUnit = 'iso' | 'epoch-s' | 'epoch-ms';
|
|
65
|
+
/** How one row summarises the interval it stands for. */
|
|
66
|
+
export type TimeAxisAggregate = 'avg' | 'min' | 'max' | 'sum' | 'count' | 'last';
|
|
67
|
+
/** The closed sets, in one place, for the judge and for its own messages. */
|
|
68
|
+
export declare const TIME_AXIS_UNITS: readonly TimeAxisUnit[];
|
|
69
|
+
export declare const TIME_AXIS_AGGREGATES: readonly TimeAxisAggregate[];
|
|
70
|
+
/**
|
|
71
|
+
* A dataset's declared time axis.
|
|
72
|
+
*
|
|
73
|
+
* @example hourly buckets, two measures summarised differently
|
|
74
|
+
* { column: 'hour', unit: 'iso', interval: '1h',
|
|
75
|
+
* aggregate: { read_iops: 'avg', peak_iops: 'max' } }
|
|
76
|
+
* @example raw samples every five minutes, epoch seconds
|
|
77
|
+
* { column: 'ts', unit: 'epoch-s', interval: '5m', aggregate: 'raw' }
|
|
78
|
+
*/
|
|
79
|
+
export interface DatasetTimeAxis {
|
|
80
|
+
/** The column that holds time. */
|
|
81
|
+
readonly column: string;
|
|
82
|
+
/** `'iso'` — ISO-8601 strings; `'epoch-s'` / `'epoch-ms'` — numbers since
|
|
83
|
+
* 1970-01-01T00:00:00Z in seconds / milliseconds. */
|
|
84
|
+
readonly unit: TimeAxisUnit;
|
|
85
|
+
/** IANA zone name (`'Europe/London'`) the values are WALL-CLOCK in — never
|
|
86
|
+
* an abbreviation such as `'PST'` or a bare offset. `'iso'` only — an epoch
|
|
87
|
+
* is an instant and has no zone to declare. Absent: every ISO value must
|
|
88
|
+
* carry its own offset (`Z` or `±HH:MM`); a value without one is NEVER
|
|
89
|
+
* read as UTC — {@link normaliseInstants} counts it (`naive-values`) or,
|
|
90
|
+
* by the reader's choice, refuses the column. */
|
|
91
|
+
readonly zone?: string;
|
|
92
|
+
/** Width of the interval one row stands for: a positive whole number and
|
|
93
|
+
* one of `s m h d w` (`'30s'`, `'5m'`, `'1h'`, `'1d'`, `'1w'`) — the time
|
|
94
|
+
* layer's one duration grammar, any number of digits. With
|
|
95
|
+
* `aggregate: 'raw'` it is the sampling cadence. */
|
|
96
|
+
readonly interval?: string;
|
|
97
|
+
/**
|
|
98
|
+
* How each row summarises its interval. `'raw'` — every row is a sample as
|
|
99
|
+
* collected, nothing was reduced. One aggregate — every measure column was
|
|
100
|
+
* reduced the same way. A record — measure column to its own aggregate
|
|
101
|
+
* (`{ avg_iops: 'avg', peak_iops: 'max' }`); a column not named there is
|
|
102
|
+
* not a declared measure. Any aggregate other than `'raw'` requires
|
|
103
|
+
* `interval`, and `interval` requires `aggregate`: a summary of an interval
|
|
104
|
+
* nobody named, or an interval with no word for what happened in it, is
|
|
105
|
+
* half a declaration.
|
|
106
|
+
*/
|
|
107
|
+
readonly aggregate?: 'raw' | TimeAxisAggregate | Readonly<Record<string, TimeAxisAggregate>>;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* THE ONE JUDGE of a time-axis declaration. Returns every problem, in words a
|
|
111
|
+
* producer can act on; an empty list means the declaration is well-formed.
|
|
112
|
+
* Never throws, never repairs, never reads a value.
|
|
113
|
+
*/
|
|
114
|
+
export declare function timeAxisIssues(value: unknown): string[];
|
|
115
|
+
/** What a consumer finds on a ticket. `malformed` exists for tickets minted
|
|
116
|
+
* outside this library's put (a foreign writer, an old store) — a consumer
|
|
117
|
+
* shows it as an error, never as an undeclared dataset. */
|
|
118
|
+
export type TimeAxisReading = {
|
|
119
|
+
readonly status: 'absent';
|
|
120
|
+
} | {
|
|
121
|
+
readonly status: 'declared';
|
|
122
|
+
readonly axis: DatasetTimeAxis;
|
|
123
|
+
} | {
|
|
124
|
+
readonly status: 'malformed';
|
|
125
|
+
readonly issues: readonly string[];
|
|
126
|
+
};
|
|
127
|
+
/** Read the declaration off a ticket (`ArtifactMeta`, or anything shaped like
|
|
128
|
+
* one). Absent is absent; anything present is judged. */
|
|
129
|
+
export declare function readTimeAxis(meta: unknown): TimeAxisReading;
|
|
130
|
+
/**
|
|
131
|
+
* The declared SUMMARY in words, for a chart title — the one wording every
|
|
132
|
+
* consumer shares, so two screens never describe one ticket two ways.
|
|
133
|
+
*
|
|
134
|
+
* `{ interval: '1h', aggregate: { a: 'avg', b: 'max' } }` → `'hourly avg and max'`
|
|
135
|
+
* `{ interval: '5m', aggregate: 'max' }` → `'5-minute max'`
|
|
136
|
+
* `{ interval: '5m', aggregate: 'raw' }` → `'raw samples every 5 minutes'`
|
|
137
|
+
* `{ aggregate: 'raw' }` → `'raw samples'`
|
|
138
|
+
*
|
|
139
|
+
* `undefined` when the declaration says nothing about summarising (column and
|
|
140
|
+
* unit only) — there is no summary to put in a title, and inventing "raw"
|
|
141
|
+
* would claim something the producer did not.
|
|
142
|
+
*/
|
|
143
|
+
export declare function describeTimeAxis(axis: DatasetTimeAxis): string | undefined;
|
|
144
|
+
/** What {@link normaliseInstants} does with a naive value: count it (`'flag'`, the default) or refuse the column. */
|
|
145
|
+
export type NaiveValues = 'flag' | 'refuse';
|
|
146
|
+
/** Options of {@link normaliseInstants}. */
|
|
147
|
+
export interface NormaliseOptions {
|
|
148
|
+
/** A value whose clock is unknown (naive, or a fall-back wall time the row
|
|
149
|
+
* order cannot place): `'flag'` counts it and reads the rest; `'refuse'`
|
|
150
|
+
* places nothing. Never read as UTC either way. Default `'flag'`. */
|
|
151
|
+
readonly naive?: NaiveValues;
|
|
152
|
+
}
|
|
153
|
+
/** The one precision every point of a view is spelled at: the finest any value was written in. */
|
|
154
|
+
export type AxisPrecision = 'second' | 'millisecond' | 'nanosecond';
|
|
155
|
+
/** One placed value: the row it came from and its UTC instant. */
|
|
156
|
+
export interface AxisPoint {
|
|
157
|
+
/** The row's index in the rows as stored. */
|
|
158
|
+
readonly row: number;
|
|
159
|
+
/** The instant in UTC (`Z`), at the view's one precision — so comparing two
|
|
160
|
+
* spellings as text compares them in time. */
|
|
161
|
+
readonly at: InstantText;
|
|
162
|
+
}
|
|
163
|
+
/** A value the fall-back overlap doubled, placed by the rows' order. */
|
|
164
|
+
export interface AxisOverlapNote {
|
|
165
|
+
readonly kind: 'dst-overlap';
|
|
166
|
+
readonly resolvedBy: 'row-order';
|
|
167
|
+
readonly row: number;
|
|
168
|
+
/** Which of the two instants the wall time names: before the clock stepped back, or after. */
|
|
169
|
+
readonly which: 'earlier' | 'later';
|
|
170
|
+
}
|
|
171
|
+
/** Every value the view could not place, by reason. */
|
|
172
|
+
export interface AxisCounts {
|
|
173
|
+
/** An ISO value with no offset under an axis with no `zone`. */
|
|
174
|
+
readonly naive: number;
|
|
175
|
+
/** A wall time the fall-back doubles, where the rows' order cannot tell which. */
|
|
176
|
+
readonly dstAmbiguous: number;
|
|
177
|
+
/** A wall time the spring-forward skips — it names no instant. */
|
|
178
|
+
readonly dstGap: number;
|
|
179
|
+
/** Present, but not a value of the declared unit (or outside years 0000–9999). */
|
|
180
|
+
readonly unreadable: number;
|
|
181
|
+
/** The row lacks the column, holds `null`, or is not a record. */
|
|
182
|
+
readonly missing: number;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The read-side view of a declared time column.
|
|
186
|
+
*
|
|
187
|
+
* - `instants` — every value whose clock is known was placed.
|
|
188
|
+
* - `naive-values` — `count` values have no known clock (`naive` +
|
|
189
|
+
* `dstAmbiguous`); they are not in `points`, and nothing should compare or
|
|
190
|
+
* join the series with another source as if they were.
|
|
191
|
+
* - `refused` — the same, under `naive: 'refuse'`: nothing is placed.
|
|
192
|
+
*
|
|
193
|
+
* `points` are sorted in time (ties by row); `unreadable`, `missing` and
|
|
194
|
+
* `dstGap` are counted under every status.
|
|
195
|
+
*/
|
|
196
|
+
export type NormalisedAxis = {
|
|
197
|
+
readonly status: 'instants';
|
|
198
|
+
readonly points: readonly AxisPoint[];
|
|
199
|
+
readonly precision: AxisPrecision;
|
|
200
|
+
readonly notes: readonly AxisOverlapNote[];
|
|
201
|
+
readonly counts: AxisCounts;
|
|
202
|
+
} | {
|
|
203
|
+
readonly status: 'naive-values';
|
|
204
|
+
readonly count: number;
|
|
205
|
+
readonly points: readonly AxisPoint[];
|
|
206
|
+
readonly precision: AxisPrecision;
|
|
207
|
+
readonly notes: readonly AxisOverlapNote[];
|
|
208
|
+
readonly counts: AxisCounts;
|
|
209
|
+
} | {
|
|
210
|
+
readonly status: 'refused';
|
|
211
|
+
readonly reason: 'naive-values';
|
|
212
|
+
readonly count: number;
|
|
213
|
+
readonly counts: AxisCounts;
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* THE READ-SIDE VIEW of a declared time column: every value turned into a UTC
|
|
217
|
+
* `Z` instant at one precision, sorted in time, with every value it could not
|
|
218
|
+
* place counted by reason (the module table). The rows are only read — never
|
|
219
|
+
* copied into, reordered or rewritten — so the stored bytes are unchanged.
|
|
220
|
+
*
|
|
221
|
+
* A malformed `axis` throws a `TypeError` naming its issues (read a ticket
|
|
222
|
+
* with `readTimeAxis` first; a declaration is never repaired).
|
|
223
|
+
*/
|
|
224
|
+
export declare function normaliseInstants(rows: readonly unknown[], axis: DatasetTimeAxis, options?: NormaliseOptions): NormalisedAxis;
|
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core/time/axis — a dataset's TIME AXIS: the declaration, its one judge, and
|
|
3
|
+
* the read-side view that turns the declared column into comparable instants.
|
|
4
|
+
*
|
|
5
|
+
* Pattern: declared, never guessed; judged at mint, never repaired; values
|
|
6
|
+
* read through ONE view ({@link normaliseInstants}) that never
|
|
7
|
+
* touches the stored rows. Moved here from `artifacts/timeAxis.ts`
|
|
8
|
+
* (which `artifacts/index.ts` still re-exports), so the axis speaks
|
|
9
|
+
* the time layer's one grammar: `interval` is a `duration.ts`
|
|
10
|
+
* duration under {@link AXIS_UNITS}, `zone` is a `zone.ts` zone name.
|
|
11
|
+
* Role: core/ leaf (the time layer's one owner). Imports `instant.ts`,
|
|
12
|
+
* `duration.ts` and `zone.ts`. Asked by `artifacts/minting.ts` ·
|
|
13
|
+
* `prepareArtifact` and `artifacts/datasetResult.ts` ·
|
|
14
|
+
* `stageDatasetArtifacts` (the judge), and by any consumer that
|
|
15
|
+
* compares a dataset's times (the view).
|
|
16
|
+
* Emits: N/A.
|
|
17
|
+
*
|
|
18
|
+
* ## Why a producer declares it
|
|
19
|
+
*
|
|
20
|
+
* A table of rows is a time series only when one column IS time, and the
|
|
21
|
+
* reader of the rows cannot know that honestly: `ts` holding 1726000000 is
|
|
22
|
+
* epoch SECONDS to the tool that wrote it and a large integer to everything
|
|
23
|
+
* else; `'2026-09-14T10:00:00'` is UTC or the collector's wall clock. So the
|
|
24
|
+
* producer SAYS it, on the ticket (`PutArtifactInput.timeAxis`, carried on
|
|
25
|
+
* `ArtifactMeta.timeAxis`). A malformed declaration is REFUSED at mint
|
|
26
|
+
* ({@link timeAxisIssues}) — never trimmed or defaulted — and the shape is
|
|
27
|
+
* CLOSED: a misspelt `agg` is refused by name, never dropped.
|
|
28
|
+
*
|
|
29
|
+
* ## The view — values, not the declaration
|
|
30
|
+
*
|
|
31
|
+
* The judge never reads a value; {@link normaliseInstants} does, at read time.
|
|
32
|
+
* It turns the declared column into UTC `Z` instants spelled at ONE precision,
|
|
33
|
+
* so a lexicographic compare downstream is chronological, and it is honest
|
|
34
|
+
* about every value it could not place:
|
|
35
|
+
*
|
|
36
|
+
* | Value | Under | Read as |
|
|
37
|
+
* |-------|-------|---------|
|
|
38
|
+
* | a number | `epoch-s` / `epoch-ms` | that instant, exactly as written (no float rounding) |
|
|
39
|
+
* | ISO with `Z` or `±HH:MM` | `iso`, any zone | that instant (the lenient profile — a producer's spelling) |
|
|
40
|
+
* | ISO with NO offset | `iso`, no `zone` | **naive** — counted, never read as UTC; `status: 'naive-values'`, or refused under `naive: 'refuse'` |
|
|
41
|
+
* | ISO with no offset | `iso` + `zone` | a wall time in that zone; one instant, or — in a fall-back overlap — the row-order rule below; in a spring-forward gap, counted `dstGap` |
|
|
42
|
+
* | anything else | — | counted `unreadable` (`missing` when the row lacks the column) |
|
|
43
|
+
*
|
|
44
|
+
* **The fall-back rule.** In the hour the clocks go back, one wall time names
|
|
45
|
+
* two instants. Read in the rows' order, the values before the wall clock
|
|
46
|
+
* steps back take the earlier offset and those from the step on the later
|
|
47
|
+
* (a note `{ kind: 'dst-overlap', resolvedBy: 'row-order' }` per value). When
|
|
48
|
+
* the order cannot tell — a lone `01:30`, no step back, two steps back, or a
|
|
49
|
+
* column whose wall times are not in order anywhere — the value is counted
|
|
50
|
+
* `dstAmbiguous` and handled like a naive one. Nothing is picked silently.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* timeAxisIssues({ column: 'ts', unit: 'epoch-s', zone: 'UTC' }); // ['timeAxis.zone is for wall-clock ISO values; …']
|
|
55
|
+
* normaliseInstants([{ ts: 1726300800 }, { ts: 1726304400.5 }], { column: 'ts', unit: 'epoch-s' });
|
|
56
|
+
* // { status: 'instants', precision: 'millisecond',
|
|
57
|
+
* // points: [{ row: 0, at: '2024-09-14T08:00:00.000Z' }, { row: 1, at: '2024-09-14T09:00:00.500Z' }], … }
|
|
58
|
+
* normaliseInstants([{ t: '2026-09-14T10:00:00' }], { column: 't', unit: 'iso' });
|
|
59
|
+
* // { status: 'naive-values', count: 1, points: [], … } — never read as UTC
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
import { AXIS_UNITS, durationParts, isDuration } from './duration.js';
|
|
63
|
+
import { instantOf, spellInstant } from './instant.js';
|
|
64
|
+
import { isZoneName, readWall } from './zone.js';
|
|
65
|
+
/** The closed sets, in one place, for the judge and for its own messages. */
|
|
66
|
+
export const TIME_AXIS_UNITS = ['iso', 'epoch-s', 'epoch-ms'];
|
|
67
|
+
export const TIME_AXIS_AGGREGATES = [
|
|
68
|
+
'avg',
|
|
69
|
+
'min',
|
|
70
|
+
'max',
|
|
71
|
+
'sum',
|
|
72
|
+
'count',
|
|
73
|
+
'last',
|
|
74
|
+
];
|
|
75
|
+
const KEYS = new Set(['column', 'unit', 'zone', 'interval', 'aggregate']);
|
|
76
|
+
function isRecord(value) {
|
|
77
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
78
|
+
}
|
|
79
|
+
function isAggregate(value) {
|
|
80
|
+
return TIME_AXIS_AGGREGATES.includes(value);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* THE ONE JUDGE of a time-axis declaration. Returns every problem, in words a
|
|
84
|
+
* producer can act on; an empty list means the declaration is well-formed.
|
|
85
|
+
* Never throws, never repairs, never reads a value.
|
|
86
|
+
*/
|
|
87
|
+
export function timeAxisIssues(value) {
|
|
88
|
+
if (!isRecord(value)) {
|
|
89
|
+
return [`timeAxis must be an object like { column, unit }, got ${describeValue(value)}.`];
|
|
90
|
+
}
|
|
91
|
+
const issues = [];
|
|
92
|
+
for (const key of Object.keys(value)) {
|
|
93
|
+
if (!KEYS.has(key)) {
|
|
94
|
+
issues.push(`timeAxis has an unknown key '${key}'; the keys are column, unit, zone, interval, aggregate.`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const { column, unit, zone, interval, aggregate } = value;
|
|
98
|
+
if (typeof column !== 'string' || column.trim() === '') {
|
|
99
|
+
issues.push(`timeAxis.column must name the time column, got ${describeValue(column)}.`);
|
|
100
|
+
}
|
|
101
|
+
if (!TIME_AXIS_UNITS.includes(unit)) {
|
|
102
|
+
issues.push(`timeAxis.unit must be one of ${TIME_AXIS_UNITS.join(', ')}, got ${describeValue(unit)}.`);
|
|
103
|
+
}
|
|
104
|
+
if (zone !== undefined) {
|
|
105
|
+
if (!isZoneName(zone)) {
|
|
106
|
+
issues.push(`timeAxis.zone must be an IANA zone such as 'Europe/London' (an abbreviation such as ` +
|
|
107
|
+
`'PST' or a bare offset is not one), got ${describeValue(zone)}.`);
|
|
108
|
+
}
|
|
109
|
+
else if (unit !== 'iso') {
|
|
110
|
+
issues.push(`timeAxis.zone is for wall-clock ISO values; an epoch is an instant and has no zone — ` +
|
|
111
|
+
`drop zone or use unit 'iso'.`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (interval !== undefined && !isDuration(interval, AXIS_UNITS)) {
|
|
115
|
+
issues.push(`timeAxis.interval must be a positive whole number and one of s m h d w ('5m', '1h', '1d'), ` +
|
|
116
|
+
`got ${describeValue(interval)}.`);
|
|
117
|
+
}
|
|
118
|
+
if (aggregate !== undefined && aggregate !== 'raw' && !isAggregate(aggregate)) {
|
|
119
|
+
if (!isRecord(aggregate)) {
|
|
120
|
+
issues.push(`timeAxis.aggregate must be 'raw', one of ${TIME_AXIS_AGGREGATES.join(', ')}, or a ` +
|
|
121
|
+
`record of measure column to one of them, got ${describeValue(aggregate)}.`);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
const entries = Object.entries(aggregate);
|
|
125
|
+
if (entries.length === 0) {
|
|
126
|
+
issues.push('timeAxis.aggregate names no measure; declare at least one, or omit it.');
|
|
127
|
+
}
|
|
128
|
+
for (const [measure, how] of entries) {
|
|
129
|
+
if (measure.trim() === '')
|
|
130
|
+
issues.push('timeAxis.aggregate has a blank measure name.');
|
|
131
|
+
if (measure === column) {
|
|
132
|
+
issues.push(`timeAxis.aggregate names the time column '${measure}' as a measure.`);
|
|
133
|
+
}
|
|
134
|
+
if (!isAggregate(how)) {
|
|
135
|
+
issues.push(`timeAxis.aggregate['${measure}'] must be one of ${TIME_AXIS_AGGREGATES.join(', ')}, ` +
|
|
136
|
+
`got ${describeValue(how)}.`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (aggregate !== undefined && aggregate !== 'raw' && interval === undefined) {
|
|
142
|
+
issues.push('timeAxis.aggregate summarises an interval, so timeAxis.interval must say how wide it is.');
|
|
143
|
+
}
|
|
144
|
+
if (interval !== undefined && aggregate === undefined) {
|
|
145
|
+
issues.push(`timeAxis.interval needs timeAxis.aggregate — say how each interval was summarised, or 'raw'.`);
|
|
146
|
+
}
|
|
147
|
+
return issues;
|
|
148
|
+
}
|
|
149
|
+
/** Read the declaration off a ticket (`ArtifactMeta`, or anything shaped like
|
|
150
|
+
* one). Absent is absent; anything present is judged. */
|
|
151
|
+
export function readTimeAxis(meta) {
|
|
152
|
+
const value = isRecord(meta) ? meta.timeAxis : undefined;
|
|
153
|
+
if (value === undefined)
|
|
154
|
+
return { status: 'absent' };
|
|
155
|
+
const issues = timeAxisIssues(value);
|
|
156
|
+
return issues.length > 0
|
|
157
|
+
? { status: 'malformed', issues }
|
|
158
|
+
: { status: 'declared', axis: value };
|
|
159
|
+
}
|
|
160
|
+
// ── The wording ─────────────────────────────────────────────────────────────
|
|
161
|
+
const UNIT_WORDS = {
|
|
162
|
+
s: 'second',
|
|
163
|
+
m: 'minute',
|
|
164
|
+
h: 'hour',
|
|
165
|
+
d: 'day',
|
|
166
|
+
w: 'week',
|
|
167
|
+
};
|
|
168
|
+
const SINGLE = {
|
|
169
|
+
s: 'per-second',
|
|
170
|
+
m: 'per-minute',
|
|
171
|
+
h: 'hourly',
|
|
172
|
+
d: 'daily',
|
|
173
|
+
w: 'weekly',
|
|
174
|
+
};
|
|
175
|
+
/** `'1h'` → `'hourly'`, `'5m'` → `'5-minute'`. */
|
|
176
|
+
function intervalAdjective(interval) {
|
|
177
|
+
const parts = durationParts(interval, AXIS_UNITS);
|
|
178
|
+
if (parts === undefined)
|
|
179
|
+
return interval;
|
|
180
|
+
return parts.digits === '1'
|
|
181
|
+
? SINGLE[parts.unit]
|
|
182
|
+
: `${parts.digits}-${UNIT_WORDS[parts.unit]}`;
|
|
183
|
+
}
|
|
184
|
+
/** `'5m'` → `'5 minutes'`, `'1h'` → `'hour'`. */
|
|
185
|
+
function intervalNoun(interval) {
|
|
186
|
+
const parts = durationParts(interval, AXIS_UNITS);
|
|
187
|
+
if (parts === undefined)
|
|
188
|
+
return interval;
|
|
189
|
+
return parts.digits === '1'
|
|
190
|
+
? UNIT_WORDS[parts.unit]
|
|
191
|
+
: `${parts.digits} ${UNIT_WORDS[parts.unit]}s`;
|
|
192
|
+
}
|
|
193
|
+
function joinWords(words) {
|
|
194
|
+
if (words.length <= 1)
|
|
195
|
+
return words[0] ?? '';
|
|
196
|
+
return `${words.slice(0, -1).join(', ')} and ${words[words.length - 1]}`;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The declared SUMMARY in words, for a chart title — the one wording every
|
|
200
|
+
* consumer shares, so two screens never describe one ticket two ways.
|
|
201
|
+
*
|
|
202
|
+
* `{ interval: '1h', aggregate: { a: 'avg', b: 'max' } }` → `'hourly avg and max'`
|
|
203
|
+
* `{ interval: '5m', aggregate: 'max' }` → `'5-minute max'`
|
|
204
|
+
* `{ interval: '5m', aggregate: 'raw' }` → `'raw samples every 5 minutes'`
|
|
205
|
+
* `{ aggregate: 'raw' }` → `'raw samples'`
|
|
206
|
+
*
|
|
207
|
+
* `undefined` when the declaration says nothing about summarising (column and
|
|
208
|
+
* unit only) — there is no summary to put in a title, and inventing "raw"
|
|
209
|
+
* would claim something the producer did not.
|
|
210
|
+
*/
|
|
211
|
+
export function describeTimeAxis(axis) {
|
|
212
|
+
const { aggregate, interval } = axis;
|
|
213
|
+
if (aggregate === undefined)
|
|
214
|
+
return undefined;
|
|
215
|
+
if (aggregate === 'raw') {
|
|
216
|
+
return interval === undefined ? 'raw samples' : `raw samples every ${intervalNoun(interval)}`;
|
|
217
|
+
}
|
|
218
|
+
const words = typeof aggregate === 'string' ? [aggregate] : [...new Set(Object.values(aggregate))];
|
|
219
|
+
const how = joinWords(words);
|
|
220
|
+
return interval === undefined ? how : `${intervalAdjective(interval)} ${how}`;
|
|
221
|
+
}
|
|
222
|
+
function describeValue(value) {
|
|
223
|
+
if (value === undefined)
|
|
224
|
+
return 'nothing';
|
|
225
|
+
try {
|
|
226
|
+
const text = JSON.stringify(value);
|
|
227
|
+
if (text === undefined)
|
|
228
|
+
return typeof value;
|
|
229
|
+
return text.length > 60 ? `${text.slice(0, 57)}...` : text;
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return typeof value;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const NS_PER_MS = 1000000n;
|
|
236
|
+
/**
|
|
237
|
+
* An epoch number read EXACTLY as written — through its decimal spelling, so
|
|
238
|
+
* `1726304400.123` is 123 ms and not the double's nearest neighbour. An
|
|
239
|
+
* exponent spelling (`1e21`) or a fraction finer than a nanosecond is
|
|
240
|
+
* unreadable.
|
|
241
|
+
*/
|
|
242
|
+
function epochInstant(value, unit) {
|
|
243
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
244
|
+
return undefined;
|
|
245
|
+
const m = /^(-?)(\d+)(?:\.(\d+))?$/.exec(String(value));
|
|
246
|
+
if (m === null)
|
|
247
|
+
return undefined;
|
|
248
|
+
const fractionDigits = unit === 'epoch-s' ? 9 : 6; // down to one nanosecond
|
|
249
|
+
const fraction = m[3] ?? '';
|
|
250
|
+
if (fraction.length > fractionDigits)
|
|
251
|
+
return undefined;
|
|
252
|
+
const magnitude = BigInt(m[2]) * 10n ** BigInt(fractionDigits) +
|
|
253
|
+
BigInt(fraction.padEnd(fractionDigits, '0') || '0');
|
|
254
|
+
const ns = m[1] === '-' ? -magnitude : magnitude;
|
|
255
|
+
let ms = ns / NS_PER_MS;
|
|
256
|
+
if (ns < 0n && ms * NS_PER_MS !== ns)
|
|
257
|
+
ms -= 1n; // floor, not truncate
|
|
258
|
+
const whole = Number(ms);
|
|
259
|
+
if (!Number.isSafeInteger(whole))
|
|
260
|
+
return undefined;
|
|
261
|
+
return { ms: whole, nanos: Number(ns - ms * NS_PER_MS) };
|
|
262
|
+
}
|
|
263
|
+
const DATE_ONLY = /^\d{4}-\d{2}-\d{2}$/;
|
|
264
|
+
/**
|
|
265
|
+
* An ISO value with no offset, read as a UTC WALL reading only to get its
|
|
266
|
+
* fields — never as an instant. `undefined` when it is not a date-time (or a
|
|
267
|
+
* date) with no zone.
|
|
268
|
+
*/
|
|
269
|
+
function naiveFields(value) {
|
|
270
|
+
const spelled = DATE_ONLY.test(value) ? `${value}T00:00Z` : `${value}Z`;
|
|
271
|
+
return instantOf(spelled, 'lenient');
|
|
272
|
+
}
|
|
273
|
+
function wallOf(fields) {
|
|
274
|
+
const d = new Date(fields.ms);
|
|
275
|
+
return {
|
|
276
|
+
year: d.getUTCFullYear(),
|
|
277
|
+
month: d.getUTCMonth() + 1,
|
|
278
|
+
day: d.getUTCDate(),
|
|
279
|
+
hour: d.getUTCHours(),
|
|
280
|
+
minute: d.getUTCMinutes(),
|
|
281
|
+
second: d.getUTCSeconds(),
|
|
282
|
+
millisecond: d.getUTCMilliseconds(),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
function spellable(instant) {
|
|
286
|
+
return spellInstant(instant, 0) !== undefined;
|
|
287
|
+
}
|
|
288
|
+
function classifyIso(value, zone, walls) {
|
|
289
|
+
if (typeof value !== 'string')
|
|
290
|
+
return { kind: 'unreadable' };
|
|
291
|
+
const instant = instantOf(value, 'lenient');
|
|
292
|
+
if (instant !== undefined)
|
|
293
|
+
return { kind: 'instant', instant };
|
|
294
|
+
const fields = naiveFields(value);
|
|
295
|
+
if (fields === undefined)
|
|
296
|
+
return { kind: 'unreadable' };
|
|
297
|
+
if (zone === undefined)
|
|
298
|
+
return { kind: 'naive' };
|
|
299
|
+
const wall = fields.ms;
|
|
300
|
+
let reading = walls.get(wall);
|
|
301
|
+
if (reading === undefined) {
|
|
302
|
+
const w = wallOf(fields);
|
|
303
|
+
if (w.year > 9999)
|
|
304
|
+
return { kind: 'unreadable' };
|
|
305
|
+
reading = readWall(w, zone);
|
|
306
|
+
walls.set(wall, reading);
|
|
307
|
+
}
|
|
308
|
+
const at = (ms) => ({ ms, nanos: fields.nanos });
|
|
309
|
+
if (reading.kind === 'gap')
|
|
310
|
+
return { kind: 'gap' };
|
|
311
|
+
if (reading.kind === 'unique')
|
|
312
|
+
return { kind: 'instant', instant: at(reading.ms), wall };
|
|
313
|
+
return {
|
|
314
|
+
kind: 'overlap',
|
|
315
|
+
earlier: at(reading.earlier),
|
|
316
|
+
later: at(reading.later),
|
|
317
|
+
wall,
|
|
318
|
+
day: value.slice(0, 10),
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function classifyEpoch(value, unit) {
|
|
322
|
+
const instant = epochInstant(value, unit);
|
|
323
|
+
return instant === undefined ? { kind: 'unreadable' } : { kind: 'instant', instant };
|
|
324
|
+
}
|
|
325
|
+
function classify(row, axis, walls) {
|
|
326
|
+
if (!isRecord(row))
|
|
327
|
+
return { kind: 'missing' };
|
|
328
|
+
const value = row[axis.column];
|
|
329
|
+
if (value === undefined || value === null)
|
|
330
|
+
return { kind: 'missing' };
|
|
331
|
+
const read = axis.unit === 'iso' ? classifyIso(value, axis.zone, walls) : classifyEpoch(value, axis.unit);
|
|
332
|
+
if (read.kind === 'instant' && !spellable(read.instant))
|
|
333
|
+
return { kind: 'unreadable' };
|
|
334
|
+
if (read.kind === 'overlap' && !(spellable(read.earlier) && spellable(read.later))) {
|
|
335
|
+
return { kind: 'unreadable' };
|
|
336
|
+
}
|
|
337
|
+
return read;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* The fall-back rule over the rows' order: for each overlap day, the one
|
|
341
|
+
* place its wall clock steps back (a value not after the one before it)
|
|
342
|
+
* splits it into `earlier` then `later`. Any step back that is NOT inside one
|
|
343
|
+
* overlap day means the rows are not in time order, and every overlap value
|
|
344
|
+
* is left unplaced; so is a day with no step back or more than one.
|
|
345
|
+
*/
|
|
346
|
+
function resolveOverlaps(read, nanos) {
|
|
347
|
+
const placed = new Map();
|
|
348
|
+
const walled = [];
|
|
349
|
+
for (let i = 0; i < read.length; i++) {
|
|
350
|
+
const r = read[i];
|
|
351
|
+
if ((r.kind === 'instant' && r.wall !== undefined) || r.kind === 'overlap')
|
|
352
|
+
walled.push(i);
|
|
353
|
+
}
|
|
354
|
+
const wallAt = (i) => read[i].wall;
|
|
355
|
+
const stepsByDay = new Map();
|
|
356
|
+
for (let k = 1; k < walled.length; k++) {
|
|
357
|
+
const prev = walled[k - 1];
|
|
358
|
+
const here = walled[k];
|
|
359
|
+
const notAfter = wallAt(here) < wallAt(prev) || (wallAt(here) === wallAt(prev) && nanos(here) <= nanos(prev));
|
|
360
|
+
if (!notAfter)
|
|
361
|
+
continue;
|
|
362
|
+
const a = read[prev];
|
|
363
|
+
const b = read[here];
|
|
364
|
+
if (a.kind !== 'overlap' || b.kind !== 'overlap' || a.day !== b.day)
|
|
365
|
+
return placed;
|
|
366
|
+
stepsByDay.set(a.day, [...(stepsByDay.get(a.day) ?? []), here]);
|
|
367
|
+
}
|
|
368
|
+
for (const [day, steps] of stepsByDay) {
|
|
369
|
+
if (steps.length !== 1)
|
|
370
|
+
continue;
|
|
371
|
+
const step = steps[0];
|
|
372
|
+
for (let i = 0; i < read.length; i++) {
|
|
373
|
+
const r = read[i];
|
|
374
|
+
if (r.kind === 'overlap' && r.day === day)
|
|
375
|
+
placed.set(i, i < step ? 'earlier' : 'later');
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return placed;
|
|
379
|
+
}
|
|
380
|
+
const pad = (n, width) => String(n).padStart(width, '0');
|
|
381
|
+
function precisionOf(instants) {
|
|
382
|
+
let precision = 'second';
|
|
383
|
+
for (const { ms, nanos } of instants) {
|
|
384
|
+
if (nanos !== 0)
|
|
385
|
+
return 'nanosecond';
|
|
386
|
+
if (((ms % 1000) + 1000) % 1000 !== 0)
|
|
387
|
+
precision = 'millisecond';
|
|
388
|
+
}
|
|
389
|
+
return precision;
|
|
390
|
+
}
|
|
391
|
+
/** `instant` in UTC with exactly the digits `precision` names — fixed width, so text order is time order. */
|
|
392
|
+
function spellAt(instant, precision) {
|
|
393
|
+
const msPart = ((instant.ms % 1000) + 1000) % 1000;
|
|
394
|
+
const whole = spellInstant({ ms: instant.ms - msPart, nanos: 0 }, 0);
|
|
395
|
+
if (precision === 'second')
|
|
396
|
+
return whole;
|
|
397
|
+
const fraction = pad(msPart * 1_000_000 + instant.nanos, 9);
|
|
398
|
+
const digits = precision === 'millisecond' ? fraction.slice(0, 3) : fraction;
|
|
399
|
+
return `${whole.slice(0, -1)}.${digits}Z`;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* THE READ-SIDE VIEW of a declared time column: every value turned into a UTC
|
|
403
|
+
* `Z` instant at one precision, sorted in time, with every value it could not
|
|
404
|
+
* place counted by reason (the module table). The rows are only read — never
|
|
405
|
+
* copied into, reordered or rewritten — so the stored bytes are unchanged.
|
|
406
|
+
*
|
|
407
|
+
* A malformed `axis` throws a `TypeError` naming its issues (read a ticket
|
|
408
|
+
* with `readTimeAxis` first; a declaration is never repaired).
|
|
409
|
+
*/
|
|
410
|
+
export function normaliseInstants(rows, axis, options = {}) {
|
|
411
|
+
const issues = timeAxisIssues(axis);
|
|
412
|
+
if (issues.length > 0) {
|
|
413
|
+
throw new TypeError(`normaliseInstants: the time axis is malformed — ${issues.join(' ')}`);
|
|
414
|
+
}
|
|
415
|
+
const naive = options.naive ?? 'flag';
|
|
416
|
+
if (naive !== 'flag' && naive !== 'refuse') {
|
|
417
|
+
throw new TypeError(`normaliseInstants: naive must be 'flag' or 'refuse', got ${describeValue(naive)}.`);
|
|
418
|
+
}
|
|
419
|
+
if (!Array.isArray(rows)) {
|
|
420
|
+
throw new TypeError(`normaliseInstants: rows must be an array, got ${describeValue(rows)}.`);
|
|
421
|
+
}
|
|
422
|
+
const walls = new Map();
|
|
423
|
+
const read = rows.map((row) => classify(row, axis, walls));
|
|
424
|
+
const nanosOf = (i) => {
|
|
425
|
+
const r = read[i];
|
|
426
|
+
return r.kind === 'instant' ? r.instant.nanos : r.kind === 'overlap' ? r.earlier.nanos : 0;
|
|
427
|
+
};
|
|
428
|
+
const byOrder = read.some((r) => r.kind === 'overlap')
|
|
429
|
+
? resolveOverlaps(read, nanosOf)
|
|
430
|
+
: new Map();
|
|
431
|
+
const counts = { naive: 0, dstAmbiguous: 0, dstGap: 0, unreadable: 0, missing: 0 };
|
|
432
|
+
const placed = [];
|
|
433
|
+
const notes = [];
|
|
434
|
+
read.forEach((r, row) => {
|
|
435
|
+
if (r.kind === 'instant')
|
|
436
|
+
placed.push({ row, instant: r.instant });
|
|
437
|
+
else if (r.kind === 'overlap') {
|
|
438
|
+
const which = byOrder.get(row);
|
|
439
|
+
if (which === undefined)
|
|
440
|
+
counts.dstAmbiguous++;
|
|
441
|
+
else {
|
|
442
|
+
placed.push({ row, instant: r[which] });
|
|
443
|
+
notes.push({ kind: 'dst-overlap', resolvedBy: 'row-order', row, which });
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
else if (r.kind === 'gap')
|
|
447
|
+
counts.dstGap++;
|
|
448
|
+
else
|
|
449
|
+
counts[r.kind]++;
|
|
450
|
+
});
|
|
451
|
+
const count = counts.naive + counts.dstAmbiguous;
|
|
452
|
+
if (count > 0 && naive === 'refuse') {
|
|
453
|
+
return { status: 'refused', reason: 'naive-values', count, counts };
|
|
454
|
+
}
|
|
455
|
+
placed.sort((a, b) => a.instant.ms - b.instant.ms || a.instant.nanos - b.instant.nanos || a.row - b.row);
|
|
456
|
+
const precision = precisionOf(placed.map((p) => p.instant));
|
|
457
|
+
const points = placed.map((p) => ({ row: p.row, at: spellAt(p.instant, precision) }));
|
|
458
|
+
return count > 0
|
|
459
|
+
? { status: 'naive-values', count, points, precision, notes, counts }
|
|
460
|
+
: { status: 'instants', points, precision, notes, counts };
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=axis.js.map
|