Skip to content

test(mock-api): add fuzzy socket-aware harness#1963

Merged
senamakel merged 6 commits into
tinyhumansai:mainfrom
senamakel:codex/mock-server-socket-fuzz
May 16, 2026
Merged

test(mock-api): add fuzzy socket-aware harness#1963
senamakel merged 6 commits into
tinyhumansai:mainfrom
senamakel:codex/mock-server-socket-fuzz

Conversation

@senamakel
Copy link
Copy Markdown
Member

@senamakel senamakel commented May 16, 2026

Summary

  • strengthen the shared mock backend with a Socket.IO-compatible test transport for polling and websocket clients
  • add admin controls for socket session inspection, event injection, disconnects, and event-log reset
  • make conversation and cron/webhook-trigger routes stateful with bounded fuzzy fixtures instead of static empty arrays
  • add request-level fault injection, delay, and jitter controls in the mock server without copying backend controller logic
  • add focused mock-api tests covering Socket.IO transport, stateful route persistence, and injected HTTP faults

Problem

  • the existing mock server was too static for provider, chat, and realtime test flows
  • its socket support only handled a narrow handshake shape, which was not enough for real socket.io-client behavior used by the app
  • several mock routes returned dead fixtures, which reduced test value for flows that need mutable backend state

Solution

  • replace the partial socket shim with a minimal Socket.IO-compatible mock transport that supports auth, ready, polling, websocket upgrade, server-pushed events, and connect errors
  • centralize socket session state and logs in the shared mock state module so tests and admin endpoints can inspect and manipulate live sessions
  • add global mock fault rules plus delay/jitter behavior in the server dispatcher to fuzz test flows without duplicating real controller behavior
  • persist mock conversations, messages, cron jobs, and webhook triggers in-memory so tests can create and observe state transitions across requests

Submission Checklist

  • Tests added or updated (happy path + at least one failure / edge case) per Testing Strategy
  • Diff coverage ≥ 80% — targeted tests were added for the changed mock surface; final diff-cover gate remains enforced by CI
  • Coverage matrix updated — N/A: mock test harness changes only
  • All affected feature IDs from the matrix are listed in the PR description under ## Related — N/A: no matrix-backed feature row changes for this harness-only update
  • No new external network dependencies introduced (mock backend used per Testing Strategy)
  • Manual smoke checklist updated if this touches release-cut surfaces (docs/RELEASE-MANUAL-SMOKE.md) — N/A: test harness only
  • Linked issue closed via Closes #NNN in the ## Related section — N/A: no linked issue was provided for this request

Impact

  • affects the shared mock backend used by Vitest, app E2E, and Rust/mock-backed test flows
  • no production runtime behavior change intended
  • expands realtime and provider-flow test coverage without adding new runtime dependencies

Related

  • Closes: N/A
  • Follow-up PR(s)/TODOs:
    • add richer provider-specific socket event presets for channel connection state transitions
    • expand Slack/Discord-specific mock endpoints if the UI starts depending on them more heavily

AI Authored PR Metadata (required for Codex/Linear PRs)

Keep this section for AI-authored PRs. For human-only PRs, mark each field N/A.

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: codex/mock-server-socket-fuzz
  • Commit SHA: f05903699dacff9351b0341dadf9a8ad7311c2ef

Validation Run

  • pnpm --filter openhuman-app format:check
  • pnpm typecheck
  • Focused tests: node --test scripts/mock-api/socket.test.mjs scripts/mock-api/routes/__tests__/stateful.test.mjs scripts/mock-api/routes/__tests__/llm.test.mjs
  • Rust fmt/check (if changed): cargo fmt --manifest-path ../Cargo.toml --all --check and cargo fmt --manifest-path app/src-tauri/Cargo.toml --all --check ran via pnpm --filter openhuman-app format:check; cargo check --manifest-path src-tauri/Cargo.toml ran via pre-push
  • Tauri fmt/check (if changed): cargo check --manifest-path src-tauri/Cargo.toml ran via pre-push

Validation Blocked

  • command: node scripts/codex-pr-preflight.mjs --strict-path --lightweight
  • error: [FAIL] expected repo path :: expected /workspace/openhuman, got /Users/enamakel/work/tinyhumansai/openhuman-1; [FAIL] branch naming convention :: codex/mock-server-socket-fuzz
  • impact: environment-specific Codex preflight could not fully pass, but branch push and focused validations completed successfully

Behavior Changes

  • Intended behavior change: improve test-harness realism for mock HTTP and Socket.IO flows
  • User-visible effect: none in production; tests can now drive richer realtime and stateful provider scenarios

Parity Contract

  • Legacy behavior preserved: existing mock auth, OAuth, and LLM route semantics stay intact while the socket and fixture layers become more capable
  • Guard/fallback/dispatch parity checks: no production controller logic copied; route dispatch remains mock-first with injected responses and in-memory state

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none
  • Canonical PR: this PR
  • Resolution (closed/superseded/updated): new canonical PR

Summary by CodeRabbit

  • New Features

    • Mock API now persists conversations, messages, cron jobs, webhook triggers, LLM threads, and socket sessions across requests.
    • Socket controls to emit events, disconnect clients, and inspect/clear event logs; improved socket transport and WebSocket handling.
    • Enhanced mock LLM behaviors: dynamic completions, streaming, thread recording, and configurable model listings.
    • Global behavior: deterministic delays and injectable HTTP fault rules.
  • Tests

    • Expanded stateful API and socket tests, plus new LLM and transport coverage.

Review Change Stack

@senamakel senamakel requested a review from a team May 16, 2026 20:47
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 16, 2026

