Skip to content

feat(flows): frontend for the memory node — palette, config panel, i18n ×14 - #5228

Merged
senamakel merged 3 commits into
tinyhumansai:mainfrom
graycyrus:feat/flows-memory-node-frontend
Jul 29, 2026
Merged

feat(flows): frontend for the memory node — palette, config panel, i18n ×14#5228
senamakel merged 3 commits into
tinyhumansai:mainfrom
graycyrus:feat/flows-memory-node-frontend

Conversation

@graycyrus

@graycyrus graycyrus commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Part of the memory-in-workflows track (#5150 #5175 #5176 #5205). Frontend half of #5226. Pairs with the host adapter #5227 (and tinyhumansai/tinyflows#23). Merge after #5227 so users can't add a memory node before the backend provider is wired (an unwired node fails at runtime with a capability error).

What

Lets a user add and configure the new memory node on the Workflows canvas. Pure frontend (app/src/**), no Rust/submodule changes.

  • lib/flows/types.ts'memory' added to NodeKind (12→13).
  • lib/flows/nodeKindMeta.tsmemory entry: 🧠 icon, sage color, actions palette group (sequenced 13th per 08-memory-node.md).
  • lib/flows/nodeSummary.ts — per-operation node-card summary line.
  • components/flows/canvas/nodeConfig/memoryFields.tsx (new) — MemoryForm, wired into NODE_CONFIG_FORMS.memory. Progressive disclosure: only the fields relevant to the selected operation render. Added NumberField/configNumber primitives for limit/min_score.
  • i18n — flows.nodeKind.memory + 23 flows.nodeConfig.memory.* keys across all 14 locales, real translations, no em dashes.

The security invariant, mirrored in the UI

When operation is remember/forget, the scope control structurally omits user/flows (write ops only ever offer flow) — matching the engine's validate-time rejection. Two layers: the operation-switch handler clamps scope to flow, and a mount/update effect self-heals any pre-existing invalid write+non-flow scope (e.g. from a raw-JSON edit or a builder proposal).

Testing

memoryFields.test.tsx (10 tests): per-operation field visibility, the write→flow-only scope lock, the self-heal effect, numeric round-tripping. Verified: pnpm typecheck clean, i18n:check/i18n:english:check (0 missing/extra/leftover), no-em-dash check, eslint (incl. import/no-cycle) + prettier clean, 420/420 flows+i18n Vitest.

Summary by CodeRabbit

  • New Features

    • Added a Memory node to the workflow editor and node palette.
    • Added operation-specific configuration for recall, search, flavour, people, remember, and forget.
    • Added scope, query, key/value, result limit, and relevance score controls.
    • Added localized labels and guidance across supported languages.
    • Memory writes are restricted to the current workflow scope.
  • Tests

    • Added coverage for conditional fields, scope enforcement, and numeric input handling.

Adds the 13th tinyflows NodeKind (`memory`) to the editable Workflows
canvas: NodeKind union + palette metadata (nodeKindMeta.ts), a dedicated
config form (memoryFields.tsx) with per-operation progressive disclosure
(recall/search/flavour/people/remember/forget), and i18n across all 14
locales. The config panel enforces the engine's hard invariant that a
remember/forget node's scope may only ever be `flow`, both by never
offering `user` in the select and by self-healing an already-invalid
config on mount. Pure frontend (app/src/**) — no Rust or submodule
changes; PR3 of tinyhumansai#5226.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The flow editor adds a memory node kind with operation-specific configuration, summaries, palette metadata, localized strings, numeric field handling, scope invariants, and automated UI tests.

Changes

Memory node frontend support

Layer / File(s) Summary
Register the memory node
app/src/lib/flows/types.ts, app/src/lib/flows/nodeKindMeta.ts, app/src/lib/flows/nodeSummary.ts, app/src/components/flows/canvas/nodeConfig/nodeConfigForms.tsx
Adds the memory node kind, palette metadata, operation-based summaries, and dedicated form registration.
Implement operation-specific configuration
app/src/components/flows/canvas/nodeConfig/memoryFields.tsx, app/src/components/flows/canvas/nodeConfig/nodeConfigFields.tsx
Adds conditional controls for operations, scopes, queries, flavours, key/value fields, limits, and minimum scores, including write-scope clamping and numeric normalization.
Validate and localize the form
app/src/components/flows/canvas/nodeConfig/__tests__/memoryFields.test.tsx, app/src/lib/flows/nodeSummary.test.ts, app/src/lib/i18n/*
Tests disclosure, invariant enforcement, summaries, and change payloads; adds memory node and configuration translations across supported locales.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels: feature, memory

Suggested reviewers: oxoxdev

Poem

I’m a bunny with memory, hopping in tune,
Recall and search beneath the moon.
Keys tucked safely, scopes aligned,
Tiny test carrots neatly mined.
New words bloom in every tongue—
Fluffy frontend work is sung!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main frontend work for the memory node, including the palette, config panel, and multi-locale i18n updates.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

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

@graycyrus
graycyrus marked this pull request as ready for review July 28, 2026 15:13
@graycyrus
graycyrus requested a review from a team July 28, 2026 15:13
Comment thread app/src/lib/flows/nodeSummary.ts Outdated
@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds the frontend half of the memory node to the Workflows canvas — palette entry, progressive-disclosure config panel, node-card summary, and i18n across 14 locales. It is pure frontend (app/src/**) with no Rust or submodule changes.

  • memoryFields.tsx (new): MemoryForm with per-operation field visibility; write ops (remember/forget) structurally restrict the scope dropdown to flow only, mirroring the engine's validation invariant; a useEffect self-heals any pre-existing invalid config on mount.
  • nodeConfigFields.tsx: Adds configNumber helper and NumberField primitive; the onChange handler uses Number(raw) without a NaN guard (see inline comment) — configNumber's isFinite check recovers on the next read, but a non-finite value can briefly live in the in-memory config.
  • i18n: All 24 new keys present and correct across all 14 locales; search and recall card summaries are now distinct (previous thread concern resolved).

Confidence Score: 5/5

Safe to merge after #5227 lands; the frontend-only change introduces no data corruption risk.

All changed paths are additive and isolated to the memory node's config form. The security invariant (write ops locked to flow scope) is enforced at two layers — the operation-change handler and the self-heal effect — and is fully covered by tests. The one gap (NaN briefly living in the config bag before configNumber filters it) is recoverable and practically unreachable via normal browser input.

Files Needing Attention: The NumberField onChange in nodeConfigFields.tsx is the only file worth a second glance, purely for the NaN edge case noted in the inline comment.

Important Files Changed

Filename Overview
app/src/components/flows/canvas/nodeConfig/memoryFields.tsx New MemoryForm component with clean progressive disclosure, correct scope restriction for write ops, and a self-heal useEffect. Logic is well-tested and matches the engine invariant.
app/src/components/flows/canvas/nodeConfig/nodeConfigFields.tsx Adds configNumber and NumberField primitives. configNumber has a correct isFinite guard on read; NumberField's onChange could emit NaN before that guard fires (see comment).
app/src/components/flows/canvas/nodeConfig/nodeConfigForms.tsx Minimal diff — imports MemoryForm and registers it in NODE_CONFIG_FORMS under the memory key.
app/src/lib/flows/nodeSummary.ts Adds the memory case to describeNode with distinct branches for all six operations; search correctly returns "Searches memory" (previous thread concern resolved).
app/src/lib/flows/types.ts Adds 'memory' to the NodeKind union with a clear doc comment; no other changes.
app/src/lib/flows/nodeKindMeta.ts Appends the memory entry (🧠, sage, actions group) as the 13th kind in both the ordered list and the META record.
app/src/components/flows/canvas/nodeConfig/tests/memoryFields.test.tsx 10-test suite covers per-operation field visibility, write-only flow scope, self-heal on mount, and round-trip for both numeric fields (limit and min_score).
app/src/lib/i18n/en.ts Adds all 24 memory-node i18n keys (nodeKind + all nodeConfig.memory.*) in English; prose is clear and matches the component's field semantics.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[MemoryForm renders] --> B[Operation selector — always shown]
    B --> C{operation}
    C -->|recall / search / remember / forget| D[Scope selector]
    C -->|flavour / people| E[No scope selector]
    D --> F{isWrite?}
    F -->|yes — remember/forget| G[Only 'flow' option]
    F -->|no — recall/search| H[user · flow · flows options]
    C -->|recall / search / people| I[Query field]
    C -->|flavour| J[Flavour dropdown — 7 slugs]
    C -->|remember / forget| K[Key field]
    C -->|remember| L[Value field]
    C -->|recall / search / people| M[Limit + Min-score NumberFields]
    N[useEffect self-heal] -->|on mount/update| O{isWrite AND scope != 'flow'?}
    O -->|yes| P[Emit onChange scope=flow]
    O -->|no| Q[No-op]
Loading

Reviews (3): Last reviewed commit: "fix(flows): memory node PR review fixes ..." | Re-trigger Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1d62259160

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

'transform',
'output_parser',
'sub_workflow',
'memory',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Register the new memory-node surface in about_app

Adding memory to the palette makes workflow memory access a new user-facing flow-builder surface, but this commit does not update src/openhuman/about_app/, so the capability/privacy catalog and the in-app about/search surfaces stay unaware of it. The repo guidance explicitly requires updating that catalog when user-facing features are added or changed.

AGENTS.md reference: AGENTS.md:L378-L389

Useful? React with 👍 / 👎.

hint={t('flows.nodeConfig.memory.flavourHint')}
value={configString(config, 'flavour')}
onChange={v => onChange({ flavour: v })}
placeholder="email-tone"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use a valid flavour slug in the form hint

When an author selects the flavour operation and follows the UI example, email-tone is written into config.flavour, but the core flavour reader only accepts persona facets like communication, coding_style, stack, workflow, environment, directives, or anti_preferences and returns Unknown flavour for other strings (src/openhuman/memory/tools/flavour.rs). This makes the newly advertised form lead users to author runtime-invalid memory nodes; the placeholder/hint should use a valid slug or render a select of valid values.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot added the feature Net-new user-facing capability or product behavior. label Jul 28, 2026

@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

🤖 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 `@app/src/components/flows/canvas/nodeConfig/memoryFields.tsx`:
- Around line 194-212: Enforce valid numeric values in the onChange callbacks
for the memory limit and min_score NumberFields before calling onChange:
normalize or reject limit values below 1 or fractional values, and min_score
values outside 0..1. Preserve valid inputs and cover the boundary cases, rather
than relying on the visual min/max/step props.

In `@app/src/lib/flows/nodeSummary.ts`:
- Around line 102-104: Update the recall/search summary logic to return a
search-specific description when operation is 'search', while preserving the
existing “Recalls memory” text for recall and the scoped suffix behavior.
- Around line 95-104: Localize all new memory-node UI text: update the
operation-summary rendering around nodeSummary.ts lines 95-104 to use an
i18n-aware boundary or passed translation function, and in memoryFields.tsx
lines 153, 165, 175, and 186 replace the query, flavour, key, and value
placeholders with translation keys resolved via useT() from I18nContext. Add the
corresponding keys to every real locale file.

In `@app/src/lib/i18n/fr.ts`:
- Around line 4453-4457: Update the French hint values for
flows.nodeConfig.memory.queryOptionalHint and
flows.nodeConfig.memory.flavourHint to use consistent formal vous-register
wording and correct “style” to the plural “styles,” while preserving their
existing meanings.
🪄 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: 2b13e6ec-9e61-4436-8525-aa4c5f3bed8d

📥 Commits

Reviewing files that changed from the base of the PR and between dcc5b9b and 09dedfa.

📒 Files selected for processing (21)
  • app/src/components/flows/canvas/nodeConfig/__tests__/memoryFields.test.tsx
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx
  • app/src/components/flows/canvas/nodeConfig/nodeConfigFields.tsx
  • app/src/components/flows/canvas/nodeConfig/nodeConfigForms.tsx
  • app/src/lib/flows/nodeKindMeta.ts
  • app/src/lib/flows/nodeSummary.ts
  • app/src/lib/flows/types.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts

Comment on lines +194 to +212
<NumberField
label={t('flows.nodeConfig.memory.limitLabel')}
hint={t('flows.nodeConfig.memory.limitHint')}
value={configNumber(config, 'limit')}
onChange={v => onChange({ limit: v })}
min={1}
step={1}
testId="node-config-memory-limit"
/>
<NumberField
label={t('flows.nodeConfig.memory.minScoreLabel')}
hint={t('flows.nodeConfig.memory.minScoreHint')}
value={configNumber(config, 'min_score')}
onChange={v => onChange({ min_score: v })}
min={0}
max={1}
step={0.05}
testId="node-config-memory-min-score"
/>

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Enforce numeric bounds before persisting.

min/max/step do not block interactive changes, so this can save limit: 0, fractional limits, or min_score outside 0..1. Normalize or reject values in these callbacks and cover the boundaries.

Proposed fix
+const normalizeLimit = (value: number | undefined) =>
+  value === undefined || !Number.isFinite(value) ? undefined : Math.max(1, Math.floor(value));
+
+const normalizeMinScore = (value: number | undefined) =>
+  value === undefined || !Number.isFinite(value) ? undefined : Math.min(1, Math.max(0, value));
+
-            onChange={v => onChange({ limit: v })}
+            onChange={v => onChange({ limit: normalizeLimit(v) })}
...
-            onChange={v => onChange({ min_score: v })}
+            onChange={v => onChange({ min_score: normalizeMinScore(v) })}
📝 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
<NumberField
label={t('flows.nodeConfig.memory.limitLabel')}
hint={t('flows.nodeConfig.memory.limitHint')}
value={configNumber(config, 'limit')}
onChange={v => onChange({ limit: v })}
min={1}
step={1}
testId="node-config-memory-limit"
/>
<NumberField
label={t('flows.nodeConfig.memory.minScoreLabel')}
hint={t('flows.nodeConfig.memory.minScoreHint')}
value={configNumber(config, 'min_score')}
onChange={v => onChange({ min_score: v })}
min={0}
max={1}
step={0.05}
testId="node-config-memory-min-score"
/>
const normalizeLimit = (value: number | undefined) =>
value === undefined || !Number.isFinite(value) ? undefined : Math.max(1, Math.floor(value));
const normalizeMinScore = (value: number | undefined) =>
value === undefined || !Number.isFinite(value) ? undefined : Math.min(1, Math.max(0, value));
<NumberField
label={t('flows.nodeConfig.memory.limitLabel')}
hint={t('flows.nodeConfig.memory.limitHint')}
value={configNumber(config, 'limit')}
onChange={v => onChange({ limit: normalizeLimit(v) })}
min={1}
step={1}
testId="node-config-memory-limit"
/>
<NumberField
label={t('flows.nodeConfig.memory.minScoreLabel')}
hint={t('flows.nodeConfig.memory.minScoreHint')}
value={configNumber(config, 'min_score')}
onChange={v => onChange({ min_score: normalizeMinScore(v) })}
min={0}
max={1}
step={0.05}
testId="node-config-memory-min-score"
/>
🤖 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 `@app/src/components/flows/canvas/nodeConfig/memoryFields.tsx` around lines 194
- 212, Enforce valid numeric values in the onChange callbacks for the memory
limit and min_score NumberFields before calling onChange: normalize or reject
limit values below 1 or fractional values, and min_score values outside 0..1.
Preserve valid inputs and cover the boundary cases, rather than relying on the
visual min/max/step props.

Comment on lines +95 to +104
if (operation === 'flavour') {
const flavour = str(config, 'flavour');
return flavour ? `Reads the "${flavour}" flavour` : 'Reads a memory flavour';
}
if (operation === 'people') return 'Looks up people memory';
if (operation === 'remember') return 'Remembers a value in this workflow';
if (operation === 'forget') return 'Forgets a value from this workflow';
// recall / search
const scoped = scope ? ` (${scope})` : '';
return `Recalls memory${scoped}`;

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.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Localize all new memory-node copy.

The new summaries and placeholders are English literals, so localized clients render untranslated memory UI.

  • app/src/lib/flows/nodeSummary.ts#L95-L104: resolve operation summaries through an i18n-aware rendering boundary or a passed translation function.
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx#L153-L153: replace the query placeholder with a translation key.
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx#L165-L165: replace the flavour placeholder with a translation key.
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx#L175-L175: replace the key placeholder with a translation key.
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx#L186-L186: replace the value placeholder with a translation key.

As per coding guidelines, “Use useT() from app/src/lib/i18n/I18nContext for all UI text,” and add new keys to every real locale file.

📍 Affects 2 files
  • app/src/lib/flows/nodeSummary.ts#L95-L104 (this comment)
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx#L153-L153
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx#L165-L165
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx#L175-L175
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx#L186-L186
🤖 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 `@app/src/lib/flows/nodeSummary.ts` around lines 95 - 104, Localize all new
memory-node UI text: update the operation-summary rendering around
nodeSummary.ts lines 95-104 to use an i18n-aware boundary or passed translation
function, and in memoryFields.tsx lines 153, 165, 175, and 186 replace the
query, flavour, key, and value placeholders with translation keys resolved via
useT() from I18nContext. Add the corresponding keys to every real locale file.

Source: Coding guidelines

Comment thread app/src/lib/flows/nodeSummary.ts Outdated
Comment thread app/src/lib/i18n/fr.ts Outdated
Comment on lines +4453 to +4457
'flows.nodeConfig.memory.queryLabel': 'Requête',
'flows.nodeConfig.memory.queryOptionalHint': 'Optionnel: affine la recherche de personnes.',
'flows.nodeConfig.memory.flavourLabel': 'Style',
'flows.nodeConfig.memory.flavourHint':
'Un ensemble de style ou de préférences à lire, par exemple email-tone.',

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the French wording and register.

"Optionnel: affine" mixes informal singular address with the surrounding formal vous style, and "un ensemble de style" should use the plural. Please update these hints for consistent, natural French.

Proposed wording
-  'flows.nodeConfig.memory.queryOptionalHint': 'Optionnel: affine la recherche de personnes.',
+  'flows.nodeConfig.memory.queryOptionalHint': 'Facultatif : affinez la recherche de personnes.',
   'flows.nodeConfig.memory.flavourLabel': 'Style',
   'flows.nodeConfig.memory.flavourHint':
-    'Un ensemble de style ou de préférences à lire, par exemple email-tone.',
+    'Un ensemble de styles ou de préférences à consulter, par exemple « email-tone ».',
📝 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
'flows.nodeConfig.memory.queryLabel': 'Requête',
'flows.nodeConfig.memory.queryOptionalHint': 'Optionnel: affine la recherche de personnes.',
'flows.nodeConfig.memory.flavourLabel': 'Style',
'flows.nodeConfig.memory.flavourHint':
'Un ensemble de style ou de préférences à lire, par exemple email-tone.',
'flows.nodeConfig.memory.queryLabel': 'Requête',
'flows.nodeConfig.memory.queryOptionalHint': 'Facultatif : affinez la recherche de personnes.',
'flows.nodeConfig.memory.flavourLabel': 'Style',
'flows.nodeConfig.memory.flavourHint':
'Un ensemble de styles ou de préférences à consulter, par exemple « email-tone ».',
🤖 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 `@app/src/lib/i18n/fr.ts` around lines 4453 - 4457, Update the French hint
values for flows.nodeConfig.memory.queryOptionalHint and
flows.nodeConfig.memory.flavourHint to use consistent formal vous-register
wording and correct “style” to the plural “styles,” while preserving their
existing meanings.

…, min_score test)

- flavour operation's config hint pointed authors at "email-tone", a slug
  the engine's memory_flavour reader rejects. Replace the free-text field
  with a dropdown of the seven valid persona facets so an invalid slug
  can't be typed, and fix the hint text; add the new i18n keys across
  all 14 locales.
- search's node-card summary fell through to recall's "Recalls memory"
  wording. Give it its own "Searches memory (scope)" string.
- add a min_score round-trip test symmetric with the existing limit test
  (emits a number, clears to undefined).
@coderabbitai coderabbitai Bot added the memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/. label Jul 28, 2026

@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.

♻️ Duplicate comments (1)
app/src/lib/flows/nodeSummary.ts (1)

92-106: 🎯 Functional Correctness | 🟠 Major

Route memory summaries through i18n.

The new memory summaries hard-code English and print raw enum values such as user and coding_style, so the localized memory labels are never used by node cards. Keep describeNode pure by returning translation keys/structured data or accepting a translator at the React boundary; do not call useT() inside this utility. This repeats the unresolved prior finding for Lines 95-105.

As per coding guidelines, UI text in app/src must use useT() and new translation keys must be added to every real locale file.

🤖 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 `@app/src/lib/flows/nodeSummary.ts` around lines 92 - 106, Update the memory
branch in describeNode to stop returning hard-coded English and raw operation
values; return translation keys/structured parameters or accept a translator
supplied by the React boundary, without calling useT() inside this utility. Add
the required memory summary keys to every real locale file and render them
through useT() in the node-card UI.

Source: Coding guidelines

🤖 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.

Duplicate comments:
In `@app/src/lib/flows/nodeSummary.ts`:
- Around line 92-106: Update the memory branch in describeNode to stop returning
hard-coded English and raw operation values; return translation keys/structured
parameters or accept a translator supplied by the React boundary, without
calling useT() inside this utility. Add the required memory summary keys to
every real locale file and render them through useT() in the node-card UI.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a5b25917-3927-4e1e-a357-96eb55d5ebb9

📥 Commits

Reviewing files that changed from the base of the PR and between 09dedfa and a0fb1cf.

📒 Files selected for processing (18)
  • app/src/components/flows/canvas/nodeConfig/__tests__/memoryFields.test.tsx
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx
  • app/src/lib/flows/nodeSummary.test.ts
  • app/src/lib/flows/nodeSummary.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/hi.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/ko.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/zh-CN.ts
🚧 Files skipped from review as they are similar to previous changes (15)
  • app/src/lib/i18n/it.ts
  • app/src/lib/i18n/fr.ts
  • app/src/lib/i18n/de.ts
  • app/src/lib/i18n/es.ts
  • app/src/lib/i18n/hi.ts
  • app/src/components/flows/canvas/nodeConfig/tests/memoryFields.test.tsx
  • app/src/lib/i18n/zh-CN.ts
  • app/src/lib/i18n/id.ts
  • app/src/lib/i18n/pt.ts
  • app/src/lib/i18n/pl.ts
  • app/src/lib/i18n/ru.ts
  • app/src/lib/i18n/en.ts
  • app/src/lib/i18n/ar.ts
  • app/src/lib/i18n/bn.ts
  • app/src/components/flows/canvas/nodeConfig/memoryFields.tsx

@graycyrus

Copy link
Copy Markdown
Contributor Author

Review comments addressed — pushed in a0fb1cfef

P2 — invalid email-tone flavour slug (@chatgpt-codex-connector). Went further than the hint: the flavour field is now a dropdown of the 7 valid persona facets (communication, coding_style, stack, workflow, environment, directives, anti_preferences) — an author can no longer type an invalid slug. i18n across all 14 locales, no em dashes.

P2 — search reused recall's card summary (@greptileai). search now renders its own summary. Test added.

P2 — min_score emit path untested (@greptileai). Added symmetric round-trip tests mirroring limit (emits a number when set, clears to undefined).

Verified: typecheck, i18n:check/english:check (0 missing/extra), em-dash coverage, and the component/summary vitest all green.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown

All three fixes look solid:

  1. Flavour dropdownMEMORY_FLAVOURS is correctly typed as a const tuple of the 7 facets the engine accepts, rendered as a SelectField. The default falls back to MEMORY_FLAVOURS[0] ('communication') rather than an empty string, so a new node is always valid. The comment referencing memory_flavour in flavour.rs is a nice paper trail for the engine constraint.

  2. Search summarynodeSummary.ts now has if (operation === 'search') return \Searches memory${scoped}`before therecallfallthrough. The symmetry with therecallbranch is correct and thenodeSummary.test.ts` additions cover it.

  3. min_score round-trip tests — the two new cases (emits min_score as a number / emits undefined for min_score when cleared) are symmetric with the limit pair and correctly start from a pre-populated value for the clear case — exactly the right way to exercise the undefined-emit path.

One minor observation: the flavour field defaults to MEMORY_FLAVOURS[0] in the controlled value but doesn't emit that default into config on mount, so if the form is saved without touching the field, config.flavour will be absent. That's consistent with how other SelectField usages in the codebase behave, so not a blocker — just worth confirming the engine also defaults gracefully in that case.

All three P2s are cleanly addressed. LGTM.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

@senamakel
senamakel merged commit 39fe7db into tinyhumansai:main Jul 29, 2026
25 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature Net-new user-facing capability or product behavior. memory Memory store, memory tree, recall, summarization, and embeddings in src/openhuman/memory/.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants