@h-ai/cli 0.1.0-alpha9 → 1.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +229 -0
- package/README.ja.md +229 -0
- package/README.md +175 -113
- package/dist/chunk-AKV2CQZV.js +1497 -0
- package/dist/chunk-AKV2CQZV.js.map +1 -0
- package/dist/chunk-EF7WOFWZ.js +7557 -0
- package/dist/chunk-EF7WOFWZ.js.map +1 -0
- package/dist/chunk-MUHRBJSW.js +29272 -0
- package/dist/chunk-MUHRBJSW.js.map +1 -0
- package/dist/chunk-ZSDEVXZ7.js +38 -0
- package/dist/{chunk-2H7UOFLK.js.map → chunk-ZSDEVXZ7.js.map} +1 -1
- package/dist/cli-config-templates-HHFHNXBN.js +5 -0
- package/dist/cli-config-templates-HHFHNXBN.js.map +1 -0
- package/dist/cli-skill-templates-PN4FLGBC.js +5 -0
- package/dist/cli-skill-templates-PN4FLGBC.js.map +1 -0
- package/dist/index.js +4444 -554
- package/dist/index.js.map +1 -1
- package/dist/metafile-esm.json +1 -0
- package/dist/src-TEBHR5I5.js +5 -0
- package/dist/src-TEBHR5I5.js.map +1 -0
- package/package.json +35 -15
- package/templates/README.md +56 -114
- package/templates/apps/admin/messages/en-US.json +7 -0
- package/templates/apps/admin/messages/ja-JP.json +40 -0
- package/templates/apps/admin/messages/zh-CN.json +7 -0
- package/templates/apps/admin/src/routes/+layout.svelte.hbs +65 -8
- package/templates/apps/admin/src/routes/+page.svelte.hbs +35 -14
- package/templates/apps/admin/src/routes/admin/+layout.svelte.hbs +54 -22
- package/templates/apps/admin/src/routes/admin/+page.svelte.hbs +33 -24
- package/templates/apps/admin/src/routes/admin/settings/+page.svelte.hbs +16 -13
- package/templates/apps/api/.dockerignore.hbs +25 -0
- package/templates/apps/api/.gitignore.hbs +22 -0
- package/templates/apps/api/.npmrc.hbs +1 -0
- package/templates/apps/api/apps/{{projectName}}-contract/README.md.hbs +39 -0
- package/templates/apps/api/apps/{{projectName}}-contract/package.json.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-contract.ts.hbs +27 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/app-schemas.ts.hbs +28 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/index.ts.hbs +5 -0
- package/templates/apps/api/apps/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tests/contract.test.ts.hbs +18 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsconfig.json.hbs +12 -0
- package/templates/apps/api/apps/{{projectName}}-contract/tsup.config.ts.hbs +11 -0
- package/templates/apps/api/apps/{{projectName}}-contract/vitest.config.ts.hbs +9 -0
- package/templates/apps/api/apps/{{projectName}}-serv/README.md.hbs +60 -0
- package/templates/apps/api/apps/{{projectName}}-serv/config/_core.yml.hbs +17 -0
- package/templates/apps/api/apps/{{projectName}}-serv/config/_serv.yml.hbs +54 -0
- package/templates/apps/api/apps/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
- package/templates/apps/api/apps/{{projectName}}-serv/package.json.hbs +66 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/app.ts.hbs +119 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/index.ts.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/lib/server/init.ts.hbs +165 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +57 -0
- package/templates/apps/api/apps/{{projectName}}-serv/src/server/procedures/index.ts.hbs +41 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tests/service.test.ts.hbs +176 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tsconfig.json.hbs +16 -0
- package/templates/apps/api/apps/{{projectName}}-serv/tsup.config.ts.hbs +20 -0
- package/templates/apps/api/apps/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
- package/templates/apps/api/e2e/api-serv.spec.ts.hbs +113 -0
- package/templates/apps/api/e2e/capture-evidence.ts.hbs +23 -0
- package/templates/apps/api/eslint.config.js.hbs +30 -0
- package/templates/apps/api/hai.json.hbs +4 -0
- package/templates/apps/api/images/serv.Dockerfile.hbs +37 -0
- package/templates/apps/api/package.json.hbs +53 -0
- package/templates/apps/api/playwright.config.ts.hbs +67 -0
- package/templates/apps/api/pnpm-workspace.yaml.hbs +40 -0
- package/templates/apps/api/tsconfig.base.json +14 -0
- package/templates/apps/fullstack/.dockerignore.hbs +25 -0
- package/templates/apps/fullstack/.gitignore.hbs +38 -0
- package/templates/apps/fullstack/.npmrc.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/.env.example.hbs +10 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/README.md.hbs +67 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/capacitor.config.ts.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/index.html.hbs +22 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/package.json.hbs +86 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/public/runtime-config.js.hbs +4 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/App.svelte.hbs +59 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.css.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/app.d.ts.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/lib/capacitor.ts.hbs +19 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/src/main.ts.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/svelte.config.js.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/tsconfig.json.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-app/vite.config.ts.hbs +74 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/.env.example.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/README.md.hbs +64 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/index.html.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/package.json.hbs +66 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/App.svelte.hbs +25 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.css.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/app.d.ts.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src/main.ts.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/Cargo.toml.hbs +33 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/build.rs.hbs +6 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/capabilities/default.json.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/128x128@2x.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/32x32.png +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.icns +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/icons/icon.ico +0 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/lib.rs.hbs +91 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/src/main.rs.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/src-tauri/tauri.conf.json.hbs +46 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/svelte.config.js.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/tsconfig.json.hbs +22 -0
- package/templates/apps/fullstack/apps/{{projectName}}-desktop/vite.config.ts.hbs +89 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/README.md.hbs +25 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/en-US.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/ja-JP.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/messages/zh-CN.json.hbs +12 -0
- package/templates/apps/fullstack/apps/{{projectName}}-miniapp/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/README.md.hbs +54 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/eslint.config.js.hbs +20 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/index.html.hbs +21 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/en-US.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/ja-JP.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/messages/zh-CN.json.hbs +7 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/package.json.hbs +53 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/project.inlang/settings.json.hbs +17 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/public/runtime-config.js.hbs +1 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/App.svelte.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.css.hbs +18 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/app.d.ts.hbs +8 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/build-metadata.ts.hbs +9 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/src/main.ts.hbs +14 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/svelte.config.js.hbs +16 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/tsconfig.json.hbs +23 -0
- package/templates/apps/fullstack/apps/{{projectName}}-web/vite.config.ts.hbs +76 -0
- package/templates/apps/fullstack/docs/security-configuration.md.hbs +349 -0
- package/templates/apps/fullstack/e2e/fullstack.spec.ts.hbs +988 -0
- package/templates/apps/fullstack/e2e/session-close.spec.ts.hbs +119 -0
- package/templates/apps/fullstack/eslint.config.js.hbs +41 -0
- package/templates/apps/fullstack/hai.json.hbs +11 -0
- package/templates/apps/fullstack/images/serv.Dockerfile.hbs +38 -0
- package/templates/apps/fullstack/images/web/19-runtime-config.envsh.hbs +5 -0
- package/templates/apps/fullstack/images/web/nginx.conf.hbs +24 -0
- package/templates/apps/fullstack/images/web/runtime-config.js.template.hbs +3 -0
- package/templates/apps/fullstack/images/web.Dockerfile.hbs +37 -0
- package/templates/apps/fullstack/package.json.hbs +61 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/README.md.hbs +40 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/package.json.hbs +30 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-contract.ts.hbs +78 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/admin-schemas.ts.hbs +134 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-contract.ts.hbs +20 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/app-schemas.ts.hbs +35 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/index.ts.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/src/{{projectName}}-contract.ts.hbs +23 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tests/contract.test.ts.hbs +31 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tsconfig.json.hbs +9 -0
- package/templates/apps/fullstack/packages/{{projectName}}-contract/tsup.config.ts.hbs +9 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/README.md.hbs +84 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_ai.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_audit.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_cache.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_core.yml.hbs +22 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_db.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_feedback.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_iam.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_payment.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_reach.yml.hbs +60 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_scheduler.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_serv.yml.hbs +64 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_storage.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/config/_vecdb.yml.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/data/.gitkeep.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/package.json.hbs +62 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/app-server.ts.hbs +115 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/build-metadata.ts.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/index.ts.hbs +40 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/admin-service.ts.hbs +294 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/audit-jobs.ts.hbs +28 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/business-settings.ts.hbs +50 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/messages.ts.hbs +50 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/admin-procedures.ts.hbs +106 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/app-procedures.ts.hbs +49 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/procedures/index.ts.hbs +34 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/runtime.ts.hbs +159 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/src/server/security-roles.ts.hbs +73 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/app-server.test.ts.hbs +505 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/runtime.test.ts.hbs +72 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tests/security.test.ts.hbs +183 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsconfig.json.hbs +10 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/tsup.config.ts.hbs +18 -0
- package/templates/apps/fullstack/packages/{{projectName}}-serv/vitest.config.ts.hbs +12 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/.gitignore.hbs +10 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/README.md.hbs +97 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/en-US.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/ja-JP.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/messages/zh-CN.json.hbs +164 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/package.json.hbs +55 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/project.inlang/settings.json.hbs +11 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/index.ts.hbs +7 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/api-client.ts.hbs +94 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/feedback-client.ts.hbs +36 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/sensitive-actions.svelte.ts.hbs +16 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/api/session-recovery.svelte.ts.hbs +4 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AdminWorkspace.svelte.hbs +122 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/AppShell.svelte.hbs +90 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/components/FeedbackEntry.svelte.hbs +86 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/audit.svelte.hbs +94 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/configuration.svelte.hbs +25 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/feedback.svelte.hbs +157 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/roles.svelte.hbs +77 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/settings.svelte.hbs +44 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/pages/users.svelte.hbs +216 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/security/role-label.ts.hbs +12 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/guide-store.ts.hbs +55 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/management-store.svelte.ts.hbs +614 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/src/lib/stores/theme-store.svelte.ts.hbs +23 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/svelte.config.js.hbs +1 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/api-client.test.ts.hbs +150 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tests/management-store.test.ts.hbs +253 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/tsconfig.json.hbs +17 -0
- package/templates/apps/fullstack/packages/{{projectName}}-shared/vitest.config.ts.hbs +7 -0
- package/templates/apps/fullstack/playwright.config.ts.hbs +114 -0
- package/templates/apps/fullstack/playwright.session-close.config.ts.hbs +18 -0
- package/templates/apps/fullstack/pnpm-workspace.yaml.hbs +38 -0
- package/templates/apps/fullstack/tsconfig.base.json +14 -0
- package/templates/apps/h5/messages/en-US.json +3 -0
- package/templates/apps/h5/messages/ja-JP.json +40 -0
- package/templates/apps/h5/messages/zh-CN.json +3 -0
- package/templates/apps/h5/src/routes/+layout.svelte.hbs +85 -30
- package/templates/apps/h5/src/routes/+page.svelte.hbs +20 -8
- package/templates/apps/h5/src/routes/discover/+page.svelte.hbs +17 -6
- package/templates/apps/h5/src/routes/profile/+page.svelte.hbs +17 -6
- package/templates/apps/mobile-app/.env.hbs +3 -0
- package/templates/apps/{android-app → mobile-app}/capacitor.config.ts.hbs +2 -2
- package/templates/apps/mobile-app/index.html.hbs +14 -0
- package/templates/apps/mobile-app/messages/en-US.json +36 -0
- package/templates/apps/mobile-app/messages/ja-JP.json +36 -0
- package/templates/apps/mobile-app/messages/zh-CN.json +36 -0
- package/templates/apps/mobile-app/public/runtime-config.js +1 -0
- package/templates/apps/mobile-app/src/App.svelte.hbs +153 -0
- package/templates/apps/mobile-app/src/lib/api.ts.hbs +213 -0
- package/templates/apps/mobile-app/src/lib/app-config.ts.hbs +14 -0
- package/templates/apps/{android-app → mobile-app}/src/lib/capacitor.ts +6 -7
- package/templates/apps/mobile-app/src/lib/pages/home.svelte.hbs +58 -0
- package/templates/apps/mobile-app/src/lib/pages/profile.svelte.hbs +13 -0
- package/templates/apps/mobile-app/src/lib/pages/tasks.svelte.hbs +16 -0
- package/templates/apps/mobile-app/src/main.ts.hbs +11 -0
- package/templates/apps/website/messages/en-US.json +4 -2
- package/templates/apps/website/messages/ja-JP.json +34 -0
- package/templates/apps/website/messages/zh-CN.json +4 -2
- package/templates/apps/website/scripts/static-website.mjs.hbs +67 -0
- package/templates/apps/website/src/routes/+layout.svelte.hbs +77 -26
- package/templates/apps/website/src/routes/+layout.ts +3 -0
- package/templates/apps/website/src/routes/+page.svelte.hbs +31 -12
- package/templates/apps/website/src/routes/about/+page.svelte.hbs +11 -6
- package/templates/apps/website/src/routes/api/health/+server.ts +3 -0
- package/templates/apps/website/src/routes/contact/+page.svelte.hbs +44 -34
- package/templates/apps/website/src/routes/services/+page.svelte.hbs +27 -40
- package/templates/base/.dockerignore.hbs +27 -0
- package/templates/base/.gitignore.hbs +41 -0
- package/templates/base/.npmrc.hbs +1 -0
- package/templates/base/e2e/app.spec.ts.hbs +213 -0
- package/templates/base/e2e/helpers.ts +1 -1
- package/templates/base/eslint-rules.js +45 -0
- package/templates/base/eslint.config.js.hbs +34 -0
- package/templates/base/hai.json.hbs +4 -0
- package/templates/base/images/web/nginx.conf.hbs +24 -0
- package/templates/base/images/web.Dockerfile.hbs +72 -0
- package/templates/base/package.json.hbs +125 -49
- package/templates/base/playwright.config.ts +44 -6
- package/templates/base/pnpm-workspace.yaml.hbs +40 -0
- package/templates/base/src/app.css.hbs +40 -0
- package/templates/base/src/app.d.ts.hbs +14 -1
- package/templates/base/src/app.html.hbs +13 -0
- package/templates/base/src/hooks.server.ts.hbs +115 -43
- package/templates/base/src/lib/build-metadata.ts.hbs +7 -0
- package/templates/base/src/lib/server/init.ts.hbs +125 -152
- package/templates/base/src/lib/server/kit-config.ts.hbs +40 -0
- package/templates/base/src/routes/+layout.server.ts.hbs +35 -0
- package/templates/base/static/favicon.png +0 -0
- package/templates/base/svelte.config.js.hbs +84 -5
- package/templates/base/tests/scaffold.test.ts.hbs +102 -0
- package/templates/base/tsconfig.json.hbs +50 -0
- package/templates/base/vite.config.ts.hbs +117 -12
- package/templates/base/vitest.config.ts.hbs +19 -0
- package/templates/features/ai/routes/api/chat/+server.ts +6 -7
- package/templates/features/iam/routes-admin/(auth)/+layout.svelte.hbs +3 -17
- package/templates/features/iam/routes-admin/(auth)/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-admin/(auth)/auth/login/+page.svelte.hbs +9 -96
- package/templates/features/iam/routes-admin/(auth)/auth/register/+page.svelte.hbs +9 -122
- package/templates/features/iam/routes-admin/(auth)/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-h5/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-h5/auth/login/+page.svelte.hbs +9 -96
- package/templates/features/iam/routes-h5/auth/register/+page.svelte.hbs +9 -112
- package/templates/features/iam/routes-h5/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-shared/api/auth/captcha/+server.ts.hbs +4 -0
- package/templates/features/iam/routes-shared/api/auth/config/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/login/+server.ts +1 -29
- package/templates/features/iam/routes-shared/api/auth/login/ldap/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/login/otp/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/logout/+server.ts +13 -6
- package/templates/features/iam/routes-shared/api/auth/otp/send/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/password/renew/+server.ts +5 -0
- package/templates/features/iam/routes-shared/api/auth/password-reset/confirm/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/password-reset/request/+server.ts +4 -0
- package/templates/features/iam/routes-shared/api/auth/reauthenticate/+server.ts +5 -0
- package/templates/features/iam/routes-shared/api/auth/register/+server.ts +1 -23
- package/templates/features/iam/routes-shared/api/auth/session/close/+server.ts.hbs +4 -0
- package/templates/features/iam/routes-website/auth/forgot-password/+page.svelte.hbs +10 -0
- package/templates/features/iam/routes-website/auth/login/+page.svelte.hbs +11 -0
- package/templates/features/iam/routes-website/auth/register/+page.svelte.hbs +11 -0
- package/templates/features/iam/routes-website/auth/reset-password/+page.svelte.hbs +10 -0
- package/templates/features/payment/routes/api/v1/payment/create/+server.ts +25 -23
- package/templates/features/payment/routes/api/v1/payment/notify/[provider]/+server.ts +5 -2
- package/templates/features/storage/routes/api/upload/+server.ts +10 -8
- package/templates/i18n/project.inlang/settings.json +2 -2
- package/templates/shared/.gitattributes +11 -0
- package/templates/shared/build-metadata.ts +42 -0
- package/templates/shared/container-runtime-config.sh +30 -0
- package/templates/shared/e2e-env.ts +98 -0
- package/templates/shared/hash-router.svelte.ts +83 -0
- package/templates/shared/public-base-path.mjs +19 -0
- package/templates/shared/run-e2e.mjs +104 -0
- package/templates/shared/vite-runtime-config.ts +56 -0
- package/templates/skills/AGENTS.md +75 -16
- package/templates/skills/CLAUDE.md +0 -11
- package/templates/skills/bridges/admin/AGENTS.md +89 -0
- package/templates/skills/bridges/api/AGENTS.md +83 -0
- package/templates/skills/bridges/fullstack/AGENTS.md.hbs +102 -0
- package/templates/skills/bridges/h5/AGENTS.md +88 -0
- package/templates/skills/bridges/mobile-app/AGENTS.md +100 -0
- package/templates/skills/bridges/website/AGENTS.md +88 -0
- package/templates/skills/copilot-instructions.md +3 -59
- package/templates/skills/hai-ai/SKILL.md +44 -715
- package/templates/skills/hai-ai/guide.md +457 -0
- package/templates/skills/hai-ai/reference.md +292 -0
- package/templates/skills/hai-api-client/SKILL.md +26 -339
- package/templates/skills/hai-api-client/reference.md +180 -0
- package/templates/skills/hai-api-contract/SKILL.md +36 -0
- package/templates/skills/hai-api-contract/reference.md +280 -0
- package/templates/skills/hai-app-create/SKILL.md +38 -351
- package/templates/skills/hai-app-create/collaboration.md +52 -0
- package/templates/skills/hai-app-create/development.md +243 -0
- package/templates/skills/hai-app-create/reference.md +376 -0
- package/templates/skills/hai-app-review/SKILL.md +57 -126
- package/templates/skills/hai-app-review/differential.md +34 -0
- package/templates/skills/hai-app-tests/SKILL.md +34 -454
- package/templates/skills/hai-app-tests/reference.md +462 -0
- package/templates/skills/hai-app-tests/validation.md +42 -0
- package/templates/skills/hai-audit/SKILL.md +37 -122
- package/templates/skills/hai-audit/reference.md +184 -0
- package/templates/skills/hai-build/SKILL.md +62 -315
- package/templates/skills/hai-build/paths.md +30 -0
- package/templates/skills/hai-build/reference.md +353 -0
- package/templates/skills/hai-cache/SKILL.md +26 -175
- package/templates/skills/hai-cache/reference.md +229 -0
- package/templates/skills/hai-capacitor/SKILL.md +24 -364
- package/templates/skills/hai-capacitor/reference.md +358 -0
- package/templates/skills/hai-change-plan/SKILL.md +46 -0
- package/templates/skills/hai-ci/SKILL.md +114 -0
- package/templates/skills/hai-core/SKILL.md +31 -469
- package/templates/skills/hai-core/reference.md +557 -0
- package/templates/skills/hai-core/request-access.md +65 -0
- package/templates/skills/hai-crypto/SKILL.md +29 -180
- package/templates/skills/hai-crypto/reference.md +317 -0
- package/templates/skills/hai-datapipe/SKILL.md +24 -207
- package/templates/skills/hai-datapipe/reference.md +204 -0
- package/templates/skills/hai-deploy/SKILL.md +53 -178
- package/templates/skills/hai-deploy/credentials.md +19 -0
- package/templates/skills/hai-deploy/middleware.md +129 -0
- package/templates/skills/hai-feedback/SKILL.md +85 -0
- package/templates/skills/hai-framework-sync/SKILL.md +105 -0
- package/templates/skills/hai-framework-sync/sync.md +49 -0
- package/templates/skills/hai-iam/SKILL.md +53 -325
- package/templates/skills/hai-iam/reference.md +535 -0
- package/templates/skills/hai-kit/SKILL.md +33 -329
- package/templates/skills/hai-kit/reference.md +202 -0
- package/templates/skills/hai-payment/SKILL.md +28 -262
- package/templates/skills/hai-payment/reference.md +295 -0
- package/templates/skills/hai-pr-review/SKILL.md +41 -0
- package/templates/skills/hai-reach/SKILL.md +28 -300
- package/templates/skills/hai-reach/reference.md +363 -0
- package/templates/skills/hai-reldb/SKILL.md +28 -449
- package/templates/skills/hai-reldb/reference.md +500 -0
- package/templates/skills/hai-scheduler/SKILL.md +26 -174
- package/templates/skills/hai-scheduler/reference.md +216 -0
- package/templates/skills/hai-serv/SKILL.md +60 -0
- package/templates/skills/hai-serv/reference.md +792 -0
- package/templates/skills/hai-spec-implement/SKILL.md +50 -0
- package/templates/skills/hai-spec-implement/changes.md +67 -0
- package/templates/skills/hai-spec-implement/evaluation.md +18 -0
- package/templates/skills/hai-spec-implement/handoff.md +47 -0
- package/templates/skills/hai-spec-implement/templates.md +117 -0
- package/templates/skills/hai-spec-implement/workflow.md +56 -0
- package/templates/skills/hai-spec-review/SKILL.md +57 -0
- package/templates/skills/hai-spec-review/checklist.md +71 -0
- package/templates/skills/hai-storage/SKILL.md +31 -262
- package/templates/skills/hai-storage/reference.md +284 -0
- package/templates/skills/hai-ui/SKILL.md +62 -238
- package/templates/skills/hai-ui/guide.md +81 -0
- package/templates/skills/hai-ui/reference.md +705 -0
- package/templates/skills/hai-ui-design/SKILL.md +31 -0
- package/templates/skills/hai-ui-design/patterns.md +31 -0
- package/templates/skills/hai-ui-review/SKILL.md +32 -0
- package/templates/skills/hai-ui-review/checklist.md +29 -0
- package/templates/skills/hai-vecdb/SKILL.md +25 -267
- package/templates/skills/hai-vecdb/reference.md +325 -0
- package/templates/skills/opencode.json +0 -5
- package/dist/chunk-2H7UOFLK.js +0 -10
- package/dist/chunk-LANIDJC7.js +0 -659
- package/dist/chunk-LANIDJC7.js.map +0 -1
- package/dist/chunk-YV7WPUI6.js +0 -206
- package/dist/chunk-YV7WPUI6.js.map +0 -1
- package/dist/config-templates-S5RI2MC6.js +0 -5
- package/dist/config-templates-S5RI2MC6.js.map +0 -1
- package/dist/skill-templates-N5DU5FNX.js +0 -5
- package/dist/skill-templates-N5DU5FNX.js.map +0 -1
- package/dist/src-XJ6YXNAF.js +0 -15030
- package/dist/src-XJ6YXNAF.js.map +0 -1
- package/templates/apps/android-app/.env.hbs +0 -3
- package/templates/apps/android-app/messages/en-US.json +0 -24
- package/templates/apps/android-app/messages/zh-CN.json +0 -24
- package/templates/apps/android-app/src/lib/api.ts.hbs +0 -30
- package/templates/apps/android-app/src/routes/+layout.svelte.hbs +0 -42
- package/templates/apps/android-app/src/routes/+layout.ts +0 -7
- package/templates/apps/android-app/src/routes/+page.svelte.hbs +0 -27
- package/templates/apps/api/src/routes/+layout.svelte +0 -14
- package/templates/apps/api/src/routes/+page.svelte +0 -11
- package/templates/apps/api/src/routes/api/v1/health/+server.ts +0 -14
- package/templates/apps/api/src/routes/api/v1/items/+server.ts +0 -37
- package/templates/apps/api/src/routes/api/v1/items/[id]/+server.ts +0 -30
- package/templates/base/src/app.css +0 -2
- package/templates/base/tsconfig.json +0 -8
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
# hai-ai — 详细用法
|
|
2
|
+
|
|
3
|
+
从 [SKILL.md](SKILL.md) 选择主题后读取对应小节。代码片段展示 API 用法;省略的业务变量、schema、依赖与 return 上下文需由应用补齐。
|
|
4
|
+
|
|
5
|
+
`@h-ai/ai` 统一提供 LLM、工具、MCP、Embedding、Memory、Retrieval/RAG、Knowledge、Context、File、Rerank、Image、Audio 与 A2A 能力。
|
|
6
|
+
|
|
7
|
+
## 使用边界
|
|
8
|
+
|
|
9
|
+
- `ai.tools`、`ai.stream` 是纯函数能力,无需 `ai.init()`。
|
|
10
|
+
- `ai.llm`、`ai.embedding`、`ai.memory`、`ai.retrieval`、`ai.rag`、`ai.knowledge`、`ai.context`、`ai.image`、`ai.audio`、`ai.a2a` 需要先 `await ai.init(...)`。
|
|
11
|
+
- 开发/显式测试未初始化 reldb/vecdb 时,`ai.init()` 使用临时 Store;关闭/进程退出后丢失。
|
|
12
|
+
- `NODE_ENV` 或 `HAI_CORE_ENV=production` 要求共享 Store,内置实现先初始化 PostgreSQL/MySQL 与网络 vecdb;自定义 `AIStoreProvider` 必须如实声明 stateScope=shared,不能把本机后端作为生产共享状态。
|
|
13
|
+
- 浏览器端不要直接调用 Node-only 能力;通过 `@h-ai/api-client` 或应用自定义 API/SSE endpoint 代理。
|
|
14
|
+
- 公共 API 返回 `HaiResult<T>` 时按 `if (!result.success) return result` 处理;不要用 `try/catch` 包裹正常业务错误。
|
|
15
|
+
|
|
16
|
+
## 初始化与关闭
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { ai } from '@h-ai/ai'
|
|
20
|
+
import { core } from '@h-ai/core'
|
|
21
|
+
|
|
22
|
+
const init = await ai.init(core.config.get('ai'))
|
|
23
|
+
if (!init.success)
|
|
24
|
+
return init
|
|
25
|
+
|
|
26
|
+
// LLM-only:未初始化 DB 时使用进程内临时 Store
|
|
27
|
+
// ... 使用 ai.llm
|
|
28
|
+
|
|
29
|
+
await ai.close()
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
需要持久化时先校验三份配置,再按依赖顺序初始化。此片段位于应用启动生命周期;应用统一关闭管理器负责释放已获取的依赖,初始化失败时不接收业务请求。
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { ai, AIConfigSchema } from '@h-ai/ai'
|
|
36
|
+
import { core } from '@h-ai/core'
|
|
37
|
+
import { reldb, ReldbConfigSchema } from '@h-ai/reldb'
|
|
38
|
+
import { vecdb, VecdbConfigSchema } from '@h-ai/vecdb'
|
|
39
|
+
|
|
40
|
+
const databaseConfig = core.config.validate('db', ReldbConfigSchema)
|
|
41
|
+
if (!databaseConfig.success)
|
|
42
|
+
return databaseConfig
|
|
43
|
+
const vectorConfig = core.config.validate('vecdb', VecdbConfigSchema)
|
|
44
|
+
if (!vectorConfig.success)
|
|
45
|
+
return vectorConfig
|
|
46
|
+
const aiConfig = core.config.validate('ai', AIConfigSchema)
|
|
47
|
+
if (!aiConfig.success)
|
|
48
|
+
return aiConfig
|
|
49
|
+
const database = await reldb.init(databaseConfig.data)
|
|
50
|
+
if (!database.success)
|
|
51
|
+
return database
|
|
52
|
+
const vectors = await vecdb.init(vectorConfig.data)
|
|
53
|
+
if (!vectors.success)
|
|
54
|
+
return vectors
|
|
55
|
+
return await ai.init(aiConfig.data)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
应用的关闭生命周期按依赖反序执行。失败时保留下层依赖并报告错误,待修正后重试关闭;业务异常也须进入同一个关闭管理器。
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { ai } from '@h-ai/ai'
|
|
62
|
+
import { reldb } from '@h-ai/reldb'
|
|
63
|
+
import { vecdb } from '@h-ai/vecdb'
|
|
64
|
+
|
|
65
|
+
await ai.close() // AI 按实际 Promise<void> 契约关闭
|
|
66
|
+
const vectorsClosed = await vecdb.close()
|
|
67
|
+
if (!vectorsClosed.success)
|
|
68
|
+
return vectorsClosed
|
|
69
|
+
return await reldb.close()
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
MySQL 首次初始化允许多个节点并发建索引:仅接受 mysql2 明确的 ER_DUP_KEYNAME/1061,并重新核对列及顺序、非唯一完整列、升序可见 BTREE 和无表达式;已有同名错误结构仍失败。账户需要建表和 INDEX 权限,元数据读取、权限或其他 DDL 错误使 ai.init 返回 CONFIGURATION_ERROR。返回前等待全部已启动 DDL 结束;MySQL DDL 不回滚,失败保留已创建结构,修复权限/结构后再重试。逐步检查初始化结果,失败不接收业务请求,并逆序关闭 AI、vecdb、reldb。
|
|
73
|
+
|
|
74
|
+
自定义存储:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
await ai.init(core.config.get('ai'), { storeProvider: myProvider })
|
|
78
|
+
await ai.close()
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 配置要点
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
llm:
|
|
85
|
+
apiKey: ''
|
|
86
|
+
baseUrl: https://api.openai.com/v1
|
|
87
|
+
model: gpt-4o-mini
|
|
88
|
+
api: chat # chat(默认)| responses | anthropic——底层协议,对使用方透明
|
|
89
|
+
timeout: 60000
|
|
90
|
+
tempModelCacheTtl: 600000 # 临时模型客户端缓存 TTL(毫秒,默认 10 分钟)
|
|
91
|
+
models: # 可为单个模型指定协议(responses / anthropic)
|
|
92
|
+
- {id: claude, model: claude-3-5-sonnet-latest, api: anthropic}
|
|
93
|
+
scenarios:
|
|
94
|
+
chat: fast
|
|
95
|
+
reasoning: strong
|
|
96
|
+
embedding: embed
|
|
97
|
+
|
|
98
|
+
embedding:
|
|
99
|
+
dimensions: 1536
|
|
100
|
+
batchSize: 100
|
|
101
|
+
|
|
102
|
+
knowledge:
|
|
103
|
+
collection: hai_ai_knowledge
|
|
104
|
+
dimension: 1536
|
|
105
|
+
chunkOptions:
|
|
106
|
+
mode: markdown
|
|
107
|
+
maxSize: 1500
|
|
108
|
+
overlap: 200
|
|
109
|
+
|
|
110
|
+
# 可选:mem0ai/oss 引擎;无法映射持久化后端时默认 fail-fast
|
|
111
|
+
memory:
|
|
112
|
+
provider: mem0
|
|
113
|
+
defaultTopK: 10
|
|
114
|
+
# allowEphemeralFallback: true # 仅开发/明确 E2E,生产禁止实际内存回退
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
约定环境变量优先于 YAML,例如 `HAI_AI_LLM_APIKEY`、
|
|
118
|
+
`HAI_AI_LLM_BASEURL`、`HAI_AI_LLM_MODEL`。
|
|
119
|
+
|
|
120
|
+
`ai.config` 是脱敏快照;`apiKey`、`privateKey`、URL 内嵌凭证会被隐藏。
|
|
121
|
+
|
|
122
|
+
## 常用 API
|
|
123
|
+
|
|
124
|
+
| 场景 | 首选 API | 备注 |
|
|
125
|
+
| ------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
126
|
+
| 非流式对话 | `ai.llm.chat({ messages })` | OpenAI 兼容 Chat Completion |
|
|
127
|
+
| 流式对话 | `ai.llm.chatStream({ messages })` | 返回 `AsyncIterable` |
|
|
128
|
+
| 多协议 | 模型 `api: chat/responses/anthropic` | 底层走 Chat Completions / Responses / Anthropic,公共形状不变 |
|
|
129
|
+
| 请求取消 | `ai.llm.chat({ messages, signal })` | 传 `AbortSignal`,`abort()` 立即停上游生成 |
|
|
130
|
+
| 临时模型 | `ai.llm.chat({ messages, tempModel })` | 单次请求级临时端点,客户端按 TTL 缓存 |
|
|
131
|
+
| 工具定义 | `ai.tools.define(...)` | Zod schema 转 JSON Schema;`handler(input, ctx)` 第二参为执行上下文 |
|
|
132
|
+
| 工具注册 | `registry.register/replace` | `register` 默认拒绝同名并返回 HaiResult;只有 `replace` 可显式替换 |
|
|
133
|
+
| 工具执行 | `registry.execute(tc, { signal, objectId, sessionId, deadline?, timeoutMs?, authorize? })` / `executeAll(...)` | Registry/单次授权必须同时通过;默认串行,支持取消/超时;只有确认无副作用时才 `parallel: true` |
|
|
134
|
+
| MCP 服务 | `createMcpServer(...)` | 按需连接 HTTP/SSE/Stdio transport |
|
|
135
|
+
| Embedding | `ai.embedding.embedText(text)` | 批量用 `embedBatch` |
|
|
136
|
+
| 记忆 | `ai.memory.extract/recall/injectMemories` | `extract(..., { signal })` 可取消整条提取链;用 `objectId` 做主体隔离,`scope` 做业务作用域隔离;scope 隔离越细,`candidateMultiplier` 调大以防漏召回 |
|
|
137
|
+
| 记忆作用域 | `ai.memory.scoped({ objectId, scope })` | **多租户推荐入口**:所有操作自动绑定 objectId/scope(含归属校验);`clear` 仅清作用域内 |
|
|
138
|
+
| 记忆管理 | `ai.memory.admin.clearAll({ confirm: true })` | 唯一的全局清空入口(需显式确认);`ai.memory.clear()` 空过滤会被拒绝,防误清全局 |
|
|
139
|
+
| 角色人格 | `ai.persona.save/get/compose` | 定义 AI 身份(systemPrompt + traits),`compose` 组合系统提示词;按 `objectId` 隔离多租户(不传默认 `system` 平台角色),`scope: { personaId }` 关联长期记忆 |
|
|
140
|
+
| Retrieval/RAG | `ai.retrieval.retrieve` / `ai.rag.query` | Retrieval source 先注册或由配置预置 |
|
|
141
|
+
| Knowledge | `ai.knowledge.setup/ingest/ask` | 入库前会调用 datapipe 清洗分块 |
|
|
142
|
+
| Context | `ai.context.createManager` | 编排 LLM + Memory + RAG + 压缩;`manager.consolidate()` 把会话固化为长期记忆 |
|
|
143
|
+
| Context 并发 | `createManager({ scope, concurrency: 'reject' \| 'queue' })` | 默认单活动生成防消息乱序;活动生成期间新 chat 返回 `CONTEXT_BUSY`(reject)或排队(queue) |
|
|
144
|
+
| Context 重置 | `await manager.reset({ preserveSystemPrompt?, cancelActiveTurn?, waitForMemoryTasks? })` | 异步:终止活动生成、清空消息/摘要/轮次,默认保留系统提示词 |
|
|
145
|
+
| 语音识别 | `ai.audio.transcribe` / `transcribeStream` | 完整音频返回 `HaiResult`;持续音频输入用 `AudioInputStream` 流式返回临时文本 |
|
|
146
|
+
| 语音合成 | `ai.audio.synthesize` / `synthesizeStream` | `text` 可为字符串或 `AsyncIterable<string>`(可接 LLM 文本流边生成边合成);完整结果可用 `serializePlayableAudio` 转为浏览器播放负载 |
|
|
147
|
+
| 图片生成 | `ai.image.generate({ prompt, size?, model?, referenceImages? })` | 可选参考图使用字节 + MIME;Provider 协议和临时 URL 下载由模块内部处理 |
|
|
148
|
+
| A2A | `ai.a2a.registerExecutor/handleRequest` | 延迟初始化 SDK handler |
|
|
149
|
+
|
|
150
|
+
## LLM + 工具调用
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { z } from 'zod'
|
|
154
|
+
|
|
155
|
+
const registry = ai.tools.createRegistry({
|
|
156
|
+
authorize: ({ toolName, context }) => canExecuteTool(context.objectId, toolName),
|
|
157
|
+
})
|
|
158
|
+
const registered = registry.register(ai.tools.define({
|
|
159
|
+
name: 'get_weather',
|
|
160
|
+
description: '获取天气',
|
|
161
|
+
parameters: z.object({ city: z.string() }),
|
|
162
|
+
handler: async ({ city }) => ({ city, temperature: 20 }),
|
|
163
|
+
}))
|
|
164
|
+
if (!registered.success)
|
|
165
|
+
return registered
|
|
166
|
+
|
|
167
|
+
const messages: ChatMessage[] = [{ role: 'user', content: '北京天气?' }]
|
|
168
|
+
const objectId = 'user-001'
|
|
169
|
+
let result = await ai.llm.chat({ messages, tools: registry.getDefinitions() })
|
|
170
|
+
|
|
171
|
+
while (result.success && result.data.choices[0]?.finish_reason === 'tool_calls') {
|
|
172
|
+
const assistant = result.data.choices[0].message
|
|
173
|
+
const toolCalls = assistant.tool_calls ?? []
|
|
174
|
+
messages.push(assistant)
|
|
175
|
+
|
|
176
|
+
const toolMessages = await registry.executeAll(toolCalls, { objectId })
|
|
177
|
+
if (!toolMessages.success)
|
|
178
|
+
return toolMessages
|
|
179
|
+
messages.push(...toolMessages.data)
|
|
180
|
+
|
|
181
|
+
result = await ai.llm.chat({ messages, tools: registry.getDefinitions() })
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 流式处理
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
const processor = ai.stream.createProcessor()
|
|
189
|
+
for await (const chunk of ai.llm.chatStream({ messages })) {
|
|
190
|
+
const delta = processor.process(chunk)
|
|
191
|
+
if (delta?.content)
|
|
192
|
+
process.stdout.write(delta.content)
|
|
193
|
+
}
|
|
194
|
+
const message = processor.toAssistantMessage()
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## 临时模型(tempModel)
|
|
198
|
+
|
|
199
|
+
单次请求级别绕过配置注册模型,直接指定端点与凭据;适用于运行时动态切换模型、多租户各带凭据。
|
|
200
|
+
`chat` / `chatStream` / `ask` / `askStream` 均支持。未指定字段回退全局 LLM 配置 / 环境变量;
|
|
201
|
+
请求显式 `max_tokens` / `temperature` 优先于 `tempModel.maxTokens` / `temperature`。
|
|
202
|
+
临时客户端按 `apiKey+baseUrl+timeout` 缓存,TTL 默认 10 分钟(`llm.tempModelCacheTtl` 毫秒,可配置),与常驻模型客户端隔离。
|
|
203
|
+
|
|
204
|
+
```ts
|
|
205
|
+
const result = await ai.llm.chat({
|
|
206
|
+
messages: [{ role: 'user', content: '你好' }],
|
|
207
|
+
tempModel: {
|
|
208
|
+
model: 'claude-3-5-sonnet',
|
|
209
|
+
apiKey: process.env.TEMP_MODEL_API_KEY,
|
|
210
|
+
baseUrl: 'https://temp.endpoint/v1',
|
|
211
|
+
maxTokens: 2048, // 可选
|
|
212
|
+
temperature: 0.3, // 可选
|
|
213
|
+
timeout: 30000, // 可选
|
|
214
|
+
},
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
// ask 便捷方法同样支持
|
|
218
|
+
await ai.llm.ask('翻译这段话', { tempModel: { model: 'gpt-4o', apiKey: process.env.TEMP_MODEL_API_KEY } })
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## MCP 服务器
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { createMcpServer, StreamableHTTPServerTransport } from '@h-ai/ai'
|
|
225
|
+
import { core } from '@h-ai/core'
|
|
226
|
+
|
|
227
|
+
const server = createMcpServer({ name: 'my-server', version: '1.0.0' })
|
|
228
|
+
server.registerTool('search', {
|
|
229
|
+
description: '搜索',
|
|
230
|
+
inputSchema: { query: z.string() },
|
|
231
|
+
}, async ({ query }) => ({
|
|
232
|
+
content: [{ type: 'text', text: `Results for ${query}` }],
|
|
233
|
+
}))
|
|
234
|
+
|
|
235
|
+
await server.connect(new StreamableHTTPServerTransport({ sessionIdGenerator: core.id.uuid }))
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## 记忆、RAG 与知识库
|
|
239
|
+
|
|
240
|
+
`memory.provider` 默认为 `native`(推荐):HAI 原生引擎,复用 vecdb/reldb/LLM/Embedding,`extract` 采用 **Mem0 式批量合并**(一次 LLM 调用对整批事实与相关既有记忆做 ADD/UPDATE/DELETE/NONE,支持 `category`)。`mem0` 则直接使用 `mem0ai/oss` 的 `Memory` 引擎:LLM/Embedder 从 `llm` 配置提取(OpenAI 兼容),向量库从底层 vecdb 后端提取(qdrant 复用)。当前适配仅映射带完整连接参数的 `qdrant`;生产环境(`NODE_ENV` 或 `HAI_CORE_ENV` 为 `production`)即使设置 `memory.allowEphemeralFallback: true` 也拒绝实际内存回退。临时回退仅限开发或明确的 `HAI_E2E=1` / `HAI_E2E_MOCK=1`;缺少后端同样不能在生产启动。两者提供同一组 `ai.memory.*` 操作。
|
|
241
|
+
|
|
242
|
+
Mem0 的 `update` 使用 SDK 原地修改文本与元数据,保持 `id` 和创建时间。SDK 查询使用 `filters.user_id`,写入和整主体删除使用 `userId`。SDK 无列表游标:`list` / `listPage` / 条件 `clear` 最多支持每主体 1000 条原始候选(含过期条目),多取一条探测完整性;超限返回 `MEMORY_LIST_INCOMPLETE`(906),不会伪造 total 或执行部分条件删除。候选完整时按 UTC 日期剔除过期项,再按类型/scope 过滤和分页;仅 `objectId` 的清理使用 SDK `deleteAll`,不受列表上限限制。公共空条件清理被拒绝;跨主体全清仅限受信管理员显式 `admin.clearAll({ confirm: true })`。
|
|
243
|
+
|
|
244
|
+
Mem0 3.3.1 的 Qdrant 适配仍依赖 `QdrantClient.search`;项目将 `@qdrant/js-client-rest` 精确锁定为受测的 `1.18.0`,AI 的可选 peer 也声明此版本。启动会检查该公开方法,缺失时明确配置失败;不要覆盖为已移除此方法的 1.19。
|
|
245
|
+
|
|
246
|
+
Mem0 的 pgvector 组合在所有环境拒绝启动:当前 SDK 将 PostgreSQL 连接保存在私有对象中,未提供公开关闭入口,框架无法履行资源清理契约。需要 pgvector 时选择 `memory.provider: native`;该原生后端保持支持。`disableHistory: true` 使用 SDK 无资源的历史占位实现,不创建历史 SQLite 文件。工厂通过公开的一条有界只读查询等待实际后端 ready 后才发布成功。
|
|
247
|
+
|
|
248
|
+
`add` / `extract` 的 SDK 回执不含完整业务字段,框架写后读取权威记录再返回;并发提取等待全部在途写入结束。若写入或写后读失败,`error.ext.requiresEffectReconciliation=true`,`memoryIds` 保存已知写入 ID(回执丢失时可能为空)。应按主体核对实际记忆后决定恢复,不能盲目重做 add/extract;框架不自动重放。
|
|
249
|
+
|
|
250
|
+
```ts
|
|
251
|
+
const enriched = await ai.memory.injectMemories(messages, { objectId: 'user-001', topK: 5 })
|
|
252
|
+
if (!enriched.success)
|
|
253
|
+
return enriched
|
|
254
|
+
|
|
255
|
+
const compressed = await ai.compress.tryCompress(enriched.data, { strategy: 'hybrid', maxTokens: 4000 })
|
|
256
|
+
if (!compressed.success)
|
|
257
|
+
return compressed
|
|
258
|
+
|
|
259
|
+
const answer = await ai.rag.query('核心架构是什么?', { sources: ['docs'], topK: 5 })
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
`tryCompress` 的成功结果一定满足 `compressedTokens <= maxTokens`。如果永久 system 指令、最近消息或最新 user 输入自身已超过预算,会返回 `HaiAIError.CONTEXT_BUDGET_EXCEEDED`;调用方应停止本次模型请求或提高预算,不能继续发送原始超长消息。
|
|
263
|
+
|
|
264
|
+
知识库流程:
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
const setup = await ai.knowledge.setup()
|
|
268
|
+
if (!setup.success)
|
|
269
|
+
return setup
|
|
270
|
+
|
|
271
|
+
const ingest = await ai.knowledge.ingest({
|
|
272
|
+
documentId: 'doc-001',
|
|
273
|
+
content: markdownText,
|
|
274
|
+
title: '产品手册',
|
|
275
|
+
enableEntityExtraction: true,
|
|
276
|
+
})
|
|
277
|
+
if (!ingest.success)
|
|
278
|
+
return ingest
|
|
279
|
+
if (ingest.data.cleanupPending) {
|
|
280
|
+
const repair = await ai.knowledge.repair({ offset: 0, limit: 100 })
|
|
281
|
+
if (!repair.success)
|
|
282
|
+
return repair
|
|
283
|
+
// 大集合继续分页,并将 repair 全页扫描纳入定期维护。
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const answer = await ai.knowledge.ask('核心架构是什么?')
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Context 管理器
|
|
290
|
+
|
|
291
|
+
`scope` 必填;共享 scope 用版本化聚合记录保存消息、摘要、owner、轮次和 pending。所有消息、对外 delta 与提交即时持久化。同步 getters 仅返回本管理器最近一次成功读写的独立快照,读取其他节点修改前调用 `await manager.reload()` 或 `restoreManager()`。`save()` 等待本节点记忆提取、刷新快照并同步目录,不能覆盖远端版本。`markTurnSpeaking` 为异步持久化方法。
|
|
292
|
+
|
|
293
|
+
共享单活动生成租约为存储端时钟30秒,每10秒续租,最终 CAS 同时检查版本、owner 和截止时间。过期生成仅 interrupted,不自动重放 LLM/工具/记忆;manual pending 持久保存,可跨节点/重启按 turnId 提交。相同终态与真实文本重复提交幂等,内容冲突失败。queue 可取消轮询,不保证FIFO。reset 更换共享纪元,删除保留永久墓碑且 scope 不复用。外部 LLM/工具/本地后台记忆不与上下文跨系统原子提交;崩溃后的未知副作用必须由应用核对。
|
|
294
|
+
|
|
295
|
+
自定义 `AIRelStore` 必须提供版本化读取、原子 CAS 和存储端 `currentTime()`;普通 save/saveMany 也推进版本。CAS 缺失版本只允许创建,notAfter 在最终持久化时严格检查,存储故障抛错不能当空数据;业务 HaiResult 边界负责转失败。默认 DB schema 含 version 列,不自动迁移旧表;SQLite 仅用于开发/测试,生产使用 PostgreSQL/MySQL。
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
const managerResult = ai.context.createManager({
|
|
299
|
+
scope: { objectId: 'user-001', sessionId: 'sess-001' },
|
|
300
|
+
systemPrompt: '你是一个友好的助手。',
|
|
301
|
+
compress: { auto: true, strategy: 'hybrid', maxTokens: 8000 },
|
|
302
|
+
memory: { enable: true, enableExtract: true },
|
|
303
|
+
})
|
|
304
|
+
if (!managerResult.success)
|
|
305
|
+
return managerResult
|
|
306
|
+
|
|
307
|
+
const reply = await managerResult.data.chat('你好')
|
|
308
|
+
const saved = await managerResult.data.save()
|
|
309
|
+
if (!saved.success)
|
|
310
|
+
return saved
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 真实对话状态(Conversation Commit Layer)
|
|
314
|
+
|
|
315
|
+
`turnCommit: 'manual'` 时,`chat` / `chatStream` 不自动写入生成文本,只返回 `turnId`;由调用方提交**实际发生的内容**(TTS 播放、被打断等场景)。`chatStream` 在调用上游模型前就产出 `turn_started`(事件序列 `turn_started → delta* → done`,中途取消 `→ cancelled`),取消时保留 `turnId` 与已生成文本:
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
const manager = ai.context.createManager({ turnCommit: 'manual', scope })
|
|
319
|
+
if (!manager.success)
|
|
320
|
+
return manager
|
|
321
|
+
const m = manager.data
|
|
322
|
+
const controller = new AbortController()
|
|
323
|
+
for await (const ev of m.chatStream('展开讲讲', { signal: controller.signal })) {
|
|
324
|
+
if (ev.type === 'delta')
|
|
325
|
+
feedTts(ev.text)
|
|
326
|
+
else if (ev.type === 'done')
|
|
327
|
+
await m.commitTurn(ev.turnId) // 完整提交
|
|
328
|
+
else if (ev.type === 'cancelled')
|
|
329
|
+
await m.interruptTurn(ev.turnId, { text: spokenSoFar }) // 只提交播放出去的部分
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
- 只有 `committed` 的内容进入上下文与记忆;`getTurns()` 可观测 `generated` / `committed` / `status`。
|
|
334
|
+
- 主持人抢话时可在 `turn_started` / 迭代过程中随时 `interruptTurn`;轮次进入终态后即便上游流恰好正常结束,`chatStream` 也**不会再产出 `done`**,业务层不会误判为正常完成。
|
|
335
|
+
|
|
336
|
+
## 语音(Audio)
|
|
337
|
+
|
|
338
|
+
`ai.audio` 提供 ASR/TTS,Provider(OpenAI / MiMo / Qwen / 豆包)作为内部实现,凭据未配置时回退平台环境变量。调用方只表达「音频还是文本、完整还是流式」,不感知 WebSocket / SSE / 厂商事件。LLM 与语音模型确认共用凭据时,可显式设置 `inheritLlmApiKey: true`;该选项默认关闭,避免跨供应商误用密钥。
|
|
339
|
+
|
|
340
|
+
```yaml
|
|
341
|
+
# ai.init 配置片段
|
|
342
|
+
audio:
|
|
343
|
+
# 仅当语音服务与 LLM 确认共用同一密钥时启用
|
|
344
|
+
inheritLlmApiKey: true
|
|
345
|
+
models:
|
|
346
|
+
- {id: asr, provider: qwen, model: qwen3-asr-flash-realtime, operations: [transcribe]}
|
|
347
|
+
- {id: tts, provider: qwen, model: qwen3-tts-flash-realtime, operations: [synthesize]}
|
|
348
|
+
transcribeModel: asr
|
|
349
|
+
synthesizeModel: tts
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
```ts
|
|
353
|
+
// 完整识别 / 合成(HaiResult)
|
|
354
|
+
const t = await ai.audio.transcribe({ audio: { data: wavBytes, format: 'wav' }, language: 'zh' })
|
|
355
|
+
if (!t.success)
|
|
356
|
+
return t
|
|
357
|
+
const s = await ai.audio.synthesize({ text: '欢迎', voice: 'Cherry', format: 'pcm16' })
|
|
358
|
+
|
|
359
|
+
// 实时识别:持续音频输入 → 增量文本(chunk.final 标记语句最终态,可直接覆盖临时文本)
|
|
360
|
+
for await (const chunk of ai.audio.transcribeStream({ audio: { chunks: micChunks, format: 'pcm16', sampleRate: 16000 } })) {
|
|
361
|
+
updateTranscript(chunk.text, chunk.final)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// 分段合成:稳定 ID 关联文本与音频,支持 AbortSignal 打断
|
|
365
|
+
const controller = new AbortController()
|
|
366
|
+
for await (const event of ai.audio.synthesizeStream({ text: { id: 'seg-1', text: '欢迎。' }, voice: 'Cherry', signal: controller.signal })) {
|
|
367
|
+
if (event.type === 'segment_started')
|
|
368
|
+
prepareDecoder(event.format, event.sampleRate, event.channels) // 真实输出格式来自服务端解析后的 Provider 输出
|
|
369
|
+
else if (event.type === 'audio')
|
|
370
|
+
await player.write(event.data)
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
需要通过 API 返回浏览器可播放的 Base64 音频时,调用 `serializePlayableAudio(result.data)`;该函数会将 `pcm16` 封装为 WAV,并透传 WAV/MP3,`opus` 不支持该转换。
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
import { serializePlayableAudio } from '@h-ai/ai'
|
|
378
|
+
|
|
379
|
+
const synthesized = await ai.audio.synthesize({ text: '欢迎参加访谈。' })
|
|
380
|
+
if (!synthesized.success)
|
|
381
|
+
return synthesized
|
|
382
|
+
|
|
383
|
+
const playable = serializePlayableAudio(synthesized.data)
|
|
384
|
+
if (!playable.success)
|
|
385
|
+
return playable
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
- 流式方法是 `AsyncIterable`,迭代期间的连接/协议/上游错误会终止迭代(抛出),不返回 `HaiResult`。
|
|
389
|
+
- `segment_started` 携带服务端解析 Provider 后的真实输出参数(`format` / `sampleRate?` / `channels?`);播放器据此解码,不按请求参数猜测格式。
|
|
390
|
+
- 平台不支持的输入方式(如 OpenAI/MiMo 的持续音频输入)会抛 `AUDIO_UNSUPPORTED_INPUT`,不伪装成实时。
|
|
391
|
+
- 浏览器/移动端经 `@h-ai/serv` 统一语音 WebSocket 入口访问;客户端用已登录 HTTP 请求获取短期一次性 ticket,`createAudioClient({ url, getTicket })` 通过独立配置的 `getTicket` 建连,不把 IAM access token 放入 URL。浏览器客户端区分正常结束、取消(`AUDIO_CANCELLED`)与 `end` 前异常断连(`AUDIO_CONNECTION_FAILED`);服务端 error 帧保留领域错误码,`synthesize` 不返回未完成的部分音频。
|
|
392
|
+
|
|
393
|
+
### 本地 CPU 模型服务
|
|
394
|
+
|
|
395
|
+
hai-framework 源码仓库提供 `pnpm model <name> --device cpu` 与 `pnpm model:run <name>`,默认优先使用 Podman,可构建/启动 `faster-whisper-large-v3`、`indextts-2.5`、`qwen3-4b`。三套权重均优先从清单锁定的 ModelScope revision 下载并复用容器 volume,Hugging Face 只作回退。Whisper/IndexTTS 仍配置为 `audio.models[].baseUrl`,Qwen3-4B 仍配置为 OpenAI-compatible `llm.models[].baseUrl`;部署位置不进入 Provider 名称。离线部署使用准备权重后的 bundled 镜像。
|
|
396
|
+
|
|
397
|
+
## 文生图(Image)
|
|
398
|
+
|
|
399
|
+
`ai.image` 只暴露稳定的提示词、模型别名、像素尺寸、可选参考图和图片字节;OpenAI、Google、Qwen、Seedream 与 Pollinations 的请求结构、鉴权、响应解析和临时 URL 下载均封装在内部 Provider。
|
|
400
|
+
|
|
401
|
+
```yaml
|
|
402
|
+
image:
|
|
403
|
+
maxImageBytes: 20971520 # 单张输出/参考图上限;最大100MiB
|
|
404
|
+
maxImages: 4 # 1–16,URL串行下载;模型timeout覆盖整个生成/下载
|
|
405
|
+
models:
|
|
406
|
+
- {id: free, provider: pollinations, model: zimage}
|
|
407
|
+
- {id: openai, provider: openai, model: gpt-image-2}
|
|
408
|
+
- {id: google, provider: google, model: gemini-3.1-flash-image-preview}
|
|
409
|
+
- {id: qwen, provider: qwen, model: qwen-image-2.0-pro}
|
|
410
|
+
- {id: seedream, provider: seedream, model: doubao-seedream-5-0-260128}
|
|
411
|
+
generateModel: free
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
LLM、Audio、Image 的可选密钥统一使用 `OptionalSecretSchema`:配置中的 YAML `null`、空字符串和纯空白字符串均表示未配置。语音密钥优先级为模型条目 → 启用继承后的 LLM 密钥 → 平台环境变量,业务启动代码不应再遍历配置修补 `apiKey`。
|
|
415
|
+
|
|
416
|
+
```ts
|
|
417
|
+
const image = await ai.image.generate({
|
|
418
|
+
prompt: '水墨风格的未来城市,清晨薄雾',
|
|
419
|
+
size: { width: 1024, height: 1024 },
|
|
420
|
+
referenceImages: [{ data: referenceBytes, mimeType: 'image/png' }],
|
|
421
|
+
})
|
|
422
|
+
if (!image.success)
|
|
423
|
+
return image
|
|
424
|
+
await saveImage(image.data.images[0].data, image.data.images[0].mimeType)
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
- `Pollinations` 提供可免费起步的开发额度,但仍需 API key;不要把“免费额度”描述为匿名或无限调用。
|
|
428
|
+
- 应用应通过 `core.init({ configDir: './config' })` 加载 `_core.yml` / `_ai.yml`,再以 `core.config.validate('ai', AIConfigSchema)` 校验并传给 `ai.init`;不要在启动代码中重复拼装模型、端点和超时,也不要传入 `logging` 覆盖 `_core.yml`。
|
|
429
|
+
- Pollinations 的 HTTP 402 表示账户余额或该 API Key 的预算耗尽;401 是密钥无效,403 是权限或模型访问被拒。诊断日志记录厂商、模型、状态、上游错误码和请求 ID,不记录密钥、提示词或图片内容。
|
|
430
|
+
- Qwen 等返回的临时图片 URL 会在 Provider 内立即下载,公共结果不泄漏易过期 URL。
|
|
431
|
+
- 参考图统一使用 `{ data: Uint8Array, mimeType: 'image/...' }`;不要把厂商 URL、multipart 或 Base64 结构泄漏到业务层。
|
|
432
|
+
- Provider 请求/响应格式变更时,先更新契约测试,再修改实现。
|
|
433
|
+
|
|
434
|
+
## SvelteKit API 端点模式
|
|
435
|
+
|
|
436
|
+
```ts
|
|
437
|
+
export const POST = kit.handler(async ({ request }) => {
|
|
438
|
+
const data = await kit.validate.body(request, ChatSchema)
|
|
439
|
+
const result = await ai.llm.chat({ messages: data.messages })
|
|
440
|
+
if (!result.success)
|
|
441
|
+
return kit.response.error(result.error.code, result.error.message)
|
|
442
|
+
return kit.response.ok(result.data)
|
|
443
|
+
})
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## 质量与安全检查
|
|
447
|
+
|
|
448
|
+
- API Key 只从配置 / 环境变量读取,禁止写死。
|
|
449
|
+
- 工具 handler 必须校验输入;用户可见错误走 i18n/错误码。
|
|
450
|
+
- 模型输出、Prompt 和检索内容均不可信;不要把用户内容拼入不可覆盖的系统规则。Zod 只保证参数形状,高权限工具还必须在 handler 内校验身份、租户、资源归属和配额。
|
|
451
|
+
- 只向模型注册允许自动执行的工具;写操作默认要求业务侧确认或幂等键,不能把“模型请求调用”当作授权。
|
|
452
|
+
- 批量导入、批量 embedding 用批量 API,避免 await-in-loop。
|
|
453
|
+
- 文件解析/OCR 失败按 `HaiAIError.FILE_*` 返回,不抛业务异常。
|
|
454
|
+
- A2A 认证失败返回 `A2A_AUTH_FAILED`;`callRemoteAgent` 只依赖 `ai.init()`,无需注册本地 executor。远端 URL 仅接受 HTTP(S) 且不得内嵌凭据,应用仍须配置 origin 白名单与出口网络策略。不要记录 token、apiKey、私钥、完整 headers 或带 query 的 URL。
|
|
455
|
+
- A2A 入站日志保存并重验租约后才执行业务,出站日志在已有有界队列内完成后才发布;日志失败产生 failed/interrupted Task,不重放相同 receipt。日志不是交付回执,按 requiresEffectReconciliation 核对可能已执行的效果;listMessages 失败为安全的 A2A_LIST_MESSAGES_FAILED(984)。
|
|
456
|
+
- A2A 任务与事件只有共享 journal 一套权威,不装配旧 TaskStore;push notification 配置和 authenticated extended card RPC 返回 SDK 标准不支持/未配置错误。应用通过公开 executor 接口接入,不导入内部 handler/Store 装配类型。
|
|
457
|
+
- Context 的 flush 会报告本节点后台提取异常及失败 HaiResult;同轮并发调用共享一次报告,返回即确认该批,后续只观察新任务。save/reset(waitForMemoryTasks)/consolidate 传播失败并停止后续写入,pendingMemoryTasks=0 不代表成功,不自动重试未知副作用。
|