Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a907a86aa7 | ||
|
|
27ee200b21 | ||
|
|
6839c80311 | ||
|
|
abe2ea3577 | ||
|
|
7f7cb61ec5 | ||
|
|
6d6e3f425e | ||
|
|
c38c575d8e |
@@ -160,38 +160,10 @@ def patches():
|
||||
|
||||
class H(BaseHTTPRequestHandler):
|
||||
server_version='AIOSChatGPTGitOps/V1R1C0'
|
||||
def log_request(self, format=''):
|
||||
import sys
|
||||
rid = getattr(self, '_request_id', uid('req'))
|
||||
method = self.command
|
||||
path = urllib.parse.urlparse(self.path).path
|
||||
code = self.responses and list(self.responses.keys())[0] if hasattr(self, 'responses') and self.responses else 0
|
||||
try:
|
||||
act = self.actor()
|
||||
a = ('auth_present=true' if act['ok'] else 'auth_present=false')
|
||||
except:
|
||||
a = 'auth_present=error'
|
||||
print(f'[{now()}] {rid} {method} {path} -> {self._resp_code if hasattr(self,"_resp_code") else "?"} {a} pid={os.getpid()}', file=sys.stderr, flush=True)
|
||||
def compat_headers(self):
|
||||
self.send_header('Access-Control-Allow-Origin', '*')
|
||||
self.send_header('Access-Control-Allow-Methods', 'GET, POST, PUT, HEAD, OPTIONS')
|
||||
self.send_header('Access-Control-Allow-Headers', 'Authorization, Content-Type, X-AIOS-Token')
|
||||
self.send_header('Cache-Control', 'no-store')
|
||||
def send_empty(self, code=204, ctype='application/json; charset=utf-8'):
|
||||
self._resp_code = code
|
||||
self.send_response(code)
|
||||
self.send_header('Content-Type', ctype)
|
||||
self.compat_headers()
|
||||
self.send_header('Content-Length', '0')
|
||||
self.end_headers()
|
||||
def sendj(self, data, code=200, head=False):
|
||||
self._resp_code = code
|
||||
b=json.dumps(data, ensure_ascii=False, indent=2).encode(); self.send_response(code); self.send_header('Content-Type','application/json; charset=utf-8'); self.compat_headers(); self.send_header('Content-Length',str(len(b))); self.end_headers()
|
||||
if not head: self.wfile.write(b)
|
||||
def sendt(self, text, ctype='text/plain; charset=utf-8', code=200, head=False):
|
||||
self._resp_code = code
|
||||
b=text.encode(); self.send_response(code); self.send_header('Content-Type',ctype); self.compat_headers(); self.send_header('Content-Length',str(len(b))); self.end_headers()
|
||||
if not head: self.wfile.write(b)
|
||||
def sendj(self, data, code=200):
|
||||
b=json.dumps(data, ensure_ascii=False, indent=2).encode(); self.send_response(code); self.send_header('Content-Type','application/json; charset=utf-8'); self.send_header('Content-Length',str(len(b))); self.end_headers(); self.wfile.write(b)
|
||||
def sendt(self, text, ctype='text/plain; charset=utf-8', code=200):
|
||||
b=text.encode(); self.send_response(code); self.send_header('Content-Type',ctype); self.send_header('Content-Length',str(len(b))); self.end_headers(); self.wfile.write(b)
|
||||
def body(self):
|
||||
n=int(self.headers.get('Content-Length','0') or '0'); raw=self.rfile.read(n).decode() if n else '{}'
|
||||
try: return json.loads(raw or '{}')
|
||||
@@ -206,18 +178,6 @@ class H(BaseHTTPRequestHandler):
|
||||
if not a['ok']: self.sendj({'error':'unauthorized','hint':'Bearer token required'},401); return None
|
||||
if '*' not in a['scopes'] and scope not in a['scopes']: self.sendj({'error':'forbidden','required_scope':scope,'account':a['account']},403); return None
|
||||
return a
|
||||
def do_OPTIONS(self):
|
||||
return self.send_empty(204)
|
||||
def do_HEAD(self):
|
||||
raw_path = urllib.parse.urlparse(self.path).path
|
||||
path = raw_path.rstrip('/') if raw_path != '/' else '/'
|
||||
if path in ('/api/openapi.yaml','/api/openapi-chatgpt-actions.yaml','/api/schema'):
|
||||
if OPENAPI.exists():
|
||||
return self.sendt(OPENAPI.read_text(encoding='utf-8'), 'application/yaml; charset=utf-8', 200, head=True)
|
||||
return self.send_empty(404)
|
||||
known={'/health','/api/health','/api','/api/status','/api/base','/api/baseline','/base','/api/ver','/api/versions','/ver','/api/diff','/diff','/api/patch','/api/patches','/api/branches','/patch','/api/model','/model','/api/run','/api/runtime-status','/run','/api/action-monitor','/action-monitor'}
|
||||
if path in known: return self.send_empty(200)
|
||||
return self.send_empty(404)
|
||||
def do_GET(self):
|
||||
u=urllib.parse.urlparse(self.path); path=u.path.rstrip('/') if u.path != '/' else u.path; q=urllib.parse.parse_qs(u.query)
|
||||
try:
|
||||
|
||||
+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"
|
||||
}
|
||||
|
||||
+38
-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",
|
||||
@@ -26,10 +26,15 @@
|
||||
"codex_rw": true,
|
||||
"portal_gitops_dashboard": true,
|
||||
"human_shortlinks_login_required": true,
|
||||
"autonomous_recovery_loop": 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-auto-recovery-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",
|
||||
@@ -47,7 +52,7 @@
|
||||
"/api",
|
||||
"/hook"
|
||||
],
|
||||
"updated_at": "2026-07-07T19:45:00Z",
|
||||
"updated_at": "2026-07-08T00:00:00Z",
|
||||
"auth": {
|
||||
"primary_domain": "https://auth.cnnetmkt.top",
|
||||
"backup_domain": "https://auth.h.imruyi.top:8443",
|
||||
@@ -56,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",
|
||||
@@ -95,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",
|
||||
@@ -105,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"
|
||||
}
|
||||
|
||||
@@ -13,32 +13,6 @@ components:
|
||||
scheme: bearer
|
||||
bearerFormat: opaque-token
|
||||
schemas:
|
||||
BaselineResponse:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
active_version: {type: string}
|
||||
active_tag: {type: string}
|
||||
mode: {type: string}
|
||||
git: {type: string}
|
||||
VersionsResponse:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
tags:
|
||||
type: array
|
||||
items: {type: string}
|
||||
versions_dir:
|
||||
type: array
|
||||
items: {type: string}
|
||||
head: {type: string}
|
||||
RuntimeStatusResponse:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
properties:
|
||||
service: {type: string}
|
||||
status: {type: string}
|
||||
workspace_branch: {type: string}
|
||||
BranchRequest:
|
||||
type: object
|
||||
required: [branch]
|
||||
@@ -134,22 +108,12 @@ paths:
|
||||
get:
|
||||
operationId: getBaseline
|
||||
summary: Read current AIOS baseline
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/BaselineResponse'}
|
||||
responses: {'200': {description: OK}}
|
||||
/api/ver:
|
||||
get:
|
||||
operationId: listVersions
|
||||
summary: List GitOps versions
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/VersionsResponse'}
|
||||
responses: {'200': {description: OK}}
|
||||
/api/diff:
|
||||
get:
|
||||
operationId: getDiff
|
||||
@@ -196,12 +160,7 @@ paths:
|
||||
get:
|
||||
operationId: getRuntimeStatus
|
||||
summary: Read runtime status
|
||||
responses:
|
||||
'200':
|
||||
description: OK
|
||||
content:
|
||||
application/json:
|
||||
schema: {$ref: '#/components/schemas/RuntimeStatusResponse'}
|
||||
responses: {'200': {description: OK}}
|
||||
/api/branch:
|
||||
post:
|
||||
operationId: createBranch
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"type": "branch",
|
||||
"branch": "test/alias-write-verify",
|
||||
"base": "main",
|
||||
"created_by": "gitops-write-bot",
|
||||
"created_at": "2026-07-07T14:43:14Z",
|
||||
"direct_main_push": false,
|
||||
"owner_approval_required": true
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
# V1R2C3 GPT Actions ClientResponseError Compatibility Fix Report
|
||||
|
||||
## Status
|
||||
|
||||
READY_FOR_OWNER_RETEST
|
||||
|
||||
## Scope
|
||||
|
||||
- Branch: `patch/V1R2C3-gpt-actions-clientresponse-compat`
|
||||
- Service: `aios-gitops-model-api.service`
|
||||
- Runtime entrypoint: `active-runtime/app/aios_chatgpt_actions_api.py`
|
||||
- Schema: `docs/gitops/openapi-chatgpt-actions.yaml`
|
||||
- Affected operations: `getBaseline`, `getRuntimeStatus`, `listVersions`
|
||||
|
||||
## Finding
|
||||
|
||||
The GPT Actions plugin was exposed in the GPT session, but read operations
|
||||
returned `ClientResponseError`. Public `GET` probes returned `200`, while
|
||||
`HEAD` and `OPTIONS` returned `501` for the schema and core read routes.
|
||||
The OpenAPI document also described the core read responses without explicit
|
||||
`application/json` response schemas.
|
||||
|
||||
## Changes
|
||||
|
||||
- Added compatibility response headers to the ChatGPT Actions adapter:
|
||||
`Access-Control-Allow-Origin`, `Access-Control-Allow-Methods`,
|
||||
`Access-Control-Allow-Headers`, and `Cache-Control`.
|
||||
- Added `HEAD` handling for schema and read endpoints.
|
||||
- Added `OPTIONS` handling for schema and read endpoints.
|
||||
- Added explicit OpenAPI response schemas for:
|
||||
- `BaselineResponse`
|
||||
- `VersionsResponse`
|
||||
- `RuntimeStatusResponse`
|
||||
- Preserved the existing runtime request logging changes already present in
|
||||
the live workspace before this fix.
|
||||
|
||||
## Verification
|
||||
|
||||
- `python3 -m py_compile active-runtime/app/aios_chatgpt_actions_api.py`: PASS
|
||||
- OpenAPI YAML parse with PyYAML: PASS
|
||||
- Service restart: PASS
|
||||
- Public `GET /api/openapi-chatgpt-actions.yaml`: `200`
|
||||
- Public `HEAD /api/openapi-chatgpt-actions.yaml`: `200`
|
||||
- Public `OPTIONS /api/openapi-chatgpt-actions.yaml`: `204`
|
||||
- Public `GET /api/base`: `200`
|
||||
- Public `HEAD /api/base`: `200`
|
||||
- Public `OPTIONS /api/base`: `204`
|
||||
- Public `GET /api/run`: `200`
|
||||
- Public `HEAD /api/run`: `200`
|
||||
- Public `OPTIONS /api/run`: `204`
|
||||
- Public `GET /api/ver`: `200`
|
||||
- Public `HEAD /api/ver`: `200`
|
||||
- Public `OPTIONS /api/ver`: `204`
|
||||
|
||||
## Owner Retest
|
||||
|
||||
Re-import or refresh the GPT Builder Actions schema from:
|
||||
|
||||
`https://cnnetmkt.top/api/openapi-chatgpt-actions.yaml`
|
||||
|
||||
Then retry in a fresh GPT preview/session:
|
||||
|
||||
1. `getRuntimeStatus`
|
||||
2. `getBaseline`
|
||||
3. `listVersions`
|
||||
|
||||
## Security Notes
|
||||
|
||||
- No API key, token, password, bearer value, cookie, or secret value was added.
|
||||
- No force push was used.
|
||||
- No tag was created.
|
||||
- No production switch was executed.
|
||||
- Direct main writes remain forbidden.
|
||||
@@ -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