Compare commits
11
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c520da625 | ||
|
|
a907a86aa7 | ||
|
|
27ee200b21 | ||
|
|
6839c80311 | ||
|
|
abe2ea3577 | ||
|
|
7f7cb61ec5 | ||
|
|
6d6e3f425e | ||
|
|
c38c575d8e | ||
|
|
b1c1e49cc5 | ||
|
|
b9e2358901 | ||
|
|
a1874c90ae |
@@ -185,15 +185,15 @@ class H(BaseHTTPRequestHandler):
|
||||
if path in ('/api/openapi.yaml','/api/openapi-chatgpt-actions.yaml','/api/schema'):
|
||||
return self.sendt(OPENAPI.read_text(encoding='utf-8'), 'application/yaml; charset=utf-8') if OPENAPI.exists() else self.sendj({'error':'schema_missing'},404)
|
||||
if path in ('/api','/api/status'): return self.sendj(api_spec())
|
||||
if path in ('/api/base','/base'):
|
||||
if path in ('/api/base','/api/baseline','/base'):
|
||||
data=jload(WS/'baseline'/'current.json', {}); data.setdefault('git', sh(['rev-parse','--short','HEAD'])['stdout']); return self.sendj(data)
|
||||
if path in ('/api/ver','/ver'):
|
||||
if path in ('/api/ver','/api/versions','/ver'):
|
||||
return self.sendj({'tags':sh(['tag','--list','V*'])['stdout'].splitlines(),'versions_dir':[p.name for p in (WS/'versions').glob('*')],'head':sh(['rev-parse','--short','HEAD'])['stdout']})
|
||||
if path in ('/api/diff','/diff'):
|
||||
frm=(q.get('from') or ['HEAD~1'])[0]; to=(q.get('to') or ['HEAD'])[0]; return self.sendj({'from':frm,'to':to,'diff':sh(['diff',frm,to])})
|
||||
if path in ('/api/patch','/patch'): return self.sendj({'patches':patches(),'branches':sh(['branch','--format','%(refname:short)'])['stdout'].splitlines()})
|
||||
if path in ('/api/patch','/api/patches','/api/branches','/patch'): return self.sendj({'patches':patches(),'branches':sh(['branch','--format','%(refname:short)'])['stdout'].splitlines()})
|
||||
if path in ('/api/model','/model'): return self.sendj({'base':BASE_MODELS,'custom':model_docs(),'priority':[jload(p,{}) for p in sorted((WS/'config'/'model_priority').glob('*.json'))]})
|
||||
if path in ('/api/run','/run'):
|
||||
if path in ('/api/run','/api/runtime-status','/run'):
|
||||
svc=subprocess.run(['systemctl','is-active','aios-gitops-model-api'], text=True, capture_output=True)
|
||||
return self.sendj({'service':'aios-gitops-model-api','status':svc.stdout.strip() or svc.stderr.strip(),'workspace_branch':sh(['rev-parse','--abbrev-ref','HEAD'])['stdout']})
|
||||
if path in ('/api/action-monitor','/action-monitor'):
|
||||
@@ -211,11 +211,11 @@ class H(BaseHTTPRequestHandler):
|
||||
def do_POST(self):
|
||||
path=urllib.parse.urlparse(self.path).path.rstrip('/'); data=self.body()
|
||||
try:
|
||||
if path == '/api/branch': return self.branch(data)
|
||||
if path == '/api/file': return self.file(data)
|
||||
if path in ('/api/branch','/api/create-branch'): return self.branch(data)
|
||||
if path in ('/api/file','/api/commit-file'): return self.file(data)
|
||||
if path == '/api/commit': return self.commit(data)
|
||||
if path == '/api/patch': return self.patch(data)
|
||||
if path == '/api/tag': return self.tag(data)
|
||||
if path in ('/api/patch','/api/create-patch'): return self.patch(data)
|
||||
if path in ('/api/tag','/api/create-tag'): return self.tag(data)
|
||||
if path == '/api/rollback': return self.rollback(data)
|
||||
if path == '/api/model': return self.model(data)
|
||||
if path == '/api/model-priority': return self.model_priority(data)
|
||||
|
||||
+39
-19
@@ -1,22 +1,42 @@
|
||||
{
|
||||
"version": "V1R1C0",
|
||||
"architecture_version": "V1",
|
||||
"release_version": "R1",
|
||||
"change_version": "C0",
|
||||
"components": [
|
||||
"webops",
|
||||
"owner-admin-user",
|
||||
"npm",
|
||||
"casdoor",
|
||||
"openclaw",
|
||||
"hermes",
|
||||
"one-api",
|
||||
"gitops-control",
|
||||
"baseline-registry",
|
||||
"custom-llm-registry",
|
||||
"runtime-selector"
|
||||
],
|
||||
"active_version": "V1R2C3",
|
||||
"active_tag": "V1R2C3",
|
||||
"version": "V1R2C3",
|
||||
"previous_version": "V1R2C2",
|
||||
"rollback_version": "V1R2C2",
|
||||
"status": "promoted",
|
||||
"mode": "gitops-online",
|
||||
"update_mode": "git_patch_only",
|
||||
"zip_update_deprecated": true,
|
||||
"entry": "https://cnnetmkt.top",
|
||||
"proxy": "npm",
|
||||
"runtime_sync": "openclaw"
|
||||
"components": {
|
||||
"gitops": true,
|
||||
"chatgpt_actions": true,
|
||||
"codex_access": true,
|
||||
"custom_llm": true,
|
||||
"multiuser_runtime": true,
|
||||
"autonomous_recovery_loop": true,
|
||||
"portal_gitops_dashboard": true,
|
||||
"casdoor_auth": true,
|
||||
"gitea": true
|
||||
},
|
||||
"compatibility": {
|
||||
"chatgpt_actions_clientresponse_compat": true,
|
||||
"route_alias_compatibility": true,
|
||||
"head_options_compatibility": true,
|
||||
"openapi_response_schema_compatibility": true,
|
||||
"structured_json_errors": true
|
||||
},
|
||||
"release": {
|
||||
"tag": "V1R2C3",
|
||||
"branch": "patch/v1r2c3-baseline-promotion-20260708",
|
||||
"rollback_version": "V1R2C2",
|
||||
"promotion_report": "reports/V1R2C3_RELEASE_PROMOTION_REPORT.md"
|
||||
},
|
||||
"security": {
|
||||
"secret_plaintext_written": false,
|
||||
"token_plaintext_written": false,
|
||||
"force_push_used": false
|
||||
},
|
||||
"updated_at": "2026-07-08T00:00:00Z"
|
||||
}
|
||||
|
||||
+39
-9
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"active_version": "V1R2C2",
|
||||
"active_tag": "V1R2C2",
|
||||
"active_version": "V1R2C3",
|
||||
"active_tag": "V1R2C3",
|
||||
"mode": "gitops-online",
|
||||
"version_policy": "VxRxCx",
|
||||
"update_mode": "git_patch_only",
|
||||
@@ -25,10 +25,16 @@
|
||||
"chatgpt_rw": true,
|
||||
"codex_rw": true,
|
||||
"portal_gitops_dashboard": true,
|
||||
"human_shortlinks_login_required": true
|
||||
"human_shortlinks_login_required": true,
|
||||
"autonomous_recovery_loop": true,
|
||||
"chatgpt_actions_clientresponse_compat": true,
|
||||
"route_alias_compatibility": true,
|
||||
"head_options_compatibility": true,
|
||||
"openapi_response_schema_compatibility": true,
|
||||
"structured_json_errors": true
|
||||
},
|
||||
"version": "V1R2C2",
|
||||
"baseline_tag": "V1R2C2-baseline",
|
||||
"version": "V1R2C3",
|
||||
"baseline_tag": "V1R2C3-baseline",
|
||||
"source": "AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip",
|
||||
"source_package": "AIOS_V1R1C0_MULTIUSER_GITOPS_CUSTOM_LLM_PROD_FULL_DEPLOY_20260706.zip",
|
||||
"zip_update_mode": "deprecated",
|
||||
@@ -46,7 +52,7 @@
|
||||
"/api",
|
||||
"/hook"
|
||||
],
|
||||
"updated_at": "2026-07-07T15:40:00Z",
|
||||
"updated_at": "2026-07-08T00:00:00Z",
|
||||
"auth": {
|
||||
"primary_domain": "https://auth.cnnetmkt.top",
|
||||
"backup_domain": "https://auth.h.imruyi.top:8443",
|
||||
@@ -55,7 +61,9 @@
|
||||
"casdoor_application": "admin/aios-portal",
|
||||
"backup_domain_role": "standby-only"
|
||||
},
|
||||
"previous_version": "V1R2C1",
|
||||
"previous_version": "V1R2C2",
|
||||
"rollback_version": "V1R2C2",
|
||||
"release_reason": "GPT Actions ClientResponseError compatibility recovery and validated GitOps Actions read/write path.",
|
||||
"codex_gitops": {
|
||||
"config": "config/codex/gitops-online.json",
|
||||
"token_account": "codex-gitops-bot",
|
||||
@@ -94,7 +102,10 @@
|
||||
"default_local_account": "disabled_without_password",
|
||||
"owner_password_sync": "aios-gitea-owner-sync.timer",
|
||||
"owner_password_source": "secret_ref://aios/user-control-center/UCC_OWNER_PASSWORD"
|
||||
}
|
||||
},
|
||||
"secret_plaintext_written": false,
|
||||
"token_plaintext_written": false,
|
||||
"force_push_used": false
|
||||
},
|
||||
"last_auth_portal_fix": {
|
||||
"version": "V1R1C4",
|
||||
@@ -104,5 +115,24 @@
|
||||
"portal_overlay": "overlays/user-control-center",
|
||||
"portal_baseline_cache": "/app/runtime/gitops/current.json",
|
||||
"sync_log_secret_hygiene": "runuser_without_sudo_command_logging"
|
||||
}
|
||||
},
|
||||
"promotion": {
|
||||
"target_version": "V1R2C3",
|
||||
"tag": "V1R2C3",
|
||||
"branch": "patch/v1r2c3-baseline-promotion-20260708",
|
||||
"previous_version": "V1R2C2",
|
||||
"rollback_version": "V1R2C2",
|
||||
"validated_actions": [
|
||||
"getRuntimeStatus",
|
||||
"getBaseline",
|
||||
"listVersions",
|
||||
"listPatches",
|
||||
"getDiff",
|
||||
"createBranch",
|
||||
"createPatch",
|
||||
"commitFile"
|
||||
],
|
||||
"owner_authorized": true
|
||||
},
|
||||
"git": "abe2ea3"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"type": "branch",
|
||||
"branch": "patch/v1r2c3-baseline-promotion-20260708",
|
||||
"base": "main",
|
||||
"created_by": "chatgpt-gitops-bot",
|
||||
"created_at": "2026-07-07T18:25:04Z",
|
||||
"direct_main_push": false,
|
||||
"owner_approval_required": true
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"id": "patch-1783448903483-a9f3ec99",
|
||||
"patch_name": "v1r2c3-final-smoke-20260708",
|
||||
"branch": "patch/v1r2c3-final-smoke-20260708",
|
||||
"risk": "low",
|
||||
"description": "Final smoke validation patch after V1R2C3 baseline promotion preparation.",
|
||||
"created_by": "chatgpt-gitops-bot",
|
||||
"created_at": "2026-07-07T18:28:23Z"
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
# V1R2C2 自动恢复链路验收测试报告
|
||||
|
||||
## 基本信息
|
||||
|
||||
- **版本**: V1R2C2
|
||||
- **测试时间**: 2026-07-07
|
||||
- **测试范围**: Action Monitor → Error Classifier → Failure Router → Recovery Controller
|
||||
- **测试方式**:
|
||||
1. 单元测试(模块级):验证各模块独立功能
|
||||
2. 集成测试(管线级):验证完整闭环
|
||||
3. API 端到端测试(HTTP 级):验证 REST API 集成
|
||||
|
||||
## 测试结果
|
||||
|
||||
### 1. Action Monitor 测试(✅ PASS)
|
||||
|
||||
| 测试项 | 结果 |
|
||||
|-------|------|
|
||||
| 事件记录 | ✅ 成功记录失败事件 |
|
||||
| 事件检索(list_events) | ✅ 正确返回所有事件 |
|
||||
| 最新事件(latest) | ✅ 正确返回最后一条事件 |
|
||||
| 事件属性完整性 | ✅ event_id, action, error, context, created_at 均正确 |
|
||||
|
||||
### 2. Error Classifier 测试(✅ PASS)
|
||||
|
||||
| 错误类型 | 示例输入 | 预期分类 | 实际结果 |
|
||||
|---------|---------|---------|---------|
|
||||
| Permission Error | "Permission denied" | permission_error | ✅ permission_error |
|
||||
| Git Error | "git failed: merge conflict" | git_error | ✅ git_error |
|
||||
| Git Error | "push rejected" | git_error | ✅ git_error |
|
||||
| Runtime Error | "Connection refused" | runtime_error | ✅ runtime_error |
|
||||
| Runtime Error | "timeout" | runtime_error | ✅ runtime_error |
|
||||
| Runtime Error | "Internal Server Error" | runtime_error | ✅ runtime_error |
|
||||
| Secret Violation | "secret_rejected: use secret_ref" | secret_violation | ✅ secret_violation |
|
||||
| Auth Error | "unauthorized" | auth_error | ✅ auth_error |
|
||||
| Unknown Error (file) | "File exists" | unknown_error | ✅ unknown_error |
|
||||
| Unknown Error (file) | "No such file or directory" | unknown_error | ✅ unknown_error |
|
||||
|
||||
### 3. Failure Router 测试(✅ PASS)
|
||||
|
||||
| 错误类型 | 主路由 | 备份路由 | 逃生路由 | 结果 |
|
||||
|---------|-------|---------|---------|------|
|
||||
| permission_error | openclaw | hermes | windows_codex_app | ✅ |
|
||||
| network/runtime_error | hermes | openclaw | windows_codex_app | ✅ |
|
||||
| secret_violation | windows_codex_app | openclaw | openclaw | ✅ |
|
||||
|
||||
### 4. Recovery Controller 管线测试(✅ PASS)
|
||||
|
||||
| 动作 | 错误 | 分类 | 路由 | 恢复计划 | 验证 |
|
||||
|-----|------|------|------|---------|------|
|
||||
| branch:create | Permission denied | permission_error | openclaw | ✅ 生成 | ✅ 包含 |
|
||||
| file:write | ClientResponseError | runtime_error | hermes | ✅ 生成 | ✅ 包含 |
|
||||
| model:write | secret_rejected: use secret_ref | secret_violation | windows_codex_app | ✅ 生成 | ✅ 包含 |
|
||||
|
||||
### 5. API 500 场景模拟测试(✅ PASS)
|
||||
|
||||
模拟了生产环境中遇到的 API 500 错误:
|
||||
- file:write → Internal Server Error → 正确记录
|
||||
- branch:create → ClientResponseError → 正确记录
|
||||
- file:write → timeout → 正确记录
|
||||
|
||||
### 6. 编译验证(✅ PASS)
|
||||
|
||||
三个核心模块和测试代码编译通过,无语法错误。
|
||||
|
||||
## 执行覆盖
|
||||
|
||||
```
|
||||
测试代码:runtime/agent-os/orchestrator/integration_test_v1r2c2.py
|
||||
被测模块:runtime/agent-os/orchestrator/action_monitor.py
|
||||
runtime/agent-os/orchestrator/error_classifier.py
|
||||
runtime/agent-os/orchestrator/failure_router.py
|
||||
runtime/agent-os/orchestrator/recovery_controller.py
|
||||
API 集成: active-runtime/app/aios_chatgpt_actions_api.py
|
||||
```
|
||||
|
||||
## 结论
|
||||
|
||||
**V1R2C2 自动恢复链路基础模块测试全部通过** ✅
|
||||
|
||||
- Action Monitor 负责记录和检索失败事件,与 API 集成正常
|
||||
- Error Classifier 能根据错误字符串准确分类(permission/git/runtime/secret/auth/unknown)
|
||||
- Failure Router 能根据错误类型将故障路由到合适处理代理人(openclaw/hermes/windows_codex_app)
|
||||
- Recovery Controller 能编排完整恢复管道:分类→路由→计划→执行→验证→记录
|
||||
|
||||
## 下一步
|
||||
|
||||
1. 将 Error Classifier/Failure Router/Recovery Controller 集成到 aios_chatgpt_actions_api.py 的 do_POST 错误处理路径中
|
||||
2. 添加 GitOps 提交和版本标记
|
||||
3. 微信通知 Owner 报告
|
||||
4. 虾马一体进展汇报
|
||||
@@ -0,0 +1 @@
|
||||
{"version":"V1R2C3","tag":"V1R2C3","status":"promoted","previous_version":"V1R2C2","rollback_version":"V1R2C2","release_reason":"GPT Actions ClientResponseError compatibility recovery","validated_actions":["getRuntimeStatus","getBaseline","listVersions","listPatches","getDiff","createBranch","createPatch","commitFile"],"security":{"secret_plaintext_written":false,"token_plaintext_written":false,"force_push_used":false},"updated_at":"2026-07-08T00:00:00Z"}
|
||||
Reference in New Issue
Block a user