Skip to content

support for Magma AI Proxy - #67

Merged
magmacomputing merged 8 commits into
mainfrom
feature/ai-proxy
Aug 3, 2026
Merged

support for Magma AI Proxy#67
magmacomputing merged 8 commits into
mainfrom
feature/ai-proxy

Conversation

@magmacomputing

@magmacomputing magmacomputing commented Jul 26, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Added centralized bounded caching with LRU eviction, TTL support, refresh modes, and glossary persistence.
    • Added AI-powered natural-language date parsing with provider fallback, race, consensus, batching, caching, metadata, and rate-limit handling.
    • Added public support APIs for cache management and license-scope status updates.
    • Improved localized parsing and timezone/offset handling.
  • Bug Fixes
    • Refined license revocation checks and scope status transitions.
  • Documentation
    • Added cache guidance, AI plugin documentation, examples, changelog entries, and an AI issue template.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Tempo 3.11.0 adds centralized bounded caching, license scope updates, timezone parsing changes, and lazy runtime behavior. The AI plugin adds provider modes, rate-limit handling, cache integration, public APIs, tests, documentation, and release metadata.

Changes

License scope updates

Layer / File(s) Summary
License state and revocation logic
packages/tempo/src/plugin/license/license.manager.ts
Adds per-scope status updates, aggregate revocation, and conditional background revocation checks.
Internal Tempo wiring
packages/tempo/src/support/support.symbol.ts, packages/tempo/src/tempo.class.ts
Adds the internal scope-status symbol and Tempo delegation.
License behavior validation
packages/tempo/test/plugins/license.phase1.test.ts
Tests scope updates and revocation behavior.

Centralized cache and runtime

Layer / File(s) Summary
Cache contract and storage
packages/tempo/src/support/*, packages/tempo/src/tempo.type.ts, packages/tempo/src/tempo.class.ts, packages/tempo/package.json
Adds BoundedCache, cache modes, state storage, initialization, facade access, and the public support export.
Cache-aware parsing
packages/tempo/src/module/module.parse.ts
Builds cache keys, stores successful parses, and returns glossary or dynamic cache hits.
Lazy Tempo instantiation
packages/tempo/src/tempo.class.ts
Defers instant, format, and term initialization and memoizes access.
Cache validation and documentation
packages/tempo/test/support/cache.test.ts, packages/tempo/doc/2-core-concepts/tempo.cache.md, packages/tempo/.vitepress/config.ts
Tests cache behavior and documents cache configuration and usage.

AI plugin updates

Layer / File(s) Summary
AI package contract and build wiring
packages/plugins/ai/src/core/config.ts, packages/plugins/ai/src/core/types.ts, packages/plugins/ai/package.json, packages/plugins/ai/tsconfig.json, packages/plugins/ai/tsup.config.ts, packages/plugins/ai/LICENSE
Defines provider, parsing, metadata, and rate-limit contracts and updates package build metadata.
AI initialization and provider support
packages/plugins/ai/src/core/init.ts, packages/plugins/ai/src/core/support.ts
Adds provider initialization, cache management, rate-limit parsing, metadata proxies, and provider requests.
AI parsing modes and public exports
packages/plugins/ai/src/functions/parse.ts, packages/plugins/ai/src/index.ts
Adds native and cached parsing, fallback, race, consensus, validation, batching, and public exports.
AI function contracts
packages/plugins/ai/src/functions/*
Adds typed asynchronous contracts for planned context, difference, extraction, formatting, recurrence, and scheduling APIs.
AI validation and supporting updates
packages/plugins/ai/test/*, packages/plugins/ai/doc/*, packages/plugins/ai/README.md, .github/ISSUE_TEMPLATE/bug_report_ai.yml, packages/plugins/vitest.shared.ts, packages/plugins/ai/CHANGELOG.md
Adds tests, issue reporting, documentation, aliases, and release records.

Parsing and release updates

Layer / File(s) Summary
Timezone and localized parsing
packages/tempo/src/engine/engine.composer.ts, packages/tempo/doc/4-advanced-reference/tempo.locale.md, packages/tempo/test/discrete/parse.locale.test.ts
Separates timezone parsing paths and adds localized parsing examples and tests.
Release metadata and dependency updates
package.json, packages/*/package.json, packages/tempo/src/tempo.version.ts, packages/tempo/CHANGELOG.md, packages/tempo/.vitepress/theme/data/catalog.json, packages/tempo/doc/1-getting-started/tempo.cookbook.md
Updates versions, dependencies, catalog data, changelogs, and release documentation.

Repository workflow updates

Layer / File(s) Summary
Agent execution workflows
.agent/rules/plan-execution.md, .agent/workflows/ok.md
Adds execution-mode rules and an approved continuation workflow.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant parseAI
  participant Provider
  participant TempoCache
  Caller->>parseAI: parseAI(input, options)
  parseAI->>TempoCache: read normalized cache key
  parseAI->>Provider: request provider result
  Provider-->>parseAI: parsed content and rate-limit headers
  parseAI->>TempoCache: write successful result
  parseAI-->>Caller: return Tempo with AI metadata
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main addition of Magma AI Proxy support, which matches the new AI plugin and proxy integration changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/ai-proxy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/tempo/src/plugin/license/license.manager.ts`:
- Around line 132-135: Make revocation checking lazy by changing the response
contract used by the license manager from an already-created
res.revocationPromise to a factory, and invoke that factory only after
shouldSkipRevocation is false in the revocation flow. Update the license phase
test mock to provide the same lazy factory and spy on its invocation, verifying
opt-out licenses do not start the revocation request; modify both
packages/tempo/src/plugin/license/license.manager.ts:132-135 and
packages/tempo/test/plugins/license.phase1.test.ts:86-100.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bfaf2e82-e170-4bfe-abc3-f571285e9938

📥 Commits

Reviewing files that changed from the base of the PR and between 0acb779 and 3bb5dc9.

📒 Files selected for processing (8)
  • package.json
  • packages/library/package.json
  • packages/tempo/package.json
  • packages/tempo/src/plugin/license/license.manager.ts
  • packages/tempo/src/support/support.index.ts
  • packages/tempo/src/support/support.symbol.ts
  • packages/tempo/src/tempo.class.ts
  • packages/tempo/test/plugins/license.phase1.test.ts

Comment thread packages/tempo/src/plugin/license/license.manager.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Nitpick comments (2)
packages/tempo/test/discrete/parse.locale.test.ts (1)

82-102: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the resolved date, not only parse validity.

These assertions do not verify that próximo/proximo means the next Monday or that article removal is applied. Use a fixed anchor and assert the resulting weekday/date for the accented, unaccented, and article-prefixed inputs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/test/discrete/parse.locale.test.ts` around lines 82 - 102,
Update the “test Spanish el próximo lunes” test to use a fixed anchor date, then
assert the resolved date (including Monday’s weekday/date) for “próximo lunes”,
“el próximo lunes”, and “el proximo lunes”. Retain validity checks as
appropriate, ensuring the assertions verify both modifier resolution and article
removal rather than parse success alone.
packages/plugins/ai/test/index.spec.ts (1)

57-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Force the AI path in the natural-language test.

This test is intended to validate mocked LLM parsing, but it neither passes force: true nor asserts a network call. If native parsing later accepts this phrase, the test can pass without exercising the provider contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/test/index.spec.ts` around lines 57 - 61, Update the
parseAI invocation in the natural-language test to pass force: true alongside
the existing anchor and timeZone options, ensuring the test always exercises the
mocked AI provider path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/plugins/ai/CHANGELOG.md`:
- Line 6: Update the 0.1.0 fallback-routing release note to accurately describe
the shipped real provider requests and fallback routing, removing the “mocked
proxy” wording; only label it test-only scaffolding if that is the actual scope
of the implementation.

In `@packages/plugins/ai/doc/architecture.md`:
- Around line 28-34: The Azure OpenAI example and provider contract currently
assume provider.key is sent as a bearer token. Update the configuration around
the openai provider to support Azure’s api-key header for AZURE_API_KEY, or
explicitly rename/document the value as an Entra bearer token when using
Authorization; keep the authentication behavior consistent with the selected
credential type.

In `@packages/plugins/ai/doc/index.md`:
- Around line 72-75: Update the forced-evaluation example for parseAI to use a
natively handled phrase such as “Next Friday” instead of the AI-oriented query.
Correct the surrounding description so force is documented as skipping cache
lookup, not bypassing the cache entirely, since the result is still written to
cache.

In `@packages/plugins/ai/doc/rate-limits.md`:
- Line 56: Update the “Granular Time Gotcha” documentation to clarify that the
cache salt normally uses the execution date but uses the caller-provided anchor
date when options.anchor is set. Explain that a fixed anchor can keep the cache
key unchanged across midnight, so the automatic midnight miss is not guaranteed.
- Around line 62-63: Update the documentation example and its accompanying
guarantee to clarify that cache: false only disables caching and does not ensure
an LLM request. When demonstrating a required provider call, use force: true
together with cache: false in the parseAI options.

In `@packages/plugins/ai/package.json`:
- Line 21: Remove the main-branch check from the prepublishOnly script in
package.json, leaving the build step intact so publishing works from tag-based
and detached HEAD checkouts. Move branch validation to the release automation if
it is still required.

In `@packages/plugins/ai/README.md`:
- Around line 13-15: Fix MD028 blockquote formatting in
packages/plugins/ai/README.md lines 13-15 by removing or prefixing the blank
line between the security warning and disclaimer; apply the same treatment to
the blank line inside the experimental-plugin warning block in
packages/plugins/ai/doc/index.md lines 9-14.
- Around line 29-33: Validate each required provider environment variable before
constructing the provider list passed to initAI. In
packages/plugins/ai/README.md lines 29-33, guard GROQ_API_KEY before assigning
it to the groq provider key; apply the same conditional filtering to every
provider environment variable in packages/plugins/ai/doc/architecture.md lines
12-18 so AiProvider.key always receives a string.

In `@packages/plugins/ai/src/cache.ts`:
- Around line 83-101: Update the Map-compatible observation APIs in the TTL
cache class: ensure inherited forEach() and size access also invoke
evictExpired() before exposing entries or counts. Preserve the existing behavior
of keys(), values(), entries(), and Symbol.iterator(), and use the class’s
existing eviction mechanism rather than adding separate expiration logic.
- Around line 61-68: Update the eviction loop in the cache class’s set flow to
inspect the iterator result’s done flag rather than treating oldestKey ===
undefined as empty. Delete the yielded key, including an explicitly stored
undefined key, and only break when the iterator is exhausted so the cache
remains within maxSize.

In `@packages/plugins/ai/src/parseAI.type.ts`:
- Around line 44-50: Ensure the rate-limit parsing flow sanitizes provider
header values before assigning _state.limits: reject NaN, sentinel values such
as 999, and invalid Tempo resetAt values. Represent unavailable limits as null
or another established unknown form by updating AiRateLimits and its consumers,
rather than exposing malformed values as valid data.

In `@packages/tempo/src/tempo.class.ts`:
- Line 1642: Update `#resolve`() in packages/tempo/src/tempo.class.ts to check for
an existing resolved `#zdt` before accessing `#now`, and only read `#now` when
fallback or unresolved parsing requires it; retain lazy caching in `#now`. In
packages/tempo/CHANGELOG.md lines 12-14, keep the performance claim only once
the implementation and benchmark verify it; otherwise remove or revise the
claim.

---

Nitpick comments:
In `@packages/plugins/ai/test/index.spec.ts`:
- Around line 57-61: Update the parseAI invocation in the natural-language test
to pass force: true alongside the existing anchor and timeZone options, ensuring
the test always exercises the mocked AI provider path.

In `@packages/tempo/test/discrete/parse.locale.test.ts`:
- Around line 82-102: Update the “test Spanish el próximo lunes” test to use a
fixed anchor date, then assert the resolved date (including Monday’s
weekday/date) for “próximo lunes”, “el próximo lunes”, and “el proximo lunes”.
Retain validity checks as appropriate, ensuring the assertions verify both
modifier resolution and article removal rather than parse success alone.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fcbd7c8a-67d6-4c9a-97b0-1fa09fe4a82e

📥 Commits

Reviewing files that changed from the base of the PR and between 3bb5dc9 and 71e0191.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (26)
  • package.json
  • packages/plugins/ai/CHANGELOG.md
  • packages/plugins/ai/LICENSE
  • packages/plugins/ai/README.md
  • packages/plugins/ai/doc/architecture.md
  • packages/plugins/ai/doc/context.md
  • packages/plugins/ai/doc/index.md
  • packages/plugins/ai/doc/rate-limits.md
  • packages/plugins/ai/package.json
  • packages/plugins/ai/src/cache.ts
  • packages/plugins/ai/src/error.ts
  • packages/plugins/ai/src/index.ts
  • packages/plugins/ai/src/parseAI.type.ts
  • packages/plugins/ai/test/index.spec.ts
  • packages/plugins/ai/test/tsconfig.json
  • packages/plugins/ai/tsconfig.json
  • packages/plugins/ai/tsup.config.ts
  • packages/plugins/parseAI/README.md
  • packages/tempo/.vitepress/theme/data/catalog.json
  • packages/tempo/CHANGELOG.md
  • packages/tempo/doc/4-advanced-reference/tempo.locale.md
  • packages/tempo/src/plugin/license/license.manager.ts
  • packages/tempo/src/tempo.class.ts
  • packages/tempo/src/tempo.version.ts
  • packages/tempo/test/discrete/parse.locale.test.ts
  • packages/tempo/test/plugins/license.phase1.test.ts
💤 Files with no reviewable changes (1)
  • packages/plugins/parseAI/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/tempo/test/plugins/license.phase1.test.ts
  • packages/tempo/src/plugin/license/license.manager.ts

Comment thread packages/plugins/ai/doc/index.md Outdated
Comment thread packages/plugins/ai/doc/rate-limits.md Outdated
Comment thread packages/plugins/ai/doc/rate-limits.md Outdated
Comment thread packages/plugins/ai/README.md
Comment thread packages/plugins/ai/README.md
Comment thread packages/tempo/src/tempo.class.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 12

🧹 Nitpick comments (2)
packages/tempo/test/discrete/parse.locale.test.ts (1)

82-102: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the resolved date, not only parse validity.

These assertions do not verify that próximo/proximo means the next Monday or that article removal is applied. Use a fixed anchor and assert the resulting weekday/date for the accented, unaccented, and article-prefixed inputs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/test/discrete/parse.locale.test.ts` around lines 82 - 102,
Update the “test Spanish el próximo lunes” test to use a fixed anchor date, then
assert the resolved date (including Monday’s weekday/date) for “próximo lunes”,
“el próximo lunes”, and “el proximo lunes”. Retain validity checks as
appropriate, ensuring the assertions verify both modifier resolution and article
removal rather than parse success alone.
packages/plugins/ai/test/index.spec.ts (1)

57-61: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Force the AI path in the natural-language test.

This test is intended to validate mocked LLM parsing, but it neither passes force: true nor asserts a network call. If native parsing later accepts this phrase, the test can pass without exercising the provider contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/test/index.spec.ts` around lines 57 - 61, Update the
parseAI invocation in the natural-language test to pass force: true alongside
the existing anchor and timeZone options, ensuring the test always exercises the
mocked AI provider path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/plugins/ai/CHANGELOG.md`:
- Line 6: Update the 0.1.0 fallback-routing release note to accurately describe
the shipped real provider requests and fallback routing, removing the “mocked
proxy” wording; only label it test-only scaffolding if that is the actual scope
of the implementation.

In `@packages/plugins/ai/doc/architecture.md`:
- Around line 28-34: The Azure OpenAI example and provider contract currently
assume provider.key is sent as a bearer token. Update the configuration around
the openai provider to support Azure’s api-key header for AZURE_API_KEY, or
explicitly rename/document the value as an Entra bearer token when using
Authorization; keep the authentication behavior consistent with the selected
credential type.

In `@packages/plugins/ai/doc/index.md`:
- Around line 72-75: Update the forced-evaluation example for parseAI to use a
natively handled phrase such as “Next Friday” instead of the AI-oriented query.
Correct the surrounding description so force is documented as skipping cache
lookup, not bypassing the cache entirely, since the result is still written to
cache.

In `@packages/plugins/ai/doc/rate-limits.md`:
- Line 56: Update the “Granular Time Gotcha” documentation to clarify that the
cache salt normally uses the execution date but uses the caller-provided anchor
date when options.anchor is set. Explain that a fixed anchor can keep the cache
key unchanged across midnight, so the automatic midnight miss is not guaranteed.
- Around line 62-63: Update the documentation example and its accompanying
guarantee to clarify that cache: false only disables caching and does not ensure
an LLM request. When demonstrating a required provider call, use force: true
together with cache: false in the parseAI options.

In `@packages/plugins/ai/package.json`:
- Line 21: Remove the main-branch check from the prepublishOnly script in
package.json, leaving the build step intact so publishing works from tag-based
and detached HEAD checkouts. Move branch validation to the release automation if
it is still required.

In `@packages/plugins/ai/README.md`:
- Around line 13-15: Fix MD028 blockquote formatting in
packages/plugins/ai/README.md lines 13-15 by removing or prefixing the blank
line between the security warning and disclaimer; apply the same treatment to
the blank line inside the experimental-plugin warning block in
packages/plugins/ai/doc/index.md lines 9-14.
- Around line 29-33: Validate each required provider environment variable before
constructing the provider list passed to initAI. In
packages/plugins/ai/README.md lines 29-33, guard GROQ_API_KEY before assigning
it to the groq provider key; apply the same conditional filtering to every
provider environment variable in packages/plugins/ai/doc/architecture.md lines
12-18 so AiProvider.key always receives a string.

In `@packages/plugins/ai/src/cache.ts`:
- Around line 83-101: Update the Map-compatible observation APIs in the TTL
cache class: ensure inherited forEach() and size access also invoke
evictExpired() before exposing entries or counts. Preserve the existing behavior
of keys(), values(), entries(), and Symbol.iterator(), and use the class’s
existing eviction mechanism rather than adding separate expiration logic.
- Around line 61-68: Update the eviction loop in the cache class’s set flow to
inspect the iterator result’s done flag rather than treating oldestKey ===
undefined as empty. Delete the yielded key, including an explicitly stored
undefined key, and only break when the iterator is exhausted so the cache
remains within maxSize.

In `@packages/plugins/ai/src/parseAI.type.ts`:
- Around line 44-50: Ensure the rate-limit parsing flow sanitizes provider
header values before assigning _state.limits: reject NaN, sentinel values such
as 999, and invalid Tempo resetAt values. Represent unavailable limits as null
or another established unknown form by updating AiRateLimits and its consumers,
rather than exposing malformed values as valid data.

In `@packages/tempo/src/tempo.class.ts`:
- Line 1642: Update `#resolve`() in packages/tempo/src/tempo.class.ts to check for
an existing resolved `#zdt` before accessing `#now`, and only read `#now` when
fallback or unresolved parsing requires it; retain lazy caching in `#now`. In
packages/tempo/CHANGELOG.md lines 12-14, keep the performance claim only once
the implementation and benchmark verify it; otherwise remove or revise the
claim.

---

Nitpick comments:
In `@packages/plugins/ai/test/index.spec.ts`:
- Around line 57-61: Update the parseAI invocation in the natural-language test
to pass force: true alongside the existing anchor and timeZone options, ensuring
the test always exercises the mocked AI provider path.

In `@packages/tempo/test/discrete/parse.locale.test.ts`:
- Around line 82-102: Update the “test Spanish el próximo lunes” test to use a
fixed anchor date, then assert the resolved date (including Monday’s
weekday/date) for “próximo lunes”, “el próximo lunes”, and “el proximo lunes”.
Retain validity checks as appropriate, ensuring the assertions verify both
modifier resolution and article removal rather than parse success alone.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fcbd7c8a-67d6-4c9a-97b0-1fa09fe4a82e

📥 Commits

Reviewing files that changed from the base of the PR and between 3bb5dc9 and 71e0191.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (26)
  • package.json
  • packages/plugins/ai/CHANGELOG.md
  • packages/plugins/ai/LICENSE
  • packages/plugins/ai/README.md
  • packages/plugins/ai/doc/architecture.md
  • packages/plugins/ai/doc/context.md
  • packages/plugins/ai/doc/index.md
  • packages/plugins/ai/doc/rate-limits.md
  • packages/plugins/ai/package.json
  • packages/plugins/ai/src/cache.ts
  • packages/plugins/ai/src/error.ts
  • packages/plugins/ai/src/index.ts
  • packages/plugins/ai/src/parseAI.type.ts
  • packages/plugins/ai/test/index.spec.ts
  • packages/plugins/ai/test/tsconfig.json
  • packages/plugins/ai/tsconfig.json
  • packages/plugins/ai/tsup.config.ts
  • packages/plugins/parseAI/README.md
  • packages/tempo/.vitepress/theme/data/catalog.json
  • packages/tempo/CHANGELOG.md
  • packages/tempo/doc/4-advanced-reference/tempo.locale.md
  • packages/tempo/src/plugin/license/license.manager.ts
  • packages/tempo/src/tempo.class.ts
  • packages/tempo/src/tempo.version.ts
  • packages/tempo/test/discrete/parse.locale.test.ts
  • packages/tempo/test/plugins/license.phase1.test.ts
💤 Files with no reviewable changes (1)
  • packages/plugins/parseAI/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/tempo/test/plugins/license.phase1.test.ts
  • packages/tempo/src/plugin/license/license.manager.ts
🛑 Comments failed to post (6)
packages/plugins/ai/CHANGELOG.md (1)

6-6: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the fallback-routing release note.

The implementation performs real provider requests and fallback routing, so “mocked proxy” understates the behavior shipped in 0.1.0. Describe the actual provider behavior or clearly mark this as test-only scaffolding.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/CHANGELOG.md` at line 6, Update the 0.1.0
fallback-routing release note to accurately describe the shipped real provider
requests and fallback routing, removing the “mocked proxy” wording; only label
it test-only scaffolding if that is the actual scope of the implementation.
packages/plugins/ai/doc/architecture.md (1)

28-34: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate architecture and related provider files =="
git ls-files | rg '(^|/)architecture\.md$|ai|provider|openai|azure|auth|authorization' | head -200

echo
echo "== Read target file excerpt =="
if [ -f packages/plugins/ai/doc/architecture.md ]; then
  nl -ba packages/plugins/ai/doc/architecture.md | sed -n '1,120p'
fi

echo
echo "== Search provider key / Authorization usage =="
rg -n "Authorization|provider\.key|AuthorizationHeader|api_key|AZURE_API_KEY|openai\.azure|azure" -S . --glob '!node_modules' --glob '!dist' --glob '!build' | head -300

Repository: magmacomputing/magma

Length of output: 1097


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Read target file excerpt =="
if [ -f packages/plugins/ai/doc/architecture.md ]; then
  awk '{printf "%6d\t%s\n", NR, $0}' packages/plugins/ai/doc/architecture.md | sed -n '1,140p'
fi

echo
echo "== Search provider key / Authorization usage =="
rg -n "Authorization|provider\.key|AuthorizationHeader|api_key|AZURE_API_KEY|openai\.azure|azure|Authorization:" -S packages packages/plugins/ai --glob '!node_modules' --glob '!dist' --glob '!build' | head -400

echo
echo "== Read AI plugin source candidates =="
for f in packages/plugins/ai/src/index.ts packages/plugins/ai/src/parseAI.type.ts packages/plugins/ai/src/error.ts packages/plugins/ai/src/cache.ts; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    wc -l "$f"
    awk '{printf "%6d\t%s\n", NR, $0}' "$f" | sed -n '1,220p'
  fi
done

Repository: magmacomputing/magma

Length of output: 20738


🌐 Web query:

Azure OpenAI chat completions API authentication Authorization header api-key Bearer

💡 Result:

Azure OpenAI Service supports multiple authentication methods for the chat completions API, categorized primarily into API Key-based and Token-based (Microsoft Entra ID) authentication [1][2]. API Key Authentication - api-key header: You can provide your API key directly in the api-key HTTP header [1][3][2]. - Authorization header: Alternatively, you can pass the API key via the Authorization header [1][4]. Token-based Authentication (Microsoft Entra ID) - Authorization header: This method requires an OAuth 2.0 access token [5][2]. - Format: The token must be provided in the Authorization header using the Bearer scheme: Authorization: Bearer {Azure_OpenAI_Auth_Token} [5][2]. - Implementation: When using Azure SDKs (such as the Azure OpenAI client libraries), this is often handled automatically using DefaultAzureCredential, which simplifies the process of obtaining and injecting the bearer token [6][7][8]. Microsoft recommends using token-based authentication (Microsoft Entra ID) over API keys as it is more secure and avoids the need to manage and store static keys [5][2][7]. Regardless of the method used, ensure your requests are sent to the correct resource endpoint [1][6].

Citations:


🌐 Web query:

Azure OpenAI chat completions authentication Authorization header api-key Bearer

💡 Result:

Azure OpenAI supports two primary methods for authenticating requests: API Key authentication and Microsoft Entra ID (token-based) authentication [1][2]. Microsoft Entra ID authentication is recommended as the more secure approach [1][3]. API Key Authentication To authenticate using an API key, you must provide the key in the request header using the header name api-key [1][2]. Example (cURL): curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "api-key: $AZURE_OPENAI_API_KEY" \ -d '{...}' Microsoft Entra ID (Bearer Token) Authentication To authenticate using Microsoft Entra ID, you must provide an OAuth 2.0 access token in the Authorization header using the Bearer scheme [1][2]. Example (cURL): curl -X POST https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $AZURE_OPENAI_AUTH_TOKEN" \ -d '{...}' The required scope for obtaining the access token is typically https://cognitiveservices.azure.com/.default (or https://ai.azure.com/.default in certain AI Foundry contexts) [1][3][4]. When using official Azure SDKs (such as those for.NET, JavaScript/TypeScript, or Python), authentication is typically handled by providing a credential object (e.g., DefaultAzureCredential) or a token provider to the client constructor, which manages the bearer token acquisition automatically [5][6][4][7].

Citations:


Use Azure’s supported API key header or a bearer token in this example.

The plugin sends Authorization: Bearer ${provider.key}, but Azure OpenAI API keys are passed in the api-key header. If AZURE_API_KEY is an API key, change the example/contract to support that header; if it is an Entra token, clarify that the value is an auth token, not an API key.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/doc/architecture.md` around lines 28 - 34, The Azure
OpenAI example and provider contract currently assume provider.key is sent as a
bearer token. Update the configuration around the openai provider to support
Azure’s api-key header for AZURE_API_KEY, or explicitly rename/document the
value as an Entra bearer token when using Authorization; keep the authentication
behavior consistent with the selected credential type.
packages/plugins/ai/package.json (1)

21-21: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package file =="
sed -n '1,80p' packages/plugins/ai/package.json 2>/dev/null || true

echo
echo "== git rev-parse abbrev-ref behavior probe =="
tmp="$(mktemp -d)"
cd "$tmp"
git init -q
echo ok > a.txt
git add a.txt
git commit -q -m init
echo "attached main: $(git rev-parse --abbrev-ref HEAD)"
git checkout -q --detach HEAD
echo "detached HEAD: $(git rev-parse --abbrev-ref HEAD)"
git checkout -q main
echo "still attached main: $(git rev-parse --abbrev-ref HEAD)"
git tag -a "v1.0.0" -m tag 2>/dev/null || true
git checkout -q "v1.0.0"
echo "tag checkout: $(git rev-parse --abbrev-ref HEAD)"
rm -rf "$tmp"

Repository: magmacomputing/magma

Length of output: 1709


🌐 Web query:

git rev-parse --abbrev-ref HEAD detached HEAD returns HEAD documentation

💡 Result:

