Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .agileplus/agileplus.db
Binary file not shown.
Binary file removed .agileplus/agileplus.db-shm
Binary file not shown.
Empty file removed .agileplus/agileplus.db-wal
Empty file.
326 changes: 326 additions & 0 deletions .agileplus/quota-keystore-type-drift/spec.md

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions .github/workflows/build-fork.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@ jobs:
persist-credentials: false

- name: Set up QEMU
uses: docker/setup-qemu-action@v4
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c

- name: Login to GitHub Container Registry
uses: docker/login-action@v4
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v6
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302
with:
images: ${{ env.IMAGE_NAME }}
tags: |
Expand All @@ -59,7 +59,7 @@ jobs:
org.opencontainers.image.licenses=MIT

- name: Build and push
uses: docker/build-push-action@v7
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
with:
context: .
target: runner-base
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: gitleaks
uses: gitleaks/gitleaks-action@v2
uses: gitleaks/gitleaks-action@ff98106e4c7b2bc287b24eaf42907196329070c7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/cross-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ jobs:
timeout-minutes: 15
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: dtolnay/rust-toolchain@stable
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30
- name: Build FFI crates
run: cargo build --release --manifest-path crates/omniroute-ffi/Cargo.toml
- name: Test FFI crates
Expand Down
18 changes: 9 additions & 9 deletions .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,24 +152,24 @@ jobs:
fetch-depth: 0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c

- name: Login to Docker Hub
uses: docker/login-action@v4
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Login to GitHub Container Registry
uses: docker/login-action@v4
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push platform image by digest
id: build
uses: docker/build-push-action@v7
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
with:
context: .
target: runner-base
Expand All @@ -186,7 +186,7 @@ jobs:

- name: Build and push WEB platform image by digest
id: build-web
uses: docker/build-push-action@v7
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a
with:
context: .
target: runner-web
Expand Down Expand Up @@ -252,16 +252,16 @@ jobs:
fetch-depth: 0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c

- name: Login to Docker Hub
uses: docker/login-action@v4
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Login to GitHub Container Registry
uses: docker/login-action@v4
uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down Expand Up @@ -399,7 +399,7 @@ jobs:
# Only refresh README/description when we actually promote :latest
# (avoids overwriting from main pushes or back-fill builds).
if: needs.prepare.outputs.promote_latest == 'true'
uses: peter-evans/dockerhub-description@v5
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/trunk-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Trunk Check
uses: trunk-io/trunk-action@04ba50e7658c81db7356da96657e6e77f220bfa3 # v1.0.4
uses: trunk-io/trunk-action@04ba50e7658c81db7356da96657e6e77f220bfa3 # embeds actions/cache@27d5ce7f (v5.0.5)

- name: Trunk Upgrade (on schedule only)
if: github.event_name == 'schedule'
uses: trunk-io/trunk-action@04ba50e7658c81db7356da96657e6e77f220bfa3 # v1.0.4
uses: trunk-io/trunk-action@04ba50e7658c81db7356da96657e6e77f220bfa3 # embeds actions/cache@27d5ce7f (v5.0.5)
with:
trunk-args: --upgrade
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ coverage/
reports/mutation/
stryker-output-*.json

# AgilePlus local DB — spec/cycle state, regenerated from kitty-specs/ via `agileplus specify`
# The DB contains transient per-machine state; the source of truth is the .md specs.
.agileplus/
agileplus-*.db
agileplus-*.db-shm
agileplus-*.db-wal


# Memory Bank and Cursor rules (local-only AI agent context)
memory-bank/
Expand Down
171 changes: 49 additions & 122 deletions .mergify.yml
Original file line number Diff line number Diff line change
@@ -1,59 +1,51 @@
# Mergify Configuration — Optimized for multi-language monorepos
# Docs: https://docs.mergify.com/
# Mergify merge queue — WS3.4/D5 of the v3.8.49 quality/velocity master plan.
#
# WHY: ~85-100 active PR authors/month and 300+ PRs/week peaks, all merged by ONE
# identity. The manual merge-train validated batches by hand; this queue automates
# it with batching + automatic batch bisection (a red batch of N costs ~log2(N)
# revalidations instead of N). Mergify Open Source plan: free, unlimited, public repo.
#
# GOVERNANCE (non-negotiable, mirrors CLAUDE.md Hard Rules #21/#22 + the owner's
# pre-merge ⭐ gate):
# • A PR enters the queue ONLY via the `queue` label — applied by the owner (or a
# session acting for the owner) AFTER the pre-merge ⭐ report/decision. The label
# IS the merge approval; Mergify only executes it.
# • During a release-freeze (open issue labeled `release-freeze`), do NOT label PRs
# targeting the frozen branch — the freeze is a human-honored coordination signal
# the queue cannot see. Retarget to the active release/vX+1 first (Hard Rule #21).
# • Never label a PR another session is actively working (Hard Rule #22b).
# • Fallback path if Mergify misbehaves or the OSS plan changes: the manual
# merge-train runbook (docs/ops/MERGE_TRAIN.md) — remove labels, proceed by hand.

pull_request_rules:
# Auto-merge when all CI checks pass and PR is approved
- name: Auto-merge when approved + CI green
conditions:
- "#review-requested=0"
- "#approved-reviews-by>=1"
- check-success=ci
- check-success=lint
- check-success=typecheck
- check-success=test
- -conflict
- -closed
actions:
merge:
method: squash
commit_message_template: |
{{ title }} (#{{ number }})

Co-authored-by: {{ author }}

# Auto-merge dependabot/Renovate PRs when CI passes
- name: Auto-merge dependency updates
conditions:
- or:
- author = dependabot[bot]
- author = renovate[bot]
- check-success=ci
- -conflict
- -closed
actions:
merge:
method: squash
commit_message_template: |
{{ title }} (#{{ number }})

Co-authored-by: {{ author }}

# Auto-merge bot PRs (CI configs, formatting) when CI passes
- name: Auto-merge bot housekeeping PRs
conditions:
- or:
- author = trunk-io[bot]
- author = mergify[bot]
- author = github-actions[bot]
- check-success=ci
- check-success=lint
queue_rules:
- name: release
# Any current or future release branch — the reason GitHub's native queue was
# rejected (no wildcard support on personal-account repos).
queue_conditions:
- base~=^release/v\d+\.\d+\.\d+$
- label=queue
- -draft
- -conflict
- -closed
actions:
merge:
method: squash
# "Everything that ran is green, nothing still running, AND the always-on
# anchor check succeeded" — robust to the path-filtered fast-gates (docs-only
# PRs skip code jobs; matrix shard names vary) while never fail-open: a PR with
# zero checks cannot vacuously merge, because `Merge integrity` runs on EVERY
# non-draft PR (quality.yml) and must be an affirmative success. Review approval
# is intentionally NOT a condition here: the owner-applied `queue` label IS the
# approval in this repo's single-maintainer model (see governance header).
merge_conditions:
- "#check-failure=0"
- "#check-pending=0"
- "#check-success>=1"
- "check-success=Merge integrity (changelog + generated skills)"
# Batching: validate up to 10 queued PRs together (the manual train's sweet spot);
# don't hold a lone PR hostage waiting for siblings.
batch_size: 10
batch_max_wait_time: 5 min
# Squash keeps the one-commit-per-PR history the CHANGELOG reconciliation expects.
merge_method: squash

# Add reviewers based on changed paths
pull_request_rules:
- name: Request review from team
conditions:
- -closed
Expand All @@ -64,75 +56,10 @@ pull_request_rules:
users:
- KooshaPari

# Label PRs based on changed files
- name: Label Python changes
conditions:
- files~=\.py$
actions:
label:
add:
- python

- name: Label Rust changes
conditions:
- files~=\.rs$|Cargo\.
actions:
label:
add:
- rust

- name: Label Go changes
conditions:
- files~=\.go$|go\.
actions:
label:
add:
- go

- name: Label TypeScript changes
conditions:
- files~=\.ts$|\.tsx$|package\.json
actions:
label:
add:
- typescript

# Close stale PRs after 30 days
- name: Close stale PRs
- name: clean up the queue label after merge
conditions:
- -closed
- -draft
- created-at <= 30 days ago
- "#review-requested=0"
actions:
comment:
message: >
This PR has been automatically closed after 30 days of inactivity.
Feel free to reopen if still relevant.
close: {}

# Warn on large PRs
- name: Warn on large PRs
conditions:
- -closed
- -draft
- "#files>20"
actions:
comment:
message: >
**Large PR Alert**: This PR touches {{ number }} files.
Consider splitting into smaller PRs for easier review.

# Add ready-to-merge label when all checks pass
- name: Add ready-to-merge label
conditions:
- -closed
- -draft
- check-success=ci
- check-success=lint
- check-success=test
- "#approved-reviews-by>=1"
- merged
actions:
label:
add:
- ready-to-merge
remove:
- queue
2 changes: 1 addition & 1 deletion electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
},
"publish": {
"provider": "github",
"owner": "diegosouzapw",
"owner": "KooshaPari",
"repo": "OmniRoute"
},
"files": [
Expand Down
8 changes: 6 additions & 2 deletions open-sse/config/credentialLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

import { readFileSync, existsSync } from "fs";
import { join } from "path";
import { createLogger } from "@/shared/utils/logger";

const log = createLogger("open-sse:credential-loader");
// Fields that can be overridden per provider
const CREDENTIAL_FIELDS = [
"clientId",
Expand Down Expand Up @@ -47,8 +49,10 @@ function resolveCredentialsPath(): string {
resolveDataDir = require("@/lib/dataPaths").resolveDataDir;
} catch (err) {
const fallbackDataDir = process.env.DATA_DIR || join(process.cwd(), "data");
console.warn(
`[CREDENTIALS] Could not load dataPaths module, using fallback: ${fallbackDataDir}`
const errorMessage = err instanceof Error ? err.message : String(err);
log.error(
{ err, fallbackDataDir },
`Could not load dataPaths module (${errorMessage}); using fallback credentials path: ${fallbackDataDir}`
);
return join(fallbackDataDir, "provider-credentials.json");
}
Expand Down
11 changes: 10 additions & 1 deletion open-sse/handlers/chatCore/codexFailover.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { getCodexModelScope } from "../../config/codexQuotaScopes.ts";
import { getProviderConnectionById, updateProviderConnection } from "@/lib/db/providers";
import { createLogger } from "@/shared/utils/logger";

const log = createLogger("chat-core:codexFailover");

type CodexFailoverCredentials = {
connectionId?: string | null;
Expand All @@ -16,7 +19,13 @@ export async function markCodexScopeRateLimited(params: {
rateLimitedUntil: string;
credentials?: CodexFailoverCredentials | null;
}): Promise<void> {
const connection = await getProviderConnectionById(params.failedConnectionId).catch(() => null);
const connection = await getProviderConnectionById(params.failedConnectionId).catch((err) => {
log.warn(
{ err, failedConnectionId: params.failedConnectionId },
"chat-core:codexFailover: failed to load connection for scope-rate-limit update — falling back to in-memory credentials"
);
return null;
});
const existingProviderData = connection
? asProviderData(connection.providerSpecificData)
: asProviderData(params.credentials?.providerSpecificData);
Expand Down
Loading
Loading