Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f9df1b6
feat: implement initial app structure with Tailwind CSS and Storybook…
rav3n11 Jun 14, 2026
f9cf434
feat: setup theme and core components
rav3n11 Jun 14, 2026
36fda81
feat: add reusable components for future use
rav3n11 Jun 14, 2026
8cd50ee
feat: add login/register and auth pages
rav3n11 Jun 14, 2026
cbd4835
feat: implement internationalization support with language picker and…
rav3n11 Jun 14, 2026
ce6a894
feat: implement hooks for loading NEL and taxonomy models with error …
rav3n11 Jun 14, 2026
fca2853
feat: add configuration page with navigation guard and save bar funct…
rav3n11 Jun 15, 2026
470c95e
feat: implement API keys management with GCP integration and MongoDB …
rav3n11 Jun 22, 2026
47643f2
feat: add API keys management page with create, revoke, and display f…
rav3n11 Jun 22, 2026
68a3cc3
feat: implement Classifier hooks with context provider and testing suite
rav3n11 Jun 22, 2026
8714ce8
feat: add EntityHighlight component with storybook stories and tests
rav3n11 Jun 22, 2026
d525d4a
feat: add EntityTypeFilter component with stories and tests
rav3n11 Jun 23, 2026
83fc437
feat: add Classifier page with routing, components, and localization
rav3n11 Jun 23, 2026
cf732f3
feat: move to /v2/health since /v1 doesnt have a health endpoint
rav3n11 Jun 23, 2026
1239722
feat: move to /v2/health since /v1 doesnt have a health endpoint
rav3n11 Jun 23, 2026
4deeac0
feat: improve layout responsiveness and overflow handling across comp…
rav3n11 Jul 8, 2026
466114a
feat: add initial plugin contract models and schemas for health, invo…
rav3n11 Jul 8, 2026
0e7622b
feat: implement Tabiya plugin bundles for core and IO with health che…
rav3n11 Jul 8, 2026
1dd3b18
feat: add initial implementation of Tabiya plugin architecture with c…
rav3n11 Jul 8, 2026
ce41a2f
feat: implement CRUD routes for pipelines with validation and activat…
rav3n11 Jul 8, 2026
a28d4c0
feat: add pipelines feature with CRUD operations, UI components, and …
rav3n11 Jul 8, 2026
9a29b75
feat: add pipeline editor routes, new pipeline creation, and edit fun…
rav3n11 Jul 9, 2026
0f12cb9
feat: add pipeline library page and update routing for pipeline manag…
rav3n11 Jul 9, 2026
966fa4f
feat: implement HTTP-backed entity extractor and linker for NER and N…
rav3n11 Jul 9, 2026
0bb4d50
feat: update torch version to 2.13.0+cpu and configure CPU-only sourc…
rav3n11 Jul 9, 2026
742293e
feat: update health endpoint to /v2/classify/health and refactor rela…
rav3n11 Jul 9, 2026
667f6d9
feat: add GCP identity token support for manifest fetches and update …
rav3n11 Jul 9, 2026
c1af619
fix: frontend pipelines page bug [deploy dev]
rav3n11 Jul 9, 2026
f6e44f2
fix: add additional pipeline nodes [deploy dev]
rav3n11 Jul 10, 2026
f2b3449
feat: add JSON entities source plugin and add slot compatibility chec…
rav3n11 Jul 10, 2026
c89c8d4
feat: implement classification history and usage endpoints with Mongo…
rav3n11 Jul 10, 2026
859e9e2
feat: improve seeding scripts
rav3n11 Jul 10, 2026
f3672ae
feat: add StatCard and UsageChart components with tests and integrati…
rav3n11 Jul 10, 2026
3984961
feat: adapt classifier UI to pipeline output slot and fix gateway pat…
rav3n11 Jul 11, 2026
b29f204
feat: i18n pipeline editor strings and mobile bottom tab bar
rav3n11 Jul 11, 2026
879d33d
feat: mobile responsiveness — reduce padding, stack layouts, fix tab …
rav3n11 Jul 11, 2026
9e68a50
feat: enhance PipelineSelectorChip with stage display and improve lay…
rav3n11 Jul 11, 2026
e3a0fa5
feat: update ClassifierPage and DashboardPage with new hooks and show…
rav3n11 Jul 11, 2026
f19529f
feat: add stage config overrides for NEL plugin in classification pip…
rav3n11 Jul 11, 2026
041494a
feat: update NEL integration to v2 service and enhance entity linking…
rav3n11 Jul 11, 2026
6320d79
chore: add readme for plugin architecture
rav3n11 Jul 11, 2026
829b162
fix: API key resolution to user ID and repair authentication flow bet…
rav3n11 Jul 11, 2026
3396213
feat: implement expandable rows in EntityGroupCard for better entity …
rav3n11 Jul 11, 2026
4e16e5a
feat: convert synchronous registry methods to asynchronous for improv…
rav3n11 Jul 11, 2026
72652f4
feat: add language menu to LoginPage and enhance API health check fun…
rav3n11 Jul 11, 2026
a9c89f4
feat: update DashboardPage to use UTC dates for accurate call counts …
rav3n11 Jul 11, 2026
bc42ff5
feat: add maxInstances configuration for Cloud Run services to contro…
rav3n11 Jul 12, 2026
4f28cfc
feat: convert entity extraction methods to async for concurrency [dep…
rav3n11 Jul 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
36 changes: 32 additions & 4 deletions .github/workflows/backend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,28 @@ jobs:
matrix:
include:
- service: ner
path: backend/ner
needs_shared: false
- service: nel
path: backend/nel
needs_shared: true
- service: classify
path: backend/classify
needs_shared: false
- service: nel_v2
path: backend/nel_v2
needs_shared: true
- service: classify_v2
path: backend/classify_v2
needs_shared: false
- service: tabiya_plugin_contracts
path: backend/tabiya_plugin_contracts
needs_shared: false
- service: tabiya_core
path: backend/plugin_bundles/tabiya_core
needs_shared: false
- service: tabiya_io
path: backend/plugin_bundles/tabiya_io
needs_shared: false
steps:
- uses: actions/checkout@v4
Expand All @@ -48,11 +62,11 @@ jobs:

- name: Install dependencies
run: poetry install --no-interaction ${{ matrix.service == 'nel_v2' && '--extras inference' || '' }}
working-directory: backend/${{ matrix.service }}
working-directory: ${{ matrix.path }}

- name: Run tests
run: poetry run pytest
working-directory: backend/${{ matrix.service }}
working-directory: ${{ matrix.path }}

build-and-push:
name: Build & push ${{ matrix.service }}
Expand All @@ -62,7 +76,21 @@ jobs:
environment: ${{ inputs.stack }}
strategy:
matrix:
service: [ner, nel, classify, nel_v2, classify_v2]
include:
- service: ner
dockerfile: backend/ner/Dockerfile
- service: nel
dockerfile: backend/nel/Dockerfile
- service: classify
dockerfile: backend/classify/Dockerfile
- service: nel_v2
dockerfile: backend/nel_v2/Dockerfile
- service: classify_v2
dockerfile: backend/classify_v2/Dockerfile
- service: tabiya_core
dockerfile: backend/plugin_bundles/tabiya_core/Dockerfile
- service: tabiya_io
dockerfile: backend/plugin_bundles/tabiya_io/Dockerfile
permissions:
contents: read
id-token: write
Expand All @@ -85,7 +113,7 @@ jobs:
REGISTRY="${{ secrets.GCP_REGION }}-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/tabiya-classifier"
echo "${{ secrets.HF_TOKEN }}" > /tmp/hf_token
docker build \
-f backend/${{ matrix.service }}/Dockerfile \
-f ${{ matrix.dockerfile }} \
--secret id=HF_TOKEN,src=/tmp/hf_token \
-t ${REGISTRY}/${{ matrix.service }}:${{ github.sha }} \
-t ${REGISTRY}/${{ matrix.service }}:latest \
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ jobs:
--nel-image "${REGISTRY}/nel:${{ github.sha }}" \
--classify-image "${REGISTRY}/classify:${{ github.sha }}" \
--nel-v2-image "${REGISTRY}/nel_v2:${{ github.sha }}" \
--classify-v2-image "${REGISTRY}/classify_v2:${{ github.sha }}"
--classify-v2-image "${REGISTRY}/classify_v2:${{ github.sha }}" \
--tabiya-core-image "${REGISTRY}/tabiya_core:${{ github.sha }}" \
--tabiya-io-image "${REGISTRY}/tabiya_io:${{ github.sha }}"

# ── Phase 1: deploy everything except frontend ─────────────────────────
- name: Deploy infrastructure (pre-frontend)
Expand Down
36 changes: 36 additions & 0 deletions app/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module.exports = {
root: true,
env: { browser: true, es2020: true, node: true },
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"plugin:storybook/recommended",
],
ignorePatterns: ["dist", ".eslintrc.cjs", "storybook-static", "coverage"],
parser: "@typescript-eslint/parser",
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
settings: { react: { version: "18.3" } },
rules: {
// Disable the base rule — @typescript-eslint version is TS-aware.
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
args: "after-used",
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrors: "all",
caughtErrorsIgnorePattern: "^_",
ignoreRestSiblings: true,
},
],
"@typescript-eslint/consistent-type-imports": [
"error",
{ prefer: "type-imports", fixStyle: "inline-type-imports" },
],
"react/prop-types": "off",
},
};
12 changes: 12 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
node_modules/
dist/
storybook-static/
coverage/
.vite/
*.log

# Yarn Berry / PnP artifacts — this app uses classic Yarn 1.x (matches CI).
# Ignore these so a stray `yarn` (Berry) run can't re-commit a v2 lockfile or
# PnP files and break `yarn install --frozen-lockfile` on the classic CI runner.
.yarn/
.pnp.*

.env
.env.local
.DS_Store
21 changes: 21 additions & 0 deletions app/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import type { StorybookConfig } from "@storybook/react-vite";

const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"msw-storybook-addon",
],
framework: {
name: "@storybook/react-vite",
options: {},
},
staticDirs: ["../public"],
docs: {
autodocs: "tag",
},
};

export default config;
63 changes: 63 additions & 0 deletions app/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useEffect } from "react";
import type { Preview, StoryFn } from "@storybook/react";
import { I18nextProvider } from "react-i18next";
import { initialize, mswLoader } from "msw-storybook-addon";
import i18n from "../src/i18n/i18n";
import { Locale, LocalesLabels } from "../src/i18n/constants";
import { handlers } from "../src/mocks/handlers";
import "../src/index.css";

initialize({ onUnhandledRequest: "bypass" });

const localeToolbarItems = Object.entries(LocalesLabels).map(
([localeValue, label]) => ({ value: localeValue, title: label }),
);

const preview: Preview = {
loaders: [mswLoader],
parameters: {
// Register the full MSW handler set for every story. Without this, MSW is
// initialized but has no handlers, so any story that hits the API (e.g. the
// pipelines pages) gets an unhandled request and fails to load. Individual
// stories still tune the backing store via seed/reset helpers.
msw: { handlers },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
globalTypes: {
locale: {
name: "Locale",
description: "Internationalization locale",
toolbar: {
icon: "globe",
items: localeToolbarItems,
defaultValue: Locale.EN_US,
showName: true,
},
},
},
decorators: [
function StoryWithLocale(
Story: StoryFn,
context: { globals: { locale?: string } },
) {
const selectedLocale = context.globals.locale ?? Locale.EN_US;

useEffect(() => {
i18n.changeLanguage(selectedLocale);
}, [selectedLocale]);

return (
<I18nextProvider i18n={i18n}>
<Story />
</I18nextProvider>
);
},
],
};

export default preview;
7 changes: 6 additions & 1 deletion app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tabiya Classifier</title>
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<style>*, *::before, *::after { box-sizing: border-box; } body { margin: 0; padding: 0; }</style>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=Source+Serif+4:opsz,wght@8..60,400;8..60,500;8..60,600&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="root"></div>
Expand Down
16 changes: 16 additions & 0 deletions app/knip.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"entry": [
"src/mocks/browser.ts",
"src/mocks/server.ts",
"src/**/*.stories.tsx",
"src/**/*.test.{ts,tsx}"
],
"project": ["src/**/*.{ts,tsx}"],
"ignoreDependencies": ["@storybook/blocks"],
"ignoreExportsUsedInFile": true,
"rules": {
"exports": "warn",
"types": "warn"
}
}
57 changes: 54 additions & 3 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,74 @@
"name": "tabiya-classifier-app",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"preview": "vite preview",
"lint": "eslint src --ext ts,tsx"
"lint": "eslint src --ext ts,tsx --max-warnings 0",
"lint:dead-code": "knip",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"dependencies": {
"@emotion/is-prop-valid": "^1.4.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"firebase": "^10.12.0",
"framer-motion": "^12.40.0",
"i18next": "^26.3.1",
"i18next-browser-languagedetector": "^8.2.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1"
"react-i18next": "^17.0.8",
"react-router-dom": "^6.23.1",
"reactflow": "^11",
"recharts": "^3.9.2",
"tailwind-merge": "^2.5.2"
},
"devDependencies": {
"@storybook/addon-essentials": "^8.3.5",
"@storybook/addon-interactions": "^8.3.5",
"@storybook/addon-links": "^8.3.5",
"@storybook/blocks": "^8.3.5",
"@storybook/react": "^8.3.5",
"@storybook/react-vite": "^8.3.5",
"@storybook/test": "^8.3.5",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.5.0",
"@testing-library/react": "^16.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"@vitejs/plugin-react": "^4.3.0",
"@vitest/coverage-v8": "^2.1.2",
"autoprefixer": "^10.4.20",
"eslint": "^8.57.0",
"eslint-plugin-react": "^7.37.1",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-storybook": "^0.9.0",
"jsdom": "^25.0.1",
"json-schema-to-typescript": "^15.0.4",
"knip": "^6.16.1",
"msw": "^2.4.9",
"msw-storybook-addon": "^2.0.4",
"postcss": "^8.4.47",
"storybook": "^8.3.5",
"tailwindcss": "^3.4.13",
"typescript": "^5.4.5",
"vite": "^5.2.12"
"vite": "^5.2.12",
"vitest": "^2.1.2"
},
"msw": {
"workerDirectory": [
"public"
]
}
}
6 changes: 6 additions & 0 deletions app/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Loading
Loading