When running git rev-parse --abbrev-ref HEAD in a detached HEAD state, the command returns the literal string HEAD [1][2][3]. This occurs because the --abbrev-ref option attempts to provide a non-ambiguous short name for a reference [4][5]. In a normal state, where HEAD points to a branch (a symbolic reference), Git resolves this to the branch name [3]. However, when in a detached HEAD state, HEAD points directly to a commit object rather than a branch, and Git identifies this state by returning the name of the reference itself, HEAD [1]. This behavior differs from other commands like git symbolic-ref --short HEAD, which will exit with an error in a detached HEAD state because HEAD is no longer a symbolic reference [1][2]. If you need to distinguish between a named branch and a detached state in scripts, it is common practice to check the output of git symbolic-ref or use logic to handle the literal "HEAD" string [2][6].

Citations:


Do not gate npm publishing on being checked out to main.

prepublishOnly runs from the checkout used by publish automation, including tag-based releases and detached HEAD checkouts, where git rev-parse --abbrev-ref HEAD is not main. This block exits before npm publish can run; move this guard to release automation or explicitly support the release ref.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/package.json` at line 21, Remove the main-branch check
from the prepublishOnly script in package.json, leaving the build step intact so
publishing works from tag-based and detached HEAD checkouts. Move branch
validation to the release automation if it is still required.
packages/plugins/ai/src/cache.ts (2)

61-68: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the iterator’s done flag instead of undefined as the empty sentinel.

K is generic and Map permits undefined keys. If the oldest key is undefined, this condition breaks without deleting it, so set() can permanently exceed maxSize.

Proposed fix
-			const oldestKey = super.keys().next().value;
-			if (oldestKey !== undefined) {
-				this.delete(oldestKey);
+			const oldest = super.keys().next();
+			if (!oldest.done) {
+				this.delete(oldest.value);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

		while (this.size > this.maxSize) {
			const oldest = super.keys().next();
			if (!oldest.done) {
				this.delete(oldest.value);
			} else {
				break;
			}
		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/src/cache.ts` around lines 61 - 68, Update the eviction
loop in the cache class’s set flow to inspect the iterator result’s done flag
rather than treating oldestKey === undefined as empty. Delete the yielded key,
including an explicitly stored undefined key, and only break when the iterator
is exhausted so the cache remains within maxSize.

83-101: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Enforce TTL through all Map observation APIs.

Inherited forEach() and size do not call evictExpired(), so expired entries can still be returned or counted when consumers use the Map-compatible interface. Override those APIs or centralize expiration before every observation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/src/cache.ts` around lines 83 - 101, Update the
Map-compatible observation APIs in the TTL cache class: ensure inherited
forEach() and size access also invoke evictExpired() before exposing entries or
counts. Preserve the existing behavior of keys(), values(), entries(), and
Symbol.iterator(), and use the class’s existing eviction mechanism rather than
adding separate expiration logic.
packages/plugins/ai/src/parseAI.type.ts (1)

44-50: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not expose malformed rate-limit headers as valid values.

The implementation can publish NaN, sentinel values such as 999, or an invalid Tempo when provider headers are missing or malformed. Validate/sanitize these values before assigning _state.limits, or represent unknown values as nullable in AiRateLimits.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/src/parseAI.type.ts` around lines 44 - 50, Ensure the
rate-limit parsing flow sanitizes provider header values before assigning
_state.limits: reject NaN, sentinel values such as 999, and invalid Tempo
resetAt values. Represent unavailable limits as null or another established
unknown form by updating AiRateLimits and its consumers, rather than exposing
malformed values as valid data.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/plugins/ai/src/index.ts (1)

153-158: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use Tempo.options for anchor fallback settings.

Lines 153-158 read Tempo.config, which does not merge defaults, persisted settings, or discovery settings. Tempo.options performs that merge. If the caller omits timeZone, calendar, locale, or sphere, this code can build a cache key with unresolved values and create parsedIso with [undefined] at Line 312.

Proposed fix
-      const resolvedConfig = Tempo.config;
+      const resolvedConfig = Tempo.options;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/src/index.ts` around lines 153 - 158, Update the anchor
fallback setup in the surrounding function to read merged settings from
Tempo.options instead of Tempo.config when resolving timeZone, calendar, locale,
and sphere. Preserve explicit options overrides and the existing anchorStr
fallback, ensuring omitted settings use resolved values rather than remaining
undefined.
🧹 Nitpick comments (3)
packages/tempo/src/support/support.cache.ts (1)

5-9: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

get() does not refresh recency, so eviction is not true LRU.

The class doc calls this "LRU," but only set() reorders an entry (lines 82-89). get() (lines 66-72) never touches #timestamps or the Map's insertion order. A frequently-read "hot" key that is never re-written can still be evicted ahead of a rarely-read key that was written more recently. This weakens the cache's purpose (avoiding repeat parses of common queries) under sustained load.

Touch the entry on read too, to make eviction reflect actual recency of use:

♻️ Proposed fix to refresh recency on read
 	override get(key: K): V | undefined {
 		if (this.#isExpired(key)) {
 			this.delete(key);
 			return undefined;
 		}
-		return super.get(key);
+		if (super.has(key) && !this.#staticKeys.has(key)) {
+			const value = super.get(key)!;
+			super.delete(key);
+			super.set(key, value);				// move to end to reflect recent use
+		}
+		return super.get(key);
 	}

Also applies to: 66-72

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/src/support/support.cache.ts` around lines 5 - 9, Update the
BoundedCache get() method to refresh a successfully retrieved entry’s recency,
matching the existing set() reordering behavior by updating its timestamp and
Map insertion order. Preserve misses, static/immortal entries, and TTL handling
while ensuring frequently read keys remain most recently used for eviction.
packages/tempo/src/support/support.init.ts (1)

27-47: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate cache-resolution logic between the idempotent and non-idempotent init paths.

Both blocks implement the same three-way branch — BoundedCache instance, Map-like entries (seeded as static), or a plain {maxSize, ttl} object — against different target variables. Extract a shared helper to avoid future divergence between the two paths:

function resolveCache(existingCache: BoundedCache | undefined, cacheOption: any): BoundedCache {
	const isBoundedCacheObj = Boolean((cacheOption as any)?.isBoundedCache || cacheOption instanceof BoundedCache);
	if (isBoundedCacheObj) return cacheOption as BoundedCache;

	if (cacheOption instanceof Map || (cacheOption && isFunction((cacheOption as any).entries))) {
		const target = existingCache ?? new BoundedCache();
		for (const [k, v] of (cacheOption as any).entries())
			target.setStatic(String(k).trim().toLowerCase(), String(v));
		return target;
	}

	if (existingCache) {
		if (isDefined(cacheOption?.maxSize)) existingCache.maxSize = cacheOption.maxSize;
		if (isDefined(cacheOption?.ttl)) existingCache.ttl = cacheOption.ttl;
		return existingCache;
	}

	return new BoundedCache(cacheOption?.maxSize ?? 1000, cacheOption?.ttl ?? (24 * 60 * 60 * 1000));
}

Then each call site reduces to a single line, e.g. runtime.state.cache = resolveCache(runtime.state.cache, options.cache); and state.cache = resolveCache(baseState?.cache ?? runtime.state?.cache ?? prevCache, options.cache);.

Also applies to: 70-90

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/src/support/support.init.ts` around lines 27 - 47, Extract the
duplicated cache-option branching from init into a shared resolveCache helper
that handles BoundedCache values, Map-like entries, and plain maxSize/ttl
options while preserving existing defaults. Replace both the idempotent
runtime.state path and the non-idempotent state path with resolveCache calls
using their respective existing cache values, and remove the duplicated inline
logic.
packages/tempo/src/tempo.type.ts (1)

16-16: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Align cache type with its defensive usage.

Internal.State.cache is typed as required (BoundedCache<string, string>), but every consumer accesses it with optional chaining (for example state.cache?.get(normalized) in the facade, and state.cache?.set(cacheKey, ...) in module.parse.ts). Confirm whether cache is truly guaranteed on every State instance.

If it is guaranteed, drop the optional chaining at call sites to match the type. If it is not always guaranteed, mark the field cache?: BoundedCache<string, string>; so the type reflects the real contract and callers keep the guard intentionally instead of by habit.

Also applies to: 385-385

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/tempo/src/tempo.type.ts` at line 16, Align Internal.State.cache with
its actual initialization contract: verify whether every State instance always
provides a BoundedCache. If guaranteed, remove optional chaining from cache
consumers such as the facade lookup and module.parse.ts update; otherwise mark
cache optional in the State definition and retain the guarded accesses
intentionally.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/tempo/doc/2-core-concepts/tempo.cache.md`:
- Around line 83-90: The cache walkthrough in the parseAI example must use an
input that requires AI resolution rather than native parsing. Replace the date
string in both the parseAI call and subsequent Tempo lookup with an AI-required
example such as “The penultimate Tuesday before Thanksgiving in 2026,”
preserving the first-call and cached-second-call flow.

In `@packages/tempo/src/engine/engine.composer.ts`:
- Around line 54-60: Update the parsing logic around zdt so strings ending in Z
or containing numeric offsets are parsed with Temporal.Instant.from and
projected into the requested tz, preserving the exact instant. Keep bracketed
zone strings on Temporal.ZonedDateTime.from and retain PlainDateTime.from only
for wall-clock inputs.

In `@packages/tempo/src/support/support.cache.ts`:
- Around line 126-147: Update the JSDoc above SupportCache.clear to state that
omitting count clears all entries, including static entries; retain the existing
eviction behavior and implementation unchanged.
- Around line 205-216: Update the facade’s deletePrefix method to delegate to
the cache class’s existing deletePrefix implementation instead of iterating keys
and maintaining a duplicate count. Preserve the normalized prefix behavior and
return the class method’s count of matched and deleted entries, including the
existing no-cache result.

---

Outside diff comments:
In `@packages/plugins/ai/src/index.ts`:
- Around line 153-158: Update the anchor fallback setup in the surrounding
function to read merged settings from Tempo.options instead of Tempo.config when
resolving timeZone, calendar, locale, and sphere. Preserve explicit options
overrides and the existing anchorStr fallback, ensuring omitted settings use
resolved values rather than remaining undefined.

---

Nitpick comments:
In `@packages/tempo/src/support/support.cache.ts`:
- Around line 5-9: Update the BoundedCache get() method to refresh a
successfully retrieved entry’s recency, matching the existing set() reordering
behavior by updating its timestamp and Map insertion order. Preserve misses,
static/immortal entries, and TTL handling while ensuring frequently read keys
remain most recently used for eviction.

In `@packages/tempo/src/support/support.init.ts`:
- Around line 27-47: Extract the duplicated cache-option branching from init
into a shared resolveCache helper that handles BoundedCache values, Map-like
entries, and plain maxSize/ttl options while preserving existing defaults.
Replace both the idempotent runtime.state path and the non-idempotent state path
with resolveCache calls using their respective existing cache values, and remove
the duplicated inline logic.

In `@packages/tempo/src/tempo.type.ts`:
- Line 16: Align Internal.State.cache with its actual initialization contract:
verify whether every State instance always provides a BoundedCache. If
guaranteed, remove optional chaining from cache consumers such as the facade
lookup and module.parse.ts update; otherwise mark cache optional in the State
definition and retain the guarded accesses intentionally.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ae7ccd7d-7ad7-451a-b329-af51900adf24

📥 Commits

Reviewing files that changed from the base of the PR and between 71e0191 and a023e7d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (22)
  • package.json
  • packages/library/package.json
  • packages/plugins/ai/CHANGELOG.md
  • packages/plugins/ai/package.json
  • packages/plugins/ai/src/index.ts
  • packages/plugins/ai/src/parseAI.type.ts
  • packages/plugins/ai/test/index.spec.ts
  • packages/tempo/.vitepress/config.ts
  • packages/tempo/.vitepress/theme/data/catalog.json
  • packages/tempo/CHANGELOG.md
  • packages/tempo/doc/2-core-concepts/tempo.cache.md
  • packages/tempo/package.json
  • packages/tempo/src/engine/engine.composer.ts
  • packages/tempo/src/module/module.parse.ts
  • packages/tempo/src/support/support.cache.ts
  • packages/tempo/src/support/support.enum.ts
  • packages/tempo/src/support/support.index.ts
  • packages/tempo/src/support/support.init.ts
  • packages/tempo/src/tempo.class.ts
  • packages/tempo/src/tempo.type.ts
  • packages/tempo/src/tempo.version.ts
  • packages/tempo/test/support/cache.test.ts
💤 Files with no reviewable changes (1)
  • packages/plugins/ai/src/parseAI.type.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/tempo/src/tempo.version.ts
  • packages/library/package.json
  • packages/plugins/ai/package.json
  • packages/tempo/src/support/support.index.ts

Comment thread packages/tempo/doc/2-core-concepts/tempo.cache.md
Comment thread packages/tempo/src/engine/engine.composer.ts Outdated
Comment thread packages/tempo/src/support/support.cache.ts
Comment thread packages/tempo/src/support/support.cache.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/plugins/ai/package.json (1)

21-28: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Restore the main-branch publish guard for packages/plugins/ai.

prepublishOnly now only builds, so npm publish can still run from a non-main branch. Other plugin packages require git rev-parse --abbrev-ref HEAD == main before building; keep the same guard in packages/plugins/ai/package.json or add an equivalent main-branch CI policy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/package.json` around lines 21 - 28, Update the
prepublishOnly script in packages/plugins/ai/package.json to restore the
main-branch publish guard before running the build, matching the protection used
by other plugin packages. Ensure npm publish is blocked when git rev-parse
--abbrev-ref HEAD is not main.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/ISSUE_TEMPLATE/bug_report_ai.yml:
- Around line 62-71: Update the “Minimal Reproduction Code” field description
and placeholder to explicitly warn reporters not to include API keys or private
endpoints, and replace the provider key example in the initAI() snippet with an
unmistakably redacted placeholder value.

In `@packages/plugins/ai/src/index.ts`:
- Around line 263-300: The provider response handling must replace, rather than
retain, prior rate-limit state. In the response logic around the rate-limit
header parsing and _state.limits assignment, build a response-local limits value
and assign it on every response, including when no usable headers are present.
Use that same local limits value for resetAt when constructing TempoAiError,
instead of reading stale _state.limits.
- Around line 271-281: The reset-token parser in the `resetTokHeader` handling
incorrectly accepts only the leading number from compound durations such as
4m12s. Replace the parseFloat-based conversion with full-duration validation and
parsing before constructing `Tempo`, or reject any string that is not fully
supported; ensure invalid or unsupported values do not update `resetAtTempo`.

---

Outside diff comments:
In `@packages/plugins/ai/package.json`:
- Around line 21-28: Update the prepublishOnly script in
packages/plugins/ai/package.json to restore the main-branch publish guard before
running the build, matching the protection used by other plugin packages. Ensure
npm publish is blocked when git rev-parse --abbrev-ref HEAD is not main.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: e2e99f7b-dd1c-4a37-95b2-91bbb55c688a

📥 Commits

Reviewing files that changed from the base of the PR and between a023e7d and 345719f.

📒 Files selected for processing (21)
  • .github/ISSUE_TEMPLATE/bug_report_ai.yml
  • packages/plugins/ai/CHANGELOG.md
  • packages/plugins/ai/README.md
  • packages/plugins/ai/doc/architecture.md
  • packages/plugins/ai/doc/index.md
  • packages/plugins/ai/doc/rate-limits.md
  • packages/plugins/ai/package.json
  • packages/plugins/ai/src/index.ts
  • packages/plugins/ai/src/parseAI.type.ts
  • packages/plugins/ai/test/index.spec.ts
  • packages/plugins/vitest.shared.ts
  • packages/tempo/CHANGELOG.md
  • packages/tempo/doc/1-getting-started/tempo.cookbook.md
  • packages/tempo/doc/2-core-concepts/tempo.cache.md
  • packages/tempo/src/engine/engine.composer.ts
  • packages/tempo/src/module/module.parse.ts
  • packages/tempo/src/support/support.cache.ts
  • packages/tempo/src/support/support.init.ts
  • packages/tempo/src/tempo.class.ts
  • packages/tempo/test/discrete/parse.locale.test.ts
  • packages/tempo/test/support/cache.test.ts
🚧 Files skipped from review as they are similar to previous changes (13)
  • packages/tempo/test/support/cache.test.ts
  • packages/tempo/test/discrete/parse.locale.test.ts
  • packages/plugins/ai/doc/architecture.md
  • packages/plugins/ai/CHANGELOG.md
  • packages/tempo/src/support/support.init.ts
  • packages/tempo/src/engine/engine.composer.ts
  • packages/plugins/ai/README.md
  • packages/plugins/ai/doc/index.md
  • packages/tempo/CHANGELOG.md
  • packages/tempo/src/module/module.parse.ts
  • packages/tempo/doc/2-core-concepts/tempo.cache.md
  • packages/plugins/ai/doc/rate-limits.md
  • packages/tempo/src/tempo.class.ts

Comment thread .github/ISSUE_TEMPLATE/bug_report_ai.yml
Comment thread packages/plugins/ai/src/index.ts Outdated
Comment thread packages/plugins/ai/src/index.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/plugins/ai/test/index.spec.ts (1)

22-24: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use vi.restoreAllMocks() instead of vi.clearAllMocks() for fetch spies.

vi.clearAllMocks() clears call history but keeps any scripted implementation, including mockImplementation. The race-mode test at Line 252 sets fetchSpy.mockImplementation(...) on globalThis.fetch. That implementation is not removed after the test, so a later test that spies on fetch again and exhausts its queued mockResolvedValueOnce values falls through to the race test's body-parsing logic instead of a controlled response.

Current tests happen to consume exactly as many queued once-values as fetch calls, so this does not fail today, but it is a fragile, unguarded state leak. Restore the spy in afterEach.

🧹 Proposed fix
 	afterEach(() => {
-		vi.clearAllMocks();
+		vi.restoreAllMocks();
 	});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/test/index.spec.ts` around lines 22 - 24, Update the test
cleanup in afterEach to call vi.restoreAllMocks() instead of vi.clearAllMocks(),
ensuring the fetch spy’s mockImplementation and other altered behavior are
restored between tests.
🧹 Nitpick comments (3)
packages/plugins/ai/src/core/init.ts (2)

96-101: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider a fallback for HTTP-date Retry-After values.

parseResetHeaderToTempo only matches plain numeric strings or compound durations (e.g. 4m12s). Per HTTP semantics, Retry-After (also read at line 108) may instead be an HTTP-date string (e.g. Wed, 21 Oct 2026 07:28:00 GMT), which neither regex matches, so the function returns null and the reset time is silently dropped for providers/proxies using that format.

Add a final fallback that attempts to parse the trimmed header with Tempo directly.

♻️ Proposed fallback
     }
   }

+  try {
+    const t = new Tempo(trimmed);
+    return t.isValid ? t : null;
+  } catch {
+    return null;
+  }
-  return null;
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/src/core/init.ts` around lines 96 - 101, Update
parseResetHeaderToTempo to add a final fallback after the numeric and
compound-duration parsing attempts: pass the trimmed Retry-After header directly
to Tempo so HTTP-date values are converted into a reset time. Preserve the
existing parsing behavior and return null only when all parsing approaches fail.

16-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate reserved-provider-id validation in two files. The same check (RESERVED_PROVIDER_IDS.has(p.id.toLowerCase()), same TempoAiError message) is implemented independently in core/init.ts and functions/parse.ts. One shared helper keeps the validation rule and error message consistent if either changes.

  • packages/plugins/ai/src/core/init.ts#L16-L19: extract this check into a shared function (e.g. assertNoReservedProviderId(p.id)) in core/support.ts and call it here.
  • packages/plugins/ai/src/functions/parse.ts#L91-L95: replace this loop's inline check with the same shared helper.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/src/core/init.ts` around lines 16 - 19, Duplicate
reserved-provider-ID validation exists in two locations; centralize it in a
shared helper to keep behavior and error messaging consistent. In
packages/plugins/ai/src/core/init.ts lines 16-19, add and call an
assertNoReservedProviderId helper from core/support.ts; in
packages/plugins/ai/src/functions/parse.ts lines 91-95, replace the inline
RESERVED_PROVIDER_IDS check with the same helper while preserving the existing
TempoAiError behavior.
packages/plugins/ai/src/functions/parse.ts (1)

107-107: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the repeated JSON-cleanup logic.

rawContent.replace(/^```json\s*/i, '').replace(/\s*```$/i, '') is duplicated identically across the Fallback, Race, and Consensus branches. A shared helper keeps the markdown-fence stripping logic consistent if it needs to change later.

♻️ Proposed helper
function stripJsonFence(raw: string): string {
  return raw.replace(/^```json\s*/i, '').replace(/\s*```$/i, '');
}

Also applies to: 143-143, 156-156

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/plugins/ai/src/functions/parse.ts` at line 107, Extract the
duplicated JSON markdown-fence cleanup into a shared stripJsonFence helper in
parse.ts, then replace the inline replace chains in the Fallback, Race, and
Consensus branches with calls to that helper while preserving the existing
behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agent/rules/plan-execution.md:
- Around line 9-11: Constrain the /ok auto-execution workflow by validating
approval state, the identity of the currently approved plan, and each command’s
scope before enabling SafeToAutoRun or invoking run_command. Update
.agent/rules/plan-execution.md at lines 9-11 to require these runtime checks and
keep destructive or external-side-effect commands interactive unless explicitly
covered by the approved plan; update .agent/workflows/ok.md at lines 4-6 to bind
/ok execution to that same approved plan and validation flow.

In `@packages/plugins/ai/src/core/config.ts`:
- Around line 21-26: Canonicalize each provider ID before looking it up in
DEFAULT_PROVIDERS within initAI, reusing the lowercase form already used for
RESERVED_PROVIDER_IDS checks. Use that normalized ID for default endpoint,
model, and token parameter selection while preserving the original provider ID
where it is needed for output or registration.
- Around line 37-41: Update the Gemini provider entry in the configuration to
use the current supported default model instead of gemini-1.5-flash, using
gemini-3.6-flash or the repository’s equivalent current model. Add a
default-provider request test covering the Gemini configuration and verifying it
uses the updated model.

In `@packages/plugins/ai/src/core/init.ts`:
- Around line 131-135: Change updateRateLimitsFromResponse and the
fetchFromProvider flow so provider responses only produce rate-limit data
without immediately overwriting shared _state.limits. In the Race and Consensus
paths in parseAI, apply the limits from the response associated with the
successful or selected consensus result after that result is determined, while
preserving getAiRateLimits() behavior for the returned parse result.
- Around line 16-25: Normalize p.id to lowercase once within the
resolvedProviders mapping and reuse that normalized identifier for both
RESERVED_PROVIDER_IDS validation and DEFAULT_PROVIDERS lookup, while preserving
the existing fallback and returned provider fields.

In `@packages/plugins/ai/src/core/support.ts`:
- Around line 30-40: Update the virtual 'ai' descriptor returned by
getOwnPropertyDescriptor in attachAiMeta to use configurable: true, while
preserving its enumerable status, frozenMeta value, and non-writable setting;
leave the get and ownKeys behavior unchanged.

In `@packages/plugins/ai/src/functions/context.ts`:
- Around line 22-24: Do not publish AI entrypoints that always reject valid
calls: implement contextAI in
packages/plugins/ai/src/functions/context.ts:22-24, extractAI in
packages/plugins/ai/src/functions/extract.ts:26-28, formatAI in
packages/plugins/ai/src/functions/format.ts:20-22, recurrenceAI in
packages/plugins/ai/src/functions/recurrence.ts:25-27, and scheduleAI in
packages/plugins/ai/src/functions/schedule.ts:24-26, or remove each function’s
public export and corresponding documentation before release.

In `@packages/plugins/ai/src/functions/parse.ts`:
- Around line 60-82: Update the native fast-path in the parseAI flow to detect
parsed matches using Tempo’s documented public parse/cache API instead of
Symbol.for('$Tempo.internal') or $Internal?.(). Ensure natural-language inputs
with valid native matches are accepted, while preserving the existing ISO-date
fallback, validation, metadata attachment, and LLM fallback behavior.

In `@packages/plugins/ai/test/index.spec.ts`:
- Around line 415-495: Fix the describe nesting around the rate-limit tests by
keeping the outer AI Parsing Plugin suite open while describe('Rate Limit &
Reset Header Parsing Hardening', ...) runs. Move the existing outer-suite
closing `});` to after the rate-limit suite’s closing block so its beforeEach
and afterEach hooks apply to these tests.

---

Outside diff comments:
In `@packages/plugins/ai/test/index.spec.ts`:
- Around line 22-24: Update the test cleanup in afterEach to call
vi.restoreAllMocks() instead of vi.clearAllMocks(), ensuring the fetch spy’s
mockImplementation and other altered behavior are restored between tests.

---

Nitpick comments:
In `@packages/plugins/ai/src/core/init.ts`:
- Around line 96-101: Update parseResetHeaderToTempo to add a final fallback
after the numeric and compound-duration parsing attempts: pass the trimmed
Retry-After header directly to Tempo so HTTP-date values are converted into a
reset time. Preserve the existing parsing behavior and return null only when all
parsing approaches fail.
- Around line 16-19: Duplicate reserved-provider-ID validation exists in two
locations; centralize it in a shared helper to keep behavior and error messaging
consistent. In packages/plugins/ai/src/core/init.ts lines 16-19, add and call an
assertNoReservedProviderId helper from core/support.ts; in
packages/plugins/ai/src/functions/parse.ts lines 91-95, replace the inline
RESERVED_PROVIDER_IDS check with the same helper while preserving the existing
TempoAiError behavior.

In `@packages/plugins/ai/src/functions/parse.ts`:
- Line 107: Extract the duplicated JSON markdown-fence cleanup into a shared
stripJsonFence helper in parse.ts, then replace the inline replace chains in the
Fallback, Race, and Consensus branches with calls to that helper while
preserving the existing behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 594c9ded-1be8-4b66-b9b4-b9e55615d44a

📥 Commits

Reviewing files that changed from the base of the PR and between 345719f and df79761.

📒 Files selected for processing (23)
  • .agent/rules/plan-execution.md
  • .agent/workflows/ok.md
  • .github/ISSUE_TEMPLATE/bug_report_ai.yml
  • packages/plugins/ai/CHANGELOG.md
  • packages/plugins/ai/package.json
  • packages/plugins/ai/src/core/config.ts
  • packages/plugins/ai/src/core/error.ts
  • packages/plugins/ai/src/core/init.ts
  • packages/plugins/ai/src/core/support.ts
  • packages/plugins/ai/src/core/types.ts
  • packages/plugins/ai/src/functions/context.ts
  • packages/plugins/ai/src/functions/diff.ts
  • packages/plugins/ai/src/functions/extract.ts
  • packages/plugins/ai/src/functions/format.ts
  • packages/plugins/ai/src/functions/parse.ts
  • packages/plugins/ai/src/functions/recurrence.ts
  • packages/plugins/ai/src/functions/schedule.ts
  • packages/plugins/ai/src/index.ts
  • packages/plugins/ai/test/benchmark.spec.ts
  • packages/plugins/ai/test/index.spec.ts
  • packages/plugins/ai/tsconfig.json
  • packages/plugins/ai/tsup.config.ts
  • packages/tempo/CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/plugins/ai/tsup.config.ts
  • packages/plugins/ai/tsconfig.json

Comment thread .agent/rules/plan-execution.md Outdated
Comment thread packages/plugins/ai/src/core/config.ts
Comment thread packages/plugins/ai/src/core/config.ts
Comment thread packages/plugins/ai/src/core/init.ts
Comment thread packages/plugins/ai/src/core/init.ts
Comment thread packages/plugins/ai/src/core/support.ts
Comment thread packages/plugins/ai/src/functions/context.ts
Comment thread packages/plugins/ai/src/functions/parse.ts
Comment thread packages/plugins/ai/test/index.spec.ts Outdated
@magmacomputing
magmacomputing merged commit cf360a3 into main Aug 3, 2026
5 checks passed
@magmacomputing
magmacomputing deleted the feature/ai-proxy branch August 3, 2026 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant