Skip to content

feat(ai-tools): greek-room repeated-words endpoint + fluent-ai client#181

Open
JEdward7777 wants to merge 11 commits into
eten-tech-foundation:mainfrom
JEdward7777:jel-word-check-impl
Open

feat(ai-tools): greek-room repeated-words endpoint + fluent-ai client#181
JEdward7777 wants to merge 11 commits into
eten-tech-foundation:mainfrom
JEdward7777:jel-word-check-impl

Conversation

@JEdward7777
Copy link
Copy Markdown
Contributor

Summary

Exposes fluent-ai's Greek-Room Repeated Words check through fluent-api as the first AI-tool endpoint, behind a generic, reusable pattern designed to absorb future AI tools (other Greek-Room checks, LLM drafting, embeddings) with a small per-tool wrapper.

This is the implementation that follows the design reviewed and approved in PR #173 (kaseywright, 2026-06-02). PR #173 was documentation/proposal only and has been merged; this PR contains the actual code on a fresh branch (jel-word-check-impl), rebased on top of current main.

⚠️ Prerequisite — paired fluent-platform PR

This PR is paired with a small fluent-platform compose PR that must land for the live fluent-api ↔ fluent-ai connection to authenticate and for the integration to run from a clean stack:

Prerequisite: eten-tech-foundation/fluent-platform#5

Without those compose overrides, fluent-api cannot reach/authenticate against fluent-ai (and the ai container fails to come up from a clean slate), so an end-to-end run / any future integration check would fail. The fluent-platform PR adds FLUENT_AI_URL: http://ai:8200, mounts fluent-api/scripts into the api container, and fixes two clean-slate ai-container issues (MIGRATIONS_DATABASE_URL password drift and a UV_CACHE_DIR on a noexec mount).

What's added

New endpoint: POST /ai/tools/greek-room/repeated-words

  • Introduces /ai/ as fluent-api's first service-family prefix. Per-tool URL preserves OpenAPI type-safety (a generic /dispatch was rejected).
  • Guarded by BetterAuth session + requirePermission(PERMISSIONS.AI_TOOLS_USE).
  • Envelope pass-through (D9): forwards fluent-ai's ToolJobResponse<T> verbatim — 200 for terminal statuses, 202 for non-terminal (queued/running) — so the same code path handles sync today and polling later.
  • No request enrichment (D8): body forwarded verbatim (intentional snake_case field names, with an in-code guardrail comment).

Shared client: callFluentAi<TReq, TResult>(toolPath, body, schema, options?) in src/lib/services/fluent-ai/

  • Modeled on the existing Mailgun service + withDatabaseRetry patterns. Adding a new tool is ~2 files / a few lines.
  • Builds the target URL from FLUENT_AI_URL + optional FLUENT_AI_API_PREFIX + toolPath; 30s default timeout; validates result against the schema only when status === "completed".
  • Maps transport/HTTP/parse failures → AI_SERVICE_UNAVAILABLE; failed/cancelled envelopes → AI_TOOL_EXECUTION_FAILED (both → HTTP 502). No polling, caching, or retries by design.

Configuration:

  • New required env vars FLUENT_AI_URL, FLUENT_AI_KEY (no defaults — boot fails if missing), plus optional FLUENT_AI_API_PREFIX (defaults to empty to match the live fluent-ai build, which serves routes at the root; set /api/v1 when fluent-ai versions its routes). Documented in .env.example, test values in .env.test.
  • PERMISSIONS.AI_TOOLS_USE as a string alias of content:update (D10).

Tests & tooling:

  • fluent-ai.client.test.ts — completed/queued happy paths, failed/cancelled and 4xx/5xx/network/parse/schema/timeout/abort error mappings, request-shape assertions, and FLUENT_AI_API_PREFIX cases.
  • ai-tools.route.test.ts — 401/403/400, 200 completed pass-through, 202 queued pass-through, 502 on failure, and a "no enrichment" verbatim-forward assertion.
  • scripts/smoke-repeated-words.ts + npm run smoke:repeated-words — host/in-container probe with BetterAuth auto sign-in and a PASS/FAIL banner.

Verification

  • ✅ Full quality gate green (pre-push hook): prettier --check, eslint, tsc --noEmit, and 78/78 vitest tests passing.
  • Live end-to-end smoke test: 10/10 checks, HTTP 200, run against the running fluent-platform stack (host → fluent-api → fluent-ai). Verified by container logs (POST /ai/tools/greek-room/repeated-words 200 on api; matching 200 on ai). The canned 3-verse corpus returns exactly two findings — one suspicious ("in in") and one legitimate ("truly truly") — with verse_count === 3.

Out of scope (deferred by design)

Polling endpoint (GET /ai/tools/jobs/{job_id}), DB persistence of tool runs, frontend hooks/UI, transport retries, caching, rate limits, MCP facade. The callFluentAi / ToolJobResponse shapes are forward-compatible with all of these.

See docs/proposals/repeated-word-check/ for the full design (Part 1/Part 2), the file-by-file implementation status, and the reviewer-orientation summary.

Joshua Lansford and others added 11 commits May 28, 2026 10:20
Mechanical prettier --write only (no semantic changes):
- emphasis markers *foo* -> _foo_
- markdown table separator padding
- reflow of TS code samples inside fenced blocks
The repo's @antfu/eslint-config (formatters: true) lints TS code blocks
inside markdown. Adjust the illustrative import statements in the
repeated-word-check proposal to satisfy perfectionist/sort-imports and
import/consistent-type-specifier-style:
- separate import groups with blank lines
- hoist inline type specifiers to top-level 'import type'

Hand-formatted (not raw eslint --fix output) so the samples stay readable.
No prose changed. Verified: 'eslint .' and 'prettier --check .' both pass.
…tools proposal

Capture kaseywright's review outcomes (approved 2026-06-02) directly in the
proposal docs so the decisions persist beyond the PR thread:
- D8/§8.1: intentional snake_case divergence accepted; add in-code-comment guardrail
- D10/§9.3: AI_TOOLS_USE permission alias confirmed; document for future reference
- D9/§8.2: envelope pass-through confirmed, conditioned on standard web-client format
- §15: mark open questions resolved, each linking its originating review comment
…ient

Implements the AI-tools integration approved in PR eten-tech-foundation#173 (per docs/proposals/repeated-word-check/ai-tools-integration-suggestion.md §2).

- New domain src/domains/ai-tools/ exposing POST /ai/tools/greek-room/repeated-words, registered on the OpenAPIHono app via app.ts.
- Shared client callFluentAi<TReq,TResult>(toolPath, body, resultSchema, options?) at src/lib/services/fluent-ai/ (30s default timeout, AbortSignal support, no polling/caching/retries per §7.3).
- Two env vars FLUENT_AI_URL and FLUENT_AI_KEY (required, no defaults) wired through env.ts + .env.example + .env.test.
- Permission alias PERMISSIONS.AI_TOOLS_USE = 'content:update' (D10) with review-link comment.
- Two ErrorCodes AI_SERVICE_UNAVAILABLE and AI_TOOL_EXECUTION_FAILED, both -> HTTP 502.
- Envelope pass-through (D9): 200 for terminal completed/failed/cancelled, 202 for queued/running; errors via getHttpStatus standard shape.
- snake_case wire contract kept verbatim (D8) with guardrail comments next to the Zod schemas.
- Tests: callFluentAi unit tests (§13.1), route tests (§13.2), and host-runnable scripts/smoke-repeated-words.ts via npm run smoke:repeated-words.

Schemas verified against the live fluent-ai contract; proposal §8.2/§10.2 updated to match.
Out of scope: polling endpoint, DB persistence, frontend hooks, retries, caching.

Refs: PR eten-tech-foundation#173 (kaseywright, 2026-06-02)
…12.10 wiring runbook

- Split the long proposal at the §10/§11 boundary so each file stays under
  the markdown line-count lint limit; sections numbered continuously across
  the pair so all 'see §N' references stay valid.
- Part 1 (ai-tools-integration-suggestion.md): contract & design, §1-§10.
- Part 2 (ai-tools-integration-operations.md, new): job-queue forward
  compatibility, service discovery / Docker / env wiring, testing, future
  work, resolved reviewer Q&A, §11-§15.
- Add §12.10 'Wiring up a running ecosystem' runbook (env vars, compose
  override, restart-just-api, health checks, BetterAuth set-auth-token
  sign-in, smoke-script invocation) reconciled with scripts/smoke-repeated-words.ts.
- Add ai-tools-integration-status.md: file-by-file account of what is
  implemented at b055f84 vs. what remains (live e2e run + paired
  fluent-platform PR) vs. out of scope.
- Update summary.md companion links to the new file set.
- Fix relative-path depth in all four docs (now under repeated-word-check/);
  all 79 internal links resolve; repoint a stale route-test example to
  server.test.ts / projects.service.test.ts. Docs-only; no source changes.
…in; verify live e2e

- Add FLUENT_AI_API_PREFIX env var (default empty) and buildToolUrl() so the
  fluent-ai base path is configurable instead of hardcoded /api/v1/, matching
  the live build that serves Greek-Room tools at the root.
- Enhance scripts/smoke-repeated-words.ts: BetterAuth auto sign-in with a
  trusted Origin header, set-auth-token capture, missing-dev-user + origin
  hints, and a PASS/FAIL verdict banner.
- Add client tests for empty-prefix and configured-prefix URL building.
- Document FLUENT_AI_API_PREFIX in .env.example.
- Update repeated-word-check proposal docs to mark the live end-to-end run and
  compose wiring as done and to reflect the configurable prefix.
# Conflicts:
#	docs/proposals/repeated-word-check/ai-tools-integration-suggestion.md
#	docs/proposals/repeated-word-check/ai-tools-integration-summary.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants