# QingLong 3.0 本机 AI Feature 操作手册 本手册只适用于 `edge` 和 `standalone`。Cluster 不得使用本机 Owner command 代替 TLS identity、平台 Policy、quota 和职责分离。 ## 部署与启动边界 基础 edge/standalone application 制品不安装 `@qinglong/ai`。需要本机 AI 时,部署 显式的 `edge-application-ai` 或 `standalone-application-ai` 制品。ADR-0178 已提供 `ql3-local-application` headless executable 和统一 product composition,但通用 CLI 当前只直接支持 `deployment=excluded`;installed AI 必须由受信 host 注入 provider authority。不要把 token 写入启动配置来绕过这道门。受审 composition 为: ```text @qinglong/local-application/ai-feature ``` 不要改为调用基础 `@qinglong/local-application` 后自行加载 provider。受审入口只在 9007 head 为 `active` 且完整 AI schema/history/checksum 通过时动态加载 AI; deployment excluded、schema absent 和 inactive 都不会加载 provider。 基础进程配置、SIGTERM drain 和低敏日志见 [本机 Headless Application 手册](./ql3-local-application-process.md)。 管理命令不会向常驻进程注入代码,也不包含 watcher: - `inspect` 成功返回 `runtimeAction: "none"`; - `activate`、`deactivate` 及其 exact replay 成功返回 `runtimeAction: "restart_required"`。 activate 后必须重启应用,重启成功且 AI 状态为 `active` 才表示 provider 已装配。 deactivate 提交后数据库 admission fence 已立即生效;当前进程下一次 AI 操作会拒绝 请求并进入 drain。完成有界 drain 后重启应用,确认 AI 状态为 `inactive` 且 provider loader 为零,才完成可验证卸载。 ## 安全前置 1. 使用 QingLong 部署用户执行,不使用远程 HTTP、聊天输入或公共目录传递命令。 2. command 目录权限设为 `0700`,command file 设为 `0600`。 3. 准备当前 local-console credential presentation 和 Owner pepper keyring。 4. 对已有数据库先完成 SQLite 文件及 `-wal`/`-shm` 一致性备份,并记录备份制品的 SHA-256;新库可使用 `fresh_database`。 5. 不手工修改 `QingLong3AiSchemaMigrations`、feature transition/head 或 AI 业务表。 以下路径必须替换成当前部署的规范化绝对路径。UUID 必须为新的 v4 UUID。 ## 1. Inspect ```json { "schemaVersion": 1, "operation": "ai-feature.inspect", "options": { "deploymentRoot": "/opt/qinglong", "databasePath": "/opt/qinglong/data/qinglong3.sqlite", "profile": "edge", "ownerPepperKeyringDirectory": "/opt/qinglong/config/owner-keys", "credentialFilePath": "/opt/qinglong/private/owner-credential.json" }, "request": { "requestId": "ai-feature-inspect-20260727", "failureAuditEventId": "00000000-0000-4000-8000-000000000001" } } ``` ```sh ql3-ai-feature run --command-file /opt/qinglong/private/ai-feature-inspect.json ``` 保存输出中的 `migrationPlanDigest`。`schemaState`: - `absent`:没有 AI feature schema; - `partial_or_drifted`:可能是中断的 reviewed migration,也可能是漂移;不要手工修表; - `ready`:9001–9007 history/checksum 和全部本机 AI 表已通过只读核对。 ## 2. 首次启用 新库使用: ```json { "schemaVersion": 1, "operation": "ai-feature.activate", "options": { "deploymentRoot": "/opt/qinglong", "databasePath": "/opt/qinglong/data/qinglong3.sqlite", "profile": "edge", "ownerPepperKeyringDirectory": "/opt/qinglong/config/owner-keys", "credentialFilePath": "/opt/qinglong/private/owner-credential.json" }, "request": { "requestId": "ai-feature-activate-20260727", "failureAuditEventId": "00000000-0000-4000-8000-000000000002", "mutationId": "ai-feature-activate-20260727", "expectedGeneration": 0, "expectedState": null, "expectedMigrationDigest": "REPLACE_WITH_INSPECTED_PLAN_DIGEST", "safety": { "mode": "fresh_database", "backupEvidenceDigest": null } } } ``` 已有库把 safety 改为: ```json { "mode": "backup_verified", "backupEvidenceDigest": "REPLACE_WITH_64_HEX_BACKUP_EVIDENCE_DIGEST" } ``` 命令中断时,保留同一私有 command file 原样重试。不得生成新 mutation 来“绕过” partial schema。只有返回 `schemaState=ready` 且 `activation.state=active` 后,价格管理和 新 ModelInvocation admission 才可用。确认响应中的 `runtimeAction="restart_required"`,随后重启 AI application 制品;不要等待后台 watcher,因为系统不会创建 watcher。 ## 3. 非破坏性停用 先停止产生新 AI 请求并等待现有 invocation 终结。使用 inspect 返回的 generation: ```json { "schemaVersion": 1, "operation": "ai-feature.deactivate", "options": { "deploymentRoot": "/opt/qinglong", "databasePath": "/opt/qinglong/data/qinglong3.sqlite", "profile": "edge", "ownerPepperKeyringDirectory": "/opt/qinglong/config/owner-keys", "credentialFilePath": "/opt/qinglong/private/owner-credential.json" }, "request": { "requestId": "ai-feature-deactivate-20260727", "failureAuditEventId": "00000000-0000-4000-8000-000000000003", "mutationId": "ai-feature-deactivate-20260727", "expectedGeneration": 1, "expectedState": "active", "expectedMigrationDigest": "REPLACE_WITH_INSPECTED_PLAN_DIGEST", "safety": { "mode": "preserve_existing", "backupEvidenceDigest": null } } } ``` 出现 `LOCAL_AI_FEATURE_IN_FLIGHT_INVOCATION` 时不要删行;等待 completion/recovery 收敛后原样重试。成功停用不会删除 schema、价格、usage、quota、invocation 或审计 事实。确认 `runtimeAction="restart_required"`,等待当前进程有界 drain,再重启并 inspect;重启后的 AI 状态必须为 `inactive`。 ## 4. 重新启用 重新 inspect,使用当前 inactive generation、`expectedState: "inactive"` 和新的 mutation/request/audit ID。已有 durable data 必须使用 `backup_verified`,不能再声明 `fresh_database`。 ## 5. 失败处理 - `...COMMAND_CONFIGURATION_INVALID`:命令 shape、路径、权限或字段不合法; - `...TRANSITION_CONFLICT`:plan digest、CAS、mutation replay 或身份发生漂移; - `...DATA_SAFETY_REJECTED`:空库/备份声明不满足当前 durable data; - `...FEATURE_NOT_READY`:schema/history/checksum 未通过; - `...FENCE_REJECTED` / `...OWNER_REJECTED`:credential/pepper/User/Owner 已漂移; - `...IN_FLIGHT_INVOCATION`:仍有未完成调用; - `...MIGRATION...UNAVAILABLE`:保留原命令和数据库,先检查磁盘、锁、完整性与审计, 不手工补 history。 每次操作后再次 inspect,并执行 SQLite `integrity_check`、备份可恢复性和应用启动门。 若 active head 存在但应用启动返回 `LOCAL_AI_FEATURE_APPLICATION_UNAVAILABLE`,不得绕过 AI 入口启动成“部分 ready”: 检查部署是否确实包含 `@qinglong/ai`、9001–9007 history/checksum、provider credential 和 recovery 状态;修复后重新执行同一产品启动门。