📝 Walkthrough

Walkthrough

Adds stateful in-memory mocks (conversations, messages, cron, webhooks, LLM threads), a full Socket.IO mock server (polling + WebSocket), deterministic fuzzing helpers, global request behavior (jittered delays and HTTP fault injection), admin socket controls, expanded LLM dynamic responses, and tests + test helpers.

Changes

Mock API Stateful Infrastructure

Layer / File(s) Summary
Mock state foundation and fuzzy helpers
scripts/mock-api/state.mjs
In-memory collections (conversations, messages, cron jobs, webhook triggers), socket session/event log, LLM threads map, deterministic fuzzing helpers, sequence generator, getters/setters/resets, socket session lifecycle and packet queueing, and updated getMockUser/getMockTeam behavior.
Socket.IO protocol helpers
scripts/mock-api/socket/protocol.mjs
Engine.IO/Socket.IO packet builders, polling payload encode/decode, URL parsing, and protocol constants (ping/payload settings, separator).
WebSocket frame handling
scripts/mock-api/socket/websocket.mjs
Server handshake (Sec-WebSocket-Accept), frame header encoding (including extended lengths), text-frame helper, and buffered frame decoder handling masking, ping/pong, close, and text callbacks.
Socket.IO server core
scripts/mock-api/socket/core.mjs
Session auth/creation, polling HTTP handler with probe/handshake/connect/event parsing, WebSocket upgrade with queued-packet draining, scripted outbound actions/delays, emit/disconnect APIs with filters, and event logging.
Socket module wiring
scripts/mock-api/socket.mjs, scripts/mock-api/socket/index.mjs
Refactored to barrel re-exports delegating to socket/core.mjs (handleSocketRequest, handleWebSocketUpgrade, emitMockSocketEvent, disconnectMockSockets).
Test helpers
scripts/mock-api/test-helpers/socket-client.mjs
Binds socket.io-client and exports createSocket() (fixed options) and onceSocket() (await an event or reject on connect_error/timeout).
Admin controls
scripts/mock-api/admin.mjs
New GET endpoints for aggregated mock state, socket sessions, and event log; extended /__admin/reset to clear conversations/messages/cron/webhooks/LLM threads/fixtures/socket sessions; POST endpoints to emit socket events, disconnect sockets, and clear event log.
Server routing and global behavior
scripts/mock-api/server.mjs
Routes /socket.io/ through handleSocketRequest(ctx) and runs maybeApplyGlobalBehavior(ctx) before route handlers to apply jittered delays and inject HTTP fault responses matched by method and optional path rules.
Stateful API routes
scripts/mock-api/routes/conversations.mjs, scripts/mock-api/routes/cron.mjs
Ensure-seeded fixtures and full CRUD: conversations/messages persist and are returned/scoped by conversationId; cron jobs and webhook triggers stored and mutated in shared arrays.
LLM shared, dynamic and integrations
scripts/mock-api/routes/llm/shared.mjs, scripts/mock-api/routes/llm/dynamic.mjs, scripts/mock-api/routes/llm.mjs, scripts/mock-api/routes/integrations.mjs
New LLM shared utilities and dynamic completion generator (buildDynamicCompletion) with family-specific behavior; streaming refactor to prefer dynamic streamScript and record thread turns; integrations route uses listMockLlmModels().
Tests
scripts/mock-api/routes/__tests__/*, scripts/mock-api/socket.*.test.mjs
Expanded tests for stateful behavior, LLM streaming/family behaviors, socket transport (polling & websocket), upgrade regression (FakeWebSocket), and socket auth required-token failure.
Public exports
scripts/mock-api/index.mjs
Index re-exports expanded to expose socket/session/event helpers and socket emit/disconnect utilities.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant MockServer
  participant SocketCore
  participant MockState
  Client->>MockServer: HTTP /socket.io GET/POST (polling) or WS upgrade
  MockServer->>SocketCore: handleSocketRequest(ctx) / handleWebSocketUpgrade(req,socket)
  SocketCore->>MockState: registerSocketSession / getSocketSession / queue/drain packets
  SocketCore-->>Client: engine-open, connect ack, ready, or error packets
  MockServer->>MockState: maybeApplyGlobalBehavior checks httpFaultRules / apply delay
  MockState-->>MockServer: state responses (conversations, events, sessions)
  MockServer-->>Client: HTTP route responses or injected fault JSON
Loading

Estimated code review effort:
🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs:

  • tinyhumansai/openhuman#1958: Overlaps changes in scripts/mock-api/routes/llm.mjs and its tests (streaming/handleStreamingCompletion).
  • tinyhumansai/openhuman#1892: Overlaps streaming path changes in scripts/mock-api/routes/llm.mjs (SSE streaming/streamScript selection).

"🐰 I stitched some mock-state and socket thread,
Conversations that linger, SSEs that spread,
A jittered delay, faults to test instead,
Hopping through sockets — code snug in my bed!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.32% 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 accurately captures the main change: adding a fuzzy socket-aware test harness to the mock API, which is the primary focus across the new socket implementation and related test infrastructure.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

@coderabbitai coderabbitai Bot added the working A PR that is being worked on by the team. label May 16, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

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

⚠️ Outside diff range comments (1)
scripts/mock-api/routes/cron.mjs (1)

83-89: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Delete response reports success even when nothing was removed.

deleted is derived from the HTTP method, not from whether a matching record existed.

Suggested fix
-    json(res, 200, {
-      success: true,
-      data: { id: cronItem[1], deleted: method === "DELETE" },
-    });
+    json(res, 200, {
+      success: true,
+      data: { id: cronItem[1], deleted: method === "DELETE" && index >= 0 },
+    });
-    json(res, 200, {
-      success: true,
-      data: { id: trgItem[1], deleted: method === "DELETE" },
-    });
+    json(res, 200, {
+      success: true,
+      data: { id: trgItem[1], deleted: method === "DELETE" && index >= 0 },
+    });

Also applies to: 124-130

🤖 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 `@scripts/mock-api/routes/cron.mjs` around lines 83 - 89, The response
currently sets deleted based on the HTTP method instead of whether a matching
record was actually removed; update the logic in the handler around
cronJobs.splice and the json(...) response so deleted is true only when a record
was found and removed (e.g., use index >= 0 or a removed flag set when
cronJobs.splice runs) and return the actual id from cronItem when present; apply
the same fix to the duplicate block referencing cronJobs.splice / cronItem
around the later section (lines 124-130) so both endpoints report deletion
status correctly.
🧹 Nitpick comments (2)
scripts/mock-api/state.mjs (1)

104-109: ⚡ Quick win

Make createMockId() seed-stable.

Date.now() and Math.random() make IDs drift across identical seeds, which undercuts reproducible mock fixtures and event logs. Derive the suffix from behaviorSeed() plus the sequence only.

Suggested change
 export function createMockId(prefix = "mock") {
-  return `${prefix}_${nextMockSequence()}_${hashString(
-    `${prefix}:${behaviorSeed()}:${Date.now()}:${Math.random()}`,
-  )
+  const sequence = nextMockSequence();
+  return `${prefix}_${sequence}_${hashString(
+    `${prefix}:${behaviorSeed()}:${sequence}`,
+  )
     .toString(16)
     .slice(0, 8)}`;
 }
🤖 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 `@scripts/mock-api/state.mjs` around lines 104 - 109, createMockId currently
uses Date.now() and Math.random(), making IDs non-deterministic; replace those
entropy sources so the suffix is derived only from behaviorSeed() and the
sequence to make IDs seed-stable. Modify createMockId (use nextMockSequence()
once into a local sequence variable) and compute the hash from a deterministic
string such as `${prefix}:${behaviorSeed()}:${sequence}` (then
toString(16).slice(0,8) as before) so the returned ID is stable for a given seed
and sequence.
scripts/mock-api/server.mjs (1)

115-131: ⚡ Quick win

Match rule.path against the pathname, not the full URL.

ctx.url still contains the query string, so a rule like { path: "/api/conversations" } will miss /api/conversations?limit=20. Parsing once and comparing pathname here makes exact-match fault rules behave predictably.

🤖 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 `@scripts/mock-api/server.mjs` around lines 115 - 131, ruleMatches currently
compares rule.path, rule.pathRegex, and rule.contains against ctx.url which
includes query strings; change it to parse ctx.url once into a pathname (e.g.
const pathname = new URL(ctx.url, "http://localhost").pathname) at the top of
ruleMatches and use pathname instead of ctx.url for the exact-match (rule.path),
regex test (rule.pathRegex) and containment checks (rule.contains) so rules like
{ path: "/api/conversations" } match "/api/conversations?limit=20"; keep the
existing try/catch around new RegExp(rule.pathRegex) and leave method handling
unchanged.
🤖 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 `@scripts/mock-api/admin.mjs`:
- Around line 63-74: The /__admin/reset handler currently calls
resetSocketSessions() but does not clear in-memory socket events, causing
socketEventCount and event reads to leak across tests; add a call to the routine
that clears the socket event log (e.g., resetSocketEvents() or
clearSocketEventLog()) in the same block—either implement resetSocketEvents() to
empty the socket events array/log and then invoke it alongside
resetSocketSessions(), or directly clear the socket events storage (e.g.,
socketEvents = [] or socketEventLog.clear()) inside the POST "/__admin/reset"
branch to ensure deterministic isolation.

In `@scripts/mock-api/routes/conversations.mjs`:
- Around line 12-16: The fixture reseeding logic in ensureConversationFixtures()
(which calls getMockConversations() and getMockMessages()) runs on every request
and repopulates data when conversations are empty; change it to only seed once
at process startup or when an explicit "seed" action is requested. Concretely,
add a module-level boolean (e.g., seeded = false) or an env/config flag and
modify ensureConversationFixtures() to return immediately if seeded is true, set
seeded = true after the first successful seed, and remove/avoid calling
ensureConversationFixtures() from per-request code paths; alternatively move the
initial call to a startup/init routine so deleting all conversations remains
durable across requests.
- Around line 75-87: The current create logic builds `created` by generating
server-controlled fields (e.g., `id` via `createMockId("conv")`, `createdAt`,
`updatedAt`, `archived`, `unreadCount`, `channel`, `title`) and then spreads
`parsedBody`, which allows clients to overwrite those fields; change this to
either whitelist allowed client-updatable fields or spread `parsedBody` first
and then explicitly set/override server fields so they cannot be clobbered.
Update the `created` construction (and the duplicate create path later that also
uses `parsedBody`) to ignore or pick only safe keys from `parsedBody` (e.g.,
title/channel) before merging, and always set `id`, `createdAt`, `updatedAt`,
`archived`, and `unreadCount` after merging to ensure server control.
- Around line 118-125: The DELETE handler currently only removes the entry from
the conversations array and always returns { deleted: true }; update the logic
in the method === "DELETE" branch (use conversationItemMatch[1] as the id) to
first check whether a conversation existed (use conversations.findIndex or
similar), set deleted = index >= 0, if deleted remove the conversation and also
remove any orphaned messages from the messages array (filter out messages with
message.conversationId === id), and return json(res, 200, { success: true, data:
{ deleted } }) (or a 404 when preferred) so the response accurately reflects
whether a deletion occurred.

In `@scripts/mock-api/routes/cron.mjs`:
- Around line 62-66: The POST and PATCH handlers currently merge parsedBody into
entities allowing callers to set/overwrite id (e.g., in the created object built
with createMockId and ...(parsedBody || {})), which can break lookups; fix by
stripping id from parsedBody before merging (or always assign id from
createMockId after the merge) in the create flow, and in the PATCH/update flow
ignore any parsedBody.id and only apply other fields to the existing entity (or
validate that parsedBody.id matches the route id and reject otherwise); update
the code paths that build created and the patch/update functions to ensure id
cannot be mutated.
- Around line 11-15: The seeding in ensureCronFixtures (which calls
getMockCronJobs, getMockWebhookTriggers and fuzzyNumber) runs on every request
when arrays are empty, so full deletions are immediately repopulated; to fix it
add a durable "seeded" guard (e.g., a module-level boolean like
seededCronFixtures) and only run the seeding logic once (check
seededCronFixtures before creating fixtures and set it true after seeding), and
apply the same guarded behavior to the other identical block referenced at lines
53-55 so deletions persist across requests.

In `@scripts/mock-api/server.mjs`:
- Around line 91-97: The Socket.IO path short-circuits before global behaviors
run: move the call to maybeApplyGlobalBehavior(ctx) so it runs before the
url.startsWith("/socket.io/") check; call const maybeShortCircuit = await
maybeApplyGlobalBehavior(ctx) first and return if truthy, then call
handleSocketRequest(ctx) for socket routes (use the same
url.startsWith("/socket.io/") condition) so polling handshakes and poll cycles
are also subject to the global delay/fault layer.

In `@scripts/mock-api/socket.mjs`:
- Around line 267-278: The connect_error path currently sends the error packet
but leaves the session in socketSessions, leaking sessions; after sending the
connect error (in the branch handling packet.startsWith("40") where
authenticateSession(auth) returns !result.ok and you call sendSocketPacket and
appendSocketEvent with socketConnectErrorPacket and session.sid), ensure you
teardown the rejected session by removing it from socketSessions,
decrementing/adjusting any activeSessionCount and performing any per-session
cleanup (clear timers, remove from other registries) for that session.sid so the
rejected session is not retained; update the branch after appendSocketEvent to
call the teardown logic (same code used for normal disconnects) or a new helper
(e.g., removeSocketSession(session.sid) / cleanupSession(session)) to centralize
removal and avoid duplicate code.

---

Outside diff comments:
In `@scripts/mock-api/routes/cron.mjs`:
- Around line 83-89: The response currently sets deleted based on the HTTP
method instead of whether a matching record was actually removed; update the
logic in the handler around cronJobs.splice and the json(...) response so
deleted is true only when a record was found and removed (e.g., use index >= 0
or a removed flag set when cronJobs.splice runs) and return the actual id from
cronItem when present; apply the same fix to the duplicate block referencing
cronJobs.splice / cronItem around the later section (lines 124-130) so both
endpoints report deletion status correctly.

---

Nitpick comments:
In `@scripts/mock-api/server.mjs`:
- Around line 115-131: ruleMatches currently compares rule.path, rule.pathRegex,
and rule.contains against ctx.url which includes query strings; change it to
parse ctx.url once into a pathname (e.g. const pathname = new URL(ctx.url,
"http://localhost").pathname) at the top of ruleMatches and use pathname instead
of ctx.url for the exact-match (rule.path), regex test (rule.pathRegex) and
containment checks (rule.contains) so rules like { path: "/api/conversations" }
match "/api/conversations?limit=20"; keep the existing try/catch around new
RegExp(rule.pathRegex) and leave method handling unchanged.

In `@scripts/mock-api/state.mjs`:
- Around line 104-109: createMockId currently uses Date.now() and Math.random(),
making IDs non-deterministic; replace those entropy sources so the suffix is
derived only from behaviorSeed() and the sequence to make IDs seed-stable.
Modify createMockId (use nextMockSequence() once into a local sequence variable)
and compute the hash from a deterministic string such as
`${prefix}:${behaviorSeed()}:${sequence}` (then toString(16).slice(0,8) as
before) so the returned ID is stable for a given seed and sequence.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b343fd87-3fb2-4c56-ba67-fcca30be0fd1

📥 Commits

Reviewing files that changed from the base of the PR and between 6707d3f and f059036.

📒 Files selected for processing (9)
  • scripts/mock-api/admin.mjs
  • scripts/mock-api/index.mjs
  • scripts/mock-api/routes/__tests__/stateful.test.mjs
  • scripts/mock-api/routes/conversations.mjs
  • scripts/mock-api/routes/cron.mjs
  • scripts/mock-api/server.mjs
  • scripts/mock-api/socket.mjs
  • scripts/mock-api/socket.test.mjs
  • scripts/mock-api/state.mjs

Comment on lines 63 to 74
if (method === "POST" && /^\/__admin\/reset\/?$/.test(url)) {
const keepBehavior = parsedBody?.keepBehavior === true;
const keepRequests = parsedBody?.keepRequests === true;
if (!keepBehavior) resetMockBehavior();
if (!keepRequests) clearRequestLog();
resetMockTunnels();
resetMockConversations();
resetMockMessages();
resetMockCronJobs();
resetMockWebhookTriggers();
resetSocketSessions();
json(res, 200, {
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Global reset should also clear socket event log for deterministic test isolation.

/__admin/reset resets sessions and other collections but leaves prior socket events in memory, so socketEventCount/event reads can leak across tests.

Suggested fix
   if (!keepBehavior) resetMockBehavior();
   if (!keepRequests) clearRequestLog();
   resetMockTunnels();
   resetMockConversations();
   resetMockMessages();
   resetMockCronJobs();
   resetMockWebhookTriggers();
   resetSocketSessions();
+  clearSocketEventLog();
🤖 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 `@scripts/mock-api/admin.mjs` around lines 63 - 74, The /__admin/reset handler
currently calls resetSocketSessions() but does not clear in-memory socket
events, causing socketEventCount and event reads to leak across tests; add a
call to the routine that clears the socket event log (e.g., resetSocketEvents()
or clearSocketEventLog()) in the same block—either implement resetSocketEvents()
to empty the socket events array/log and then invoke it alongside
resetSocketSessions(), or directly clear the socket events storage (e.g.,
socketEvents = [] or socketEventLog.clear()) inside the POST "/__admin/reset"
branch to ensure deterministic isolation.

Comment thread scripts/mock-api/routes/conversations.mjs
Comment thread scripts/mock-api/routes/conversations.mjs
Comment on lines 118 to 125
if (method === "DELETE") {
const index = conversations.findIndex(
(entry) => entry.id === conversationItemMatch[1],
);
if (index >= 0) {
conversations.splice(index, 1);
}
json(res, 200, { success: true, data: { deleted: true } });
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Conversation delete leaves orphan messages and misreports deletion.

Delete only removes the conversation, not its messages, and response always returns deleted: true even when the id is absent.

Suggested fix
     if (method === "DELETE") {
       const index = conversations.findIndex(
         (entry) => entry.id === conversationItemMatch[1],
       );
+      let deleted = false;
       if (index >= 0) {
+        const removedId = conversations[index].id;
         conversations.splice(index, 1);
+        deleted = true;
+        for (let i = messages.length - 1; i >= 0; i -= 1) {
+          if (messages[i].conversationId === removedId) messages.splice(i, 1);
+        }
       }
-      json(res, 200, { success: true, data: { deleted: true } });
+      json(res, 200, { success: true, data: { deleted } });
       return true;
     }
📝 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.

Suggested change
if (method === "DELETE") {
const index = conversations.findIndex(
(entry) => entry.id === conversationItemMatch[1],
);
if (index >= 0) {
conversations.splice(index, 1);
}
json(res, 200, { success: true, data: { deleted: true } });
if (method === "DELETE") {
const index = conversations.findIndex(
(entry) => entry.id === conversationItemMatch[1],
);
let deleted = false;
if (index >= 0) {
const removedId = conversations[index].id;
conversations.splice(index, 1);
deleted = true;
for (let i = messages.length - 1; i >= 0; i -= 1) {
if (messages[i].conversationId === removedId) messages.splice(i, 1);
}
}
json(res, 200, { success: true, data: { deleted } });
🤖 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 `@scripts/mock-api/routes/conversations.mjs` around lines 118 - 125, The DELETE
handler currently only removes the entry from the conversations array and always
returns { deleted: true }; update the logic in the method === "DELETE" branch
(use conversationItemMatch[1] as the id) to first check whether a conversation
existed (use conversations.findIndex or similar), set deleted = index >= 0, if
deleted remove the conversation and also remove any orphaned messages from the
messages array (filter out messages with message.conversationId === id), and
return json(res, 200, { success: true, data: { deleted } }) (or a 404 when
preferred) so the response accurately reflects whether a deletion occurred.

Comment thread scripts/mock-api/routes/cron.mjs
Comment thread scripts/mock-api/routes/cron.mjs
Comment thread scripts/mock-api/server.mjs Outdated
Comment thread scripts/mock-api/socket.mjs Outdated
Comment on lines +267 to +278
if (packet.startsWith("40")) {
const auth = normalizeAuthPayload(packet);
const result = authenticateSession(auth);
if (!result.ok) {
sendSocketPacket(session, socketConnectErrorPacket(result.message));
appendSocketEvent({
direction: "outbound",
kind: "connect_error",
sid: session.sid,
message: result.message,
});
return;
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.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Clean up rejected sessions after connect_error.

This path sends/queues the error packet but keeps the session in socketSessions forever. Repeated auth-failure tests will accumulate stale sessions, inflate activeSessionCount, and make later admin/event operations see dead sockets. Please add a post-delivery teardown path for rejected sessions.

🤖 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 `@scripts/mock-api/socket.mjs` around lines 267 - 278, The connect_error path
currently sends the error packet but leaves the session in socketSessions,
leaking sessions; after sending the connect error (in the branch handling
packet.startsWith("40") where authenticateSession(auth) returns !result.ok and
you call sendSocketPacket and appendSocketEvent with socketConnectErrorPacket
and session.sid), ensure you teardown the rejected session by removing it from
socketSessions, decrementing/adjusting any activeSessionCount and performing any
per-session cleanup (clear timers, remove from other registries) for that
session.sid so the rejected session is not retained; update the branch after
appendSocketEvent to call the teardown logic (same code used for normal
disconnects) or a new helper (e.g., removeSocketSession(session.sid) /
cleanupSession(session)) to centralize removal and avoid duplicate code.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
scripts/mock-api/socket/core.mjs (1)

194-205: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Rejected auth sessions are retained after connect_error.

Line 197 sends/queues connect_error, but this branch returns without any teardown marker/path. Rejected sessions can accumulate and pollute session-based admin/state operations.

🤖 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 `@scripts/mock-api/socket/core.mjs` around lines 194 - 205, The auth-rejection
path for packet.startsWith("40") currently sends a connect_error but returns
without cleaning up the session; update the branch handling
authenticateSession(auth) failure to perform proper teardown: call the existing
session teardown/cleanup function (or explicitly close the socket and remove the
session from the session store), mark the session as rejected/closed (so
session.sid is not retained for admin/state ops), and then append the
connect_error event via appendSocketEvent and return; locate this logic around
normalizeAuthPayload, authenticateSession, sendSocketPacket, appendSocketEvent
and ensure the same cleanup is used elsewhere to avoid duplicating teardown
logic.
🧹 Nitpick comments (1)
scripts/mock-api/socket/websocket.mjs (1)

94-97: 💤 Low value

Consider sending a close frame before ending the socket.

RFC 6455 Section 5.5.1 specifies that when receiving a close frame, the server should send a close frame in response before closing. Current code calls socket.end() without responding. For a mock server this likely won't affect test behavior, but if any tests validate proper close handshake, this could be relevant.

♻️ Optional: RFC-compliant close response
       if (opcode === 0x08) {
+        sendWsFrame(socket, 0x08, payload);
         socket.end();
         return;
       }
🤖 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 `@scripts/mock-api/socket/websocket.mjs` around lines 94 - 97, When handling an
incoming close opcode (the opcode === 0x08 branch) send a WebSocket close frame
back to the client before closing the connection: construct and write a close
frame (opcode 0x08) to the socket, echoing the received close payload if
present, then call socket.end(); update the code around the opcode === 0x08
check to write the close frame (via the existing frame-send utility or
socket.write) prior to socket.end() so the server performs the RFC‑compliant
close handshake.
🤖 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 `@scripts/mock-api/socket/core.mjs`:
- Around line 334-337: The close handler currently always calls
dropSocketSession(session.sid); change it to only drop the session if the
WebSocket upgrade was fully finalized: add/consult an upgrade flag (e.g.
session.upgradeComplete or session.upgraded) that is set to true when the "5"
upgrade packet is received/processed in your packet handling logic, then in
socket.on("close", ...) check that flag before calling
dropSocketSession(session.sid) and still call
logSocketCheckpoint("websocket_closed", { sid: session.sid }); regardless;
update the upgrade-packet handler to set the same flag so the check is
effective.

---

Duplicate comments:
In `@scripts/mock-api/socket/core.mjs`:
- Around line 194-205: The auth-rejection path for packet.startsWith("40")
currently sends a connect_error but returns without cleaning up the session;
update the branch handling authenticateSession(auth) failure to perform proper
teardown: call the existing session teardown/cleanup function (or explicitly
close the socket and remove the session from the session store), mark the
session as rejected/closed (so session.sid is not retained for admin/state ops),
and then append the connect_error event via appendSocketEvent and return; locate
this logic around normalizeAuthPayload, authenticateSession, sendSocketPacket,
appendSocketEvent and ensure the same cleanup is used elsewhere to avoid
duplicating teardown logic.

---

Nitpick comments:
In `@scripts/mock-api/socket/websocket.mjs`:
- Around line 94-97: When handling an incoming close opcode (the opcode === 0x08
branch) send a WebSocket close frame back to the client before closing the
connection: construct and write a close frame (opcode 0x08) to the socket,
echoing the received close payload if present, then call socket.end(); update
the code around the opcode === 0x08 check to write the close frame (via the
existing frame-send utility or socket.write) prior to socket.end() so the server
performs the RFC‑compliant close handshake.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9bd61fae-97c7-4c9f-a13b-fa931a953b9f

📥 Commits

Reviewing files that changed from the base of the PR and between f059036 and 47481dc.

📒 Files selected for processing (8)
  • scripts/mock-api/socket.auth.test.mjs
  • scripts/mock-api/socket.mjs
  • scripts/mock-api/socket.transport.test.mjs
  • scripts/mock-api/socket/core.mjs
  • scripts/mock-api/socket/index.mjs
  • scripts/mock-api/socket/protocol.mjs
  • scripts/mock-api/socket/websocket.mjs
  • scripts/mock-api/test-helpers/socket-client.mjs
✅ Files skipped from review due to trivial changes (1)
  • scripts/mock-api/socket/index.mjs

Comment thread scripts/mock-api/socket/core.mjs
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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)
scripts/mock-api/routes/cron.mjs (1)

83-99: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Return not-found semantics for missing PATCH/DELETE targets.

At Line 97 and Line 139, DELETE reports success even when the id does not exist. PATCH also silently succeeds on misses. This hides incorrect client behavior in tests.

💡 Suggested fix
   if (cronItem && (method === "PATCH" || method === "DELETE")) {
     const index = cronJobs.findIndex((entry) => entry.id === cronItem[1]);
+    const found = index >= 0;
+    if (!found) {
+      json(res, 404, { success: false, error: "Cron job not found" });
+      return true;
+    }
-    if (index >= 0 && method === "PATCH") {
+    if (method === "PATCH") {
       const { id: _ignoredId, ...patch } = parsedBody || {};
       cronJobs[index] = {
         ...cronJobs[index],
         ...patch,
       };
     }
-    if (index >= 0 && method === "DELETE") {
+    if (method === "DELETE") {
       cronJobs.splice(index, 1);
     }
@@
   if (trgItem && (method === "PATCH" || method === "DELETE")) {
     const index = webhookTriggers.findIndex((entry) => entry.id === trgItem[1]);
-    if (index >= 0 && method === "PATCH") {
+    const found = index >= 0;
+    if (!found) {
+      json(res, 404, { success: false, error: "Webhook trigger not found" });
+      return true;
+    }
+    if (method === "PATCH") {
       const { id: _ignoredId, ...patch } = parsedBody || {};
       webhookTriggers[index] = {
         ...webhookTriggers[index],
         ...patch,
       };
     }
-    if (index >= 0 && method === "DELETE") {
+    if (method === "DELETE") {
       webhookTriggers.splice(index, 1);
     }

Also applies to: 125-142

🤖 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 `@scripts/mock-api/routes/cron.mjs` around lines 83 - 99, The current handler
treats PATCH/DELETE as successful even when the target id isn't found; update
the logic around cronItem, cronJobs and method to check the found index and
return a not-found response when index < 0: for PATCH, do not apply the patch
and instead call json(res, 404, { success: false, error: "Not found", data: {
id: cronItem[1] } }); for DELETE, do not splice and return the same 404
semantics; keep the existing 200 success response only when index >= 0 (and
include deleted: true for successful DELETE).
🤖 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 `@scripts/mock-api/routes/llm/dynamic.mjs`:
- Around line 98-103: The generator emits an `await` without ensuring the
function is `async` when language === "js"; update the logic to compute a single
isAsync flag (e.g., const isAsync = /async/.test(lower) || language === "ts")
and use that flag for both asyncKeyword and awaitLine so asyncKeyword and
awaitLine stay in sync (affecting the variables asyncKeyword and awaitLine used
to build runTask); this ensures JS snippets only include `await` when the
function is declared async.

In `@scripts/mock-api/server.mjs`:
- Around line 152-153: Validate and sanitize the injected fault status before
using it: read rule.status into a local variable (e.g., statusRaw), parse it to
an integer and ensure it's finite and within HTTP range 100–599; if it's invalid
(NaN, non-integer, or out of range) fall back to 500. Replace the direct
Number(rule.status || 500) logic around the status and subsequent response write
in the request handler so the code uses the validated/clamped integer
(referencing the variables rule and status/body) to avoid thrown errors during
response writes.

In `@scripts/mock-api/state.mjs`:
- Around line 483-485: Generate and reuse the daily limit value instead of
calling fuzzyNumber twice: create a variable (e.g., dailyTokenLimit) by calling
fuzzyNumber("team:dailyTokenLimit", 500, 5000) and then set remainingTokens so
it cannot exceed that value (e.g., call fuzzyNumber with max = dailyTokenLimit
or clamp the result with Math.min), keeping activeSessionCount as
listSocketSessions().length; update the assignments for dailyTokenLimit and
remainingTokens in the same block so remainingTokens <= dailyTokenLimit.

---

Outside diff comments:
In `@scripts/mock-api/routes/cron.mjs`:
- Around line 83-99: The current handler treats PATCH/DELETE as successful even
when the target id isn't found; update the logic around cronItem, cronJobs and
method to check the found index and return a not-found response when index < 0:
for PATCH, do not apply the patch and instead call json(res, 404, { success:
false, error: "Not found", data: { id: cronItem[1] } }); for DELETE, do not
splice and return the same 404 semantics; keep the existing 200 success response
only when index >= 0 (and include deleted: true for successful DELETE).
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 68a64acb-9d77-4085-b62f-7240e457ce3c

📥 Commits

Reviewing files that changed from the base of the PR and between 47481dc and e39f4e9.

📒 Files selected for processing (15)
  • scripts/mock-api/admin.mjs
  • scripts/mock-api/index.mjs
  • scripts/mock-api/routes/__tests__/llm.test.mjs
  • scripts/mock-api/routes/__tests__/stateful.test.mjs
  • scripts/mock-api/routes/conversations.mjs
  • scripts/mock-api/routes/cron.mjs
  • scripts/mock-api/routes/integrations.mjs
  • scripts/mock-api/routes/llm.mjs
  • scripts/mock-api/routes/llm/dynamic.mjs
  • scripts/mock-api/routes/llm/shared.mjs
  • scripts/mock-api/server.mjs
  • scripts/mock-api/socket.auth.test.mjs
  • scripts/mock-api/socket.transport.test.mjs
  • scripts/mock-api/socket/core.mjs
  • scripts/mock-api/state.mjs
🚧 Files skipped from review as they are similar to previous changes (5)
  • scripts/mock-api/socket.auth.test.mjs
  • scripts/mock-api/index.mjs
  • scripts/mock-api/admin.mjs
  • scripts/mock-api/routes/conversations.mjs
  • scripts/mock-api/socket/core.mjs

Comment on lines +98 to +103
const asyncKeyword = language === "ts" ? "async " : "";
const typeSuffix = language === "ts" ? ": Promise<string>" : "";
const awaitLine = /async/.test(lower) ? " await Promise.resolve();\n" : "";
const testBlock = /test/.test(lower)
? `\nexport function runTaskTest() {\n return runTask("build");\n}\n`
: "\n";
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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

cat -n scripts/mock-api/routes/llm/dynamic.mjs | head -120

Repository: tinyhumansai/openhuman

Length of output: 4299


Fix invalid JavaScript snippet generation for async prompts.

Line 100 can emit await while line 106 still emits a non-async function when language === "js", producing invalid syntax. JavaScript await requires an async context, but asyncKeyword on line 98 is tied only to language === "ts". When a prompt contains "async" but language is JavaScript, the generated code becomes function runTask(...) { await Promise.resolve(); }, which is invalid. See how Python (line 41) and Rust (line 63) handle this correctly by gating both the async keyword and await statement on the same check.

💡 Suggested fix
-  const asyncKeyword = language === "ts" ? "async " : "";
-  const typeSuffix = language === "ts" ? ": Promise<string>" : "";
-  const awaitLine = /async/.test(lower) ? "  await Promise.resolve();\n" : "";
+  const isAsync = /async/.test(lower);
+  const asyncKeyword = isAsync ? "async " : "";
+  const typeSuffix =
+    language === "ts" ? (isAsync ? ": Promise<string>" : ": string") : "";
+  const awaitLine = isAsync ? "  await Promise.resolve();\n" : "";
📝 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.

Suggested change
const asyncKeyword = language === "ts" ? "async " : "";
const typeSuffix = language === "ts" ? ": Promise<string>" : "";
const awaitLine = /async/.test(lower) ? " await Promise.resolve();\n" : "";
const testBlock = /test/.test(lower)
? `\nexport function runTaskTest() {\n return runTask("build");\n}\n`
: "\n";
const isAsync = /async/.test(lower);
const asyncKeyword = isAsync ? "async " : "";
const typeSuffix =
language === "ts" ? (isAsync ? ": Promise<string>" : ": string") : "";
const awaitLine = isAsync ? " await Promise.resolve();\n" : "";
const testBlock = /test/.test(lower)
? `\nexport function runTaskTest() {\n return runTask("build");\n}\n`
: "\n";
🤖 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 `@scripts/mock-api/routes/llm/dynamic.mjs` around lines 98 - 103, The generator
emits an `await` without ensuring the function is `async` when language ===
"js"; update the logic to compute a single isAsync flag (e.g., const isAsync =
/async/.test(lower) || language === "ts") and use that flag for both
asyncKeyword and awaitLine so asyncKeyword and awaitLine stay in sync (affecting
the variables asyncKeyword and awaitLine used to build runTask); this ensures JS
snippets only include `await` when the function is declared async.

Comment on lines +152 to +153
const status = Number(rule.status || 500);
const body =
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate injected fault status before writing the response.

Line 152 currently accepts NaN or out-of-range values from rule.status, which can throw during response write and break intended fault-injection behavior. Add a guarded integer fallback.

Suggested fix
-    const status = Number(rule.status || 500);
+    const parsedStatus = Number(rule.status);
+    const status =
+      Number.isInteger(parsedStatus) && parsedStatus >= 100 && parsedStatus <= 599
+        ? parsedStatus
+        : 500;
📝 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.

Suggested change
const status = Number(rule.status || 500);
const body =
const parsedStatus = Number(rule.status);
const status =
Number.isInteger(parsedStatus) && parsedStatus >= 100 && parsedStatus <= 599
? parsedStatus
: 500;
const body =
🤖 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 `@scripts/mock-api/server.mjs` around lines 152 - 153, Validate and sanitize
the injected fault status before using it: read rule.status into a local
variable (e.g., statusRaw), parse it to an integer and ensure it's finite and
within HTTP range 100–599; if it's invalid (NaN, non-integer, or out of range)
fall back to 500. Replace the direct Number(rule.status || 500) logic around the
status and subsequent response write in the request handler so the code uses the
validated/clamped integer (referencing the variables rule and status/body) to
avoid thrown errors during response writes.

Comment on lines +483 to +485
dailyTokenLimit: fuzzyNumber("team:dailyTokenLimit", 500, 5000),
remainingTokens: fuzzyNumber("team:remainingTokens", 100, 5000),
activeSessionCount: listSocketSessions().length,
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Bound remainingTokens to the generated token limit.

Line 484 can exceed Line 483, producing impossible usage state (remainingTokens > dailyTokenLimit).

💡 Suggested fix
 export function getMockTeam() {
@@
   const teamName =
@@
       "Personal",
     );
+  const dailyTokenLimit = fuzzyNumber("team:dailyTokenLimit", 500, 5000);
+  const remainingTokens = fuzzyNumber("team:remainingTokens", 0, dailyTokenLimit);
   return {
@@
       usage: {
-        dailyTokenLimit: fuzzyNumber("team:dailyTokenLimit", 500, 5000),
-        remainingTokens: fuzzyNumber("team:remainingTokens", 100, 5000),
+        dailyTokenLimit,
+        remainingTokens,
         activeSessionCount: listSocketSessions().length,
       },
📝 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.

Suggested change
dailyTokenLimit: fuzzyNumber("team:dailyTokenLimit", 500, 5000),
remainingTokens: fuzzyNumber("team:remainingTokens", 100, 5000),
activeSessionCount: listSocketSessions().length,
const dailyTokenLimit = fuzzyNumber("team:dailyTokenLimit", 500, 5000);
const remainingTokens = fuzzyNumber("team:remainingTokens", 0, dailyTokenLimit);
// ... (other code in getMockTeam function)
usage: {
dailyTokenLimit,
remainingTokens,
activeSessionCount: listSocketSessions().length,
}
🤖 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 `@scripts/mock-api/state.mjs` around lines 483 - 485, Generate and reuse the
daily limit value instead of calling fuzzyNumber twice: create a variable (e.g.,
dailyTokenLimit) by calling fuzzyNumber("team:dailyTokenLimit", 500, 5000) and
then set remainingTokens so it cannot exceed that value (e.g., call fuzzyNumber
with max = dailyTokenLimit or clamp the result with Math.min), keeping
activeSessionCount as listSocketSessions().length; update the assignments for
dailyTokenLimit and remainingTokens in the same block so remainingTokens <=
dailyTokenLimit.

@senamakel senamakel merged commit 32d09e7 into tinyhumansai:main May 16, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

working A PR that is being worked on by the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant