Emit CONTENT-FREE reward signals to `POST {VITE_HANZO_API_URL}/v1/feedback` so
the router training loop gets production feedback. Payload carries ONLY
{request_id, signal, rating?} — never any prompt/response/tag/text/filename/code.
Fire-and-forget: never blocks UX, silent no-op on any failure.
The routing ledger keys each RoutingEvent on the upstream gateway response id
(chatcmpl-…/msg_…). The chat client previously held only locally-minted UUIDs,
so capture the REAL id server-side and thread it to the client as one field:
- server: ModelEndHandler captures `data.output.response_metadata.id ?? .id`
(the last CHAT_MODEL_END = the visible answer) into a shared `runMetadata`;
AgentClient surfaces it via `this.metadata` → `feedbackRequestId` on the saved
response message, riding the SSE final event + DB save to the client.
- schema: add optional `feedbackRequestId` to tMessageSchema (zod), IMessage
(mongo type) and the mongoose message schema (persists; SQLite keeps it in its
JSON doc blob automatically). Absent id ⇒ signal no-ops (never fabricated).
Client signals wired via new `client/src/utils/rewardSignal.ts`:
- thumbs up/down → up/down; regenerate → regenerate; copy → up (weak positive);
model-switch right after a response → switch (last assistant msg's id).
Dedicated cross-origin credentialed fetch (keepalive) to the Hanzo API — NOT the
same-origin chat backend — forwarding the end-user bearer for per-org attribution.
Honors local opt-out `VITE_HANZO_FEEDBACK=0|false|off` (server-side org/user
training opt-in is the preferred enforcement). 13 unit tests, all green.
Claude-Session: https://claude.ai/code/session_015Z1iLf7QBrq1LhignJrzDw
Co-authored-by: hanzo-dev <dev@hanzo.ai>
204 lines
9.0 KiB
JSON
204 lines
9.0 KiB
JSON
{
|
|
"name": "@hanzochat/chat",
|
|
"version": "0.9.23",
|
|
"description": "Chat - Unified interface to Agents, LLMs, MCPs and any AI model or OpenAPI documented API with full RAG stack",
|
|
"packageManager": "pnpm@10.27.0",
|
|
"workspaces": [
|
|
"api",
|
|
"client",
|
|
"packages/*"
|
|
],
|
|
"scripts": {
|
|
"update": "node config/update.js",
|
|
"add-balance": "node config/add-balance.js",
|
|
"set-balance": "node config/set-balance.js",
|
|
"list-balances": "node config/list-balances.js",
|
|
"user-stats": "node config/user-stats.js",
|
|
"rebuild:package-lock": "node config/packages",
|
|
"reinstall": "node config/update.js -l -g",
|
|
"smart-reinstall": "node config/smart-reinstall.js",
|
|
"b:reinstall": "bun config/update.js -b -l -g",
|
|
"reinstall:docker": "node config/update.js -d -g",
|
|
"update:local": "node config/update.js -l",
|
|
"update:docker": "node config/update.js -d",
|
|
"update:single": "node config/update.js -s",
|
|
"update:sudo": "node config/update.js --sudo",
|
|
"update:deployed": "node config/deployed-update.js",
|
|
"rebase:deployed": "node config/deployed-update.js --rebase",
|
|
"start:deployed": "docker compose -f ./deploy-compose.yml up -d || docker-compose -f ./deploy-compose.yml up -d",
|
|
"stop:deployed": "docker compose -f ./deploy-compose.yml down || docker-compose -f ./deploy-compose.yml down",
|
|
"upgrade": "node config/upgrade.js",
|
|
"create-user": "node config/create-user.js",
|
|
"invite-user": "node config/invite-user.js",
|
|
"list-users": "node config/list-users.js",
|
|
"reset-password": "node config/reset-password.js",
|
|
"ban-user": "node config/ban-user.js",
|
|
"delete-user": "node config/delete-user.js",
|
|
"reset-meili-sync": "node config/reset-meili-sync.js",
|
|
"update-banner": "node config/update-banner.js",
|
|
"delete-banner": "node config/delete-banner.js",
|
|
"backend": "cross-env NODE_ENV=production node api/server/index.js",
|
|
"backend:inspect": "cross-env NODE_ENV=production node --inspect api/server/index.js",
|
|
"backend:dev": "cross-env NODE_ENV=development npx nodemon api/server/index.js",
|
|
"backend:experimental": "cross-env NODE_ENV=production node api/server/experimental.js",
|
|
"backend:stop": "node config/stop-backend.js",
|
|
"build:data-provider": "cd packages/data-provider && npm run build",
|
|
"build:api": "cd packages/api && npm run build",
|
|
"build:data-schemas": "cd packages/data-schemas && npm run build",
|
|
"build:client": "cd client && npm run build",
|
|
"build:client-package": "cd packages/client && npm run build",
|
|
"build:packages": "npm run build:data-provider && npm run build:data-schemas && npm run build:api && npm run build:client-package",
|
|
"build": "npx turbo run build",
|
|
"frontend": "npm run build:data-provider && npm run build:data-schemas && npm run build:api && npm run build:client-package && cd client && npm run build",
|
|
"frontend:ci": "npm run build:data-provider && npm run build:client-package && cd client && npm run build:ci",
|
|
"build:static": "cp .env.static .env && npm run build:data-provider && npm run build:client-package && cd client && npm run build",
|
|
"frontend:dev": "cd client && npm run dev",
|
|
"e2e": "playwright test --config=e2e/playwright.config.local.ts",
|
|
"e2e:headed": "playwright test --config=e2e/playwright.config.local.ts --headed",
|
|
"e2e:a11y": "playwright test --config=e2e/playwright.config.a11y.ts --headed",
|
|
"e2e:ci": "playwright test --config=e2e/playwright.config.ts",
|
|
"e2e:debug": "cross-env PWDEBUG=1 playwright test --config=e2e/playwright.config.local.ts",
|
|
"e2e:codegen": "npx playwright codegen --load-storage=e2e/storageState.json http://localhost:3080/c/new",
|
|
"e2e:login": "npx playwright codegen --save-storage=e2e/auth.json http://localhost:3080/login",
|
|
"e2e:github": "act -W .github/workflows/playwright.yml --secret-file my.secrets",
|
|
"test:client": "cd client && npm run test:ci",
|
|
"test:api": "cd api && npm run test:ci",
|
|
"test:packages:api": "cd packages/api && npm run test:ci",
|
|
"test:packages:data-provider": "cd packages/data-provider && npm run test:ci",
|
|
"test:packages:data-schemas": "cd packages/data-schemas && npm run test:ci",
|
|
"test:all": "npm run test:client && npm run test:api && npm run test:packages:api && npm run test:packages:data-provider && npm run test:packages:data-schemas",
|
|
"e2e:update": "playwright test --config=e2e/playwright.config.js --update-snapshots",
|
|
"e2e:report": "npx playwright show-report e2e/playwright-report",
|
|
"lint:fix": "eslint --fix \"{,!(node_modules|venv)/**/}*.{js,jsx,ts,tsx}\"",
|
|
"lint": "eslint \"{,!(node_modules|venv)/**/}*.{js,jsx,ts,tsx}\"",
|
|
"format": "npx prettier --write \"{,!(node_modules|venv)/**/}*.{js,jsx,ts,tsx}\"",
|
|
"b:api": "NODE_ENV=production bun run api/server/index.js",
|
|
"b:api-inspect": "NODE_ENV=production bun --inspect run api/server/index.js",
|
|
"b:api:dev": "NODE_ENV=production bun run --watch api/server/index.js",
|
|
"b:data": "cd packages/data-provider && bun run b:build",
|
|
"b:build:client-package": "cd packages/client && bun run b:build",
|
|
"b:data-schemas": "cd packages/data-schemas && bun run b:build",
|
|
"b:build:api": "cd packages/api && bun run b:build",
|
|
"b:build:client": "cd client && bun --bun run b:build",
|
|
"b:client": "bun --bun run b:data && bun --bun run b:data-schemas && bun --bun run b:build:api && bun --bun run b:build:client-package && bun --bun run b:build:client",
|
|
"b:client:dev": "cd client && bun run b:dev",
|
|
"b:test:client": "cd client && bun run b:test",
|
|
"b:test:api": "cd api && bun run b:test",
|
|
"b:balance": "bun config/add-balance.js",
|
|
"b:list-balances": "bun config/list-balances.js",
|
|
"reset-terms": "node config/reset-terms.js",
|
|
"flush-cache": "node config/flush-cache.js",
|
|
"migrate:agent-permissions:dry-run": "node config/migrate-agent-permissions.js --dry-run",
|
|
"migrate:agent-permissions": "node config/migrate-agent-permissions.js",
|
|
"migrate:agent-permissions:batch": "node config/migrate-agent-permissions.js --batch-size=50",
|
|
"migrate:prompt-permissions:dry-run": "node config/migrate-prompt-permissions.js --dry-run",
|
|
"migrate:prompt-permissions": "node config/migrate-prompt-permissions.js",
|
|
"migrate:prompt-permissions:batch": "node config/migrate-prompt-permissions.js --batch-size=50"
|
|
},
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "git+https://github.com/hanzoai/chat.git"
|
|
},
|
|
"author": "",
|
|
"license": "ISC",
|
|
"bugs": {
|
|
"url": "https://github.com/hanzoai/chat/issues"
|
|
},
|
|
"homepage": "https://hanzo.ai/chat",
|
|
"devDependencies": {
|
|
"@axe-core/playwright": "^4.10.1",
|
|
"@eslint/compat": "^1.2.6",
|
|
"@eslint/eslintrc": "^3.3.1",
|
|
"@eslint/js": "^9.20.0",
|
|
"@playwright/test": "^1.56.1",
|
|
"@types/react-virtualized": "^9.22.0",
|
|
"caniuse-lite": "^1.0.30001741",
|
|
"cross-env": "^7.0.3",
|
|
"elliptic": "^6.6.1",
|
|
"eslint": "^9.39.1",
|
|
"eslint-config-prettier": "^10.0.1",
|
|
"eslint-import-resolver-typescript": "^3.7.0",
|
|
"eslint-plugin-i18next": "^6.1.1",
|
|
"eslint-plugin-import": "^2.31.0",
|
|
"eslint-plugin-jest": "^29.1.0",
|
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
"eslint-plugin-prettier": "^5.2.3",
|
|
"eslint-plugin-react": "^7.37.4",
|
|
"eslint-plugin-react-hooks": "^5.1.0",
|
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
"globals": "^15.14.0",
|
|
"husky": "^9.1.7",
|
|
"jest": "^30.2.0",
|
|
"lint-staged": "^15.4.3",
|
|
"prettier": "^3.5.0",
|
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
"turbo": "^2.8.7",
|
|
"typescript-eslint": "^8.24.0"
|
|
},
|
|
"overrides": {
|
|
"@ariakit/react": "0.4.29",
|
|
"@anthropic-ai/sdk": "0.73.0",
|
|
"@hanzochat/agents": {
|
|
"@langchain/anthropic": {
|
|
"@anthropic-ai/sdk": "0.73.0",
|
|
"fast-xml-parser": "5.3.6"
|
|
},
|
|
"@anthropic-ai/sdk": "0.73.0",
|
|
"fast-xml-parser": "5.3.6"
|
|
},
|
|
"axios": "^1.13.5",
|
|
"elliptic": "^6.6.1",
|
|
"fast-xml-parser": "5.3.6",
|
|
"form-data": "^4.0.4",
|
|
"tslib": "^2.8.1",
|
|
"mdast-util-gfm-autolink-literal": "2.0.0",
|
|
"remark-gfm": {
|
|
"mdast-util-gfm-autolink-literal": "2.0.0"
|
|
},
|
|
"mdast-util-gfm": {
|
|
"mdast-util-gfm-autolink-literal": "2.0.0"
|
|
},
|
|
"katex": "^0.16.21",
|
|
"rehype-katex": {
|
|
"katex": "^0.16.21"
|
|
},
|
|
"remark-math": {
|
|
"micromark-extension-math": {
|
|
"katex": "^0.16.21"
|
|
}
|
|
},
|
|
"langsmith": "0.4.12",
|
|
"zod-to-json-schema": "3.24.6"
|
|
},
|
|
"nodemonConfig": {
|
|
"ignore": [
|
|
"api/data/",
|
|
"data/",
|
|
"client/",
|
|
"admin/",
|
|
"packages/"
|
|
]
|
|
},
|
|
"dependencies": {
|
|
"@opentelemetry/api": "^1.9.0",
|
|
"@opentelemetry/core": "^2.5.1",
|
|
"@opentelemetry/exporter-trace-otlp-http": "^0.212.0",
|
|
"@opentelemetry/sdk-trace-base": "^2.5.1"
|
|
},
|
|
"pnpm": {
|
|
"onlyBuiltDependencies": [
|
|
"sharp",
|
|
"protobufjs",
|
|
"mongodb-memory-server",
|
|
"unrs-resolver",
|
|
"better-sqlite3-multiple-ciphers"
|
|
],
|
|
"overrides": {
|
|
"@ariakit/react": "0.4.29",
|
|
"zod-to-json-schema": "3.24.6",
|
|
"@modelcontextprotocol/sdk": "1.22.0",
|
|
"zod@3.24.4": "3.25.76"
|
|
}
|
|
}
|
|
}
|