Copy disabled (too large)
Download .txt
Showing preview only (18,085K chars total). Download the full file to get everything.
Repository: alibaba/higress
Branch: main
Commit: ca22fcb90b05
Files: 2130
Total size: 100.7 MB
Directory structure:
gitextract__hz1lxah/
├── .claude/
│ └── skills/
│ ├── agent-session-monitor/
│ │ ├── QUICKSTART.md
│ │ ├── README.md
│ │ ├── SKILL.md
│ │ ├── example/
│ │ │ ├── clawdbot_demo.py
│ │ │ ├── demo.sh
│ │ │ ├── demo_v2.sh
│ │ │ ├── test_access.log
│ │ │ ├── test_access_v2.log
│ │ │ └── test_rotation.sh
│ │ ├── main.py
│ │ └── scripts/
│ │ ├── cli.py
│ │ └── webserver.py
│ ├── higress-auto-router/
│ │ └── SKILL.md
│ ├── higress-daily-report/
│ │ ├── README.md
│ │ ├── SKILL.md
│ │ └── scripts/
│ │ └── generate-report.sh
│ ├── higress-openclaw-integration/
│ │ ├── SKILL.md
│ │ ├── references/
│ │ │ └── TROUBLESHOOTING.md
│ │ └── scripts/
│ │ ├── detect-region.sh
│ │ └── plugin/
│ │ ├── README.md
│ │ ├── index.ts
│ │ ├── openclaw.plugin.json
│ │ └── package.json
│ ├── higress-wasm-go-plugin/
│ │ ├── SKILL.md
│ │ └── references/
│ │ ├── advanced-patterns.md
│ │ ├── http-client.md
│ │ ├── local-testing.md
│ │ └── redis-client.md
│ └── nginx-to-higress-migration/
│ ├── README.md
│ ├── README_CN.md
│ ├── SKILL.md
│ ├── references/
│ │ ├── annotation-mapping.md
│ │ ├── builtin-plugins.md
│ │ ├── plugin-deployment.md
│ │ └── snippet-patterns.md
│ └── scripts/
│ ├── analyze-ingress.sh
│ ├── generate-migration-test.sh
│ ├── generate-plugin-scaffold.sh
│ └── install-harbor.sh
├── .cursor/
│ └── rules/
│ └── plugin-development.mdc
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── FEATURE_REQUEST.md
│ │ ├── config.yml
│ │ └── non--crash-security--bug.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── build-and-push-wasm-plugin-image.yaml
│ ├── build-and-test-plugin.yaml
│ ├── build-and-test.yaml
│ ├── build-image-and-push.yaml
│ ├── codeql-analysis.yaml
│ ├── deploy-standalone-to-oss.yaml
│ ├── deploy-to-oss.yaml
│ ├── generate-release-notes.yaml
│ ├── helm-docs.yaml
│ ├── license-checker.yaml
│ ├── release-crd.yaml
│ ├── release-hgctl.yaml
│ ├── sync-crds.yaml
│ ├── sync-skills-to-oss.yaml
│ ├── translate-readme.yaml
│ ├── translate-test.yml
│ └── wasm-plugin-unit-test.yml
├── .gitignore
├── .gitmodules
├── .licenserc.yaml
├── ADOPTERS.md
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING_CN.md
├── CONTRIBUTING_EN.md
├── CONTRIBUTING_JP.md
├── DEP_VERSION
├── LICENSE
├── Makefile
├── Makefile.core.mk
├── Makefile.overrides.mk
├── README.md
├── README_JP.md
├── README_ZH.md
├── SECURITY.md
├── VERSION
├── api/
│ ├── buf.gen.yaml
│ ├── buf.yaml
│ ├── cue.yaml
│ ├── extensions/
│ │ └── v1alpha1/
│ │ ├── wasmplugin.pb.go
│ │ ├── wasmplugin.proto
│ │ ├── wasmplugin_deepcopy.gen.go
│ │ └── wasmplugin_json.gen.go
│ ├── gen.sh
│ ├── kubernetes/
│ │ └── customresourcedefinitions.gen.yaml
│ ├── networking/
│ │ └── v1/
│ │ ├── http_2_rpc.pb.go
│ │ ├── http_2_rpc.proto
│ │ ├── http_2_rpc_deepcopy.gen.go
│ │ ├── http_2_rpc_json.gen.go
│ │ ├── mcp_bridge.pb.go
│ │ ├── mcp_bridge.proto
│ │ ├── mcp_bridge_deepcopy.gen.go
│ │ └── mcp_bridge_json.gen.go
│ └── protocol.yaml
├── client/
│ ├── Makefile
│ ├── header.go.txt
│ └── pkg/
│ ├── apis/
│ │ ├── extensions/
│ │ │ └── v1alpha1/
│ │ │ ├── doc.go
│ │ │ ├── register.gen.go
│ │ │ ├── types.gen.go
│ │ │ └── zz_generated.deepcopy.gen.go
│ │ └── networking/
│ │ └── v1/
│ │ ├── doc.go
│ │ ├── register.gen.go
│ │ ├── types.gen.go
│ │ └── zz_generated.deepcopy.gen.go
│ ├── applyconfiguration/
│ │ ├── extensions/
│ │ │ └── v1alpha1/
│ │ │ └── wasmplugin.go
│ │ ├── internal/
│ │ │ └── internal.go
│ │ ├── meta/
│ │ │ └── v1/
│ │ │ ├── managedfieldsentry.go
│ │ │ ├── objectmeta.go
│ │ │ ├── ownerreference.go
│ │ │ └── typemeta.go
│ │ ├── networking/
│ │ │ └── v1/
│ │ │ ├── http2rpc.go
│ │ │ └── mcpbridge.go
│ │ └── utils.go
│ ├── clientset/
│ │ └── versioned/
│ │ ├── clientset.gen.go
│ │ ├── fake/
│ │ │ ├── clientset_generated.gen.go
│ │ │ ├── doc.go
│ │ │ └── register.gen.go
│ │ ├── scheme/
│ │ │ ├── doc.go
│ │ │ └── register.gen.go
│ │ └── typed/
│ │ ├── extensions/
│ │ │ └── v1alpha1/
│ │ │ ├── doc.go
│ │ │ ├── extensions_client.gen.go
│ │ │ ├── fake/
│ │ │ │ ├── doc.go
│ │ │ │ ├── fake_extensions_client.gen.go
│ │ │ │ └── fake_wasmplugin.gen.go
│ │ │ ├── generated_expansion.gen.go
│ │ │ └── wasmplugin.gen.go
│ │ └── networking/
│ │ └── v1/
│ │ ├── doc.go
│ │ ├── fake/
│ │ │ ├── doc.go
│ │ │ ├── fake_http2rpc.gen.go
│ │ │ ├── fake_mcpbridge.gen.go
│ │ │ └── fake_networking_client.gen.go
│ │ ├── generated_expansion.gen.go
│ │ ├── http2rpc.gen.go
│ │ ├── mcpbridge.gen.go
│ │ └── networking_client.gen.go
│ ├── informers/
│ │ └── externalversions/
│ │ ├── extensions/
│ │ │ ├── interface.gen.go
│ │ │ └── v1alpha1/
│ │ │ ├── interface.gen.go
│ │ │ └── wasmplugin.gen.go
│ │ ├── factory.gen.go
│ │ ├── generic.gen.go
│ │ ├── internalinterfaces/
│ │ │ └── factory_interfaces.gen.go
│ │ └── networking/
│ │ ├── interface.gen.go
│ │ └── v1/
│ │ ├── http2rpc.gen.go
│ │ ├── interface.gen.go
│ │ └── mcpbridge.gen.go
│ └── listers/
│ ├── extensions/
│ │ └── v1alpha1/
│ │ ├── expansion_generated.gen.go
│ │ └── wasmplugin.gen.go
│ └── networking/
│ └── v1/
│ ├── expansion_generated.gen.go
│ ├── http2rpc.gen.go
│ └── mcpbridge.gen.go
├── cmd/
│ └── higress/
│ └── main.go
├── codecov.yml
├── docker/
│ ├── Dockerfile.base
│ ├── Dockerfile.higress
│ ├── docker-copy.sh
│ └── docker.mk
├── docs/
│ └── architecture.md
├── get_helm.sh
├── go.mod
├── go.sum
├── helm/
│ ├── core/
│ │ ├── .helmignore
│ │ ├── Chart.yaml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── charts/
│ │ │ └── redis/
│ │ │ ├── .helmignore
│ │ │ ├── Chart.yaml
│ │ │ ├── templates/
│ │ │ │ ├── _helpers.tpl
│ │ │ │ ├── configmap.yaml
│ │ │ │ ├── pvc.yaml
│ │ │ │ ├── service.yaml
│ │ │ │ └── statefulset.yaml
│ │ │ └── values.yaml
│ │ ├── crds/
│ │ │ ├── customresourcedefinitions.gen.yaml
│ │ │ ├── customresourcedefinitions.gen_lt1.16.yaml
│ │ │ └── istio-envoyfilter.yaml
│ │ ├── templates/
│ │ │ ├── NOTES.txt
│ │ │ ├── _helpers.tpl
│ │ │ ├── _pod.tpl
│ │ │ ├── clusterrole.yaml
│ │ │ ├── configmap.yaml
│ │ │ ├── controller-clusterrole.yaml
│ │ │ ├── controller-clusterrolebinding.yaml
│ │ │ ├── controller-deployment.yaml
│ │ │ ├── controller-role.yaml
│ │ │ ├── controller-rolebinding.yaml
│ │ │ ├── controller-service.yaml
│ │ │ ├── controller-serviceaccont.yaml
│ │ │ ├── daemonset.yaml
│ │ │ ├── deployment.yaml
│ │ │ ├── fallback-envoyfilter.yaml
│ │ │ ├── hpa.yaml
│ │ │ ├── ingressclass.yaml
│ │ │ ├── plugin-server-deployment.yaml
│ │ │ ├── plugin-server-service.yaml
│ │ │ ├── podmonitor.yaml
│ │ │ ├── promtail.yaml
│ │ │ ├── role.yaml
│ │ │ ├── service.yaml
│ │ │ └── serviceaccount.yaml
│ │ └── values.yaml
│ └── higress/
│ ├── Chart.yaml
│ ├── LICENSE
│ ├── README.md
│ ├── README.md.gotmpl
│ └── README.zh.md
├── hgctl/
│ ├── cmd/
│ │ └── hgctl/
│ │ ├── config/
│ │ │ ├── gateway_config.go
│ │ │ ├── gateway_config_test.go
│ │ │ └── testdata/
│ │ │ └── config/
│ │ │ ├── input/
│ │ │ │ └── in.all.json
│ │ │ └── output/
│ │ │ ├── out.all.json
│ │ │ ├── out.all.yaml
│ │ │ ├── out.bootstrap.json
│ │ │ ├── out.bootstrap.yaml
│ │ │ ├── out.cluster.json
│ │ │ ├── out.cluster.yaml
│ │ │ ├── out.endpoints.json
│ │ │ ├── out.endpoints.yaml
│ │ │ ├── out.listener.json
│ │ │ ├── out.listener.yaml
│ │ │ ├── out.route.json
│ │ │ └── out.route.yaml
│ │ └── main.go
│ ├── go.mod
│ ├── go.sum
│ └── pkg/
│ ├── agent/
│ │ ├── README.md
│ │ ├── agent.go
│ │ ├── base.go
│ │ ├── common/
│ │ │ └── base.go
│ │ ├── config.go
│ │ ├── core.go
│ │ ├── deploy.go
│ │ ├── mcp.go
│ │ ├── new.go
│ │ ├── prompt/
│ │ │ ├── agent_guide.md
│ │ │ └── base.go
│ │ ├── services/
│ │ │ ├── client.go
│ │ │ ├── service.go
│ │ │ └── utils.go
│ │ ├── types.go
│ │ └── utils.go
│ ├── code_debug.go
│ ├── common.go
│ ├── completion.go
│ ├── config_bootstrap.go
│ ├── config_cluster.go
│ ├── config_cmd.go
│ ├── config_endpoint.go
│ ├── config_listener.go
│ ├── config_route.go
│ ├── dashboard.go
│ ├── docker/
│ │ └── compose.go
│ ├── helm/
│ │ ├── common.go
│ │ ├── name/
│ │ │ └── name.go
│ │ ├── object/
│ │ │ ├── objects.go
│ │ │ └── objects_test.go
│ │ ├── profile.go
│ │ ├── render.go
│ │ └── tpath/
│ │ ├── tree.go
│ │ ├── tree_test.go
│ │ ├── util.go
│ │ └── util_test.go
│ ├── install.go
│ ├── installer/
│ │ ├── component.go
│ │ ├── gateway_api.go
│ │ ├── helm_agent.go
│ │ ├── higress.go
│ │ ├── installer.go
│ │ ├── installer_docker.go
│ │ ├── installer_k8s.go
│ │ ├── istio.go
│ │ ├── profile_store.go
│ │ ├── server_info.go
│ │ ├── standalone.go
│ │ └── standalone_agent.go
│ ├── kubernetes/
│ │ ├── client.go
│ │ ├── common.go
│ │ ├── port-forwarder.go
│ │ └── wasmplugin.go
│ ├── manifest.go
│ ├── manifests/
│ │ ├── agent/
│ │ │ ├── agents/
│ │ │ │ ├── agentscope-test-runner.md
│ │ │ │ ├── openapi-generator.md
│ │ │ │ └── openapi-to-mcp-generator.md
│ │ │ ├── commands/
│ │ │ │ └── gen-agent.md
│ │ │ └── template/
│ │ │ ├── agent.tmpl
│ │ │ ├── agentrun.tmpl
│ │ │ ├── agentrun_s.tmpl
│ │ │ ├── agentscope.tmpl
│ │ │ └── toolkit.tmpl
│ │ ├── gatewayapi/
│ │ │ └── experimental-install.yaml
│ │ ├── istiobase/
│ │ │ ├── Chart.yaml
│ │ │ ├── README.md
│ │ │ ├── crds/
│ │ │ │ ├── crd-all.gen.yaml
│ │ │ │ └── crd-operator.yaml
│ │ │ ├── templates/
│ │ │ │ ├── NOTES.txt
│ │ │ │ ├── clusterrole.yaml
│ │ │ │ ├── clusterrolebinding.yaml
│ │ │ │ ├── crds.yaml
│ │ │ │ ├── default.yaml
│ │ │ │ ├── endpoints.yaml
│ │ │ │ ├── reader-serviceaccount.yaml
│ │ │ │ ├── role.yaml
│ │ │ │ ├── rolebinding.yaml
│ │ │ │ ├── serviceaccount.yaml
│ │ │ │ └── services.yaml
│ │ │ └── values.yaml
│ │ ├── manifest.go
│ │ └── profiles/
│ │ ├── _all.yaml
│ │ ├── k8s.yaml
│ │ ├── local-docker.yaml
│ │ └── local-k8s.yaml
│ ├── plugin/
│ │ ├── build/
│ │ │ ├── build.go
│ │ │ ├── signal.go
│ │ │ ├── signal_windows.go
│ │ │ └── templates.go
│ │ ├── config/
│ │ │ ├── config.go
│ │ │ ├── create.go
│ │ │ ├── edit.go
│ │ │ └── templates.go
│ │ ├── init/
│ │ │ ├── init.go
│ │ │ └── templates.go
│ │ ├── install/
│ │ │ ├── asker.go
│ │ │ └── install.go
│ │ ├── ls/
│ │ │ └── ls.go
│ │ ├── option/
│ │ │ ├── option.go
│ │ │ └── template.go
│ │ ├── plugin.go
│ │ ├── test/
│ │ │ ├── clean.go
│ │ │ ├── create.go
│ │ │ ├── ls.go
│ │ │ ├── start.go
│ │ │ ├── stop.go
│ │ │ ├── templates.go
│ │ │ └── test.go
│ │ ├── types/
│ │ │ ├── annotation.go
│ │ │ ├── marshal.go
│ │ │ ├── meta.go
│ │ │ ├── model_parser.go
│ │ │ ├── model_parser_test.go
│ │ │ ├── schema.go
│ │ │ └── testdata/
│ │ │ ├── doc_tag/
│ │ │ │ └── main.go
│ │ │ └── types/
│ │ │ ├── ext/
│ │ │ │ ├── ext.go
│ │ │ │ └── nested/
│ │ │ │ └── nested.go
│ │ │ └── main.go
│ │ ├── uninstall/
│ │ │ └── uninstall.go
│ │ └── utils/
│ │ ├── common.go
│ │ ├── debugger.go
│ │ ├── printer.go
│ │ └── survey_wrapper.go
│ ├── profile.go
│ ├── profile_dump.go
│ ├── profile_list.go
│ ├── root.go
│ ├── uninstall.go
│ ├── upgrade.go
│ ├── util/
│ │ ├── env.go
│ │ ├── filter.go
│ │ ├── filter_test.go
│ │ ├── http_fetcher.go
│ │ ├── path.go
│ │ ├── path_test.go
│ │ ├── reflect.go
│ │ ├── util.go
│ │ ├── yaml.go
│ │ └── yaml_test.go
│ ├── utils.go
│ └── version.go
├── pkg/
│ ├── bootstrap/
│ │ ├── server.go
│ │ └── server_test.go
│ ├── cert/
│ │ ├── certmgr.go
│ │ ├── config.go
│ │ ├── config_test.go
│ │ ├── controller.go
│ │ ├── ingress.go
│ │ ├── log.go
│ │ ├── secret.go
│ │ ├── server.go
│ │ ├── storage.go
│ │ ├── storage_test.go
│ │ └── util.go
│ ├── cmd/
│ │ ├── options/
│ │ │ └── global.go
│ │ ├── root.go
│ │ ├── server.go
│ │ ├── server_test.go
│ │ ├── version/
│ │ │ └── version.go
│ │ └── version.go
│ ├── common/
│ │ ├── protocol.go
│ │ ├── proxy.go
│ │ └── symbol.go
│ ├── config/
│ │ ├── constants/
│ │ │ └── constants.go
│ │ └── envs.go
│ ├── ingress/
│ │ ├── config/
│ │ │ ├── ingress_config.go
│ │ │ ├── ingress_config_test.go
│ │ │ ├── ingress_template.go
│ │ │ ├── ingress_template_test.go
│ │ │ ├── kingress_config.go
│ │ │ ├── kingress_config_test.go
│ │ │ ├── secret_config_mgr.go
│ │ │ └── secret_config_mgr_test.go
│ │ ├── kube/
│ │ │ ├── annotations/
│ │ │ │ ├── annotations.go
│ │ │ │ ├── annotations_test.go
│ │ │ │ ├── auth.go
│ │ │ │ ├── canary.go
│ │ │ │ ├── canary_test.go
│ │ │ │ ├── cors.go
│ │ │ │ ├── cors_test.go
│ │ │ │ ├── default_backend.go
│ │ │ │ ├── default_backend_test.go
│ │ │ │ ├── destination.go
│ │ │ │ ├── destination_test.go
│ │ │ │ ├── downstreamtls.go
│ │ │ │ ├── downstreamtls_test.go
│ │ │ │ ├── header_control.go
│ │ │ │ ├── header_control_test.go
│ │ │ │ ├── http2rpc.go
│ │ │ │ ├── http2rpc_test.go
│ │ │ │ ├── ignore_case.go
│ │ │ │ ├── ignore_case_test.go
│ │ │ │ ├── interface.go
│ │ │ │ ├── ip_access_control.go
│ │ │ │ ├── ip_access_control_test.go
│ │ │ │ ├── loadbalance.go
│ │ │ │ ├── loadbalance_test.go
│ │ │ │ ├── local_rate_limit.go
│ │ │ │ ├── local_rate_limit_test.go
│ │ │ │ ├── match.go
│ │ │ │ ├── match_test.go
│ │ │ │ ├── mcpserver.go
│ │ │ │ ├── mcpserver_test.go
│ │ │ │ ├── mirror.go
│ │ │ │ ├── mirror_test.go
│ │ │ │ ├── parser.go
│ │ │ │ ├── redirect.go
│ │ │ │ ├── redirect_test.go
│ │ │ │ ├── retry.go
│ │ │ │ ├── retry_test.go
│ │ │ │ ├── rewrite.go
│ │ │ │ ├── rewrite_test.go
│ │ │ │ ├── timeout.go
│ │ │ │ ├── timeout_test.go
│ │ │ │ ├── upstreamtls.go
│ │ │ │ ├── upstreamtls_test.go
│ │ │ │ ├── util.go
│ │ │ │ └── util_test.go
│ │ │ ├── common/
│ │ │ │ ├── controller.go
│ │ │ │ ├── metrics.go
│ │ │ │ ├── model.go
│ │ │ │ ├── model_test.go
│ │ │ │ ├── schema.go
│ │ │ │ ├── tool.go
│ │ │ │ └── tool_test.go
│ │ │ ├── configmap/
│ │ │ │ ├── config.go
│ │ │ │ ├── controller.go
│ │ │ │ ├── global.go
│ │ │ │ ├── global_test.go
│ │ │ │ ├── gzip.go
│ │ │ │ ├── gzip_test.go
│ │ │ │ ├── mcp_server.go
│ │ │ │ ├── mcp_server_test.go
│ │ │ │ └── tracing.go
│ │ │ ├── controller/
│ │ │ │ └── model.go
│ │ │ ├── gateway/
│ │ │ │ ├── controller.go
│ │ │ │ └── istio/
│ │ │ │ ├── backend_policies.go
│ │ │ │ ├── conditions.go
│ │ │ │ ├── conditions_test.go
│ │ │ │ ├── context.go
│ │ │ │ ├── controller.go
│ │ │ │ ├── controller_test.go
│ │ │ │ ├── conversion.go
│ │ │ │ ├── conversion_test.go
│ │ │ │ ├── deploymentcontroller.go
│ │ │ │ ├── gateway_collection.go
│ │ │ │ ├── gatewayclass.go
│ │ │ │ ├── gatewayclass_collection.go
│ │ │ │ ├── gatewayclass_test.go
│ │ │ │ ├── inferencepool_collection.go
│ │ │ │ ├── inferencepool_status_test.go
│ │ │ │ ├── inferencepool_test.go
│ │ │ │ ├── leak_test.go
│ │ │ │ ├── references.go
│ │ │ │ ├── references_collection.go
│ │ │ │ ├── route_collections.go
│ │ │ │ ├── status_test.go
│ │ │ │ ├── supported_features.go
│ │ │ │ └── testdata/
│ │ │ │ ├── backend-lb-policy.status.yaml.golden
│ │ │ │ ├── backend-lb-policy.yaml
│ │ │ │ ├── backend-lb-policy.yaml.golden
│ │ │ │ ├── backend-tls-policy.status.yaml.golden
│ │ │ │ ├── backend-tls-policy.yaml
│ │ │ │ ├── backend-tls-policy.yaml.golden
│ │ │ │ ├── benchmark-httproute.yaml
│ │ │ │ ├── delegated.status.yaml.golden
│ │ │ │ ├── delegated.yaml
│ │ │ │ ├── delegated.yaml.golden
│ │ │ │ ├── east-west-ambient.status.yaml.golden
│ │ │ │ ├── east-west-ambient.yaml
│ │ │ │ ├── east-west-ambient.yaml.golden
│ │ │ │ ├── eastwest-labelport.status.yaml.golden
│ │ │ │ ├── eastwest-labelport.yaml
│ │ │ │ ├── eastwest-labelport.yaml.golden
│ │ │ │ ├── eastwest-remote.status.yaml.golden
│ │ │ │ ├── eastwest-remote.yaml
│ │ │ │ ├── eastwest-remote.yaml.golden
│ │ │ │ ├── eastwest-tlsoption.status.yaml.golden
│ │ │ │ ├── eastwest-tlsoption.yaml
│ │ │ │ ├── eastwest-tlsoption.yaml.golden
│ │ │ │ ├── eastwest.status.yaml.golden
│ │ │ │ ├── eastwest.yaml
│ │ │ │ ├── eastwest.yaml.golden
│ │ │ │ ├── grpc.status.yaml.golden
│ │ │ │ ├── grpc.yaml
│ │ │ │ ├── grpc.yaml.golden
│ │ │ │ ├── http.status.yaml.golden
│ │ │ │ ├── http.yaml
│ │ │ │ ├── http.yaml.golden
│ │ │ │ ├── invalid.status.yaml.golden
│ │ │ │ ├── invalid.yaml
│ │ │ │ ├── invalid.yaml.golden
│ │ │ │ ├── isolation.status.yaml.golden
│ │ │ │ ├── isolation.yaml
│ │ │ │ ├── isolation.yaml.golden
│ │ │ │ ├── listenerset-cross-namespace.status.yaml.golden
│ │ │ │ ├── listenerset-cross-namespace.yaml
│ │ │ │ ├── listenerset-cross-namespace.yaml.golden
│ │ │ │ ├── listenerset-empty-listeners.status.yaml.golden
│ │ │ │ ├── listenerset-empty-listeners.yaml
│ │ │ │ ├── listenerset-empty-listeners.yaml.golden
│ │ │ │ ├── listenerset-invalid.status.yaml.golden
│ │ │ │ ├── listenerset-invalid.yaml
│ │ │ │ ├── listenerset-invalid.yaml.golden
│ │ │ │ ├── listenerset.status.yaml.golden
│ │ │ │ ├── listenerset.yaml
│ │ │ │ ├── listenerset.yaml.golden
│ │ │ │ ├── mcs.status.yaml.golden
│ │ │ │ ├── mcs.yaml
│ │ │ │ ├── mcs.yaml.golden
│ │ │ │ ├── mesh.status.yaml.golden
│ │ │ │ ├── mesh.yaml
│ │ │ │ ├── mesh.yaml.golden
│ │ │ │ ├── mismatch.status.yaml.golden
│ │ │ │ ├── mismatch.yaml
│ │ │ │ ├── mismatch.yaml.golden
│ │ │ │ ├── mix-backend-policy.status.yaml.golden
│ │ │ │ ├── mix-backend-policy.yaml
│ │ │ │ ├── mix-backend-policy.yaml.golden
│ │ │ │ ├── multi-gateway.status.yaml.golden
│ │ │ │ ├── multi-gateway.yaml
│ │ │ │ ├── multi-gateway.yaml.golden
│ │ │ │ ├── reference-policy-inferencepool.status.yaml.golden
│ │ │ │ ├── reference-policy-inferencepool.yaml
│ │ │ │ ├── reference-policy-inferencepool.yaml.golden
│ │ │ │ ├── reference-policy-service.status.yaml.golden
│ │ │ │ ├── reference-policy-service.yaml
│ │ │ │ ├── reference-policy-service.yaml.golden
│ │ │ │ ├── reference-policy-tcp.status.yaml.golden
│ │ │ │ ├── reference-policy-tcp.yaml
│ │ │ │ ├── reference-policy-tcp.yaml.golden
│ │ │ │ ├── reference-policy-tls.status.yaml.golden
│ │ │ │ ├── reference-policy-tls.yaml
│ │ │ │ ├── reference-policy-tls.yaml.golden
│ │ │ │ ├── route-binding.status.yaml.golden
│ │ │ │ ├── route-binding.yaml
│ │ │ │ ├── route-binding.yaml.golden
│ │ │ │ ├── route-precedence.status.yaml.golden
│ │ │ │ ├── route-precedence.yaml
│ │ │ │ ├── route-precedence.yaml.golden
│ │ │ │ ├── serviceentry.status.yaml.golden
│ │ │ │ ├── serviceentry.yaml
│ │ │ │ ├── serviceentry.yaml.golden
│ │ │ │ ├── status.status.yaml.golden
│ │ │ │ ├── status.yaml
│ │ │ │ ├── status.yaml.golden
│ │ │ │ ├── tcp.status.yaml.golden
│ │ │ │ ├── tcp.yaml
│ │ │ │ ├── tcp.yaml.golden
│ │ │ │ ├── tls.status.yaml.golden
│ │ │ │ ├── tls.yaml
│ │ │ │ ├── tls.yaml.golden
│ │ │ │ ├── valid-invalid-parent-ref.status.yaml.golden
│ │ │ │ ├── valid-invalid-parent-ref.yaml
│ │ │ │ ├── valid-invalid-parent-ref.yaml.golden
│ │ │ │ ├── waypoint.status.yaml.golden
│ │ │ │ ├── waypoint.yaml
│ │ │ │ ├── waypoint.yaml.golden
│ │ │ │ ├── weighted.status.yaml.golden
│ │ │ │ ├── weighted.yaml
│ │ │ │ ├── weighted.yaml.golden
│ │ │ │ ├── zero.status.yaml.golden
│ │ │ │ ├── zero.yaml
│ │ │ │ └── zero.yaml.golden
│ │ │ ├── http2rpc/
│ │ │ │ └── controller.go
│ │ │ ├── ingress/
│ │ │ │ ├── controller.go
│ │ │ │ ├── controller_test.go
│ │ │ │ └── status.go
│ │ │ ├── ingressv1/
│ │ │ │ ├── controller.go
│ │ │ │ ├── controller_test.go
│ │ │ │ └── status.go
│ │ │ ├── kingress/
│ │ │ │ ├── controller.go
│ │ │ │ ├── controller_test.go
│ │ │ │ ├── resources/
│ │ │ │ │ ├── doc.go
│ │ │ │ │ ├── virtual_service.go
│ │ │ │ │ └── virtual_service_test.go
│ │ │ │ └── status.go
│ │ │ ├── mcpbridge/
│ │ │ │ └── controller.go
│ │ │ ├── mcpserver/
│ │ │ │ ├── model.go
│ │ │ │ ├── provider.go
│ │ │ │ └── provider_test.go
│ │ │ ├── secret/
│ │ │ │ ├── controller.go
│ │ │ │ └── controller_test.go
│ │ │ ├── util/
│ │ │ │ ├── transformer.go
│ │ │ │ ├── util.go
│ │ │ │ └── util_test.go
│ │ │ └── wasmplugin/
│ │ │ └── controller.go
│ │ ├── log/
│ │ │ └── log.go
│ │ ├── mcp/
│ │ │ ├── generator.go
│ │ │ └── generator_test.go
│ │ └── translation/
│ │ └── translation.go
│ └── kube/
│ └── client.go
├── plugins/
│ ├── README.md
│ ├── golang-filter/
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── README_en.md
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ ├── mcp-server/
│ │ │ ├── README.md
│ │ │ ├── README_en.md
│ │ │ ├── config.go
│ │ │ ├── filter.go
│ │ │ ├── registry/
│ │ │ │ ├── nacos/
│ │ │ │ │ ├── nacos.go
│ │ │ │ │ └── server.go
│ │ │ │ ├── registry.go
│ │ │ │ └── remote.go
│ │ │ └── servers/
│ │ │ ├── gorm/
│ │ │ │ ├── db.go
│ │ │ │ ├── server.go
│ │ │ │ └── tools.go
│ │ │ ├── higress/
│ │ │ │ ├── client.go
│ │ │ │ ├── higress-api/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── README_en.md
│ │ │ │ │ ├── server.go
│ │ │ │ │ └── tools/
│ │ │ │ │ ├── ai_provider.go
│ │ │ │ │ ├── ai_route.go
│ │ │ │ │ ├── mcp_server.go
│ │ │ │ │ ├── plugins/
│ │ │ │ │ │ ├── common.go
│ │ │ │ │ │ ├── custom-response.go
│ │ │ │ │ │ ├── request-block.go
│ │ │ │ │ │ ├── types.go
│ │ │ │ │ │ └── util.go
│ │ │ │ │ ├── route.go
│ │ │ │ │ └── service.go
│ │ │ │ ├── higress-ops/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── README_en.md
│ │ │ │ │ ├── client.go
│ │ │ │ │ ├── server.go
│ │ │ │ │ └── tools/
│ │ │ │ │ ├── client.go
│ │ │ │ │ ├── envoy.go
│ │ │ │ │ ├── istiod.go
│ │ │ │ │ └── utils.go
│ │ │ │ ├── nginx-migration/
│ │ │ │ │ ├── .gitignore
│ │ │ │ │ ├── Makefile
│ │ │ │ │ ├── QUICKSTART.md
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── config/
│ │ │ │ │ │ └── rag.json.example
│ │ │ │ │ ├── go.mod
│ │ │ │ │ ├── go.sum
│ │ │ │ │ ├── integration/
│ │ │ │ │ │ ├── mcptools/
│ │ │ │ │ │ │ ├── adapter.go
│ │ │ │ │ │ │ ├── context.go
│ │ │ │ │ │ │ ├── lua_tools.go
│ │ │ │ │ │ │ ├── nginx_tools.go
│ │ │ │ │ │ │ ├── rag_integration.go
│ │ │ │ │ │ │ └── tool_chain.go
│ │ │ │ │ │ └── server.go
│ │ │ │ │ ├── internal/
│ │ │ │ │ │ ├── rag/
│ │ │ │ │ │ │ ├── client.go
│ │ │ │ │ │ │ ├── config.go
│ │ │ │ │ │ │ └── manager.go
│ │ │ │ │ │ └── standalone/
│ │ │ │ │ │ └── server.go
│ │ │ │ │ ├── mcp-tools.json
│ │ │ │ │ ├── standalone/
│ │ │ │ │ │ ├── cmd/
│ │ │ │ │ │ │ └── main.go
│ │ │ │ │ │ ├── config.go
│ │ │ │ │ │ ├── server.go
│ │ │ │ │ │ └── types.go
│ │ │ │ │ └── tools/
│ │ │ │ │ ├── lua_converter.go
│ │ │ │ │ ├── mcp_tools.go
│ │ │ │ │ ├── nginx_parser.go
│ │ │ │ │ └── tool_chain.go
│ │ │ │ └── types.go
│ │ │ ├── rag/
│ │ │ │ ├── README.md
│ │ │ │ ├── common/
│ │ │ │ │ └── httpclient.go
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── embedding/
│ │ │ │ │ ├── openai.go
│ │ │ │ │ └── provider.go
│ │ │ │ ├── llm/
│ │ │ │ │ ├── openai.go
│ │ │ │ │ ├── prompt.go
│ │ │ │ │ └── provider.go
│ │ │ │ ├── rag_client.go
│ │ │ │ ├── rag_client_test.go
│ │ │ │ ├── schema/
│ │ │ │ │ └── document.go
│ │ │ │ ├── server.go
│ │ │ │ ├── server_test.go
│ │ │ │ ├── textsplitter/
│ │ │ │ │ ├── options.go
│ │ │ │ │ ├── recursive_character.go
│ │ │ │ │ ├── recursive_character_test.go
│ │ │ │ │ ├── splitter_document.go
│ │ │ │ │ └── text_splitter.go
│ │ │ │ ├── tools.go
│ │ │ │ └── vectordb/
│ │ │ │ ├── mapper.go
│ │ │ │ ├── milvus.go
│ │ │ │ ├── milvus_test.go
│ │ │ │ └── provider.go
│ │ │ └── tool-search/
│ │ │ ├── README.md
│ │ │ ├── config-example.json
│ │ │ ├── embedding.go
│ │ │ ├── milvus.go
│ │ │ ├── search.go
│ │ │ ├── server.go
│ │ │ ├── server_test.go
│ │ │ └── tools.go
│ │ └── mcp-session/
│ │ ├── common/
│ │ │ ├── auth.go
│ │ │ ├── crypto.go
│ │ │ ├── match.go
│ │ │ ├── redis.go
│ │ │ ├── registry.go
│ │ │ ├── server.go
│ │ │ ├── sse.go
│ │ │ └── utils.go
│ │ ├── config.go
│ │ ├── filter.go
│ │ ├── filter_test.go
│ │ └── handler/
│ │ ├── config_handler.go
│ │ ├── config_store.go
│ │ └── rate_limit_handler.go
│ ├── wasm-assemblyscript/
│ │ ├── README.md
│ │ ├── asconfig.json
│ │ ├── assembly/
│ │ │ ├── cluster_wrapper.ts
│ │ │ ├── http_wrapper.ts
│ │ │ ├── index.ts
│ │ │ ├── log_wrapper.ts
│ │ │ ├── plugin_wrapper.ts
│ │ │ ├── request_wrapper.ts
│ │ │ ├── rule_matcher.ts
│ │ │ └── tsconfig.json
│ │ ├── extensions/
│ │ │ ├── custom-response/
│ │ │ │ ├── README.md
│ │ │ │ ├── asconfig.json
│ │ │ │ ├── assembly/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── tsconfig.json
│ │ │ │ └── package.json
│ │ │ └── hello-world/
│ │ │ ├── asconfig.json
│ │ │ ├── assembly/
│ │ │ │ ├── index.ts
│ │ │ │ └── tsconfig.json
│ │ │ └── package.json
│ │ └── package.json
│ ├── wasm-cpp/
│ │ ├── .bazelrc
│ │ ├── .bazelversion
│ │ ├── .clang-format
│ │ ├── BUILD
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── README_EN.md
│ │ ├── WORKSPACE
│ │ ├── bazel/
│ │ │ ├── BUILD
│ │ │ ├── absl.patch
│ │ │ ├── boringssl.patch
│ │ │ ├── re2.patch
│ │ │ ├── third_party.bzl
│ │ │ └── wasm.bzl
│ │ ├── common/
│ │ │ ├── BUILD
│ │ │ ├── base64.h
│ │ │ ├── common_util.h
│ │ │ ├── crypt_blowfish.c
│ │ │ ├── crypto_util.cc
│ │ │ ├── crypto_util.h
│ │ │ ├── http_util.cc
│ │ │ ├── http_util.h
│ │ │ ├── json_util.cc
│ │ │ ├── json_util.h
│ │ │ ├── nlohmann_json.hpp
│ │ │ ├── regex.h
│ │ │ └── route_rule_matcher.h
│ │ ├── extensions/
│ │ │ ├── basic_auth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── bot_detect/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── custom_response/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── hmac_auth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── jwt_auth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── extractor.cc
│ │ │ │ ├── extractor.h
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── key_auth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── key_rate_limit/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── bucket.cc
│ │ │ │ ├── bucket.h
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── model_mapper/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── model_router/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── oauth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── request_block/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ └── sni_misdirect/
│ │ │ ├── BUILD
│ │ │ ├── README.md
│ │ │ ├── VERSION
│ │ │ ├── plugin.cc
│ │ │ ├── plugin.h
│ │ │ └── plugin_test.cc
│ │ └── scripts/
│ │ └── build_and_push.sh
│ ├── wasm-go/
│ │ ├── .devcontainer/
│ │ │ ├── Dockerfile
│ │ │ ├── devcontainer.json
│ │ │ └── gen_config.py
│ │ ├── Dockerfile
│ │ ├── DockerfileBuilder
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── README_EN.md
│ │ ├── examples/
│ │ │ ├── custom-log/
│ │ │ │ ├── config.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── custom-span-attribute/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ └── test-foreign-function/
│ │ │ ├── README.md
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ │ └── main.go
│ │ ├── extensions/
│ │ │ ├── ai-agent/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config.go
│ │ │ │ ├── dashscope/
│ │ │ │ │ ├── message.go
│ │ │ │ │ └── types.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── promptTpl/
│ │ │ │ └── prompt.go
│ │ │ ├── ai-cache/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── cache/
│ │ │ │ │ ├── provider.go
│ │ │ │ │ └── redis.go
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── core.go
│ │ │ │ ├── embedding/
│ │ │ │ │ ├── azure.go
│ │ │ │ │ ├── cohere.go
│ │ │ │ │ ├── dashscope.go
│ │ │ │ │ ├── huggingface.go
│ │ │ │ │ ├── ollama.go
│ │ │ │ │ ├── openai.go
│ │ │ │ │ ├── provider.go
│ │ │ │ │ ├── textin.go
│ │ │ │ │ └── xfyun.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── option.yaml
│ │ │ │ ├── util.go
│ │ │ │ └── vector/
│ │ │ │ ├── chroma.go
│ │ │ │ ├── dashvector.go
│ │ │ │ ├── elasticsearch.go
│ │ │ │ ├── milvus.go
│ │ │ │ ├── pinecone.go
│ │ │ │ ├── provider.go
│ │ │ │ ├── qdrant.go
│ │ │ │ └── weaviate.go
│ │ │ ├── ai-history/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── option.yaml
│ │ │ ├── ai-image-reader/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── dashscope.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── provider.go
│ │ │ ├── ai-intent/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-json-resp/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── model.go
│ │ │ │ └── util.go
│ │ │ ├── ai-load-balancer/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── cluster_metrics/
│ │ │ │ │ └── lb_policy.go
│ │ │ │ ├── endpoint_metrics/
│ │ │ │ │ ├── backend/
│ │ │ │ │ │ ├── types.go
│ │ │ │ │ │ └── vllm/
│ │ │ │ │ │ └── metrics.go
│ │ │ │ │ ├── lb_policy.go
│ │ │ │ │ └── scheduling/
│ │ │ │ │ ├── filter.go
│ │ │ │ │ ├── scheduler.go
│ │ │ │ │ └── types.go
│ │ │ │ ├── global_least_request/
│ │ │ │ │ ├── lb_policy.go
│ │ │ │ │ ├── lb_script_test.lua
│ │ │ │ │ └── rate_limit.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── prefix_cache/
│ │ │ │ │ └── lb_policy.go
│ │ │ │ └── utils/
│ │ │ │ ├── queue.go
│ │ │ │ └── utils.go
│ │ │ ├── ai-prompt-decorator/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-prompt-template/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-proxy/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── README_dev.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── option.yaml
│ │ │ │ ├── provider/
│ │ │ │ │ ├── ai360.go
│ │ │ │ │ ├── azure.go
│ │ │ │ │ ├── baichuan.go
│ │ │ │ │ ├── baidu.go
│ │ │ │ │ ├── bedrock.go
│ │ │ │ │ ├── bedrock_sigv4_path_test.go
│ │ │ │ │ ├── claude.go
│ │ │ │ │ ├── claude_test.go
│ │ │ │ │ ├── claude_to_openai.go
│ │ │ │ │ ├── claude_to_openai_test.go
│ │ │ │ │ ├── cloudflare.go
│ │ │ │ │ ├── cohere.go
│ │ │ │ │ ├── context.go
│ │ │ │ │ ├── coze.go
│ │ │ │ │ ├── custom_setting.go
│ │ │ │ │ ├── deepl.go
│ │ │ │ │ ├── deepseek.go
│ │ │ │ │ ├── dify.go
│ │ │ │ │ ├── doubao.go
│ │ │ │ │ ├── failover.go
│ │ │ │ │ ├── fireworks.go
│ │ │ │ │ ├── gemini.go
│ │ │ │ │ ├── generic.go
│ │ │ │ │ ├── github.go
│ │ │ │ │ ├── grok.go
│ │ │ │ │ ├── groq.go
│ │ │ │ │ ├── hunyuan.go
│ │ │ │ │ ├── longcat.go
│ │ │ │ │ ├── longcat_test.go
│ │ │ │ │ ├── minimax.go
│ │ │ │ │ ├── mistral.go
│ │ │ │ │ ├── model.go
│ │ │ │ │ ├── moonshot.go
│ │ │ │ │ ├── multipart_helper.go
│ │ │ │ │ ├── ollama.go
│ │ │ │ │ ├── openai.go
│ │ │ │ │ ├── openrouter.go
│ │ │ │ │ ├── provider.go
│ │ │ │ │ ├── provider_test.go
│ │ │ │ │ ├── qwen.go
│ │ │ │ │ ├── request_helper.go
│ │ │ │ │ ├── request_helper_test.go
│ │ │ │ │ ├── retry.go
│ │ │ │ │ ├── spark.go
│ │ │ │ │ ├── stepfun.go
│ │ │ │ │ ├── together_ai.go
│ │ │ │ │ ├── triton.go
│ │ │ │ │ ├── vertex.go
│ │ │ │ │ ├── vllm.go
│ │ │ │ │ ├── yi.go
│ │ │ │ │ └── zhipuai.go
│ │ │ │ ├── test/
│ │ │ │ │ ├── ai360.go
│ │ │ │ │ ├── api_paths.go
│ │ │ │ │ ├── azure.go
│ │ │ │ │ ├── bedrock.go
│ │ │ │ │ ├── claude-test/
│ │ │ │ │ │ └── claude-message-api.yaml
│ │ │ │ │ ├── claude.go
│ │ │ │ │ ├── consumer_affinity.go
│ │ │ │ │ ├── fireworks.go
│ │ │ │ │ ├── gemini.go
│ │ │ │ │ ├── generic.go
│ │ │ │ │ ├── minimax.go
│ │ │ │ │ ├── mock_context.go
│ │ │ │ │ ├── openai.go
│ │ │ │ │ ├── qwen.go
│ │ │ │ │ ├── util.go
│ │ │ │ │ └── vertex.go
│ │ │ │ └── util/
│ │ │ │ ├── http.go
│ │ │ │ ├── json.go
│ │ │ │ ├── json_test.go
│ │ │ │ ├── ptr.go
│ │ │ │ ├── string.go
│ │ │ │ └── string_test.go
│ │ │ ├── ai-quota/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── plugin.yaml
│ │ │ │ └── util/
│ │ │ │ ├── http.go
│ │ │ │ └── http_test.go
│ │ │ ├── ai-rag/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── dashscope/
│ │ │ │ │ └── types.go
│ │ │ │ ├── dashvector/
│ │ │ │ │ └── types.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-search/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── engine/
│ │ │ │ │ ├── arxiv/
│ │ │ │ │ │ └── arxiv.go
│ │ │ │ │ ├── bing/
│ │ │ │ │ │ └── bing.go
│ │ │ │ │ ├── elasticsearch/
│ │ │ │ │ │ └── elasticsearch.go
│ │ │ │ │ ├── google/
│ │ │ │ │ │ └── google.go
│ │ │ │ │ ├── quark/
│ │ │ │ │ │ └── quark.go
│ │ │ │ │ └── types.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── guide.md
│ │ │ │ ├── main.go
│ │ │ │ └── prompts/
│ │ │ │ ├── arxiv.md
│ │ │ │ ├── chinese-internet.md
│ │ │ │ ├── full.md
│ │ │ │ ├── internet.md
│ │ │ │ ├── private.md
│ │ │ │ └── test_ai_search.py
│ │ │ ├── ai-security-guard/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── lvwang/
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── request_builder.go
│ │ │ │ │ │ ├── request_builder_test.go
│ │ │ │ │ │ └── text/
│ │ │ │ │ │ └── openai.go
│ │ │ │ │ ├── multi_modal_guard/
│ │ │ │ │ │ ├── handler.go
│ │ │ │ │ │ ├── image/
│ │ │ │ │ │ │ ├── common.go
│ │ │ │ │ │ │ ├── openai.go
│ │ │ │ │ │ │ └── qwen.go
│ │ │ │ │ │ ├── mcp/
│ │ │ │ │ │ │ └── mcp.go
│ │ │ │ │ │ └── text/
│ │ │ │ │ │ └── openai.go
│ │ │ │ │ └── text_moderation_plus/
│ │ │ │ │ ├── handler.go
│ │ │ │ │ └── text/
│ │ │ │ │ └── openai.go
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── utils/
│ │ │ │ └── utils.go
│ │ │ ├── ai-statistics/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── fix_tool_calls.patch
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-token-ratelimit/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ └── utils.go
│ │ │ ├── ai-transformer/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── api-workflow/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── README.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── utils/
│ │ │ │ │ ├── conditional.go
│ │ │ │ │ ├── conditional_test.go
│ │ │ │ │ ├── http.go
│ │ │ │ │ └── tools.go
│ │ │ │ └── workflow/
│ │ │ │ └── workflow.go
│ │ │ ├── basic-auth/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── bot-detect/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── botdetect.yaml
│ │ │ │ ├── config/
│ │ │ │ │ ├── bot_detect_config.go
│ │ │ │ │ └── bot_detect_config_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── cache-control/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── chatgpt-proxy/
│ │ │ │ ├── README.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── cluster-key-rate-limit/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ └── utils.go
│ │ │ ├── cors/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── cors_config.go
│ │ │ │ │ └── cors_config_test.go
│ │ │ │ ├── cors.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── custom-response/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── de-graphql/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── degraphql_config.go
│ │ │ │ │ └── degraphql_config_test.go
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── graphql.yaml
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ext-auth/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── expr/
│ │ │ │ │ ├── match_rules.go
│ │ │ │ │ ├── match_rules_test.go
│ │ │ │ │ ├── matcher.go
│ │ │ │ │ ├── matcher_test.go
│ │ │ │ │ ├── repeated_string_matcher.go
│ │ │ │ │ └── repeated_string_matcher_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ └── utils.go
│ │ │ ├── frontend-gray/
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ ├── gc-test/
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── geo-ip/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── generateCidr/
│ │ │ │ │ ├── ip.merge.txt
│ │ │ │ │ ├── ipRange2Cidr.go
│ │ │ │ │ └── ipRange2Cidr_test.go
│ │ │ │ ├── geoCidr.txt
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── gw-error-format/
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── gw-error-format.yaml
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── hello-world/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── hmac-auth-apisix/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── http-call/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ip-restriction/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ ├── jsonrpc-converter/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── jwt-auth/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── Makefile
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── checker.go
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── parser.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── go.work.sum
│ │ │ │ ├── handler/
│ │ │ │ │ ├── claims.go
│ │ │ │ │ ├── extractor.go
│ │ │ │ │ ├── handler.go
│ │ │ │ │ ├── verify.go
│ │ │ │ │ └── verify_test.go
│ │ │ │ ├── main.go
│ │ │ │ ├── option.yaml
│ │ │ │ └── test/
│ │ │ │ ├── jwt_test.go
│ │ │ │ ├── jwts.json
│ │ │ │ └── keys.json
│ │ │ ├── key-auth/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── keyauth.yaml
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── log-request-response/
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── mcp-router/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── mcp-server/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── model-mapper/
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── model-router/
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── oidc/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── opa/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config.go
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── replay-protection/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ └── utils.go
│ │ │ ├── request-block/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── request-validation/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── response-cache/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── cache/
│ │ │ │ │ ├── provider.go
│ │ │ │ │ └── redis.go
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── core.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── option.yaml
│ │ │ ├── simple-jwt-auth/
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── sni-misdirect/
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── streaming-body-example/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── traffic-editor/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config.go
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── http.go
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── pkg/
│ │ │ │ ├── command.go
│ │ │ │ ├── command_test.go
│ │ │ │ ├── condition.go
│ │ │ │ ├── condition_test.go
│ │ │ │ ├── context.go
│ │ │ │ ├── context_test.go
│ │ │ │ ├── mock_test.go
│ │ │ │ └── ref.go
│ │ │ ├── traffic-tag/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── SampleConfig.yaml
│ │ │ │ ├── VERSION
│ │ │ │ ├── config.yaml
│ │ │ │ ├── content.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── parse.go
│ │ │ │ ├── utils.go
│ │ │ │ └── weight.go
│ │ │ ├── transformer/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ └── waf/
│ │ │ ├── Dockerfile
│ │ │ ├── README.md
│ │ │ ├── README_EN.md
│ │ │ ├── VERSION
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ │ ├── init_tinygo.go
│ │ │ ├── local/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── app.py
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ └── envoy-config.yaml
│ │ │ ├── mage.go
│ │ │ ├── magefiles/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── magefile.go
│ │ │ ├── main.go
│ │ │ └── wasmplugin/
│ │ │ ├── fs.go
│ │ │ ├── logger.go
│ │ │ ├── plugin.go
│ │ │ ├── rules/
│ │ │ │ ├── coraza-demo.conf
│ │ │ │ ├── coraza.conf-recommended.conf
│ │ │ │ ├── crs/
│ │ │ │ │ ├── REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example
│ │ │ │ │ ├── REQUEST-901-INITIALIZATION.conf
│ │ │ │ │ ├── REQUEST-905-COMMON-EXCEPTIONS.conf
│ │ │ │ │ ├── REQUEST-911-METHOD-ENFORCEMENT.conf
│ │ │ │ │ ├── REQUEST-913-SCANNER-DETECTION.conf
│ │ │ │ │ ├── REQUEST-920-PROTOCOL-ENFORCEMENT.conf
│ │ │ │ │ ├── REQUEST-921-PROTOCOL-ATTACK.conf
│ │ │ │ │ ├── REQUEST-922-MULTIPART-ATTACK.conf
│ │ │ │ │ ├── REQUEST-930-APPLICATION-ATTACK-LFI.conf
│ │ │ │ │ ├── REQUEST-931-APPLICATION-ATTACK-RFI.conf
│ │ │ │ │ ├── REQUEST-932-APPLICATION-ATTACK-RCE.conf
│ │ │ │ │ ├── REQUEST-933-APPLICATION-ATTACK-PHP.conf
│ │ │ │ │ ├── REQUEST-934-APPLICATION-ATTACK-GENERIC.conf
│ │ │ │ │ ├── REQUEST-941-APPLICATION-ATTACK-XSS.conf
│ │ │ │ │ ├── REQUEST-942-APPLICATION-ATTACK-SQLI.conf
│ │ │ │ │ ├── REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
│ │ │ │ │ ├── REQUEST-944-APPLICATION-ATTACK-JAVA.conf
│ │ │ │ │ ├── REQUEST-949-BLOCKING-EVALUATION.conf
│ │ │ │ │ ├── RESPONSE-950-DATA-LEAKAGES.conf
│ │ │ │ │ ├── RESPONSE-951-DATA-LEAKAGES-SQL.conf
│ │ │ │ │ ├── RESPONSE-952-DATA-LEAKAGES-JAVA.conf
│ │ │ │ │ ├── RESPONSE-953-DATA-LEAKAGES-PHP.conf
│ │ │ │ │ ├── RESPONSE-954-DATA-LEAKAGES-IIS.conf
│ │ │ │ │ ├── RESPONSE-955-WEB-SHELLS.conf
│ │ │ │ │ ├── RESPONSE-959-BLOCKING-EVALUATION.conf
│ │ │ │ │ ├── RESPONSE-980-CORRELATION.conf
│ │ │ │ │ ├── RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example
│ │ │ │ │ ├── crawlers-user-agents.data
│ │ │ │ │ ├── iis-errors.data
│ │ │ │ │ ├── java-classes.data
│ │ │ │ │ ├── java-code-leakages.data
│ │ │ │ │ ├── java-errors.data
│ │ │ │ │ ├── lfi-os-files.data
│ │ │ │ │ ├── php-config-directives.data
│ │ │ │ │ ├── php-errors-pl2.data
│ │ │ │ │ ├── php-errors.data
│ │ │ │ │ ├── php-function-names-933150.data
│ │ │ │ │ ├── php-function-names-933151.data
│ │ │ │ │ ├── php-variables.data
│ │ │ │ │ ├── restricted-files.data
│ │ │ │ │ ├── restricted-upload.data
│ │ │ │ │ ├── scanners-headers.data
│ │ │ │ │ ├── scanners-urls.data
│ │ │ │ │ ├── scanners-user-agents.data
│ │ │ │ │ ├── scripting-user-agents.data
│ │ │ │ │ ├── sql-errors.data
│ │ │ │ │ ├── ssrf.data
│ │ │ │ │ ├── unix-shell.data
│ │ │ │ │ ├── web-shells-php.data
│ │ │ │ │ └── windows-powershell-commands.data
│ │ │ │ ├── crs-setup-demo.conf
│ │ │ │ ├── crs-setup.conf.example
│ │ │ │ └── ftw-config.conf
│ │ │ └── utils.go
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── mcp-servers/
│ │ │ ├── Dockerfile
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── README_zh.md
│ │ │ ├── amap-tools/
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── tools/
│ │ │ │ ├── load_tools.go
│ │ │ │ ├── maps_around_search.go
│ │ │ │ ├── maps_bicycling.go
│ │ │ │ ├── maps_direction_driving.go
│ │ │ │ ├── maps_direction_transit_integrated.go
│ │ │ │ ├── maps_direction_walking.go
│ │ │ │ ├── maps_distance.go
│ │ │ │ ├── maps_geo.go
│ │ │ │ ├── maps_ip_location.go
│ │ │ │ ├── maps_regeocode.go
│ │ │ │ ├── maps_search_detail.go
│ │ │ │ ├── maps_text_search.go
│ │ │ │ └── maps_weather.go
│ │ │ ├── mcp-agricultural-product-price-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-bid-tools/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-blockscout/
│ │ │ │ ├── README.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-book-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-bravesearch/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-business-credit-rating/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-business-info-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-business-patent-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-calendar-holiday-helper/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-chatppt/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-context7/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-deadbeat-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-document-conversion/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-e2bdev/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-exchange-rate-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-firecrawl/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-fund-data-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-github/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-global-financial-news/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-hackmd/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-heavenly-stems-and-earthly-branches-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-hot-news/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-invoice-verification/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-ip-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-jd-hot-words/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-librechat/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-logistics-tracking-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-national-bid-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-notion/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-oil-price-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-openweather/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-parking-lot-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-plate-quote/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-product-barcode-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-recipe-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-resume-analysis/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-route-planning/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-scripts/
│ │ │ │ ├── create_api_directories.sh
│ │ │ │ ├── mcp-server-docs.md
│ │ │ │ ├── translate_readme.py
│ │ │ │ ├── yaml_to_markdown.py
│ │ │ │ └── yunmarket-tmpl.yaml
│ │ │ ├── mcp-shebao-tools/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── city_data.xls
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-stock-helper/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-stock-history-data/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-taobao-hot-words/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-time/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-today-in-history/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-tourist-attraction-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-traditional-chinese-medicine-tongue-diagnosis/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-train-ticket-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-vehicle-info-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-vehicle-restriction-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-weather-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-wolframalpha/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-yuque/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-zodiac-analysis/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ └── quark-search/
│ │ │ ├── config/
│ │ │ │ └── config.go
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ │ ├── main.go
│ │ │ └── tools/
│ │ │ ├── load_tools.go
│ │ │ ├── web_search.go
│ │ │ └── web_search_test.go
│ │ └── pkg/
│ │ └── mcp/
│ │ ├── consts/
│ │ │ └── vars.go
│ │ ├── filter/
│ │ │ └── plugin.go
│ │ ├── go.mod
│ │ ├── mcp.go
│ │ ├── server/
│ │ │ ├── auth_utils.go
│ │ │ ├── base_server.go
│ │ │ ├── composed_server.go
│ │ │ ├── config_validator_test.go
│ │ │ ├── plugin.go
│ │ │ ├── proxy_auth_test.go
│ │ │ ├── proxy_integration_test.go
│ │ │ ├── proxy_server.go
│ │ │ ├── proxy_server_test.go
│ │ │ ├── proxy_tool.go
│ │ │ ├── proxy_tools_test.go
│ │ │ ├── rest_server.go
│ │ │ ├── rest_server_test.go
│ │ │ ├── sse_proxy.go
│ │ │ └── sse_proxy_test.go
│ │ ├── utils/
│ │ │ ├── json_rpc.go
│ │ │ ├── json_rpc_test.go
│ │ │ ├── log.go
│ │ │ ├── mcp_rpc.go
│ │ │ └── session.go
│ │ └── validator/
│ │ ├── README.md
│ │ ├── config_validator.go
│ │ ├── config_validator_test.go
│ │ └── example_usage.go
│ └── wasm-rust/
│ ├── .dockerignore
│ ├── Cargo.toml
│ ├── Dockerfile
│ ├── DockerfileBuilder
│ ├── Makefile
│ ├── README.md
│ ├── example/
│ │ ├── sse-timing/
│ │ │ ├── Cargo.toml
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── docker-compose.yaml
│ │ │ ├── envoy.yaml
│ │ │ ├── src/
│ │ │ │ └── lib.rs
│ │ │ └── sse-server/
│ │ │ ├── Dockerfile
│ │ │ ├── go.mod
│ │ │ └── main.go
│ │ └── wrapper-say-hello/
│ │ ├── Cargo.toml
│ │ ├── docker-compose.yaml
│ │ ├── envoy.yaml
│ │ └── src/
│ │ └── lib.rs
│ ├── extensions/
│ │ ├── ai-data-masking/
│ │ │ ├── .prebuild
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ ├── README_EN.md
│ │ │ ├── res/
│ │ │ │ └── sensitive_word_dict.txt
│ │ │ ├── src/
│ │ │ │ ├── ai_data_masking.rs
│ │ │ │ ├── deny_word.rs
│ │ │ │ ├── lib.rs
│ │ │ │ ├── msg_win_openai.rs
│ │ │ │ ├── msg_window.rs
│ │ │ │ └── number_merge.rs
│ │ │ └── test/
│ │ │ └── raw_message.txt
│ │ ├── ai-intent/
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ ├── README_EN.md
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── demo-wasm/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── request-block/
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ └── say-hello/
│ │ ├── Cargo.toml
│ │ ├── docker-compose.yaml
│ │ ├── envoy.yaml
│ │ └── src/
│ │ └── lib.rs
│ └── src/
│ ├── cluster_wrapper.rs
│ ├── error.rs
│ ├── event_stream.rs
│ ├── internal.rs
│ ├── lib.rs
│ ├── log.rs
│ ├── plugin_wrapper.rs
│ ├── redis_wrapper.rs
│ ├── request_wrapper.rs
│ └── rule_matcher.rs
├── registry/
│ ├── auth_option.go
│ ├── consul/
│ │ └── watcher.go
│ ├── direct/
│ │ └── watcher.go
│ ├── eureka/
│ │ ├── client/
│ │ │ ├── http_client.go
│ │ │ ├── plan.go
│ │ │ └── struct.go
│ │ └── watcher.go
│ ├── mcp_model.go
│ ├── memory/
│ │ └── cache.go
│ ├── nacos/
│ │ ├── address/
│ │ │ ├── address_discovery.go
│ │ │ └── address_discovery_test.go
│ │ ├── mcpserver/
│ │ │ ├── client.go
│ │ │ ├── client_test.go
│ │ │ ├── watcher.go
│ │ │ └── watcher_test.go
│ │ ├── v2/
│ │ │ ├── watcher.go
│ │ │ └── watcher_test.go
│ │ ├── watcher.go
│ │ └── watcher_test.go
│ ├── proxy/
│ │ └── factory.go
│ ├── reconcile/
│ │ └── reconcile.go
│ ├── watcher.go
│ └── zookeeper/
│ ├── types.go
│ ├── watcher.go
│ └── watcher_test.go
├── release-notes/
│ ├── 2.1.10/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.11/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.4/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.5/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.6/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.7/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.8/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.9/
│ │ ├── README.md
│ │ └── README_ZH.md
│ └── 2.2.0/
│ ├── README.md
│ └── README_ZH.md
├── samples/
│ ├── gateway-api/
│ │ └── demo.yaml
│ ├── hello-world/
│ │ └── quickstart.yaml
│ ├── loadbalance/
│ │ └── useSourceIp-example.yaml
│ ├── nacos-discovery/
│ │ ├── canary.yaml
│ │ ├── multi-destination.yaml
│ │ └── quickstart.yaml
│ ├── quickstart.yaml
│ └── wasmplugin/
│ ├── default-config.yaml
│ ├── ingress-level-config.yaml
│ └── waf.yaml
├── test/
│ ├── README.md
│ ├── README_CN.md
│ ├── e2e/
│ │ ├── conformance/
│ │ │ ├── base/
│ │ │ │ ├── consul.yaml
│ │ │ │ ├── dubbo.yaml
│ │ │ │ ├── eureka.yaml
│ │ │ │ ├── llm-mock.yaml
│ │ │ │ ├── manifests.yaml
│ │ │ │ ├── nacos.yaml
│ │ │ │ └── opa.yaml
│ │ │ ├── embed.go
│ │ │ ├── tests/
│ │ │ │ ├── configmap-global.go
│ │ │ │ ├── configmap-global.yaml
│ │ │ │ ├── configmap-gzip.go
│ │ │ │ ├── configmap-gzip.yaml
│ │ │ │ ├── configmap-https.go
│ │ │ │ ├── configmap-https.yaml
│ │ │ │ ├── configmap-mcp-redis-secret.go
│ │ │ │ ├── configmap-mcp-redis-secret.yaml
│ │ │ │ ├── cpp-wasm-basic-auth.go
│ │ │ │ ├── cpp-wasm-basic-auth.yaml
│ │ │ │ ├── cpp-wasm-key-auth.go
│ │ │ │ ├── cpp-wasm-key-auth.yaml
│ │ │ │ ├── cpp-wasm-request-block.go
│ │ │ │ ├── cpp-wasm-request-block.yaml
│ │ │ │ ├── go-wasm-ai-cache.go
│ │ │ │ ├── go-wasm-ai-cache.yaml
│ │ │ │ ├── go-wasm-ai-proxy.go
│ │ │ │ ├── go-wasm-ai-proxy.yaml
│ │ │ │ ├── go-wasm-basic-auth-template.go
│ │ │ │ ├── go-wasm-basic-auth-template.yaml
│ │ │ │ ├── go-wasm-basic-auth.go
│ │ │ │ ├── go-wasm-basic-auth.yaml
│ │ │ │ ├── go-wasm-bot-detect.go
│ │ │ │ ├── go-wasm-bot-detect.yaml
│ │ │ │ ├── go-wasm-cache-control.go
│ │ │ │ ├── go-wasm-cache-control.yaml
│ │ │ │ ├── go-wasm-custom-response.go
│ │ │ │ ├── go-wasm-custom-response.yaml
│ │ │ │ ├── go-wasm-geo-ip.go
│ │ │ │ ├── go-wasm-geo-ip.yaml
│ │ │ │ ├── go-wasm-ip-restriction-allow.yaml
│ │ │ │ ├── go-wasm-ip-restriction-deny.yaml
│ │ │ │ ├── go-wasm-ip-restriction.go
│ │ │ │ ├── go-wasm-jwt-auth-allow.yaml
│ │ │ │ ├── go-wasm-jwt-auth-deny.yaml
│ │ │ │ ├── go-wasm-jwt-auth-single-consumer.yaml
│ │ │ │ ├── go-wasm-jwt-auth.go
│ │ │ │ ├── go-wasm-key-auth.go
│ │ │ │ ├── go-wasm-key-auth.yaml
│ │ │ │ ├── go-wasm-opa.go
│ │ │ │ ├── go-wasm-opa.yaml
│ │ │ │ ├── go-wasm-replay-protection.go
│ │ │ │ ├── go-wasm-replay-protection.yaml
│ │ │ │ ├── go-wasm-request-block.go
│ │ │ │ ├── go-wasm-request-block.yaml
│ │ │ │ ├── go-wasm-request-validation.go
│ │ │ │ ├── go-wasm-request-validation.yaml
│ │ │ │ ├── go-wasm-simple-jwt-auth.go
│ │ │ │ ├── go-wasm-simple-jwt-auth.yaml
│ │ │ │ ├── go-wasm-sni-misdirect.go
│ │ │ │ ├── go-wasm-sni-misdirect.yaml
│ │ │ │ ├── go-wasm-transformer.go
│ │ │ │ ├── go-wasm-transformer.yaml
│ │ │ │ ├── httproute-app-root.go
│ │ │ │ ├── httproute-app-root.yaml
│ │ │ │ ├── httproute-canary-header-with-customized-header.go
│ │ │ │ ├── httproute-canary-header-with-customized-header.yaml
│ │ │ │ ├── httproute-canary-header.go
│ │ │ │ ├── httproute-canary-header.yaml
│ │ │ │ ├── httproute-canary-weight.go
│ │ │ │ ├── httproute-canary-weight.yaml
│ │ │ │ ├── httproute-consul-httpbin.go
│ │ │ │ ├── httproute-consul-httpbin.yaml
│ │ │ │ ├── httproute-default-backend.go
│ │ │ │ ├── httproute-default-backend.yaml
│ │ │ │ ├── httproute-dns-registry.go
│ │ │ │ ├── httproute-dns-registry.yaml
│ │ │ │ ├── httproute-downstream-encryption.go
│ │ │ │ ├── httproute-downstream-encryption.yaml
│ │ │ │ ├── httproute-enable-cors.go
│ │ │ │ ├── httproute-enable-cors.yaml
│ │ │ │ ├── httproute-enable-ignore-case.go
│ │ │ │ ├── httproute-enable-ignore-case.yaml
│ │ │ │ ├── httproute-eureka-registry.go
│ │ │ │ ├── httproute-eureka-registry.yaml
│ │ │ │ ├── httproute-exact-domain-fallback.go
│ │ │ │ ├── httproute-exact-domain-fallback.yaml
│ │ │ │ ├── httproute-force-redirect-https.go
│ │ │ │ ├── httproute-force-redirect-https.yaml
│ │ │ │ ├── httproute-full-path-regex.go
│ │ │ │ ├── httproute-full-path-regex.yaml
│ │ │ │ ├── httproute-hostname-same-namespace.go
│ │ │ │ ├── httproute-hostname-same-namespace.yaml
│ │ │ │ ├── httproute-http2rpc-0-create.yaml
│ │ │ │ ├── httproute-http2rpc-1-update.yaml
│ │ │ │ ├── httproute-http2rpc.go
│ │ │ │ ├── httproute-https-without-sni.go
│ │ │ │ ├── httproute-https-without-sni.yaml
│ │ │ │ ├── httproute-limit.go
│ │ │ │ ├── httproute-limit.yaml
│ │ │ │ ├── httproute-match-headers.go
│ │ │ │ ├── httproute-match-headers.yaml
│ │ │ │ ├── httproute-match-methods.go
│ │ │ │ ├── httproute-match-methods.yaml
│ │ │ │ ├── httproute-match-path.go
│ │ │ │ ├── httproute-match-path.yaml
│ │ │ │ ├── httproute-match-pseudo-headers.go
│ │ │ │ ├── httproute-match-pseudo-headers.yaml
│ │ │ │ ├── httproute-match-query-params.go
│ │ │ │ ├── httproute-match-query-params.yaml
│ │ │ │ ├── httproute-mirror-target-service.go
│ │ │ │ ├── httproute-mirror-target-service.yaml
│ │ │ │ ├── httproute-permanent-redirect-code.go
│ │ │ │ ├── httproute-permanent-redirect-code.yaml
│ │ │ │ ├── httproute-permanent-redirect.go
│ │ │ │ ├── httproute-permanent-redirect.yaml
│ │ │ │ ├── httproute-redirct-as-https.yaml
│ │ │ │ ├── httproute-redirect-as-https.go
│ │ │ │ ├── httproute-request-header-control.go
│ │ │ │ ├── httproute-request-header-control.yaml
│ │ │ │ ├── httproute-response-header-control.go
│ │ │ │ ├── httproute-response-header-control.yaml
│ │ │ │ ├── httproute-rewrite-host.go
│ │ │ │ ├── httproute-rewrite-host.yaml
│ │ │ │ ├── httproute-rewrite-path.go
│ │ │ │ ├── httproute-rewrite-path.yaml
│ │ │ │ ├── httproute-same-host-and-path.go
│ │ │ │ ├── httproute-same-host-and-path.yaml
│ │ │ │ ├── httproute-simple-same-namespace.go
│ │ │ │ ├── httproute-simple-same-namespace.yaml
│ │ │ │ ├── httproute-static-registry.go
│ │ │ │ ├── httproute-static-registry.yaml
│ │ │ │ ├── httproute-temporal-redirect.go
│ │ │ │ ├── httproute-temporal-redirect.yaml
│ │ │ │ ├── httproute-timeout.go
│ │ │ │ ├── httproute-timeout.yaml
│ │ │ │ ├── httproute-whitelist-source-range.go
│ │ │ │ ├── httproute-whitelist-source-range.yaml
│ │ │ │ ├── ingress-loadbalance-mcp-sse.go
│ │ │ │ ├── ingress-loadbalance-mcp-sse.yaml
│ │ │ │ ├── rust-wasm-ai-data-masking.go
│ │ │ │ ├── rust-wasm-ai-data-masking.yaml
│ │ │ │ ├── rust-wasm-request-block.go
│ │ │ │ ├── rust-wasm-request-block.yaml
│ │ │ │ └── tests.go
│ │ │ └── utils/
│ │ │ ├── cert/
│ │ │ │ └── cert.go
│ │ │ ├── config/
│ │ │ │ └── timeout.go
│ │ │ ├── envoy/
│ │ │ │ ├── envoy.go
│ │ │ │ └── envoy_test.go
│ │ │ ├── flags/
│ │ │ │ └── flags.go
│ │ │ ├── http/
│ │ │ │ ├── http.go
│ │ │ │ └── http_test.go
│ │ │ ├── kubernetes/
│ │ │ │ ├── apply.go
│ │ │ │ ├── apply_test.go
│ │ │ │ ├── cert.go
│ │ │ │ └── helpers.go
│ │ │ ├── roundtripper/
│ │ │ │ ├── roundtripper.go
│ │ │ │ └── roundtripper_test.go
│ │ │ └── suite/
│ │ │ ├── features.go
│ │ │ └── suite.go
│ │ └── e2e_test.go
│ └── gateway/
│ ├── e2e.go
│ └── e2e_test.go
└── tools/
├── hack/
│ ├── build-envoy.patch
│ ├── build-envoy.sh
│ ├── build-golang-filters.sh
│ ├── build-istio-image.sh
│ ├── build-istio-pilot.sh
│ ├── build-wasm-plugins.sh
│ ├── create-cluster.sh
│ ├── docker-pull-image.sh
│ ├── get-hgctl.sh
│ ├── gobuild.sh
│ ├── kind-load-image.sh
│ ├── prebuild.sh
│ ├── report_build_info.sh
│ ├── run.sh
│ ├── setup-istio-env.sh
│ └── setup_env.sh
├── lint.mk
├── linter/
│ ├── codespell/
│ │ ├── .codespell.ignorewords
│ │ ├── .codespell.skip
│ │ └── matcher.json
│ ├── golangci-lint/
│ │ └── .golangci.yml
│ └── yamllint/
│ └── .yamllint
├── src/
│ ├── codespell/
│ │ └── requirements.txt
│ ├── controller-gen/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ ├── golangci-lint/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ ├── kind/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ ├── kustomize/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ ├── setup-envtest/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ └── yamllint/
│ └── requirements.txt
└── tools.mk
================================================
FILE CONTENTS
================================================
================================================
FILE: .claude/skills/agent-session-monitor/QUICKSTART.md
================================================
# Agent Session Monitor - Quick Start
实时Agent对话观测程序,用于监控Higress访问日志,追踪多轮对话的token开销和模型使用情况。
## 快速开始
### 1. 运行Demo
```bash
cd example
bash demo.sh
```
这将:
- 解析示例日志文件
- 列出所有session
- 显示session详细信息(包括完整的messages、question、answer、reasoning、tool_calls)
- 按模型和日期统计token开销
- 导出FinOps报表
### 2. 启动Web界面(推荐)
```bash
# 先解析日志生成session数据
python3 main.py --log-path /var/log/higress/access.log --output-dir ./sessions
# 启动Web服务器
python3 scripts/webserver.py --data-dir ./sessions --port 8888
# 浏览器访问
open http://localhost:8888
```
Web界面功能:
- 📊 总览所有session,按模型分组统计
- 🔍 点击session ID下钻查看完整对话
- 💬 查看每轮的messages、question、answer、reasoning、tool_calls
- 💰 实时计算token开销和成本
- 🔄 每30秒自动刷新
### 3. 在Clawdbot对话中使用
当用户询问当前会话token消耗时,生成观测链接:
```
你的当前会话ID: agent:main:discord:channel:1465367993012981988
查看详情:http://localhost:8888/session?id=agent:main:discord:channel:1465367993012981988
点击可以看到:
✅ 完整对话历史(每轮messages)
✅ Token消耗明细
✅ 工具调用记录
✅ 成本统计
```
### 4. 使用CLI查询(可选)
```bash
# 查看session详细信息
python3 scripts/cli.py show <session-id>
# 列出所有session
python3 scripts/cli.py list
# 按模型统计
python3 scripts/cli.py stats-model
# 导出报表
python3 scripts/cli.py export finops-report.json
```
## 核心功能
✅ **完整对话追踪**:记录每轮对话的完整messages、question、answer、reasoning、tool_calls
✅ **Token开销统计**:区分input/output/reasoning/cached token,实时计算成本
✅ **Session聚合**:按session_id关联多轮对话
✅ **Web可视化界面**:浏览器访问,总览+下钻查看session详情
✅ **实时URL生成**:Clawdbot可根据当前会话ID生成观测链接
✅ **FinOps报表**:导出JSON/CSV格式的成本分析报告
## 日志格式要求
Higress访问日志需要包含ai_log字段(JSON格式),示例:
```json
{
"__file_offset__": "1000",
"timestamp": "2026-02-01T09:30:15Z",
"ai_log": "{\"session_id\":\"sess_abc\",\"messages\":[...],\"question\":\"...\",\"answer\":\"...\",\"input_token\":250,\"output_token\":160,\"model\":\"Qwen3-rerank\"}"
}
```
ai_log字段支持的属性:
- `session_id`: 会话标识(必需)
- `messages`: 完整对话历史
- `question`: 当前轮次问题
- `answer`: AI回答
- `reasoning`: 思考过程(DeepSeek等模型)
- `tool_calls`: 工具调用列表
- `input_token`: 输入token数
- `output_token`: 输出token数
- `model`: 模型名称
- `response_type`: 响应类型
## 输出目录结构
```
sessions/
├── agent:main:discord:1465367993012981988.json
└── agent:test:discord:9999999999999999999.json
```
每个session文件包含:
- 基本信息(创建时间、更新时间、模型)
- Token统计(总输入、总输出、总reasoning、总cached)
- 对话轮次列表(每轮的完整messages、question、answer、reasoning、tool_calls)
## 常见问题
**Q: 如何在Higress中配置session_id header?**
A: 在ai-statistics插件中配置`session_id_header`,或使用默认header(x-openclaw-session-key、x-clawdbot-session-key等)。详见PR #3420。
**Q: 支持哪些模型的pricing?**
A: 目前支持Qwen、DeepSeek、GPT-4、Claude等主流模型。可以在main.py的TOKEN_PRICING字典中添加新模型。
**Q: 如何实时监控日志文件变化?**
A: 直接运行main.py即可,程序使用定时轮询机制(每秒自动检查一次),无需安装额外依赖。
**Q: CLI查询速度慢?**
A: 大量session时,可以使用`--limit`限制结果数量,或按条件过滤(如`--sort-by cost`只查看成本最高的session)。
## 下一步
- 集成到Higress FinOps Dashboard
- 支持更多模型的pricing
- 添加趋势预测和异常检测
- 支持多数据源聚合分析
================================================
FILE: .claude/skills/agent-session-monitor/README.md
================================================
# Agent Session Monitor
Real-time agent conversation monitoring for Clawdbot, designed to monitor Higress access logs and track token usage across multi-turn conversations.
## Features
- 🔍 **Complete Conversation Tracking**: Records messages, question, answer, reasoning, tool_calls for each turn
- 💰 **Token Usage Statistics**: Distinguishes input/output/reasoning/cached tokens, calculates costs in real-time
- 🌐 **Web Visualization**: Browser-based UI with overview and drill-down into session details
- 🔗 **Real-time URL Generation**: Clawdbot can generate observation links based on current session ID
- 🔄 **Log Rotation Support**: Automatically handles rotated log files (access.log, access.log.1, etc.)
- 📊 **FinOps Reporting**: Export usage data in JSON/CSV formats
## Quick Start
### 1. Run Demo
```bash
cd example
bash demo.sh
```
### 2. Start Web UI
```bash
# Parse logs
python3 main.py --log-path /var/log/higress/access.log --output-dir ./sessions
# Start web server
python3 scripts/webserver.py --data-dir ./sessions --port 8888
# Access in browser
open http://localhost:8888
```
### 3. Use in Clawdbot
When users ask "How many tokens did this conversation use?", you can respond with:
```
Your current session statistics:
- Session ID: agent:main:discord:channel:1465367993012981988
- View details: http://localhost:8888/session?id=agent:main:discord:channel:1465367993012981988
Click to see:
✅ Complete conversation history
✅ Token usage breakdown per turn
✅ Tool call records
✅ Cost statistics
```
## Files
- `main.py`: Background monitor, parses Higress access logs
- `scripts/webserver.py`: Web server, provides browser-based UI
- `scripts/cli.py`: Command-line tools for queries and exports
- `example/`: Demo examples and test data
## Dependencies
- Python 3.8+
- No external dependencies (uses only standard library)
## Documentation
- `SKILL.md`: Main skill documentation
- `QUICKSTART.md`: Quick start guide
## License
MIT
================================================
FILE: .claude/skills/agent-session-monitor/SKILL.md
================================================
---
name: agent-session-monitor
description: Real-time agent conversation monitoring - monitors Higress access logs, aggregates conversations by session, tracks token usage. Supports web interface for viewing complete conversation history and costs. Use when users ask about current session token consumption, conversation history, or cost statistics.
---
## Overview
Real-time monitoring of Higress access logs, extracting ai_log JSON, grouping multi-turn conversations by session_id, and calculating token costs with visualization.
### Core Features
- **Real-time Log Monitoring**: Monitors Higress access log files, parses new ai_log entries in real-time
- **Log Rotation Support**: Full logrotate support, automatically tracks access.log.1~5 etc.
- **Incremental Parsing**: Inode-based tracking, processes only new content, no duplicates
- **Session Grouping**: Associates multi-turn conversations by session_id (each turn is a separate request)
- **Complete Conversation Tracking**: Records messages, question, answer, reasoning, tool_calls for each turn
- **Token Usage Tracking**: Distinguishes input/output/reasoning/cached tokens
- **Web Visualization**: Browser-based UI with overview and session drill-down
- **Real-time URL Generation**: Clawdbot can generate observation links based on current session ID
- **Background Processing**: Independent process, continuously parses access logs
- **State Persistence**: Maintains parsing progress and session data across runs
## Usage
### 1. Background Monitoring (Continuous)
```bash
# Parse Higress access logs (with log rotation support)
python3 main.py --log-path /var/log/proxy/access.log --output-dir ./sessions
# Filter by session key
python3 main.py --log-path /var/log/proxy/access.log --session-key <session-id>
# Scheduled task (incremental parsing every minute)
* * * * * python3 /path/to/main.py --log-path /var/log/proxy/access.log --output-dir /var/lib/sessions
```
### 2. Start Web UI (Recommended)
```bash
# Start web server
python3 scripts/webserver.py --data-dir ./sessions --port 8888
# Access in browser
open http://localhost:8888
```
Web UI features:
- 📊 Overview: View all session statistics and group by model
- 🔍 Session Details: Click session ID to drill down into complete conversation history
- 💬 Conversation Log: Display messages, question, answer, reasoning, tool_calls for each turn
- 💰 Cost Statistics: Real-time token usage and cost calculation
- 🔄 Auto Refresh: Updates every 30 seconds
### 3. Use in Clawdbot Conversations
When users ask about current session token consumption or conversation history:
1. Get current session_id (from runtime or context)
2. Generate web UI URL and return to user
Example response:
```
Your current session statistics:
- Session ID: agent:main:discord:channel:1465367993012981988
- View details: http://localhost:8888/session?id=agent:main:discord:channel:1465367993012981988
Click the link to see:
✅ Complete conversation history
✅ Token usage breakdown per turn
✅ Tool call records
✅ Cost statistics
```
### 4. CLI Queries (Optional)
```bash
# View specific session details
python3 scripts/cli.py show <session-id>
# List all sessions
python3 scripts/cli.py list --sort-by cost --limit 10
# Statistics by model
python3 scripts/cli.py stats-model
# Statistics by date (last 7 days)
python3 scripts/cli.py stats-date --days 7
# Export reports
python3 scripts/cli.py export finops-report.json
```
## Configuration
### main.py (Background Monitor)
| Parameter | Description | Required | Default |
|-----------|-------------|----------|---------|
| `--log-path` | Higress access log file path | Yes | /var/log/higress/access.log |
| `--output-dir` | Session data storage directory | No | ./sessions |
| `--session-key` | Monitor only specified session key | No | Monitor all sessions |
| `--state-file` | State file path (records read offsets) | No | <output-dir>/.state.json |
| `--refresh-interval` | Log refresh interval (seconds) | No | 1 |
### webserver.py (Web UI)
| Parameter | Description | Required | Default |
|-----------|-------------|----------|---------|
| `--data-dir` | Session data directory | No | ./sessions |
| `--port` | HTTP server port | No | 8888 |
| `--host` | HTTP server address | No | 0.0.0.0 |
## Output Examples
### 1. Real-time Monitor
```
🔍 Session Monitor - Active
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 Active Sessions: 3
┌──────────────────────────┬─────────┬──────────┬───────────┐
│ Session ID │ Msgs │ Input │ Output │
├──────────────────────────┼─────────┼──────────┼───────────┤
│ sess_abc123 │ 5 │ 1,250 │ 800 │
│ sess_xyz789 │ 3 │ 890 │ 650 │
│ sess_def456 │ 8 │ 2,100 │ 1,200 │
└──────────────────────────┴─────────┴──────────┴───────────┘
📈 Token Statistics
Total Input: 4240 tokens
Total Output: 2650 tokens
Total Cached: 0 tokens
Total Cost: $0.00127
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
### 2. CLI Session Details
```bash
$ python3 scripts/cli.py show agent:main:discord:channel:1465367993012981988
======================================================================
📊 Session Detail: agent:main:discord:channel:1465367993012981988
======================================================================
🕐 Created: 2026-02-01T09:30:00+08:00
🕑 Updated: 2026-02-01T10:35:12+08:00
🤖 Model: Qwen3-rerank
💬 Messages: 5
📈 Token Statistics:
Input: 1,250 tokens
Output: 800 tokens
Reasoning: 150 tokens
Total: 2,200 tokens
💰 Estimated Cost: $0.00126000 USD
📝 Conversation Rounds (5):
──────────────────────────────────────────────────────────────────────
Round 1 @ 2026-02-01T09:30:15+08:00
Tokens: 250 in → 160 out
🔧 Tool calls: Yes
Messages (2):
[user] Check Beijing weather
❓ Question: Check Beijing weather
✅ Answer: Checking Beijing weather for you...
🧠 Reasoning: User wants to know Beijing weather, I need to call weather API.
🛠️ Tool Calls:
- get_weather({"location":"Beijing"})
```
### 3. Statistics by Model
```bash
$ python3 scripts/cli.py stats-model
================================================================================
📊 Statistics by Model
================================================================================
Model Sessions Input Output Cost (USD)
────────────────────────────────────────────────────────────────────────────
Qwen3-rerank 12 15,230 9,840 $ 0.016800
DeepSeek-R1 5 8,450 6,200 $ 0.010600
Qwen-Max 3 4,200 3,100 $ 0.008300
GPT-4 2 2,100 1,800 $ 0.017100
────────────────────────────────────────────────────────────────────────────
TOTAL 22 29,980 20,940 $ 0.052800
================================================================================
```
### 4. Statistics by Date
```bash
$ python3 scripts/cli.py stats-date --days 7
================================================================================
📊 Statistics by Date (Last 7 days)
================================================================================
Date Sessions Input Output Cost (USD) Models
────────────────────────────────────────────────────────────────────────────
2026-01-26 3 2,100 1,450 $ 0.0042 Qwen3-rerank
2026-01-27 5 4,850 3,200 $ 0.0096 Qwen3-rerank, GPT-4
2026-01-28 4 3,600 2,800 $ 0.0078 DeepSeek-R1, Qwen
────────────────────────────────────────────────────────────────────────────
TOTAL 22 29,980 20,940 $ 0.0528
================================================================================
```
### 5. Web UI (Recommended)
Access `http://localhost:8888` to see:
**Home Page:**
- 📊 Total sessions, token consumption, cost cards
- 📋 Recent sessions list (clickable for details)
- 📈 Statistics by model table
**Session Detail Page:**
- 💬 Complete conversation log (messages, question, answer, reasoning, tool_calls per turn)
- 🔧 Tool call history
- 💰 Token usage breakdown and costs
**Features:**
- 🔄 Auto-refresh every 30 seconds
- 📱 Responsive design, mobile-friendly
- 🎨 Clean UI, easy to read
## Session Data Structure
Each session is stored as an independent JSON file with complete conversation history and token statistics:
```json
{
"session_id": "agent:main:discord:channel:1465367993012981988",
"created_at": "2026-02-01T10:30:00Z",
"updated_at": "2026-02-01T10:35:12Z",
"messages_count": 5,
"total_input_tokens": 1250,
"total_output_tokens": 800,
"total_reasoning_tokens": 150,
"total_cached_tokens": 0,
"model": "Qwen3-rerank",
"rounds": [
{
"round": 1,
"timestamp": "2026-02-01T10:30:15Z",
"input_tokens": 250,
"output_tokens": 160,
"reasoning_tokens": 0,
"cached_tokens": 0,
"model": "Qwen3-rerank",
"has_tool_calls": true,
"response_type": "normal",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant..."
},
{
"role": "user",
"content": "Check Beijing weather"
}
],
"question": "Check Beijing weather",
"answer": "Checking Beijing weather for you...",
"reasoning": "User wants to know Beijing weather, need to call weather API.",
"tool_calls": [
{
"index": 0,
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\":\"Beijing\"}"
}
}
],
"input_token_details": {"cached_tokens": 0},
"output_token_details": {}
}
]
}
```
### Field Descriptions
**Session Level:**
- `session_id`: Unique session identifier (from ai_log's session_id field)
- `created_at`: Session creation time
- `updated_at`: Last update time
- `messages_count`: Number of conversation turns
- `total_input_tokens`: Cumulative input tokens
- `total_output_tokens`: Cumulative output tokens
- `total_reasoning_tokens`: Cumulative reasoning tokens (DeepSeek, o1, etc.)
- `total_cached_tokens`: Cumulative cached tokens (prompt caching)
- `model`: Current model in use
**Round Level (rounds):**
- `round`: Turn number
- `timestamp`: Current turn timestamp
- `input_tokens`: Input tokens for this turn
- `output_tokens`: Output tokens for this turn
- `reasoning_tokens`: Reasoning tokens (o1, etc.)
- `cached_tokens`: Cached tokens (prompt caching)
- `model`: Model used for this turn
- `has_tool_calls`: Whether includes tool calls
- `response_type`: Response type (normal/error, etc.)
- `messages`: Complete conversation history (OpenAI messages format)
- `question`: User's question for this turn (last user message)
- `answer`: AI's answer for this turn
- `reasoning`: AI's thinking process (if model supports)
- `tool_calls`: Tool call list (if any)
- `input_token_details`: Complete input token details (JSON)
- `output_token_details`: Complete output token details (JSON)
## Log Format Requirements
Higress access logs must include ai_log field (JSON format). Example:
```json
{
"__file_offset__": "1000",
"timestamp": "2026-02-01T09:30:15Z",
"ai_log": "{\"session_id\":\"sess_abc\",\"messages\":[...],\"question\":\"...\",\"answer\":\"...\",\"input_token\":250,\"output_token\":160,\"model\":\"Qwen3-rerank\"}"
}
```
Supported ai_log attributes:
- `session_id`: Session identifier (required)
- `messages`: Complete conversation history
- `question`: Question for current turn
- `answer`: AI answer
- `reasoning`: Thinking process (DeepSeek, o1, etc.)
- `reasoning_tokens`: Reasoning token count (from PR #3424)
- `cached_tokens`: Cached token count (from PR #3424)
- `tool_calls`: Tool call list
- `input_token`: Input token count
- `output_token`: Output token count
- `input_token_details`: Complete input token details (JSON)
- `output_token_details`: Complete output token details (JSON)
- `model`: Model name
- `response_type`: Response type
## Implementation
### Technology Stack
- **Log Parsing**: Direct JSON parsing, no regex needed
- **File Monitoring**: Polling-based (no watchdog dependency)
- **Session Management**: In-memory + disk hybrid storage
- **Token Calculation**: Model-specific pricing for GPT-4, Qwen, Claude, o1, etc.
### Privacy and Security
- ✅ Does not record conversation content in logs, only token statistics
- ✅ Session data stored locally, not uploaded to external services
- ✅ Supports log file path allowlist
- ✅ Session key access control
### Performance Optimization
- Incremental log parsing, avoids full scans
- In-memory session data with periodic persistence
- Optimized log file reading (offset tracking)
- Inode-based file identification (handles rotation efficiently)
================================================
FILE: .claude/skills/agent-session-monitor/example/clawdbot_demo.py
================================================
#!/usr/bin/env python3
"""
演示如何在Clawdbot中生成Session观测URL
"""
from urllib.parse import quote
def generate_session_url(session_id: str, base_url: str = "http://localhost:8888") -> dict:
"""
生成session观测URL
Args:
session_id: 当前会话的session ID
base_url: Web服务器基础URL
Returns:
包含各种URL的字典
"""
# URL编码session_id(处理特殊字符)
encoded_id = quote(session_id, safe='')
return {
"session_detail": f"{base_url}/session?id={encoded_id}",
"api_session": f"{base_url}/api/session?id={encoded_id}",
"index": f"{base_url}/",
"api_sessions": f"{base_url}/api/sessions",
"api_stats": f"{base_url}/api/stats",
}
def format_response_message(session_id: str, base_url: str = "http://localhost:8888") -> str:
"""
生成给用户的回复消息
Args:
session_id: 当前会话的session ID
base_url: Web服务器基础URL
Returns:
格式化的回复消息
"""
urls = generate_session_url(session_id, base_url)
return f"""你的当前会话信息:
📊 **Session ID**: `{session_id}`
🔗 **查看详情**: {urls['session_detail']}
点击链接可以看到:
✅ 完整对话历史(每轮messages)
✅ Token消耗明细(input/output/reasoning)
✅ 工具调用记录
✅ 实时成本统计
**更多链接:**
- 📋 所有会话: {urls['index']}
- 📥 API数据: {urls['api_session']}
- 📊 总体统计: {urls['api_stats']}
"""
# 示例使用
if __name__ == '__main__':
# 模拟clawdbot的session ID
demo_session_id = "agent:main:discord:channel:1465367993012981988"
print("=" * 70)
print("🤖 Clawdbot Session Monitor Demo")
print("=" * 70)
print()
# 生成URL
urls = generate_session_url(demo_session_id)
print("生成的URL:")
print(f" Session详情: {urls['session_detail']}")
print(f" API数据: {urls['api_session']}")
print(f" 总览页面: {urls['index']}")
print()
# 生成回复消息
message = format_response_message(demo_session_id)
print("回复消息模板:")
print("-" * 70)
print(message)
print("-" * 70)
print()
print("✅ 在Clawdbot中,你可以直接返回上面的消息给用户")
print()
# 测试特殊字符的session ID
special_session_id = "agent:test:session/with?special&chars"
special_urls = generate_session_url(special_session_id)
print("特殊字符处理示例:")
print(f" 原始ID: {special_session_id}")
print(f" URL: {special_urls['session_detail']}")
print()
================================================
FILE: .claude/skills/agent-session-monitor/example/demo.sh
================================================
#!/bin/bash
# Agent Session Monitor - 演示脚本
set -e
SKILL_DIR="$(dirname "$(dirname "$(realpath "$0")")")"
EXAMPLE_DIR="$SKILL_DIR/example"
LOG_FILE="$EXAMPLE_DIR/test_access.log"
OUTPUT_DIR="$EXAMPLE_DIR/sessions"
echo "========================================"
echo "Agent Session Monitor - Demo"
echo "========================================"
echo ""
# 清理旧数据
if [ -d "$OUTPUT_DIR" ]; then
echo "🧹 Cleaning up old session data..."
rm -rf "$OUTPUT_DIR"
fi
echo "📂 Log file: $LOG_FILE"
echo "📁 Output dir: $OUTPUT_DIR"
echo ""
# 步骤1:解析日志文件(单次模式)
echo "========================================"
echo "步骤1:解析日志文件"
echo "========================================"
python3 "$SKILL_DIR/main.py" \
--log-path "$LOG_FILE" \
--output-dir "$OUTPUT_DIR"
echo ""
echo "✅ 日志解析完成!Session数据已保存到: $OUTPUT_DIR"
echo ""
# 步骤2:列出所有session
echo "========================================"
echo "步骤2:列出所有session"
echo "========================================"
python3 "$SKILL_DIR/scripts/cli.py" list \
--data-dir "$OUTPUT_DIR" \
--limit 10
# 步骤3:查看第一个session的详细信息
echo "========================================"
echo "步骤3:查看session详细信息"
echo "========================================"
FIRST_SESSION=$(ls -1 "$OUTPUT_DIR"/*.json | head -1 | xargs -I {} basename {} .json)
python3 "$SKILL_DIR/scripts/cli.py" show "$FIRST_SESSION" \
--data-dir "$OUTPUT_DIR"
# 步骤4:按模型统计
echo "========================================"
echo "步骤4:按模型统计token开销"
echo "========================================"
python3 "$SKILL_DIR/scripts/cli.py" stats-model \
--data-dir "$OUTPUT_DIR"
# 步骤5:按日期统计
echo "========================================"
echo "步骤5:按日期统计token开销"
echo "========================================"
python3 "$SKILL_DIR/scripts/cli.py" stats-date \
--data-dir "$OUTPUT_DIR" \
--days 7
# 步骤6:导出FinOps报表
echo "========================================"
echo "步骤6:导出FinOps报表"
echo "========================================"
python3 "$SKILL_DIR/scripts/cli.py" export "$EXAMPLE_DIR/finops-report.json" \
--data-dir "$OUTPUT_DIR" \
--format json
echo ""
echo "✅ 报表已导出到: $EXAMPLE_DIR/finops-report.json"
echo ""
# 显示报表内容
if [ -f "$EXAMPLE_DIR/finops-report.json" ]; then
echo "📊 FinOps报表内容:"
echo "========================================"
cat "$EXAMPLE_DIR/finops-report.json" | python3 -m json.tool | head -50
echo "..."
fi
echo ""
echo "========================================"
echo "✅ Demo完成!"
echo "========================================"
echo ""
echo "💡 提示:"
echo " - Session数据保存在: $OUTPUT_DIR/"
echo " - FinOps报表: $EXAMPLE_DIR/finops-report.json"
echo " - 使用 'python3 scripts/cli.py --help' 查看更多命令"
echo ""
echo "🌐 启动Web界面查看:"
echo " python3 $SKILL_DIR/scripts/webserver.py --data-dir $OUTPUT_DIR --port 8888"
echo " 然后访问: http://localhost:8888"
================================================
FILE: .claude/skills/agent-session-monitor/example/demo_v2.sh
================================================
#!/bin/bash
# Agent Session Monitor - Demo for PR #3424 token details
set -e
SKILL_DIR="$(dirname "$(dirname "$(realpath "$0")")")"
EXAMPLE_DIR="$SKILL_DIR/example"
LOG_FILE="$EXAMPLE_DIR/test_access_v2.log"
OUTPUT_DIR="$EXAMPLE_DIR/sessions_v2"
echo "========================================"
echo "Agent Session Monitor - Token Details Demo"
echo "========================================"
echo ""
# 清理旧数据
if [ -d "$OUTPUT_DIR" ]; then
echo "🧹 Cleaning up old session data..."
rm -rf "$OUTPUT_DIR"
fi
echo "📂 Log file: $LOG_FILE"
echo "📁 Output dir: $OUTPUT_DIR"
echo ""
# 步骤1:解析日志文件
echo "========================================"
echo "步骤1:解析日志文件(包含token details)"
echo "========================================"
python3 "$SKILL_DIR/main.py" \
--log-path "$LOG_FILE" \
--output-dir "$OUTPUT_DIR"
echo ""
echo "✅ 日志解析完成!Session数据已保存到: $OUTPUT_DIR"
echo ""
# 步骤2:查看使用prompt caching的session(gpt-4o)
echo "========================================"
echo "步骤2:查看GPT-4o session(包含cached tokens)"
echo "========================================"
python3 "$SKILL_DIR/scripts/cli.py" show "agent:main:discord:1465367993012981988" \
--data-dir "$OUTPUT_DIR"
# 步骤3:查看使用reasoning的session(o1)
echo "========================================"
echo "步骤3:查看o1 session(包含reasoning tokens)"
echo "========================================"
python3 "$SKILL_DIR/scripts/cli.py" show "agent:main:discord:9999999999999999999" \
--data-dir "$OUTPUT_DIR"
# 步骤4:按模型统计
echo "========================================"
echo "步骤4:按模型统计(包含新token类型)"
echo "========================================"
python3 "$SKILL_DIR/scripts/cli.py" stats-model \
--data-dir "$OUTPUT_DIR"
echo ""
echo "========================================"
echo "✅ Demo完成!"
echo "========================================"
echo ""
echo "💡 新功能说明:"
echo " ✅ cached_tokens - 缓存命中的token数(prompt caching)"
echo " ✅ reasoning_tokens - 推理token数(o1等模型)"
echo " ✅ input_token_details - 完整输入token详情(JSON)"
echo " ✅ output_token_details - 完整输出token详情(JSON)"
echo ""
echo "💰 成本计算已优化:"
echo " - cached tokens通常比regular input便宜(50-90%折扣)"
echo " - reasoning tokens单独计费(o1系列)"
echo ""
echo "🌐 启动Web界面查看:"
echo " python3 $SKILL_DIR/scripts/webserver.py --data-dir $OUTPUT_DIR --port 8889"
echo " 然后访问: http://localhost:8889"
================================================
FILE: .claude/skills/agent-session-monitor/example/test_access.log
================================================
{"__file_offset__":"1000","timestamp":"2026-02-01T09:30:15Z","ai_log":"{\"session_id\":\"agent:main:discord:1465367993012981988\",\"api\":\"Qwen3-rerank@higress\",\"api_type\":\"LLM\",\"chat_round\":1,\"consumer\":\"clawdbot\",\"input_token\":250,\"output_token\":160,\"model\":\"Qwen3-rerank\",\"response_type\":\"normal\",\"total_token\":410,\"messages\":[{\"role\":\"system\",\"content\":\"You are a helpful assistant.\"},{\"role\":\"user\",\"content\":\"查询北京天气\"}],\"question\":\"查询北京天气\",\"answer\":\"正在为您查询北京天气...\",\"reasoning\":\"用户想知道北京的天气,我需要调用天气查询工具。\",\"tool_calls\":[{\"index\":0,\"id\":\"call_abc123\",\"type\":\"function\",\"function\":{\"name\":\"get_weather\",\"arguments\":\"{\\\"location\\\":\\\"Beijing\\\"}\"}}]}"}
{"__file_offset__":"2000","timestamp":"2026-02-01T09:32:00Z","ai_log":"{\"session_id\":\"agent:main:discord:1465367993012981988\",\"api\":\"Qwen3-rerank@higress\",\"api_type\":\"LLM\",\"chat_round\":2,\"consumer\":\"clawdbot\",\"input_token\":320,\"output_token\":180,\"model\":\"Qwen3-rerank\",\"response_type\":\"normal\",\"total_token\":500,\"messages\":[{\"role\":\"tool\",\"content\":\"{\\\"temperature\\\": 15, \\\"weather\\\": \\\"晴\\\"}\"}],\"question\":\"\",\"answer\":\"北京今天天气晴朗,温度15°C。\",\"reasoning\":\"\",\"tool_calls\":[]}"}
{"__file_offset__":"3000","timestamp":"2026-02-01T09:35:12Z","ai_log":"{\"session_id\":\"agent:main:discord:1465367993012981988\",\"api\":\"Qwen3-rerank@higress\",\"api_type\":\"LLM\",\"chat_round\":3,\"consumer\":\"clawdbot\",\"input_token\":380,\"output_token\":220,\"model\":\"Qwen3-rerank\",\"response_type\":\"normal\",\"total_token\":600,\"messages\":[{\"role\":\"user\",\"content\":\"谢谢!\"},{\"role\":\"assistant\",\"content\":\"不客气!如果还有其他问题,随时问我。\"}],\"question\":\"谢谢!\",\"answer\":\"不客气!如果还有其他问题,随时问我。\",\"reasoning\":\"\",\"tool_calls\":[]}"}
{"__file_offset__":"4000","timestamp":"2026-02-01T10:00:00Z","ai_log":"{\"session_id\":\"agent:test:discord:9999999999999999999\",\"api\":\"DeepSeek-R1@higress\",\"api_type\":\"LLM\",\"chat_round\":1,\"consumer\":\"clawdbot\",\"input_token\":50,\"output_token\":30,\"model\":\"DeepSeek-R1\",\"response_type\":\"normal\",\"total_token\":80,\"messages\":[{\"role\":\"user\",\"content\":\"计算2+2\"}],\"question\":\"计算2+2\",\"answer\":\"4\",\"reasoning\":\"这是一个简单的加法运算,2加2等于4。\",\"tool_calls\":[]}"}
================================================
FILE: .claude/skills/agent-session-monitor/example/test_access_v2.log
================================================
{"__file_offset__":"1000","timestamp":"2026-02-01T10:00:00Z","ai_log":"{\"session_id\":\"agent:main:discord:1465367993012981988\",\"api\":\"gpt-4o\",\"api_type\":\"LLM\",\"chat_round\":1,\"consumer\":\"clawdbot\",\"input_token\":150,\"output_token\":100,\"reasoning_tokens\":0,\"cached_tokens\":120,\"input_token_details\":\"{\\\"cached_tokens\\\":120}\",\"output_token_details\":\"{}\",\"model\":\"gpt-4o\",\"response_type\":\"normal\",\"total_token\":250,\"messages\":[{\"role\":\"system\",\"content\":\"You are a helpful assistant.\"},{\"role\":\"user\",\"content\":\"你好\"}],\"question\":\"你好\",\"answer\":\"你好!有什么我可以帮助你的吗?\",\"reasoning\":\"\",\"tool_calls\":[]}"}
{"__file_offset__":"2000","timestamp":"2026-02-01T10:01:00Z","ai_log":"{\"session_id\":\"agent:main:discord:1465367993012981988\",\"api\":\"gpt-4o\",\"api_type\":\"LLM\",\"chat_round\":2,\"consumer\":\"clawdbot\",\"input_token\":200,\"output_token\":150,\"reasoning_tokens\":0,\"cached_tokens\":80,\"input_token_details\":\"{\\\"cached_tokens\\\":80}\",\"output_token_details\":\"{}\",\"model\":\"gpt-4o\",\"response_type\":\"normal\",\"total_token\":350,\"messages\":[{\"role\":\"user\",\"content\":\"介绍一下你的能力\"}],\"question\":\"介绍一下你的能力\",\"answer\":\"我可以帮助你回答问题、写作、编程等...\",\"reasoning\":\"\",\"tool_calls\":[]}"}
{"__file_offset__":"3000","timestamp":"2026-02-01T10:02:00Z","ai_log":"{\"session_id\":\"agent:main:discord:9999999999999999999\",\"api\":\"o1\",\"api_type\":\"LLM\",\"chat_round\":1,\"consumer\":\"clawdbot\",\"input_token\":100,\"output_token\":80,\"reasoning_tokens\":500,\"cached_tokens\":0,\"input_token_details\":\"{}\",\"output_token_details\":\"{\\\"reasoning_tokens\\\":500}\",\"model\":\"o1\",\"response_type\":\"normal\",\"total_token\":580,\"messages\":[{\"role\":\"user\",\"content\":\"解释量子纠缠\"}],\"question\":\"解释量子纠缠\",\"answer\":\"量子纠缠是量子力学中的一种现象...\",\"reasoning\":\"这是一个复杂的物理概念,我需要仔细思考如何用简单的方式解释...\",\"tool_calls\":[]}"}
{"__file_offset__":"4000","timestamp":"2026-02-01T10:03:00Z","ai_log":"{\"session_id\":\"agent:main:discord:1465367993012981988\",\"api\":\"gpt-4o\",\"api_type\":\"LLM\",\"chat_round\":3,\"consumer\":\"clawdbot\",\"input_token\":300,\"output_token\":200,\"reasoning_tokens\":0,\"cached_tokens\":200,\"input_token_details\":\"{\\\"cached_tokens\\\":200}\",\"output_token_details\":\"{}\",\"model\":\"gpt-4o\",\"response_type\":\"normal\",\"total_token\":500,\"messages\":[{\"role\":\"user\",\"content\":\"写一个Python函数计算斐波那契数列\"}],\"question\":\"写一个Python函数计算斐波那契数列\",\"answer\":\"```python\\ndef fibonacci(n):\\n if n <= 1:\\n return n\\n return fibonacci(n-1) + fibonacci(n-2)\\n```\",\"reasoning\":\"\",\"tool_calls\":[]}"}
================================================
FILE: .claude/skills/agent-session-monitor/example/test_rotation.sh
================================================
#!/bin/bash
# 测试日志轮转功能
set -e
SKILL_DIR="$(dirname "$(dirname "$(realpath "$0")")")"
EXAMPLE_DIR="$SKILL_DIR/example"
TEST_DIR="$EXAMPLE_DIR/rotation_test"
LOG_FILE="$TEST_DIR/access.log"
OUTPUT_DIR="$TEST_DIR/sessions"
echo "========================================"
echo "Log Rotation Test"
echo "========================================"
echo ""
# 清理旧测试数据
rm -rf "$TEST_DIR"
mkdir -p "$TEST_DIR"
echo "📁 Test directory: $TEST_DIR"
echo ""
# 模拟日志轮转场景
echo "========================================"
echo "步骤1:创建初始日志文件"
echo "========================================"
# 创建第一批日志(10条)
for i in {1..10}; do
echo "{\"timestamp\":\"2026-02-01T10:0${i}:00Z\",\"ai_log\":\"{\\\"session_id\\\":\\\"session_001\\\",\\\"model\\\":\\\"gpt-4o\\\",\\\"input_token\\\":$((100+i)),\\\"output_token\\\":$((50+i)),\\\"cached_tokens\\\":$((30+i))}\"}" >> "$LOG_FILE"
done
echo "✅ Created $LOG_FILE with 10 lines"
echo ""
# 首次解析
echo "========================================"
echo "步骤2:首次解析(应该处理10条记录)"
echo "========================================"
python3 "$SKILL_DIR/main.py" \
--log-path "$LOG_FILE" \
--output-dir "$OUTPUT_DIR" \
echo ""
# 检查session数据
echo "Session数据:"
cat "$OUTPUT_DIR/session_001.json" | python3 -c "import sys, json; d=json.load(sys.stdin); print(f\" Messages: {d['messages_count']}, Total Input: {d['total_input_tokens']}\")"
echo ""
# 模拟日志轮转
echo "========================================"
echo "步骤3:模拟日志轮转"
echo "========================================"
mv "$LOG_FILE" "$LOG_FILE.1"
echo "✅ Rotated: access.log -> access.log.1"
echo ""
# 创建新的日志文件(5条新记录)
for i in {11..15}; do
echo "{\"timestamp\":\"2026-02-01T10:${i}:00Z\",\"ai_log\":\"{\\\"session_id\\\":\\\"session_001\\\",\\\"model\\\":\\\"gpt-4o\\\",\\\"input_token\\\":$((100+i)),\\\"output_token\\\":$((50+i)),\\\"cached_tokens\\\":$((30+i))}\"}" >> "$LOG_FILE"
done
echo "✅ Created new $LOG_FILE with 5 lines"
echo ""
# 再次解析(应该只处理新的5条)
echo "========================================"
echo "步骤4:再次解析(应该只处理新的5条)"
echo "========================================"
python3 "$SKILL_DIR/main.py" \
--log-path "$LOG_FILE" \
--output-dir "$OUTPUT_DIR" \
echo ""
# 检查session数据
echo "Session数据:"
cat "$OUTPUT_DIR/session_001.json" | python3 -c "import sys, json; d=json.load(sys.stdin); print(f\" Messages: {d['messages_count']}, Total Input: {d['total_input_tokens']} (应该是15条记录)\")"
echo ""
# 再次轮转
echo "========================================"
echo "步骤5:再次轮转"
echo "========================================"
mv "$LOG_FILE.1" "$LOG_FILE.2"
mv "$LOG_FILE" "$LOG_FILE.1"
echo "✅ Rotated: access.log -> access.log.1"
echo "✅ Rotated: access.log.1 -> access.log.2"
echo ""
# 创建新的日志文件(3条新记录)
for i in {16..18}; do
echo "{\"timestamp\":\"2026-02-01T10:${i}:00Z\",\"ai_log\":\"{\\\"session_id\\\":\\\"session_001\\\",\\\"model\\\":\\\"gpt-4o\\\",\\\"input_token\\\":$((100+i)),\\\"output_token\\\":$((50+i)),\\\"cached_tokens\\\":$((30+i))}\"}" >> "$LOG_FILE"
done
echo "✅ Created new $LOG_FILE with 3 lines"
echo ""
# 再次解析(应该只处理新的3条)
echo "========================================"
echo "步骤6:再次解析(应该只处理新的3条)"
echo "========================================"
python3 "$SKILL_DIR/main.py" \
--log-path "$LOG_FILE" \
--output-dir "$OUTPUT_DIR" \
echo ""
# 检查session数据
echo "Session数据:"
cat "$OUTPUT_DIR/session_001.json" | python3 -c "import sys, json; d=json.load(sys.stdin); print(f\" Messages: {d['messages_count']}, Total Input: {d['total_input_tokens']} (应该是18条记录)\")"
echo ""
# 检查状态文件
echo "========================================"
echo "步骤7:查看状态文件"
echo "========================================"
echo "状态文件内容:"
cat "$OUTPUT_DIR/.state.json" | python3 -m json.tool | head -20
echo ""
echo "========================================"
echo "✅ 测试完成!"
echo "========================================"
echo ""
echo "💡 验证要点:"
echo " 1. 首次解析处理了10条记录"
echo " 2. 轮转后只处理新增的5条记录(总计15条)"
echo " 3. 再次轮转后只处理新增的3条记录(总计18条)"
echo " 4. 状态文件记录了每个文件的inode和offset"
echo ""
echo "📂 测试数据保存在: $TEST_DIR/"
================================================
FILE: .claude/skills/agent-session-monitor/main.py
================================================
#!/usr/bin/env python3
"""
Agent Session Monitor - 实时Agent对话观测程序
监控Higress访问日志,按session聚合对话,追踪token开销
"""
import argparse
import json
import re
import os
import sys
import time
from collections import defaultdict
from datetime import datetime
from pathlib import Path
from typing import Dict, List, Optional
# 使用定时轮询机制,不依赖watchdog
# ============================================================================
# 配置
# ============================================================================
# Token定价(单位:美元/1M tokens)
TOKEN_PRICING = {
"Qwen": {
"input": 0.0002, # $0.2/1M
"output": 0.0006,
"cached": 0.0001, # cached tokens通常是input的50%
},
"Qwen3-rerank": {
"input": 0.0003,
"output": 0.0012,
"cached": 0.00015,
},
"Qwen-Max": {
"input": 0.0005,
"output": 0.002,
"cached": 0.00025,
},
"GPT-4": {
"input": 0.003,
"output": 0.006,
"cached": 0.0015,
},
"GPT-4o": {
"input": 0.0025,
"output": 0.01,
"cached": 0.00125, # GPT-4o prompt caching: 50% discount
},
"GPT-4-32k": {
"input": 0.01,
"output": 0.03,
"cached": 0.005,
},
"o1": {
"input": 0.015,
"output": 0.06,
"cached": 0.0075,
"reasoning": 0.06, # o1 reasoning tokens same as output
},
"o1-mini": {
"input": 0.003,
"output": 0.012,
"cached": 0.0015,
"reasoning": 0.012,
},
"Claude": {
"input": 0.015,
"output": 0.075,
"cached": 0.0015, # Claude prompt caching: 90% discount
},
"DeepSeek-R1": {
"input": 0.004,
"output": 0.012,
"reasoning": 0.002,
"cached": 0.002,
}
}
DEFAULT_LOG_PATH = "/var/log/higress/access.log"
DEFAULT_OUTPUT_DIR = "./sessions"
# ============================================================================
# Session管理器
# ============================================================================
class SessionManager:
"""管理多个会话的token统计"""
def __init__(self, output_dir: str, load_existing: bool = True):
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
self.sessions: Dict[str, dict] = {}
# 加载已有的session数据
if load_existing:
self._load_existing_sessions()
def _load_existing_sessions(self):
"""加载已有的session数据"""
loaded_count = 0
for session_file in self.output_dir.glob("*.json"):
try:
with open(session_file, 'r', encoding='utf-8') as f:
session = json.load(f)
session_id = session.get('session_id')
if session_id:
self.sessions[session_id] = session
loaded_count += 1
except Exception as e:
print(f"Warning: Failed to load session {session_file}: {e}", file=sys.stderr)
if loaded_count > 0:
print(f"📦 Loaded {loaded_count} existing session(s)")
def update_session(self, session_id: str, ai_log: dict) -> dict:
"""更新或创建session"""
if session_id not in self.sessions:
self.sessions[session_id] = {
"session_id": session_id,
"created_at": datetime.now().isoformat(),
"updated_at": datetime.now().isoformat(),
"messages_count": 0,
"total_input_tokens": 0,
"total_output_tokens": 0,
"total_reasoning_tokens": 0,
"total_cached_tokens": 0,
"rounds": [],
"model": ai_log.get("model", "unknown")
}
session = self.sessions[session_id]
# 更新统计
model = ai_log.get("model", "unknown")
session["model"] = model
session["updated_at"] = datetime.now().isoformat()
# Token统计
session["total_input_tokens"] += ai_log.get("input_token", 0)
session["total_output_tokens"] += ai_log.get("output_token", 0)
# 检查reasoning tokens(优先使用ai_log中的reasoning_tokens字段)
reasoning_tokens = ai_log.get("reasoning_tokens", 0)
if reasoning_tokens == 0 and "reasoning" in ai_log and ai_log["reasoning"]:
# 如果没有reasoning_tokens字段,估算reasoning的token数(大致按字符数/4)
reasoning_text = ai_log["reasoning"]
reasoning_tokens = len(reasoning_text) // 4
session["total_reasoning_tokens"] += reasoning_tokens
# 检查cached tokens(prompt caching)
cached_tokens = ai_log.get("cached_tokens", 0)
session["total_cached_tokens"] += cached_tokens
# 检查是否有tool_calls(工具调用)
has_tool_calls = "tool_calls" in ai_log and ai_log["tool_calls"]
# 更新消息数
session["messages_count"] += 1
# 解析token details(如果有)
input_token_details = {}
output_token_details = {}
if "input_token_details" in ai_log:
try:
# input_token_details可能是字符串或字典
details = ai_log["input_token_details"]
if isinstance(details, str):
import json
input_token_details = json.loads(details)
else:
input_token_details = details
except (json.JSONDecodeError, TypeError):
pass
if "output_token_details" in ai_log:
try:
# output_token_details可能是字符串或字典
details = ai_log["output_token_details"]
if isinstance(details, str):
import json
output_token_details = json.loads(details)
else:
output_token_details = details
except (json.JSONDecodeError, TypeError):
pass
# 添加轮次记录(包含完整的llm请求和响应信息)
round_data = {
"round": session["messages_count"],
"timestamp": datetime.now().isoformat(),
"input_tokens": ai_log.get("input_token", 0),
"output_tokens": ai_log.get("output_token", 0),
"reasoning_tokens": reasoning_tokens,
"cached_tokens": cached_tokens,
"model": model,
"has_tool_calls": has_tool_calls,
"response_type": ai_log.get("response_type", "normal"),
# 完整的对话信息
"messages": ai_log.get("messages", []),
"question": ai_log.get("question", ""),
"answer": ai_log.get("answer", ""),
"reasoning": ai_log.get("reasoning", ""),
"tool_calls": ai_log.get("tool_calls", []),
# Token详情
"input_token_details": input_token_details,
"output_token_details": output_token_details,
}
session["rounds"].append(round_data)
# 保存到文件
self._save_session(session)
return session
def _save_session(self, session: dict):
"""保存session数据到文件"""
session_file = self.output_dir / f"{session['session_id']}.json"
with open(session_file, 'w', encoding='utf-8') as f:
json.dump(session, f, ensure_ascii=False, indent=2)
def get_all_sessions(self) -> List[dict]:
"""获取所有session"""
return list(self.sessions.values())
def get_session(self, session_id: str) -> Optional[dict]:
"""获取指定session"""
return self.sessions.get(session_id)
def get_summary(self) -> dict:
"""获取总体统计"""
total_input = sum(s["total_input_tokens"] for s in self.sessions.values())
total_output = sum(s["total_output_tokens"] for s in self.sessions.values())
total_reasoning = sum(s.get("total_reasoning_tokens", 0) for s in self.sessions.values())
total_cached = sum(s.get("total_cached_tokens", 0) for s in self.sessions.values())
# 计算成本
total_cost = 0
for session in self.sessions.values():
model = session.get("model", "unknown")
input_tokens = session["total_input_tokens"]
output_tokens = session["total_output_tokens"]
reasoning_tokens = session.get("total_reasoning_tokens", 0)
cached_tokens = session.get("total_cached_tokens", 0)
pricing = TOKEN_PRICING.get(model, TOKEN_PRICING.get("GPT-4", {}))
# 基础成本计算
# 注意:cached_tokens已经包含在input_tokens中,需要分开计算
regular_input_tokens = input_tokens - cached_tokens
input_cost = regular_input_tokens * pricing.get("input", 0) / 1000000
output_cost = output_tokens * pricing.get("output", 0) / 1000000
# reasoning成本
reasoning_cost = 0
if "reasoning" in pricing and reasoning_tokens > 0:
reasoning_cost = reasoning_tokens * pricing["reasoning"] / 1000000
# cached成本(通常比input便宜)
cached_cost = 0
if "cached" in pricing and cached_tokens > 0:
cached_cost = cached_tokens * pricing["cached"] / 1000000
total_cost += input_cost + output_cost + reasoning_cost + cached_cost
return {
"total_sessions": len(self.sessions),
"total_input_tokens": total_input,
"total_output_tokens": total_output,
"total_reasoning_tokens": total_reasoning,
"total_cached_tokens": total_cached,
"total_tokens": total_input + total_output + total_reasoning + total_cached,
"total_cost_usd": round(total_cost, 4),
"active_session_ids": list(self.sessions.keys())
}
# ============================================================================
# 日志解析器
# ============================================================================
class LogParser:
"""解析Higress访问日志,提取ai_log,支持日志轮转"""
def __init__(self, state_file: str = None):
self.state_file = Path(state_file) if state_file else None
self.file_offsets = {} # {文件路径: 已读取的字节偏移}
self._load_state()
def _load_state(self):
"""加载上次的读取状态"""
if self.state_file and self.state_file.exists():
try:
with open(self.state_file, 'r') as f:
self.file_offsets = json.load(f)
except Exception as e:
print(f"Warning: Failed to load state file: {e}", file=sys.stderr)
def _save_state(self):
"""保存当前的读取状态"""
if self.state_file:
try:
self.state_file.parent.mkdir(parents=True, exist_ok=True)
with open(self.state_file, 'w') as f:
json.dump(self.file_offsets, f, indent=2)
except Exception as e:
print(f"Warning: Failed to save state file: {e}", file=sys.stderr)
def parse_log_line(self, line: str) -> Optional[dict]:
"""解析单行日志,提取ai_log JSON"""
try:
# 直接解析整个日志行为JSON
log_obj = json.loads(line.strip())
# 获取ai_log字段(这是一个JSON字符串)
if 'ai_log' in log_obj:
ai_log_str = log_obj['ai_log']
# 解析内层JSON
ai_log = json.loads(ai_log_str)
return ai_log
except (json.JSONDecodeError, ValueError, KeyError):
# 静默忽略非JSON行或缺少ai_log字段的行
pass
return None
def parse_rotated_logs(self, log_pattern: str, session_manager) -> None:
"""解析日志文件及其轮转文件
Args:
log_pattern: 日志文件路径,如 /var/log/proxy/access.log
session_manager: Session管理器
"""
base_path = Path(log_pattern)
# 自动扫描所有轮转的日志文件(从旧到新)
log_files = []
# 自动扫描轮转文件(最多扫描到 .100,超过这个数量的日志应该很少见)
for i in range(100, 0, -1):
rotated_path = Path(f"{log_pattern}.{i}")
if rotated_path.exists():
log_files.append(str(rotated_path))
# 添加当前日志文件
if base_path.exists():
log_files.append(str(base_path))
if not log_files:
print(f"❌ No log files found for pattern: {log_pattern}")
return
print(f"📂 Found {len(log_files)} log file(s):")
for f in log_files:
print(f" - {f}")
print()
# 按顺序解析每个文件(从旧到新)
for log_file in log_files:
self._parse_file_incremental(log_file, session_manager)
# 保存状态
self._save_state()
def _parse_file_incremental(self, file_path: str, session_manager) -> None:
"""增量解析单个日志文件"""
try:
file_stat = os.stat(file_path)
file_size = file_stat.st_size
file_inode = file_stat.st_ino
# 使用inode作为主键
inode_key = str(file_inode)
last_offset = self.file_offsets.get(inode_key, 0)
# 如果文件变小了,说明是新文件(被truncate或新创建),从头开始读
if file_size < last_offset:
print(f" 📝 File truncated or recreated, reading from start: {file_path}")
last_offset = 0
# 如果offset相同,说明没有新内容
if file_size == last_offset:
print(f" ⏭️ No new content in: {file_path} (inode:{inode_key})")
return
print(f" 📖 Reading {file_path} from offset {last_offset} to {file_size} (inode:{inode_key})")
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
f.seek(last_offset)
lines_processed = 0
for line in f:
ai_log = self.parse_log_line(line)
if ai_log:
session_id = ai_log.get("session_id", "default")
session_manager.update_session(session_id, ai_log)
lines_processed += 1
# 每处理1000行打印一次进度
if lines_processed % 1000 == 0:
print(f" Processed {lines_processed} lines, {len(session_manager.sessions)} sessions")
# 更新offset(使用inode作为key)
current_offset = f.tell()
self.file_offsets[inode_key] = current_offset
print(f" ✅ Processed {lines_processed} new lines from {file_path}")
except FileNotFoundError:
print(f" ❌ File not found: {file_path}")
except Exception as e:
print(f" ❌ Error parsing {file_path}: {e}")
# ============================================================================
# 实时显示器
# ============================================================================
class RealtimeMonitor:
"""实时监控显示和交互(定时轮询模式)"""
def __init__(self, session_manager: SessionManager, log_parser=None, log_path: str = None, refresh_interval: int = 1):
self.session_manager = session_manager
self.log_parser = log_parser
self.log_path = log_path
self.refresh_interval = refresh_interval
self.running = True
self.last_poll_time = 0
def start(self):
"""启动实时监控(定时轮询日志文件)"""
print(f"\n{'=' * 50}")
print(f"🔍 Agent Session Monitor - Real-time View")
print(f"{'=' * 50}")
print()
print("Press Ctrl+C to stop...")
print()
try:
while self.running:
# 定时轮询日志文件(检查新增内容和轮转)
current_time = time.time()
if self.log_parser and self.log_path and (current_time - self.last_poll_time >= self.refresh_interval):
self.log_parser.parse_rotated_logs(self.log_path, self.session_manager)
self.last_poll_time = current_time
# 显示状态
self._display_status()
time.sleep(self.refresh_interval)
except KeyboardInterrupt:
print("\n\n👋 Stopping monitor...")
self.running = False
self._display_summary()
def _display_status(self):
"""显示当前状态"""
summary = self.session_manager.get_summary()
# 清屏
os.system('clear' if os.name == 'posix' else 'cls')
print(f"{'=' * 50}")
print(f"🔍 Session Monitor - Active")
print(f"{'=' * 50}")
print()
print(f"📊 Active Sessions: {summary['total_sessions']}")
print()
# 显示活跃session的token统计
if summary['active_session_ids']:
print("┌──────────────────────────┬─────────┬──────────┬───────────┐")
print("│ Session ID │ Msgs │ Input │ Output │")
print("├──────────────────────────┼─────────┼──────────┼───────────┤")
for session_id in summary['active_session_ids'][:10]: # 最多显示10个
session = self.session_manager.get_session(session_id)
if session:
sid = session_id[:24] if len(session_id) > 24 else session_id
print(f"│ {sid:<24} │ {session['messages_count']:>7} │ {session['total_input_tokens']:>8,} │ {session['total_output_tokens']:>9,} │")
print("└──────────────────────────┴─────────┴──────────┴───────────┘")
print()
print(f"📈 Token Statistics")
print(f" Total Input: {summary['total_input_tokens']:,} tokens")
print(f" Total Output: {summary['total_output_tokens']:,} tokens")
if summary['total_reasoning_tokens'] > 0:
print(f" Total Reasoning: {summary['total_reasoning_tokens']:,} tokens")
print(f" Total Cached: {summary['total_cached_tokens']:,} tokens")
print(f" Total Cost: ${summary['total_cost_usd']:.4f}")
def _display_summary(self):
"""显示最终汇总"""
summary = self.session_manager.get_summary()
print()
print(f"{'=' * 50}")
print(f"📊 Session Monitor - Summary")
print(f"{'=' * 50}")
print()
print(f"📈 Final Statistics")
print(f" Total Sessions: {summary['total_sessions']}")
print(f" Total Input: {summary['total_input_tokens']:,} tokens")
print(f" Total Output: {summary['total_output_tokens']:,} tokens")
if summary['total_reasoning_tokens'] > 0:
print(f" Total Reasoning: {summary['total_reasoning_tokens']:,} tokens")
print(f" Total Cached: {summary['total_cached_tokens']:,} tokens")
print(f" Total Tokens: {summary['total_tokens']:,} tokens")
print(f" Total Cost: ${summary['total_cost_usd']:.4f}")
print(f"{'=' * 50}")
print()
# ============================================================================
# 主程序
# ============================================================================
def main():
parser = argparse.ArgumentParser(
description="Agent Session Monitor - 实时监控多轮Agent对话的token开销",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
示例:
# 监控默认日志
%(prog)s
# 监控指定日志文件
%(prog)s --log-path /var/log/higress/access.log
# 设置预算为500K tokens
%(prog)s --budget 500000
# 监控特定session
%(prog)s --session-key agent:main:discord:channel:1465367993012981988
""",
allow_abbrev=False
)
parser.add_argument(
'--log-path',
default=DEFAULT_LOG_PATH,
help=f'Higress访问日志文件路径(默认: {DEFAULT_LOG_PATH})'
)
parser.add_argument(
'--output-dir',
default=DEFAULT_OUTPUT_DIR,
help=f'Session数据存储目录(默认: {DEFAULT_OUTPUT_DIR})'
)
parser.add_argument(
'--session-key',
help='只监控包含指定session key的日志'
)
parser.add_argument(
'--refresh-interval',
type=int,
default=1,
help=f'实时监控刷新间隔(秒,默认: 1)'
)
parser.add_argument(
'--state-file',
help='状态文件路径,用于记录已读取的offset(默认: <output-dir>/.state.json)'
)
args = parser.parse_args()
# 初始化组件
session_manager = SessionManager(output_dir=args.output_dir)
# 状态文件路径
state_file = args.state_file or str(Path(args.output_dir) / '.state.json')
log_parser = LogParser(state_file=state_file)
print(f"{'=' * 60}")
print(f"🔍 Agent Session Monitor")
print(f"{'=' * 60}")
print()
print(f"📂 Log path: {args.log_path}")
print(f"📁 Output dir: {args.output_dir}")
if args.session_key:
print(f"🔑 Session key filter: {args.session_key}")
print(f"{'=' * 60}")
print()
# 模式选择:实时监控或单次解析
if len(sys.argv) == 1:
# 默认模式:实时监控(定时轮询)
print("📺 Mode: Real-time monitoring (polling mode with log rotation support)")
print(f" Refresh interval: {args.refresh_interval} second(s)")
print()
# 首次解析现有日志文件(包括轮转的文件)
log_parser.parse_rotated_logs(args.log_path, session_manager)
# 启动实时监控(定时轮询模式)
monitor = RealtimeMonitor(
session_manager,
log_parser=log_parser,
log_path=args.log_path,
refresh_interval=args.refresh_interval
)
monitor.start()
else:
# 单次解析模式
print("📊 Mode: One-time log parsing (with log rotation support)")
print()
log_parser.parse_rotated_logs(args.log_path, session_manager)
# 显示汇总
summary = session_manager.get_summary()
print(f"\n{'=' * 50}")
print(f"📊 Session Summary")
print(f"{'=' * 50}")
print()
print(f"📈 Final Statistics")
print(f" Total Sessions: {summary['total_sessions']}")
print(f" Total Input: {summary['total_input_tokens']:,} tokens")
print(f" Total Output: {summary['total_output_tokens']:,} tokens")
if summary['total_reasoning_tokens'] > 0:
print(f" Total Reasoning: {summary['total_reasoning_tokens']:,} tokens")
print(f" Total Cached: {summary['total_cached_tokens']:,} tokens")
print(f" Total Tokens: {summary['total_tokens']:,} tokens")
print(f" Total Cost: ${summary['total_cost_usd']:.4f}")
print(f"{'=' * 50}")
print()
print(f"💾 Session data saved to: {args.output_dir}/")
print(f" Run with --output-dir to specify custom directory")
if __name__ == '__main__':
main()
================================================
FILE: .claude/skills/agent-session-monitor/scripts/cli.py
================================================
#!/usr/bin/env python3
"""
Agent Session Monitor CLI - 查询和分析agent对话数据
支持:
1. 实时查询指定session的完整llm请求和响应
2. 按模型统计token开销
3. 按日期统计token开销
4. 生成FinOps报表
"""
import argparse
import json
import sys
from collections import defaultdict
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Optional
import re
# Token定价(单位:美元/1M tokens)
TOKEN_PRICING = {
"Qwen": {
"input": 0.0002, # $0.2/1M
"output": 0.0006,
"cached": 0.0001, # cached tokens通常是input的50%
},
"Qwen3-rerank": {
"input": 0.0003,
"output": 0.0012,
"cached": 0.00015,
},
"Qwen-Max": {
"input": 0.0005,
"output": 0.002,
"cached": 0.00025,
},
"GPT-4": {
"input": 0.003,
"output": 0.006,
"cached": 0.0015,
},
"GPT-4o": {
"input": 0.0025,
"output": 0.01,
"cached": 0.00125, # GPT-4o prompt caching: 50% discount
},
"GPT-4-32k": {
"input": 0.01,
"output": 0.03,
"cached": 0.005,
},
"o1": {
"input": 0.015,
"output": 0.06,
"cached": 0.0075,
"reasoning": 0.06, # o1 reasoning tokens same as output
},
"o1-mini": {
"input": 0.003,
"output": 0.012,
"cached": 0.0015,
"reasoning": 0.012,
},
"Claude": {
"input": 0.015,
"output": 0.075,
"cached": 0.0015, # Claude prompt caching: 90% discount
},
"DeepSeek-R1": {
"input": 0.004,
"output": 0.012,
"reasoning": 0.002,
"cached": 0.002,
}
}
class SessionAnalyzer:
"""Session数据分析器"""
def __init__(self, data_dir: str):
self.data_dir = Path(data_dir)
if not self.data_dir.exists():
raise FileNotFoundError(f"Session data directory not found: {data_dir}")
def load_session(self, session_id: str) -> Optional[dict]:
"""加载指定session的完整数据"""
session_file = self.data_dir / f"{session_id}.json"
if not session_file.exists():
return None
with open(session_file, 'r', encoding='utf-8') as f:
return json.load(f)
def load_all_sessions(self) -> List[dict]:
"""加载所有session数据"""
sessions = []
for session_file in self.data_dir.glob("*.json"):
try:
with open(session_file, 'r', encoding='utf-8') as f:
session = json.load(f)
sessions.append(session)
except Exception as e:
print(f"Warning: Failed to load {session_file}: {e}", file=sys.stderr)
return sessions
def display_session_detail(self, session_id: str, show_messages: bool = True):
"""显示session的详细信息"""
session = self.load_session(session_id)
if not session:
print(f"❌ Session not found: {session_id}")
return
print(f"\n{'='*70}")
print(f"📊 Session Detail: {session_id}")
print(f"{'='*70}\n")
# 基本信息
print(f"🕐 Created: {session['created_at']}")
print(f"🕑 Updated: {session['updated_at']}")
print(f"🤖 Model: {session['model']}")
print(f"💬 Messages: {session['messages_count']}")
print()
# Token统计
print(f"📈 Token Statistics:")
total_input = session['total_input_tokens']
total_output = session['total_output_tokens']
total_reasoning = session.get('total_reasoning_tokens', 0)
total_cached = session.get('total_cached_tokens', 0)
# 区分regular input和cached input
regular_input = total_input - total_cached
if total_cached > 0:
print(f" Input: {regular_input:>10,} tokens (regular)")
print(f" Cached: {total_cached:>10,} tokens (from cache)")
print(f" Total Input:{total_input:>10,} tokens")
else:
print(f" Input: {total_input:>10,} tokens")
print(f" Output: {total_output:>10,} tokens")
if total_reasoning > 0:
print(f" Reasoning: {total_reasoning:>10,} tokens")
# 总计(不重复计算cached)
total_tokens = total_input + total_output + total_reasoning
print(f" ────────────────────────")
print(f" Total: {total_tokens:>10,} tokens")
print()
# 成本计算
cost = self._calculate_cost(session)
print(f"💰 Estimated Cost: ${cost:.8f} USD")
print()
# 对话轮次
if show_messages and 'rounds' in session:
print(f"📝 Conversation Rounds ({len(session['rounds'])}):")
print(f"{'─'*70}")
for i, round_data in enumerate(session['rounds'], 1):
timestamp = round_data.get('timestamp', 'N/A')
input_tokens = round_data.get('input_tokens', 0)
output_tokens = round_data.get('output_tokens', 0)
has_tool_calls = round_data.get('has_tool_calls', False)
response_type = round_data.get('response_type', 'normal')
print(f"\n Round {i} @ {timestamp}")
print(f" Tokens: {input_tokens:,} in → {output_tokens:,} out")
if has_tool_calls:
print(f" 🔧 Tool calls: Yes")
if response_type != 'normal':
print(f" Type: {response_type}")
# 显示完整的messages(如果有)
if 'messages' in round_data:
messages = round_data['messages']
print(f" Messages ({len(messages)}):")
for msg in messages[-3:]: # 只显示最后3条
role = msg.get('role', 'unknown')
content = msg.get('content', '')
content_preview = content[:100] + '...' if len(content) > 100 else content
print(f" [{role}] {content_preview}")
# 显示question/answer/reasoning(如果有)
if 'question' in round_data:
q = round_data['question']
q_preview = q[:150] + '...' if len(q) > 150 else q
print(f" ❓ Question: {q_preview}")
if 'answer' in round_data:
a = round_data['answer']
a_preview = a[:150] + '...' if len(a) > 150 else a
print(f" ✅ Answer: {a_preview}")
if 'reasoning' in round_data and round_data['reasoning']:
r = round_data['reasoning']
r_preview = r[:150] + '...' if len(r) > 150 else r
print(f" 🧠 Reasoning: {r_preview}")
if 'tool_calls' in round_data and round_data['tool_calls']:
print(f" 🛠️ Tool Calls:")
for tool_call in round_data['tool_calls']:
func_name = tool_call.get('function', {}).get('name', 'unknown')
args = tool_call.get('function', {}).get('arguments', '')
print(f" - {func_name}({args[:80]}...)")
# 显示token details(如果有)
if round_data.get('input_token_details'):
print(f" 📊 Input Token Details: {round_data['input_token_details']}")
if round_data.get('output_token_details'):
print(f" 📊 Output Token Details: {round_data['output_token_details']}")
print(f"\n{'─'*70}")
print(f"\n{'='*70}\n")
def _calculate_cost(self, session: dict) -> float:
"""计算session的成本"""
model = session.get('model', 'unknown')
pricing = TOKEN_PRICING.get(model, TOKEN_PRICING.get("GPT-4", {}))
input_tokens = session['total_input_tokens']
output_tokens = session['total_output_tokens']
reasoning_tokens = session.get('total_reasoning_tokens', 0)
cached_tokens = session.get('total_cached_tokens', 0)
# 区分regular input和cached input
regular_input_tokens = input_tokens - cached_tokens
input_cost = regular_input_tokens * pricing.get('input', 0) / 1000000
output_cost = output_tokens * pricing.get('output', 0) / 1000000
reasoning_cost = 0
if 'reasoning' in pricing and reasoning_tokens > 0:
reasoning_cost = reasoning_tokens * pricing['reasoning'] / 1000000
cached_cost = 0
if 'cached' in pricing and cached_tokens > 0:
cached_cost = cached_tokens * pricing['cached'] / 1000000
return input_cost + output_cost + reasoning_cost + cached_cost
def stats_by_model(self) -> Dict[str, dict]:
"""按模型统计token开销"""
sessions = self.load_all_sessions()
stats = defaultdict(lambda: {
'session_count': 0,
'total_input': 0,
'total_output': 0,
'total_reasoning': 0,
'total_cost': 0.0
})
for session in sessions:
model = session.get('model', 'unknown')
stats[model]['session_count'] += 1
stats[model]['total_input'] += session['total_input_tokens']
stats[model]['total_output'] += session['total_output_tokens']
stats[model]['total_reasoning'] += session.get('total_reasoning_tokens', 0)
stats[model]['total_cost'] += self._calculate_cost(session)
return dict(stats)
def stats_by_date(self, days: int = 30) -> Dict[str, dict]:
"""按日期统计token开销(最近N天)"""
sessions = self.load_all_sessions()
stats = defaultdict(lambda: {
'session_count': 0,
'total_input': 0,
'total_output': 0,
'total_reasoning': 0,
'total_cost': 0.0,
'models': set()
})
cutoff_date = datetime.now() - timedelta(days=days)
for session in sessions:
created_at = datetime.fromisoformat(session['created_at'])
if created_at < cutoff_date:
continue
date_key = created_at.strftime('%Y-%m-%d')
stats[date_key]['session_count'] += 1
stats[date_key]['total_input'] += session['total_input_tokens']
stats[date_key]['total_output'] += session['total_output_tokens']
stats[date_key]['total_reasoning'] += session.get('total_reasoning_tokens', 0)
stats[date_key]['total_cost'] += self._calculate_cost(session)
stats[date_key]['models'].add(session.get('model', 'unknown'))
# 转换sets为lists以便JSON序列化
for date_key in stats:
stats[date_key]['models'] = list(stats[date_key]['models'])
return dict(stats)
def display_model_stats(self):
"""显示按模型的统计"""
stats = self.stats_by_model()
print(f"\n{'='*80}")
print(f"📊 Statistics by Model")
print(f"{'='*80}\n")
print(f"{'Model':<20} {'Sessions':<10} {'Input':<15} {'Output':<15} {'Cost (USD)':<12}")
print(f"{'─'*80}")
# 按成本降序排列
sorted_models = sorted(stats.items(), key=lambda x: x[1]['total_cost'], reverse=True)
for model, data in sorted_models:
print(f"{model:<20} "
f"{data['session_count']:<10} "
f"{data['total_input']:>12,} "
f"{data['total_output']:>12,} "
f"${data['total_cost']:>10.6f}")
# 总计
total_sessions = sum(d['session_count'] for d in stats.values())
total_input = sum(d['total_input'] for d in stats.values())
total_output = sum(d['total_output'] for d in stats.values())
total_cost = sum(d['total_cost'] for d in stats.values())
print(f"{'─'*80}")
print(f"{'TOTAL':<20} "
f"{total_sessions:<10} "
f"{total_input:>12,} "
f"{total_output:>12,} "
f"${total_cost:>10.6f}")
print(f"\n{'='*80}\n")
def display_date_stats(self, days: int = 30):
"""显示按日期的统计"""
stats = self.stats_by_date(days)
print(f"\n{'='*80}")
print(f"📊 Statistics by Date (Last {days} days)")
print(f"{'='*80}\n")
print(f"{'Date':<12} {'Sessions':<10} {'Input':<15} {'Output':<15} {'Cost (USD)':<12} {'Models':<20}")
print(f"{'─'*80}")
# 按日期升序排列
sorted_dates = sorted(stats.items())
for date, data in sorted_dates:
models_str = ', '.join(data['models'][:3]) # 最多显示3个模型
if len(data['models']) > 3:
models_str += f" +{len(data['models'])-3}"
print(f"{date:<12} "
f"{data['session_count']:<10} "
f"{data['total_input']:>12,} "
f"{data['total_output']:>12,} "
f"${data['total_cost']:>10.4f} "
f"{models_str}")
# 总计
total_sessions = sum(d['session_count'] for d in stats.values())
total_input = sum(d['total_input'] for d in stats.values())
total_output = sum(d['total_output'] for d in stats.values())
total_cost = sum(d['total_cost'] for d in stats.values())
print(f"{'─'*80}")
print(f"{'TOTAL':<12} "
f"{total_sessions:<10} "
f"{total_input:>12,} "
f"{total_output:>12,} "
f"${total_cost:>10.4f}")
print(f"\n{'='*80}\n")
def list_sessions(self, limit: int = 20, sort_by: str = 'updated'):
"""列出所有session"""
sessions = self.load_all_sessions()
# 排序
if sort_by == 'updated':
sessions.sort(key=lambda s: s.get('updated_at', ''), reverse=True)
elif sort_by == 'cost':
sessions.sort(key=lambda s: self._calculate_cost(s), reverse=True)
elif sort_by == 'tokens':
sessions.sort(key=lambda s: s['total_input_tokens'] + s['total_output_tokens'], reverse=True)
print(f"\n{'='*100}")
print(f"📋 Sessions (sorted by {sort_by}, showing {min(limit, len(sessions))} of {len(sessions)})")
print(f"{'='*100}\n")
print(f"{'Session ID':<30} {'Updated':<20} {'Model':<15} {'Msgs':<6} {'Tokens':<12} {'Cost':<10}")
print(f"{'─'*100}")
for session in sessions[:limit]:
session_id = session['session_id'][:28] + '..' if len(session['session_id']) > 30 else session['session_id']
updated = session.get('updated_at', 'N/A')[:19]
model = session.get('model', 'unknown')[:13]
msg_count = session.get('messages_count', 0)
total_tokens = session['total_input_tokens'] + session['total_output_tokens']
cost = self._calculate_cost(session)
print(f"{session_id:<30} {updated:<20} {model:<15} {msg_count:<6} {total_tokens:>10,} ${cost:>8.4f}")
print(f"\n{'='*100}\n")
def export_finops_report(self, output_file: str, format: str = 'json'):
"""导出FinOps报表"""
model_stats = self.stats_by_model()
date_stats = self.stats_by_date(30)
report = {
'generated_at': datetime.now().isoformat(),
'summary': {
'total_sessions': sum(d['session_count'] for d in model_stats.values()),
'total_input_tokens': sum(d['total_input'] for d in model_stats.values()),
'total_output_tokens': sum(d['total_output'] for d in model_stats.values()),
'total_cost_usd': sum(d['total_cost'] for d in model_stats.values()),
},
'by_model': model_stats,
'by_date': date_stats,
}
output_path = Path(output_file)
if format == 'json':
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(report, f, ensure_ascii=False, indent=2)
print(f"✅ FinOps report exported to: {output_path}")
elif format == 'csv':
import csv
# 按模型导出CSV
model_csv = output_path.with_suffix('.model.csv')
with open(model_csv, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['Model', 'Sessions', 'Input Tokens', 'Output Tokens', 'Cost (USD)'])
for model, data in model_stats.items():
writer.writerow([
model,
data['session_count'],
data['total_input'],
data['total_output'],
f"{data['total_cost']:.6f}"
])
# 按日期导出CSV
date_csv = output_path.with_suffix('.date.csv')
with open(date_csv, 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['Date', 'Sessions', 'Input Tokens', 'Output Tokens', 'Cost (USD)', 'Models'])
for date, data in sorted(date_stats.items()):
writer.writerow([
date,
data['session_count'],
data['total_input'],
data['total_output'],
f"{data['total_cost']:.6f}",
', '.join(data['models'])
])
print(f"✅ FinOps report exported to:")
print(f" Model stats: {model_csv}")
print(f" Date stats: {date_csv}")
def main():
parser = argparse.ArgumentParser(
description="Agent Session Monitor CLI - 查询和分析agent对话数据",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Commands:
show <session-id> 显示session的详细信息
list 列出所有session
stats-model 按模型统计token开销
stats-date 按日期统计token开销(默认30天)
export 导出FinOps报表
Examples:
# 查看特定session的详细对话
%(prog)s show agent:main:discord:channel:1465367993012981988
# 列出最近20个session(按更新时间)
%(prog)s list
# 列出token开销最高的10个session
%(prog)s list --sort-by cost --limit 10
# 按模型统计token开销
%(prog)s stats-model
# 按日期统计token开销(最近7天)
%(prog)s stats-date --days 7
# 导出FinOps报表(JSON格式)
%(prog)s export finops-report.json
# 导出FinOps报表(CSV格式)
%(prog)s export finops-report --format csv
"""
)
parser.add_argument(
'command',
choices=['show', 'list', 'stats-model', 'stats-date', 'export'],
help='命令'
)
parser.add_argument(
'args',
nargs='*',
help='命令参数(例如:session-id或输出文件名)'
)
parser.add_argument(
'--data-dir',
default='./sessions',
help='Session数据目录(默认: ./sessions)'
)
parser.add_argument(
'--limit',
type=int,
default=20,
help='list命令的结果限制(默认: 20)'
)
parser.add_argument(
'--sort-by',
choices=['updated', 'cost', 'tokens'],
default='updated',
help='list命令的排序方式(默认: updated)'
)
parser.add_argument(
'--days',
type=int,
default=30,
help='stats-date命令的天数(默认: 30)'
)
parser.add_argument(
'--format',
choices=['json', 'csv'],
default='json',
help='export命令的输出格式(默认: json)'
)
parser.add_argument(
'--no-messages',
action='store_true',
help='show命令:不显示对话内容'
)
args = parser.parse_args()
try:
analyzer = SessionAnalyzer(args.data_dir)
if args.command == 'show':
if not args.args:
parser.error("show命令需要session-id参数")
session_id = args.args[0]
analyzer.display_session_detail(session_id, show_messages=not args.no_messages)
elif args.command == 'list':
analyzer.list_sessions(limit=args.limit, sort_by=args.sort_by)
elif args.command == 'stats-model':
analyzer.display_model_stats()
elif args.command == 'stats-date':
analyzer.display_date_stats(days=args.days)
elif args.command == 'export':
if not args.args:
parser.error("export命令需要输出文件名参数")
output_file = args.args[0]
analyzer.export_finops_report(output_file, format=args.format)
except FileNotFoundError as e:
print(f"❌ Error: {e}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"❌ Unexpected error: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == '__main__':
main()
================================================
FILE: .claude/skills/agent-session-monitor/scripts/webserver.py
================================================
#!/usr/bin/env python3
"""
Agent Session Monitor - Web Server
提供浏览器访问的观测界面
"""
import argparse
import json
import sys
from pathlib import Path
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
from collections import defaultdict
from datetime import datetime, timedelta
import re
# 添加父目录到path以导入cli模块
sys.path.insert(0, str(Path(__file__).parent.parent))
try:
from scripts.cli import SessionAnalyzer, TOKEN_PRICING
except ImportError:
# 如果导入失败,定义简单版本
TOKEN_PRICING = {
"Qwen3-rerank": {"input": 0.0003, "output": 0.0012},
"DeepSeek-R1": {"input": 0.004, "output": 0.012, "reasoning": 0.002},
}
class SessionMonitorHandler(BaseHTTPRequestHandler):
"""HTTP请求处理器"""
def __init__(self, *args, data_dir=None, **kwargs):
self.data_dir = Path(data_dir) if data_dir else Path("./sessions")
super().__init__(*args, **kwargs)
def do_GET(self):
"""处理GET请求"""
parsed_path = urlparse(self.path)
path = parsed_path.path
query = parse_qs(parsed_path.query)
if path == '/' or path == '/index.html':
self.serve_index()
elif path == '/session':
session_id = query.get('id', [None])[0]
if session_id:
self.serve_session_detail(session_id)
else:
self.send_error(400, "Missing session id")
elif path == '/api/sessions':
self.serve_api_sessions()
elif path == '/api/session':
session_id = query.get('id', [None])[0]
if session_id:
self.serve_api_session(session_id)
else:
self.send_error(400, "Missing session id")
elif path == '/api/stats':
self.serve_api_stats()
else:
self.send_error(404, "Not Found")
def serve_index(self):
"""首页 - 总览"""
html = self.generate_index_html()
self.send_html(html)
def serve_session_detail(self, session_id: str):
"""Session详情页"""
html = self.generate_session_html(session_id)
self.send_html(html)
def serve_api_sessions(self):
"""API: 获取所有session列表"""
sessions = self.load_all_sessions()
# 简化数据
data = []
for session in sessions:
data.append({
'session_id': session['session_id'],
'model': session.get('model', 'unknown'),
'messages_count': session.get('messages_count', 0),
'total_tokens': session['total_input_tokens'] + session['total_output_tokens'],
'updated_at': session.get('updated_at', ''),
'cost': self.calculate_cost(session)
})
# 按更新时间降序排序
data.sort(key=lambda x: x['updated_at'], reverse=True)
self.send_json(data)
def serve_api_session(self, session_id: str):
"""API: 获取指定session的详细数据"""
session = self.load_session(session_id)
if session:
session['cost'] = self.calculate_cost(session)
self.send_json(session)
else:
self.send_error(404, "Session not found")
def serve_api_stats(self):
"""API: 获取统计数据"""
sessions = self.load_all_sessions()
# 按模型统计
by_model = defaultdict(lambda: {
'count': 0,
'input_tokens': 0,
'output_tokens': 0,
'cost': 0.0
})
# 按日期统计
by_date = defaultdict(lambda: {
'count': 0,
'input_tokens': 0,
'output_tokens': 0,
'cost': 0.0,
'models': set()
})
total_cost = 0.0
for session in sessions:
model = session.get('model', 'unknown')
cost = self.calculate_cost(session)
total_cost += cost
# 按模型
by_model[model]['count'] += 1
by_model[model]['input_tokens'] += session['total_input_tokens']
by_model[model]['output_tokens'] += session['total_output_tokens']
by_model[model]['cost'] += cost
# 按日期
created_at = session.get('created_at', '')
date_key = created_at[:10] if len(created_at) >= 10 else 'unknown'
by_date[date_key]['count'] += 1
by_date[date_key]['input_tokens'] += session['total_input_tokens']
by_date[date_key]['output_tokens'] += session['total_output_tokens']
by_date[date_key]['cost'] += cost
by_date[date_key]['models'].add(model)
# 转换sets为lists
for date in by_date:
by_date[date]['models'] = list(by_date[date]['models'])
stats = {
'total_sessions': len(sessions),
'total_cost': total_cost,
'by_model': dict(by_model),
'by_date': dict(sorted(by_date.items(), reverse=True))
}
self.send_json(stats)
def load_session(self, session_id: str):
"""加载指定session"""
session_file = self.data_dir / f"{session_id}.json"
if session_file.exists():
with open(session_file, 'r', encoding='utf-8') as f:
return json.load(f)
return None
def load_all_sessions(self):
"""加载所有session"""
sessions = []
for session_file in self.data_dir.glob("*.json"):
try:
with open(session_file, 'r', encoding='utf-8') as f:
sessions.append(json.load(f))
except Exception as e:
print(f"Warning: Failed to load {session_file}: {e}", file=sys.stderr)
return sessions
def calculate_cost(self, session: dict) -> float:
"""计算session成本"""
model = session.get('model', 'unknown')
pricing = TOKEN_PRICING.get(model, TOKEN_PRICING.get("GPT-4", {"input": 0.003, "output": 0.006}))
input_tokens = session['total_input_tokens']
output_tokens = session['total_output_tokens']
reasoning_tokens = session.get('total_reasoning_tokens', 0)
cached_tokens = session.get('total_cached_tokens', 0)
# 区分regular input和cached input
regular_input_tokens = input_tokens - cached_tokens
input_cost = regular_input_tokens * pricing.get('input', 0) / 1000000
output_cost = output_tokens * pricing.get('output', 0) / 1000000
reasoning_cost = 0
if 'reasoning' in pricing and reasoning_tokens > 0:
reasoning_cost = reasoning_tokens * pricing['reasoning'] / 1000000
cached_cost = 0
if 'cached' in pricing and cached_tokens > 0:
cached_cost = cached_tokens * pricing['cached'] / 1000000
return input_cost + output_cost + reasoning_cost + cached_cost
def send_html(self, html: str):
"""发送HTML响应"""
self.send_response(200)
self.send_header('Content-type', 'text/html; charset=utf-8')
self.end_headers()
self.wfile.write(html.encode('utf-8'))
def send_json(self, data):
"""发送JSON响应"""
self.send_response(200)
self.send_header('Content-type', 'application/json; charset=utf-8')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
self.wfile.write(json.dumps(data, ensure_ascii=False, indent=2).encode('utf-8'))
def generate_index_html(self) -> str:
"""生成首页HTML"""
return '''<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Agent Session Monitor</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #f5f5f5;
padding: 20px;
}
.container { max-width: 1400px; margin: 0 auto; }
header {
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
h1 { color: #333; margin-bottom: 10px; }
.subtitle { color: #666; font-size: 14px; }
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.stat-card {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.stat-label { color: #666; font-size: 14px; margin-bottom: 8px; }
.stat-value { color: #333; font-size: 32px; font-weight: bold; }
.stat-unit { color: #999; font-size: 16px; margin-left: 4px; }
.section {
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}
h2 { color: #333; margin-bottom: 20px; font-size: 20px; }
table { width: 100%; border-collapse: collapse; }
thead { background: #f8f9fa; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #e9ecef; }
th { font-weight: 600; color: #666; font-size: 14px; }
td { color: #333; }
tbody tr:hover { background: #f8f9fa; }
.session-link {
color: #007bff;
text-decoration: none;
font-family: monospace;
font-size: 13px;
}
.session-link:hover { text-decoration: underline; }
.badge {
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
}
.badge-qwen { background: #e3f2fd; color: #1976d2; }
.badge-deepseek { background: #f3e5f5; color: #7b1fa2; }
.badge-gpt { background: #e8f5e9; color: #388e3c; }
.badge-claude { background: #fff3e0; color: #f57c00; }
.loading { text-align: center; padding: 40px; color: #666; }
.error { color: #d32f2f; padding: 20px; }
.refresh-btn {
background: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.refresh-btn:hover { background: #0056b3; }
</style>
</head>
<body>
<div class="container">
<header>
<h1>🔍 Agent Session Monitor</h1>
<p class="subtitle">实时观测Clawdbot对话过程和Token开销</p>
</header>
<div class="stats-grid" id="stats-grid">
<div class="stat-card">
<div class="stat-label">总会话数</div>
<div class="stat-value">-</div>
</div>
<div class="stat-card">
<div class="stat-label">总Token消耗</div>
<div class="stat-value">-</div>
</div>
<div class="stat-card">
<div class="stat-label">总成本</div>
<div class="stat-value">-</div>
</div>
</div>
<div class="section">
<h2>📊 最近会话</h2>
<button class="refresh-btn" onclick="loadSessions()">🔄 刷新</button>
<div id="sessions-table">
<div class="loading">加载中...</div>
</div>
</div>
<div class="section">
<h2>📈 按模型统计</h2>
<div id="model-stats">
<div class="loading">加载中...</div>
</div>
</div>
</div>
<script>
function loadSessions() {
fetch('/api/sessions')
.then(r => r.json())
.then(sessions => {
const html = `
<table>
<thead>
<tr>
<th>Session ID</th>
<th>模型</th>
<th>消息数</th>
<th>总Token</th>
<th>成本</th>
<th>更新时间</th>
</tr>
</thead>
<tbody>
${sessions.slice(0, 50).map(s => `
<tr>
<td><a href="/session?id=${encodeURIComponent(s.session_id)}" class="session-link">${s.session_id}</a></td>
<td>${getModelBadge(s.model)}</td>
<td>${s.messages_count}</td>
<td>${s.total_tokens.toLocaleString()}</td>
<td>$${s.cost.toFixed(6)}</td>
<td>${new Date(s.updated_at).toLocaleString()}</td>
</tr>
`).join('')}
</tbody>
</table>
`;
document.getElementById('sessions-table').innerHTML = html;
})
.catch(err => {
document.getElementById('sessions-table').innerHTML = `<div class="error">加载失败: ${err.message}</div>`;
});
}
function loadStats() {
fetch('/api/stats')
.then(r => r.json())
.then(stats => {
// 更新顶部统计卡片
const cards = document.querySelectorAll('.stat-card');
cards[0].querySelector('.stat-value').textContent = stats.total_sessions;
const totalTokens = Object.values(stats.by_model).reduce((sum, m) => sum + m.input_tokens + m.output_tokens, 0);
cards[1].querySelector('.stat-value').innerHTML = totalTokens.toLocaleString() + '<span class="stat-unit">tokens</span>';
cards[2].querySelector('.stat-value').innerHTML = '$' + stats.total_cost.toFixed(4);
// 模型统计表格
const modelHtml = `
<table>
<thead>
<tr>
<th>模型</th>
<th>会话数</th>
<th>输入Token</th>
<th>输出Token</th>
<th>成本</th>
</tr>
</thead>
<tbody>
${Object.entries(stats.by_model).map(([model, data]) => `
<tr>
<td>${getModelBadge(model)}</td>
<td>${data.count}</td>
<td>${data.input_tokens.toLocaleString()}</td>
<td>${data.output_tokens.toLocaleString()}</td>
<td>$${data.cost.toFixed(6)}</td>
</tr>
`).join('')}
</tbody>
</table>
`;
document.getElementById('model-stats').innerHTML = modelHtml;
})
.catch(err => {
console.error('Failed to load stats:', err);
});
}
function getModelBadge(model) {
let cls = 'badge';
if (model.includes('Qwen')) cls += ' badge-qwen';
else if (model.includes('DeepSeek')) cls += ' badge-deepseek';
else if (model.includes('GPT')) cls += ' badge-gpt';
else if (model.includes('Claude')) cls += ' badge-claude';
return `<span class="${cls}">${model}</span>`;
}
// 初始加载
loadSessions();
loadStats();
// 每30秒自动刷新
setInterval(() => {
loadSessions();
loadStats();
}, 30000);
</script>
</body>
</html>'''
def generate_session_html(self, session_id: str) -> str:
"""生成Session详情页HTML"""
session = self.load_session(session_id)
if not session:
return f'<html><body><h1>Session not found: {session_id}</h1></body></html>'
cost = self.calculate_cost(session)
# 生成对话轮次HTML
rounds_html = []
for r in session.get('rounds', []):
messages_html = ''
if r.get('messages'):
messages_html = '<div class="messages">'
for msg in r['messages'][-5:]: # 最多显示5条
role = msg.get('role', 'unknown')
content = msg.get('content', '')
messages_html += f'<div class="message message-{role}"><strong>[{role}]</strong> {self.escape_html(content)}</div>'
messages_html += '</div>'
tool_calls_html = ''
if r.get('tool_calls'):
tool_calls_html = '<div class="tool-calls"><strong>🛠️ Tool Calls:</strong><ul>'
for tc in r['tool_calls']:
func_name = tc.get('function', {}).get('name', 'unknown')
tool_calls_html += f'<li>{func_name}()</li>'
tool_calls_html += '</ul></div>'
# Token详情显示
token_details_html = ''
if r.get('input_token_details') or r.get('output_token_details'):
token_details_html = '<div class="token-details"><strong>📊 Token Details:</strong><ul>'
if r.get('input_token_details'):
token_details_html += f'<li>Input: {r["input_token_details"]}</li>'
if r.get('output_token_details'):
token_details_html += f'<li>Output: {r["output_token_details"]}</li>'
token_details_html += '</ul></div>'
# Token类型标签
token_badges = ''
if r.get('cached_tokens', 0) > 0:
token_badges += f' <span class="token-badge token-badge-cached">📦 {r["cached_tokens"]:,} cached</span>'
if r.get('reasoning_tokens', 0) > 0:
token_badges += f' <span class="token-badge token-badge-reasoning">🧠 {r["reasoning_tokens"]:,} reasoning</span>'
rounds_html.append(f'''
<div class="round">
<div class="round-header">
<span class="round-number">Round {r['round']}</span>
<span class="round-time">{r['timestamp']}</span>
<span class="round-tokens">{r['input_tokens']:,} in → {r['output_tokens']:,} out{token_badges}</span>
</div>
{messages_html}
{f'<div class="question"><strong>❓ Question:</strong> {self.escape_html(r.get("question", ""))}</div>' if r.get('question') else ''}
{f'<div class="answer"><strong>✅ Answer:</strong> {self.escape_html(r.get("answer", ""))}</div>' if r.get('answer') else ''}
{f'<div class="reasoning"><strong>🧠 Reasoning:</strong> {self.escape_html(r.get("reasoning", ""))}</div>' if r.get('reasoning') else ''}
{tool_calls_html}
{token_details_html}
</div>
''')
return f'''<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{session_id} - Session Monitor</title>
<style>
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
body {{
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #f5f5f5;
padding: 20px;
}}
.container {{ max-width: 1200px; margin: 0 auto; }}
header {{
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}}
h1 {{ color: #333; margin-bottom: 10px; font-size: 24px; }}
.back-link {{ color: #007bff; text-decoration: none; margin-bottom: 10px; display: inline-block; }}
.back-link:hover {{ text-decoration: underline; }}
.info-grid {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-top: 20px;
}}
.info-item {{ padding: 10px 0; }}
.info-label {{ color: #666; font-size: 14px; }}
.info-value {{ color: #333; font-size: 18px; font-weight: 600; margin-top: 4px; }}
.section {{
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
margin-bottom: 20px;
}}
h2 {{ color: #333; margin-bottom: 20px; font-size: 20px; }}
.round {{
border-left: 3px solid #007bff;
padding: 20px;
margin-bottom: 20px;
background: #f8f9fa;
border-radius: 4px;
}}
.round-header {{
display: flex;
justify-content: space-between;
margin-bottom: 15px;
font-size: 14px;
}}
.round-number {{ font-weight: 600; color: #007bff; }}
.round-time {{ color: #666; }}
.round-tokens {{ color: #333; }}
.messages {{ margin: 15px 0; }}
.message {{
padding: 10px;
margin: 5px 0;
border-radius: 4px;
font-size: 14px;
line-height: 1.6;
}}
.message-system {{ background: #fff3cd; }}
.message-user {{ background: #d1ecf1; }}
.message-assistant {{ background: #d4edda; }}
.message-tool {{ background: #e2e3e5; }}
.question, .answer, .reasoning, .tool-calls {{
margin: 10px 0;
padding: 10px;
background: white;
border-radius: 4px;
font-size: 14px;
line-height: 1.6;
}}
.question {{ border-left: 3px solid #ffc107; }}
.answer {{ border-left: 3px solid #28a745; }}
.reasoning {{ border-left: 3px solid #17a2b8; }}
.tool-calls {{ border-left: 3px solid #6c757d; }}
.tool-calls ul {{ margin-left: 20px; margin-top: 5px; }}
.token-details {{
margin: 10px 0;
padding: 10px;
background: white;
border-radius: 4px;
font-size: 13px;
border-left: 3px solid #17a2b8;
}}
.token-details ul {{ margin-left: 20px; margin-top: 5px; color: #666; }}
.token-badge {{
display: inline-block;
padding: 2px 6px;
border-radius: 3px;
font-size: 11px;
margin-left: 5px;
}}
.token-badge-cached {{
background: #d4edda;
color: #155724;
}}
.token-badge-reasoning {{
background: #cce5ff;
color: #004085;
}}
.badge {{
display: inline-block;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
font-weight: 500;
background: #e3f2fd;
color: #1976d2;
}}
</style>
</head>
<body>
<div class="container">
<header>
<a href="/" class="back-link">← 返回列表</a>
<h1>📊 Session Detail</h1>
<p style="color: #666; font-family: monospace; font-size: 14px; margin-top: 10px;">{session_id}</p>
<div class="info-grid">
<div class="info-item">
<div class="info-label">模型</div>
<div class="info-value"><span class="badge">{session.get('model', 'unknown')}</span></div>
</div>
<div class="info-item">
<div class="info-label">消息数</div>
<div class="info-value">{session.get('messages_count', 0)}</div>
</div>
<div class="info-item">
<div class="info-label">总Token</div>
<div class="info-value">{session['total_input_tokens'] + session['total_output_tokens']:,}</div>
</div>
<div class="info-item">
<div class="info-label">成本</div>
<div class="info-value">${cost:.6f}</div>
</div>
</div>
</header>
<div class="section">
<h2>💬 对话记录 ({len(session.get('rounds', []))} 轮)</h2>
{"".join(rounds_html) if rounds_html else '<p style="color: #666;">暂无对话记录</p>'}
</div>
</div>
</body>
</html>'''
def escape_html(self, text: str) -> str:
"""转义HTML特殊字符"""
return (text.replace('&', '&')
.replace('<', '<')
.replace('>', '>')
.replace('"', '"')
.replace("'", '''))
def log_message(self, format, *args):
"""重写日志方法,简化输出"""
pass # 不打印每个请求
def create_handler(data_dir):
"""创建带数据目录的处理器"""
def handler(*args, **kwargs):
return SessionMonitorHandler(*args, data_dir=data_dir, **kwargs)
return handler
def main():
parser = argparse.ArgumentParser(
description="Agent Session Monitor - Web Server",
formatter_class=argparse.RawDescriptionHelpFormatter
)
parser.add_argument(
'--data-dir',
default='./sessions',
help='Session数据目录(默认: ./sessions)'
)
parser.add_argument(
'--port',
type=int,
default=8888,
help='HTTP服务器端口(默认: 8888)'
)
parser.add_argument(
'--host',
default='0.0.0.0',
help='HTTP服务器地址(默认: 0.0.0.0)'
)
args = parser.parse_args()
# 检查数据目录是否存在
data_dir = Path(args.data_dir)
if not data_dir.exists():
print(f"❌ Error: Data directory not found: {data_dir}")
print(f" Please run main.py first to generate session data.")
sys.exit(1)
# 创建HTTP服务器
handler_class = create_handler(args.data_dir)
server = HTTPServer((args.host, args.port), handler_class)
print(f"{'=' * 60}")
print(f"🌐 Agent Session Monitor - Web Server")
print(f"{'=' * 60}")
print()
print(f"📂 Data directory: {args.data_dir}")
print(f"🌍 Server address: http://{args.host}:{args.port}")
print()
print(f"✅ Server started. Press Ctrl+C to stop.")
print(f"{'=' * 60}")
print()
try:
server.serve_forever()
except KeyboardInterrupt:
print("\n\n👋 Shutting down server...")
server.shutdown()
if __name__ == '__main__':
main()
================================================
FILE: .claude/skills/higress-auto-router/SKILL.md
================================================
---
name: higress-auto-router
description: "Configure automatic model routing using the get-ai-gateway.sh CLI tool for Higress AI Gateway. Use when: (1) User wants to configure automatic model routing, (2) User mentions 'route to', 'switch model', 'use model when', 'auto routing', (3) User describes scenarios that should trigger specific models, (4) User wants to add, list, or remove routing rules."
---
# Higress Auto Router
Configure automatic model routing using the get-ai-gateway.sh CLI tool for intelligent model selection based on message content triggers.
## Prerequisites
- Higress AI Gateway running (container name: `higress-ai-gateway`)
- get-ai-gateway.sh script downloaded
## CLI Commands
### Add a Routing Rule
```bash
./get-ai-gateway.sh route add --model <model-name> --trigger "<trigger-phrases>"
```
**Options:**
- `--model MODEL` (required): Target model to route to
- `--trigger PHRASE`: Trigger phrase(s), separated by `|` (e.g., `"深入思考|deep thinking"`)
- `--pattern REGEX`: Custom regex pattern (alternative to `--trigger`)
**Examples:**
```bash
# Route complex reasoning to Claude
./get-ai-gateway.sh route add \
--model claude-opus-4.5 \
--trigger "深入思考|deep thinking"
# Route coding tasks to Qwen Coder
./get-ai-gateway.sh route add \
--model qwen-coder \
--trigger "写代码|code:|coding:"
# Route creative writing
./get-ai-gateway.sh route add \
--model gpt-4o \
--trigger "创意写作|creative:"
# Use custom regex pattern
./get-ai-gateway.sh route add \
--model deepseek-chat \
--pattern "(?i)^(数学题|math:)"
```
### List Routing Rules
```bash
./get-ai-gateway.sh route list
```
Output:
```
Default model: qwen-turbo
ID Pattern Model
----------------------------------------------------------------------
0 (?i)^(深入思考|deep thinking) claude-opus-4.5
1 (?i)^(写代码|code:|coding:) qwen-coder
```
### Remove a Routing Rule
```bash
./get-ai-gateway.sh route remove --rule-id <id>
```
**Example:**
```bash
# Remove rule with ID 0
./get-ai-gateway.sh route remove --rule-id 0
```
## Common Trigger Mappings
| Scenario | Suggested Triggers | Recommended Model |
|----------|-------------------|-------------------|
| Complex reasoning | `深入思考\|deep thinking` | claude-opus-4.5, o1 |
| Coding tasks | `写代码\|code:\|coding:` | qwen-coder, deepseek-coder |
| Creative writing | `创意写作\|creative:` | gpt-4o, claude-sonnet |
| Translation | `翻译:\|translate:` | gpt-4o, qwen-max |
| Math problems | `数学题\|math:` | deepseek-r1, o1-mini |
| Quick answers | `快速回答\|quick:` | qwen-turbo, gpt-4o-mini |
## Usage Flow
1. **User Request:** "我希望在解决困难问题时路由到claude-opus-4.5"
2. **Execute CLI:**
```bash
./get-ai-gateway.sh route add \
--model claude-opus-4.5 \
--trigger "深入思考|deep thinking"
```
3. **Response to User:**
```
✅ 自动路由配置完成!
触发方式:以 "深入思考" 或 "deep thinking" 开头
目标模型:claude-opus-4.5
使用示例:
- 深入思考 这道算法题应该怎么解?
- deep thinking What's the best architecture?
提示:确保请求中 model 参数为 'higress/auto'
```
## How Auto-Routing Works
1. User sends request with `model: "higress/auto"`
2. Higress checks message content against routing rules
3. If a trigger pattern matches, routes to the specified model
4. If no match, uses the default model (e.g., `qwen-turbo`)
## Configuration File
Rules are stored in the container at:
```
/data/wasmplugins/model-router.internal.yaml
```
The CLI tool automatically:
- Edits the configuration file
- Triggers hot-reload (no container restart needed)
- Validates YAML syntax
## Error Handling
- **Container not running:** Start with `./get-ai-gateway.sh start`
- **Rule ID not found:** Use `route list` to see valid IDs
- **Invalid model:** Check configured providers in Higress Console
================================================
FILE: .claude/skills/higress-daily-report/README.md
================================================
# Higress 社区治理日报 - Clawdbot Skill
这个 skill 让 AI 助手通过 Clawdbot 自动追踪 Higress 项目的 GitHub 活动,并生成结构化的每日社区治理报告。
## 架构概览
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Clawdbot │────▶│ AI + Skill │────▶│ GitHub API │
│ (Gateway) │ │ │ │ (gh CLI) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │
│ ▼
│ ┌─────────────────┐
│ │ 数据文件 │
│ │ - tracking.json│
│ │ - knowledge.md │
│ └─────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Discord/Slack │◀────│ 日报输出 │
│ Channel │ │ │
└─────────────────┘ └─────────────────┘
```
## 什么是 Clawdbot?
[Clawdbot](https://github.com/clawdbot/clawdbot) 是一个 AI Agent 网关,可以将 Claude、GPT、GLM 等 AI 模型连接到各种消息平台(Discord、Slack、Telegram 等)和工具(GitHub CLI、浏览器、文件系统等)。
通过 Clawdbot,AI 助手可以:
- 接收来自 Discord 等平台的消息
- 执行 shell 命令(如 `gh` CLI)
- 读写文件
- 定时执行任务(cron)
- 将生成的内容发送回消息平台
## 工作流程
### 1. 定时触发
通过 Clawdbot 的 cron 功能,每天定时触发日报生成:
```
# Clawdbot 配置示例
cron:
- schedule: "0 9 * * *" # 每天早上 9 点
task: "生成 Higress 昨日日报并发送到 #issue-pr-notify 频道"
```
### 2. Skill 加载
当 AI 助手收到生成日报的指令时,会自动加载此 skill(SKILL.md),获取:
- 数据获取方法(gh CLI 命令)
- 数据结构定义
- 日报格式模板
- 知识库维护规则
### 3. 数据获取
AI 助手使用 GitHub CLI 获取数据:
```bash
# 获取昨日新建的 issues
gh search issues --repo alibaba/higress --created yesterday --json number,title,author,url,body,state,labels
# 获取昨日新建的 PRs
gh search prs --repo alibaba/higress --created yesterday --json number,title,author,url,body,state
# 获取特定 issue 的评论
gh api repos/alibaba/higress/issues/{number}/comments
```
### 4. 状态追踪
AI 助手维护一个 JSON 文件追踪每个 issue 的状态:
```json
{
"issues": [
{
"number": 3398,
"title": "浏览器发起的options请求报401",
"lastCommentCount": 13,
"status": "waiting_for_user",
"waitingFor": "用户验证解决方案"
}
]
}
```
### 5. 知识沉淀
当 issue 被解决时,AI 助手会将问题模式和解决方案记录到知识库:
```markdown
## KB-001: OPTIONS 预检请求被认证拦截
**问题**: 浏览器 OPTIONS 请求返回 401
**根因**: key-auth 在 AUTHN 阶段执行,先于 CORS
**解决方案**: 为 OPTIONS 请求创建单独路由,不启用认证插件
**关联 Issue**: #3398
```
### 6. 日报生成
最终生成结构化日报,包含:
- 📋 概览统计
- 📌 新增 Issues
- 🔀 新增 PRs
- 🔔 Issue 动态(新评论、已解决)
- ⏰ 跟进提醒
- 📚 知识沉淀
### 7. 消息推送
AI 助手通过 Clawdbot 将日报发送到指定的 Discord 频道。
## 快速开始
### 前置要求
1. 安装并配置 [Clawdbot](https://github.com/clawdbot/clawdbot)
2. 配置 GitHub CLI (`gh`) 并登录
3. 配置消息平台(如 Discord)
### 配置 Skill
将此 skill 目录复制到 Clawdbot 的 skills 目录:
```bash
cp -r .claude/skills/higress-daily-report ~/.clawdbot/skills/
```
### 使用方式
**手动触发:**
```
生成 Higress 昨日日报
```
**定时触发(推荐):**
在 Clawdbot 配置中添加 cron 任务,每天自动生成并推送日报。
## 文件说明
```
higress-daily-report/
├── README.md # 本文件
├── SKILL.md # Skill 定义(AI 助手读取)
└── scripts/
└── generate-report.sh # 辅助脚本(可选)
```
## 自定义
### 修改日报格式
编辑 `SKILL.md` 中的「日报格式」章节。
### 添加新的追踪维度
在 `SKILL.md` 的数据结构中添加新字段。
### 调整知识库规则
修改 `SKILL.md` 中的「知识沉淀」章节。
## 示例日报
```markdown
📊 Higress 项目每日报告 - 2026-01-29
📋 概览
• 新增 Issues: 2 个
• 新增 PRs: 3 个
• 待跟进: 1 个
📌 新增 Issues
• #3399: 网关启动失败问题
- 作者: user123
- 标签: bug
🔔 Issue 动态
✅ 已解决
• #3398: OPTIONS 请求 401 问题
- 知识库: KB-001
⏰ 跟进提醒
🟡 等待反馈
• #3396: 等待用户提供配置信息(2天)
```
## 相关链接
- [Clawdbot 文档](https://docs.clawd.bot)
- [Higress 项目](https://github.com/alibaba/higress)
- [GitHub CLI 文档](https://cli.github.com/manual/)
================================================
FILE: .claude/skills/higress-daily-report/SKILL.md
================================================
---
name: higress-daily-report
description: 生成 Higress 项目每日报告,追踪 issue/PR 动态,沉淀问题处理经验,驱动社区问题闭环。用于生成日报、跟进 issue、记录解决方案。
---
# Higress Daily Report
驱动 Higress 社区问题处理的智能工作流。
## 核心目标
1. **每日感知** - 追踪新 issues/PRs 和评论动态
2. **进度跟踪** - 确保每个 issue 被持续跟进直到关闭
3. **知识沉淀** - 积累问题分析和解决方案,提升处理能力
4. **闭环驱动** - 通过日报推动问题解决,避免遗忘
## 数据文件
| 文件 | 用途 |
|------|------|
| `/root/clawd/memory/higress-issue-tracking.json` | Issue 追踪状态(评论数、跟进状态) |
| `/root/clawd/memory/higress-knowledge-base.md` | 知识库:问题模式、解决方案、经验教训 |
| `/root/clawd/reports/report_YYYY-MM-DD.md` | 每日报告存档 |
## 工作流程
### 1. 获取每日数据
```bash
# 获取昨日 issues
gh search issues --repo alibaba/higress --created yesterday --json number,title,author,url,body,state,labels --limit 50
# 获取昨日 PRs
gh search prs --repo alibaba/higress --created yesterday --json number,title,author,url,body,state,additions,deletions,reviewDecision --limit 50
```
### 2. Issue 追踪状态管理
**追踪数据结构** (`higress-issue-tracking.json`):
```json
{
"date": "2026-01-28",
"issues": [
{
"number": 3398,
"title": "Issue 标题",
"state": "open",
"author": "username",
"url": "https://github.com/...",
"created_at": "2026-01-27",
"comment_count": 11,
"last_comment_by": "johnlanni",
"last_comment_at": "2026-01-28",
"follow_up_status": "waiting_user",
"follow_up_note": "等待用户提供请求日志",
"priority": "high",
"category": "cors",
"solution_ref": "KB-001"
}
]
}
```
**跟进状态枚举**:
- `new` - 新 issue,待分析
- `analyzing` - 正在分析中
- `waiting_user` - 等待用户反馈
- `waiting_review` - 等待 PR review
- `in_progress` - 修复进行中
- `resolved` - 已解决(待关闭)
- `closed` - 已关闭
- `wontfix` - 不予修复
- `stale` - 超过 7 天无活动
### 3. 知识库结构
**知识库** (`higress-knowledge-base.md`) 用于沉淀经验:
```markdown
# Higress 问题知识库
## 问题模式索引
### 认证与跨域类
- KB-001: OPTIONS 预检请求被认证拦截
- KB-002: CORS 配置不生效
### 路由配置类
- KB-010: 路由状态 address 为空
- KB-011: 服务发现失败
### 部署运维类
- KB-020: Helm 安装问题
- KB-021: 升级兼容性问题
---
## KB-001: OPTIONS 预检请求被认证拦截
**问题特征**:
- 浏览器 OPTIONS 请求返回 401
- 已配置 CORS 和认证插件
**根因分析**:
Higress 插件执行阶段优先级:AUTHN (310) > AUTHZ (340) > STATS
- key-auth 在 AUTHN 阶段执行
- CORS 在 AUTHZ 阶段执行
- OPTIONS 请求先被 key-auth 拦截,CORS 无机会处理
**解决方案**:
1. **推荐**:修改 CORS 插件 stage 从 AUTHZ 改为 AUTHN
2. **Workaround**:创建 OPTIONS 专用路由,不启用认证
3. **Workaround**:使用实例级 CORS 配置
**关联 Issue**:#3398
**学到的经验**:
- 排查跨域问题时,首先确认插件执行顺序
- Higress 阶段优先级由 phase 决定,不是 priority 数值
```
### 4. 日报生成规则
**报告结构**:
```markdown
# 📊 Higress 项目每日报告 - YYYY-MM-DD
## 📋 概览
- 统计时间: YYYY-MM-DD
- 新增 Issues: X 个
- 新增 PRs: X 个
- 待跟进 Issues: X 个
- 本周关闭: X 个
## 📌 新增 Issues
(按优先级排序,包含分类标签)
## 🔀 新增 PRs
(包含代码变更量和 review 状态)
## 🔔 Issue 动态
(有新评论的 issues,标注最新进展)
## ⏰ 跟进提醒
### 🔴 需要立即处理
(等待我方回复超过 24h 的 issues)
### 🟡 等待用户反馈
(等待用户回复的 issues,标注等待天数)
### 🟢 进行中
(正在处理的 issues)
### ⚪ 已过期
(超过 7 天无活动的 issues,需决定是否关闭)
## 📚 本周知识沉淀
(新增的知识库条目摘要)
```
### 5. 智能分析能力
生成日报时,对每个新 issue 进行初步分析:
1. **问题分类** - 根据标题和内容判断类别
2. **知识库匹配** - 检索相似问题的解决方案
3. **优先级评估** - 根据影响范围和紧急程度
4. **建议回复** - 基于知识库生成初步回复建议
### 6. Issue 跟进触发
当用户在 Discord 中提到以下关键词时触发跟进记录:
**完成跟进**:
- "已跟进 #xxx"
- "已回复 #xxx"
- "issue #xxx 已处理"
**记录解决方案**:
- "issue #xxx 的问题是..."
- "#xxx 根因是..."
- "#xxx 解决方案..."
触发后更新追踪状态和知识库。
## 执行检查清单
每次生成日报时:
- [ ] 获取昨日新 issues 和 PRs
- [ ] 加载追踪数据,检查评论变化
- [ ] 对比 `last_comment_by` 判断是等待用户还是等待我方
- [ ] 超过 7 天无活动的 issue 标记为 stale
- [ ] 检索知识库,为新 issue 匹配相似问题
- [ ] 生成报告并保存到 `/root/clawd/reports/`
- [ ] 更新追踪数据
- [ ] 发送到 Discord channel:1465549185632702591
- [ ] 格式:使用列表而非表格(Discord 不支持 Markdown 表格)
## 知识库维护
### 新增条目时机
1. Issue 被成功解决后
2. 发现新的问题模式
3. 踩坑后的经验总结
### 条目模板
```markdown
## KB-XXX: 问题简述
**问题特征**:
- 症状1
- 症状2
**根因分析**:
(技术原因说明)
**解决方案**:
1. 推荐方案
2. 备选方案
**关联 Issue**:#xxx
**学到的经验**:
- 经验1
- 经验2
```
## 命令参考
```bash
# 查看 issue 详情和评论
gh issue view <number> --repo alibaba/higress --json number,title,state,comments,author,createdAt,labels,url
# 查看 issue 评论
gh issue view <number> --repo alibaba/higress --comments
# 发送 issue 评论
gh issue comment <number> --repo alibaba/higress --body "评论内容"
# 关闭 issue
gh issue close <number> --repo alibaba/higress --reason completed
# 添加标签
gh issue edit <number> --repo alibaba/higress --add-label "bug"
```
## Discord 输出
- 频道: `channel:1465549185632702591`
- 格式: 纯文本 + emoji + 链接(用 `<url>` 抑制预览)
- 长度: 单条消息不超过 2000 字符,超过则分多条发送
================================================
FILE: .claude/skills/higress-daily-report/scripts/generate-report.sh
================================================
#!/bin/bash
# Higress Daily Report Generator
# Generates daily report for alibaba/higress repository
# set -e # 临时禁用以调试
REPO="alibaba/higress"
CHANNEL="1465549185632702591"
DATE=$(date +"%Y-%m-%d")
REPORT_DIR="/root/clawd/reports"
TRACKING_DIR="/root/clawd/memory"
RECORD_FILE="${TRACKING_DIR}/higress-issue-process-record.md"
mkdir -p "$REPORT_DIR" "$TRACKING_DIR"
echo "=== Higress Daily Report - $DATE ==="
# Get yesterday's date
YESTERDAY=$(date -d "yesterday" +"%Y-%m-%d" 2>/dev/null || date -v-1d +"%Y-%m-%d")
echo "Fetching issues created on $YESTERDAY..."
# Fetch issues created yesterday
ISSUES=$(gh search issues --repo "${REPO}" --state open --created "${YESTERDAY}..${YESTERDAY}" --json number,title,labels,author,url,body,state --limit 50 2>/dev/null)
if [ -z "$ISSUES" ]; then
ISSUES_COUNT=0
else
ISSUES_COUNT=$(echo "$ISSUES" | jq 'length' 2>/dev/null || echo "0")
fi
# Fetch PRs created yesterday
PRS=$(gh search prs --repo "${REPO}" --state open --created "${YESTERDAY}..${YESTERDAY}" --json number,title,labels,author,url,reviewDecision,additions,deletions,body,state --limit 50 2>/dev/null)
if [ -z "$PRS" ]; then
PRS_COUNT=0
else
PRS_COUNT=$(echo "$PRS" | jq 'length' 2>/dev/null || echo "0")
fi
echo "Found: $ISSUES_COUNT issues, $PRS_COUNT PRs"
# Build report
REPORT="📊 **Higress 项目每日报告 - ${DATE}**
**📋 概览**
- 统计时间: ${YESTERDAY} 全天
- 新增 Issues: **${ISSUES_COUNT}** 个
- 新增 PRs: **${PRS_COUNT}** 个
---
"
# Process issues
if [ "$ISSUES_COUNT" -gt 0 ]; then
REPORT="${REPORT}**📌 Issues 详情**
"
# Use a temporary file to avoid subshell variable scoping issues
ISSUE_DETAILS=$(mktemp)
echo "$ISSUES" | jq -r '.[] | @json' | while IFS= read -r ISSUE; do
NUM=$(echo "$ISSUE" | jq -r '.number')
TITLE=$(echo "$ISSUE" | jq -r '.title')
URL=$(echo "$ISSUE" | jq -r '.url')
AUTHOR=$(echo "$ISSUE" | jq -r '.author.login')
BODY=$(echo "$ISSUE" | jq -r '.body // ""')
LABELS=$(echo "$ISSUE" | jq -r '.labels[]?.name // ""' | head -1)
# Determine emoji
EMOJI="📝"
echo "$LABELS" | grep -q "priority/high" && EMOJI="🔴"
echo "$LABELS" | grep -q "type/bug" && EMOJI="🐛"
echo "$LABELS" | grep -q "type/enhancement" && EMOJI="✨"
# Extract content
CONTENT=$(echo "$BODY" | head -n 8 | sed 's/```.*```//g' | sed 's/`//g' | tr '\n' ' ' | head -c 300)
if [ -z "$CONTENT" ]; then
CONTENT="无详细描述"
fi
if [ ${#CONTENT} -eq 300 ]; then
CONTENT="${CONTENT}..."
fi
# Append to temporary file
echo "${EMOJI} **[#${NUM}](${URL})**: ${TITLE}
👤 @${AUTHOR}
📝 ${CONTENT}
" >> "$ISSUE_DETAILS"
done
# Read from temp file and append to REPORT
REPORT="${REPORT}$(cat $ISSUE_DETAILS)"
rm -f "$ISSUE_DETAILS"
fi
REPORT="${REPORT}
---
"
# Process PRs
if [ "$PRS_COUNT" -gt 0 ]; then
REPORT="${REPORT}**🔀 PRs 详情**
"
# Use a temporary file to avoid subshell variable scoping issues
PR_DETAILS=$(mktemp)
echo "$PRS" | jq -r '.[] | @json' | while IFS= read -r PR; do
NUM=$(echo "$PR" | jq -r '.number')
TITLE=$(echo "$PR" | jq -r '.title')
URL=$(echo "$PR" | jq -r '.url')
AUTHOR=$(echo "$PR" | jq -r '.author.login')
ADDITIONS=$(echo "$PR" | jq -r '.additions')
DELETIONS=$(echo "$PR" | jq -r '.deletions')
REVIEW=$(echo "$PR" | jq -r '.reviewDecision // "pending"')
BODY=$(echo "$PR" | jq -r '.body // ""')
# Determine status
STATUS="👀"
[ "$REVIEW" = "APPROVED" ] && STATUS="✅"
[ "$REVIEW" = "CHANGES_REQUESTED" ] && STATUS="🔄"
# Calculate size
TOTAL=$((ADDITIONS + DELETIONS))
SIZE="M"
[ $TOTAL -lt 100 ] && SIZE="XS"
[ $TOTAL -lt 500 ] && SIZE="S"
[ $TOTAL -lt 1000 ] && SIZE="M"
[ $TOTAL -lt 5000 ] && SIZE="L"
[ $TOTAL -ge 5000 ] && SIZE="XL"
# Extract content
CONTENT=$(echo "$BODY" | head -n 8 | sed 's/```.*```//g' | sed 's/`//g' | tr '\n' ' ' | head -c 300)
if [ -z "$CONTENT" ]; then
CONTENT="无详细描述"
fi
if [ ${#CONTENT} -eq 300 ]; then
CONTENT="${CONTENT}..."
fi
# Append to temporary file
echo "${STATUS} **[#${NUM}](${URL})**: ${TITLE} ${SIZE}
👤 @${AUTHOR} | ${STATUS} | 变更: +${ADDITIONS}/-${DELETIONS}
📝 ${CONTENT}
" >> "$PR_DETAILS"
done
# Read from temp file and append to REPORT
REPORT="${REPORT}$(cat $PR_DETAILS)"
rm -f "$PR_DETAILS"
fi
# Check for new comments on tracked issues
TRACKING_FILE="${TRACKING_DIR}/higress-issue-tracking.json"
echo ""
echo "Checking for new comments on tracked issues..."
# Load previous tracking data
if [ -f "$TRACKING_FILE" ]; then
PREV_TRACKING=$(cat "$TRACKING_FILE")
PREV_ISSUES=$(echo "$PREV_TRACKING" | jq -r '.issues[]?.number // empty' 2>/dev/null)
if [ -n "$PREV_ISSUES" ]; then
REPORT="${REPORT}**🔔 Issue跟进(新评论)**"
HAS_NEW_COMMENTS=false
for issue_num in $PREV_ISSUES; do
# Get current comment count
CURRENT_INFO=$(gh issue view "$issue_num" --repo "$REPO" --json number,title,state,comments,url 2>/dev/null)
if [ -n "$CURRENT_INFO" ]; then
CURRENT_COUNT=$(echo "$CURRENT_INFO" | jq '.comments | length')
CURRENT_TITLE=$(echo "$CURRENT_INFO" | jq -r '.title')
CURRENT_STATE=$(echo "$CURRENT_INFO" | jq -r '.state')
ISSUE_URL=$(echo "$CURRENT_INFO" | jq -r '.url')
PREV_COUNT=$(echo "$PREV_TRACKING" | jq -r ".issues[] | select(.number == $issue_num) | .comment_count // 0")
if [ -z "$PREV_COUNT" ]; then
PREV_COUNT=0
fi
NEW_COMMENTS=$((CURRENT_COUNT - PREV_COUNT))
if [ "$NEW_COMMENTS" -gt 0 ]; then
HAS_NEW_COMMENTS=true
REPORT="${REPORT}
• [#${issue_num}](${ISSUE_URL}) ${CURRENT_TITLE}
📬 +${NEW_COMMENTS}条新评论(总计: ${CURRENT_COUNT}) | 状态: ${CURRENT_STATE}"
fi
fi
done
if [ "$HAS_NEW_COMMENTS" = false ]; then
REPORT="${REPORT}
• 暂无新评论"
fi
REPORT="${REPORT}
---
"
fi
fi
# Save current tracking data for tomorrow
echo "Saving issue tracking data for follow-up..."
if [ -z "$ISSUES" ]; then
TRACKING_DATA='{"date":"'"$DATE"'","issues":[]}'
else
TRACKING_DATA=$(echo "$ISSUES" | jq '{
date: "'"$DATE"'",
issues: [.[] | {
number: .number,
title: .title,
state: .state,
comment_count: 0,
url: .url
}]
}')
fi
echo "$TRACKING_DATA" > "$TRACKING_FILE"
echo "Tracking data saved to $TRACKING_FILE"
# Save report to file
REPORT_FILE="${REPORT_DIR}/report_${DATE}.md"
echo "$REPORT" > "$REPORT_FILE"
echo "Report saved to $REPORT_FILE"
# Follow-up reminder
FOLLOWUP_ISSUES=$(echo "$PREV_TRACKING" | jq -r '[.issues[] | select(.comment_count > 0 or .state == "open")] | "#\(.number) [\(.title)]"' 2>/dev/null || echo "")
if [ -n "$FOLLOWUP_ISSUES" ]; then
REPORT="${REPORT}
**📌 需要跟进的Issues**
以下Issues需要跟进处理:
${FOLLOWUP_ISSUES}
---
"
fi
# Footer
REPORT="${REPORT}
---
📅 生成时间: $(date +"%Y-%m-%d %H:%M:%S %Z")
🔗 项目: https://github.com/${REPO}
🤖 本报告由 AI 辅助生成,所有链接均可点击跳转
"
# Send report
echo "Sending report to Discord..."
echo "$REPORT" | /root/.nvm/versions/node/v24.13.0/bin/clawdbot message send --channel discord -t "$CHANNEL" -m "$(cat -)"
echo "Done!"
================================================
FILE: .claude/skills/higress-openclaw-integration/SKILL.md
================================================
---
name: higress-openclaw-integration
description: "Deploy and configure Higress AI Gateway for OpenClaw integration. Use when: (1) User wants to deploy Higress AI Gateway, (2) User wants to configure OpenClaw to use more model providers, (3) User mentions 'higress', 'ai gateway', 'model gateway', 'AI网关', (4) User wants to set up model routing or auto-routing, (5) User needs to manage LLM provider API keys."
---
# Higress AI Gateway Integration
Deploy Higress AI Gateway and configure OpenClaw to use it as a unified model provider.
## Quick Start
### Step 1: Collect Information from User
**Ask the user for the following information upfront:**
1. **Which LLM provider(s) to use?** (at least one required)
**Commonly Used Providers:**
| Provider | Parameter | Notes |
|----------|-----------|-------|
| 智谱 / z.ai | `--zhipuai-key` | Models: glm-*, Code Plan mode enabled by default |
| Claude Code | `--claude-code-key` | **Requires OAuth token from `claude setup-token`** |
| Moonshot (Kimi) | `--moonshot-key` | Models: moonshot-*, kimi-* |
| Minimax | `--minimax-key` | Models: abab-* |
| 阿里云通义千问 (Dashscope) | `--dashscope-key` | Models: qwen* |
| OpenAI | `--openai-key` | Models: gpt-*, o1-*, o3-* |
| DeepSeek | `--deepseek-key` | Models: deepseep-* |
| Grok | `--grok-key` | Models: grok-* |
**Other Providers:**
| Provider | Parameter | Notes |
|----------|-----------|-------|
| Claude | `--claude-key` | Models: claude-* |
| Google Gemini | `--gemini-key` | Models: gemini-* |
| OpenRouter | `--openrouter-key` | Supports all models (catch-all) |
| Groq | `--groq-key` | Fast inference |
| Doubao (豆包) | `--doubao-key` | Models: doubao-* |
| Mistral | `--mistral-key` | Models: mistral-* |
| Baichuan (百川) | `--baichuan-key` | Models: Baichuan* |
| 01.AI (Yi) | `--yi-key` | Models: yi-* |
| Stepfun (阶跃星辰) | `--stepfun-key` | Models: step-* |
| Cohere | `--cohere-key` | Models: command* |
| Fireworks AI | `--fireworks-key` | - |
| Together AI | `--togetherai-key` | - |
| GitHub Models | `--github-key` | - |
**Cloud Providers (require additional config):**
- Azure OpenAI: `--azure-key` (requires service URL)
- AWS Bedrock: `--bedrock-key` (requires region and access key)
- Google Vertex AI: `--vertex-key` (requires project ID and region)
**Brand Name Display (z.ai / 智谱):**
- If user communicates in Chinese: display as "智谱"
- If user communicates in English: display as "z.ai"
2. **Enable auto-routing?** (recommended)
- If yes: `--auto-routing --auto-routing-default-model <model-name>`
- Auto-routing allows using `model="higress/auto"` to automatically route requests based on message content
3. **Custom ports?** (optional, defaults: HTTP=8080, HTTPS=8443, Console=8001)
### Step 2: Deploy Gateway
**Auto-detect region for z.ai / 智谱 domain configuration:**
When user selects z.ai / 智谱 provider, detect their region:
```bash
# Run region detection script (scripts/detect-region.sh relative to skill directory)
REGION=$(bash scripts/detect-region.sh)
# Output: "china" or "international"
```
**Based on detection result:**
- If `REGION="china"`: use default domain `open.bigmodel.cn`, no extra parameter needed
- If `REGION="international"`: automatically add `--zhipuai-domain api.z.ai` to deployment command
**After deployment (for international users):**
Notify user in English: "The z.ai endpoint domain has been set to api.z.ai. If you want to change it, let me know and I can update the configuration."
```bash
# Create installation directory
mkdir -p higress-install
cd higress-install
# Download script (if not exists)
curl -fsSL https://higress.ai/ai-gateway/install.sh -o get-ai-gateway.sh
chmod +x get-ai-gateway.sh
# Deploy with user's configuration
# For z.ai / 智谱: always include --zhipuai-code-plan-mode
# For non-China users: include --zhipuai-domain api.z.ai
./get-ai-gateway.sh start --non-interactive \
--<provider>-key <api-key> \
[--auto-routing --auto-routing-default-model <model>]
```
**z.ai / 智谱 Options:**
| Option | Description |
|--------|-------------|
| `--zhipuai-code-plan-mode` | Enable Code Plan mode (enabled by default) |
| `--zhipuai-domain <domain>` | Custom domain, default: `open.bigmodel.cn` (China), `api.z.ai` (international) |
**Example (China user):**
```bash
./get-ai-gateway.sh start --non-interactive \
--zhipuai-key sk-xxx \
--zhipuai-code-plan-mode \
--auto-routing \
--auto-routing-default-model glm-5
```
**Example (International user):**
```bash
./get-ai-gateway.sh start --non-interactive \
--zhipuai-key sk-xxx \
--zhipuai-domain api.z.ai \
--zhipuai-code-plan-mode \
--auto-routing \
--auto-routing-default-model glm-5
```
### Step 3: Install OpenClaw Plugin
Install the Higress provider plugin for OpenClaw:
```bash
# Copy plugin files (PLUGIN_SRC is relative to skill directory: scripts/plugin)
PLUGIN_SRC="scripts/plugin"
PLUGIN_DEST="$HOME/.openclaw/extensions/higress"
mkdir -p "$PLUGIN_DEST"
cp -r "$PLUGIN_SRC"/* "$PLUGIN_DEST/"
```
**Tell user to run the following commands manually in their terminal (interactive commands, cannot be executed by AI agent):**
```bash
# Step 1: Enable the plugin
openclaw plugins enable higress
# Step 2: Configure provider (interactive - will prompt for Gateway URL, API Key, models, etc.)
openclaw models auth login --provider higress --set-default
# Step 3: Restart OpenClaw gateway to apply changes
openclaw gateway restart
```
The `openclaw models auth login` command will interactively prompt for:
1. Gateway URL (default: `http://localhost:8080`)
2. Console URL (default: `http://localhost:8001`)
3. API Key (optional for local deployments)
4. Model list (auto-detected or manually specified)
5. Auto-routing default model (if using `higress/auto`)
After configuration and restart, Higress models are available in OpenClaw with `higress/` prefix (e.g., `higress/glm-5`, `higress/auto`).
**Future Configuration Updates (No Restart Needed)**
After the initial setup, you can manage your configuration through conversation with OpenClaw:
- **Add New Providers**: Add new LLM providers (e.g., DeepSeek, OpenAI, Claude) and their models dynamically.
- **Update API Keys**: Update existing provider API keys without service restart.
- **Configure Auto-routing**: If you've set up multiple models, ask OpenClaw to configure auto-routing rules. Requests will be intelligently routed based on your message content, using the most suitable model automatically.
All configuration changes are hot-loaded through Higress — no `openclaw gateway restart` required. Iterate on your model provider setup dynamically without service interruption!
## Post-Deployment Management
### Add/Update API Keys (Hot-reload)
```bash
./get-ai-gateway.sh config add --provider <provider> --key <api-key>
./get-ai-gateway.sh config list
./get-ai-gateway.sh config remove --provider <provider>
```
Provider aliases: `dashscope`/`qwen`, `moonshot`/`kimi`, `zhipuai`/`zhipu`
### Update z.ai Domain (Hot-reload)
If user wants to change the z.ai domain after deployment:
```bash
# Update domain configuration
./get-ai-gateway.sh config add --provider zhipuai --extra-config "zhipuDomain=api.z.ai"
# Or revert to China endpoint
./get-ai-gateway.sh config add --provider zhipuai --extra-config "zhipuDomain=open.bigmodel.cn"
```
### Add Routing Rules (for auto-routing)
```bash
# Add rule: route to specific model when message starts with trigger
./get-ai-gateway.sh route add --model <model> --trigger "keyword1|keyword2"
# Examples
./get-ai-gateway.sh route add --model glm-4-flash --trigger "quick|fast"
./get-ai-gateway.sh route add --model claude-opus-4 --trigger "think|complex"
./get-ai-gateway.sh route add --model deepseek-coder --trigger "code|debug"
# List/remove rules
./get-ai-gateway.sh route list
./get-ai-gateway.sh route remove --rule-id 0
```
### Stop/Delete Gateway
```bash
./get-ai-gateway.sh stop
./get-ai-gateway.sh delete
```
## Endpoints
| Endpoint | URL |
|----------|-----|
| Chat Completions | http://localhost:8080/v1/chat/completions |
| Console | http://localhost:8001 |
| Logs | `./higress-install/logs/access.log` |
## Testing
```bash
# Test with specific model
curl 'http://localhost:8080/v1/chat/completions' \
-H 'Content-Type: application/json' \
-d '{"model": "<model-name>", "messages": [{"role": "user", "content": "Hello"}]}'
# Test auto-routing (if enabled)
curl 'http://localhost:8080/v1/chat/completions' \
-H 'Content-Type: application/json' \
-d '{"model": "higress/auto", "messages": [{"role": "user", "content": "What is AI?"}]}'
```
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Container fails to start | Check `docker logs higress-ai-gateway` |
| Port already in use | Use `--http-port`, `--console-port` to change ports |
| API key error | Run `./get-ai-gateway.sh config list` to verify keys |
| Auto-routing not working | Ensure `--auto-routing` was set during deployment |
| Slow image download | Script auto-selects nearest registry based on timezone |
## Important Notes
1. **Claude Code Mode**: Requires OAuth token from `claude setup-token` command, not a regular API key
2. **z.ai Code Plan Mode**: Enabled by default, uses `/api/coding/paas/v4/chat/completions` endpoint, optimized for coding tasks
3. **z.ai Domain Selection**:
- China users: `open.bigmodel.cn` (default)
- International users: `api.z.ai` (auto-detected based on timezone)
- Users can update domain anytime after deployment
4. **Auto-routing**: Must be enabled during initial deployment (`--auto-routing`); routing rules can be added later
5. **OpenClaw Integration**: The `openclaw models auth login` and `openclaw gateway restart` commands are **interactive** and must be run by the user manually in their terminal
6. **Hot-reload**: API key changes take effect immediately; no container restart needed
================================================
FILE: .claude/skills/higress-openclaw-integration/references/TROUBLESHOOTING.md
================================================
# Higress AI Gateway - Troubleshooting
Common issues and solutions for Higress AI Gateway deployment and operation.
## Container Issues
### Container fails to start
**Check Docker is running:**
```bash
docker info
```
**Check port availability:**
```bash
netstat -tlnp | grep 8080
```
**View container logs:**
```bash
docker logs higress-ai-gateway
```
### Gateway not responding
**Check container status:**
```bash
docker ps -a
```
**Verify port mapping:**
```bash
docker port higress-ai-gateway
```
**Test locally:**
```bash
curl http://localhost:8080/v1/models
```
## File System Issues
### "too many open files" error from API server
**Symptom:**
```
panic: unable to create REST storage for a resource due to too many open files, will die
```
or
```
command failed err="failed to create shared file watcher: too many open files"
```
**Root Cause:**
The system's `fs.inotify.max_user_instances` limit is too low. This commonly occurs on systems with many Docker containers, as each container can consume inotify instances.
**Check current limit:**
```bash
cat /proc/sys/fs/inotify/max_user_instances
```
Default is often 128, which is insufficient when running multiple containers.
**Solution:**
Increase the inotify instance limit to 8192:
```bash
# Temporarily (until next reboot)
sudo sysctl -w fs.inotify.max_user_instances=8192
# Permanently (survives reboots)
echo "fs.inotify.max_user_instances = 8192" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```
**Verify:**
```bash
cat /proc/sys/fs/inotify/max_user_instances
# Should output: 8192
```
**Restart the container:**
```bash
docker restart higress-ai-gateway
```
**Additional inotify tunables** (if still experiencing issues):
```bash
# Increase max watches per user
sudo sysctl -w fs.inotify.max_user_watches=524288
# Increase max queued events
sudo sysctl -w fs.inotify.max_queued_events=32768
```
To make these permanent as well:
```bash
echo "fs.inotify.max_user_watches = 524288" | sudo tee -a /etc/sysctl.conf
echo "fs.inotify.max_queued_events = 32768" | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```
## Plugin Issues
### Plugin not recognized
**Verify plugin installation:**
For Clawdbot:
```bash
ls -la ~/.clawdbot/extensions/higress-ai-gateway
```
For OpenClaw:
```bash
ls -la ~/.openclaw/extensions/higress-ai-gateway
```
**Check package.json:**
Ensure `package.json` contains the correct extension field:
- Clawdbot: `"clawdbot.extensions"`
- OpenClaw: `"openclaw.extensions"`
**Restart the runtime:**
```bash
# Restart Clawdbot gateway
clawdbot gateway restart
# Or OpenClaw gateway
openclaw gateway restart
```
## Routing Issues
### Auto-routing not working
**Confirm model is in list:**
```bash
# Check if higress/auto is available
clawdbot models list | grep "higress/auto"
```
**Check routing rules exist:**
```bash
./get-ai-gateway.sh route list
```
**Verify default model is configured:**
```bash
./get-ai-gateway.sh config list
```
**Check gateway logs:**
```bash
docker logs higress-ai-gateway | grep -i routing
```
**View access logs:**
```bash
tail -f ./higress/logs/access.log
```
## Configuration Issues
### Timezone detection fails
**Manually check timezone:**
```bash
timedatectl show --property=Timezone --value
```
**Or check timezone file:**
```bash
cat /etc/timezone
```
**Fallback behavior:**
- If detection fails, defaults to Hangzhou mirror
- Manual override: Set `IMAGE_REPO` environment variable
**Manual repository selection:**
```bash
# For China/Asia
IMAGE_REPO="higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/all-in-one"
# For Southeast Asia
IMAGE_REPO="higress-registry.ap-southeast-7.cr.aliyuncs.com/higress/all-in-one"
# For North America
IMAGE_REPO="higress-registry.us-west-1.cr.aliyuncs.com/higress/all-in-one"
# Use in deployment
IMAGE_REPO="$IMAGE_REPO" ./get-ai-gateway.sh start --non-interactive ...
```
## Performance Issues
### Slow image downloads
**Check selected repository:**
```bash
echo $IMAGE_REPO
```
**Manually select closest mirror:**
See [Configuration Issues → Timezone detection fails](#timezone-detection-fails) for manual repository selection.
### High memory usage
**Check container stats:**
```bash
docker stats higress-ai-gateway
```
**View resource limits:**
```bash
docker inspect higress-ai-gateway | grep -A 10 "HostConfig"
```
**Set memory limits:**
```bash
# Stop container
./get-ai-gateway.sh stop
# Manually restart with limits
docker run -d \
--name higress-ai-gateway \
--memory="4g" \
--memory-swap="4g" \
...
```
## Log Analysis
### Access logs location
```bash
# Default location
./higress/logs/access.log
# View real-time logs
tail -f ./higress/logs/access.log
```
### Container logs
```bash
# View all logs
docker logs higress-ai-gateway
# Follow logs
docker logs -f higress-ai-gateway
# Last 100 lines
docker logs --tail 100 higress-ai-gateway
# With timestamps
docker logs -t higress-ai-gateway
```
## Network Issues
### Cannot connect to gateway
**Verify container is running:**
```bash
docker ps | grep higress-ai-gateway
```
**Check port bindings:**
```bash
docker port higress-ai-gateway
```
**Test from inside container:**
```bash
docker exec higress-ai-gateway curl localhost:8080/v1/models
```
**Check firewall rules:**
```bash
# Check if port is accessible
sudo ufw status | grep 8080
# Allow port (if needed)
sudo ufw allow 8080/tcp
```
### DNS resolution issues
**Test from container:**
```bash
docker exec higress-ai-gateway ping -c 3 api.openai.com
```
**Check DNS settings:**
```bash
docker exec higress-ai-gateway cat /etc/resolv.conf
```
## Getting Help
If you're still experiencing issues:
1. **Collect logs:**
```bash
docker logs higress-ai-gateway > gateway.log 2>&1
cat ./higress/logs/access.log > access.log
```
2. **Check system info:**
```bash
docker version
docker info
uname -a
cat /proc/sys/fs/inotify/max_user_instances
```
3. **Report issue:**
- Repository: https://github.com/higress-group/higress-standalone
- Include: logs, system info, deployment command used
================================================
FILE: .claude/skills/higress-openclaw-integration/scripts/detect-region.sh
================================================
#!/bin/bash
# Detect if user is in China region based on timezone
# Returns: "china" or "international"
TIMEZONE=$(cat /etc/timezone 2>/dev/null || timedatectl show --property=Timezone --value 2>/dev/null || echo "Unknown")
# Check if timezone indicates China region (including Hong Kong)
if [[ "$TIMEZONE" == "Asia/Shanghai" ]] || \
[[ "$TIMEZONE" == "Asia/Hong_Kong" ]] || \
[[ "$TIMEZONE" == *"China"* ]] || \
[[ "$TIMEZONE" == *"Beijing"* ]]; then
echo "china"
else
echo "international"
fi
================================================
FILE: .claude/skills/higress-openclaw-integration/scripts/plugin/README.md
================================================
# Higress AI Gateway Plugin
OpenClaw model provider plugin for Higress AI Gateway with auto-routing support.
## What is this?
This is a TypeScript-based provider plugin that enables OpenClaw to use Higress AI Gateway as a model provider. It provides:
- **Auto-routing support**: Use `higress/auto` to intelligently route requests based on message content
- **Dynamic model discovery**: Auto-detect available models from Higress Console
- **Smart URL handling**: Automatic URL normalization and validation
- **Flexible authentication**: Support for both local and remote gateway deployments
## Files
- **index.ts**: Main plugin implementation
- **package.json**: NPM package metadata and OpenClaw extension declaration
- **openclaw.plugin.json**: Plugin manifest for OpenClaw
## Installation
This plugin is automatically installed when you use the `higress-openclaw-integration` skill. See parent SKILL.md for complete installation instructions.
### Manual Installation
If you need to install manually:
```bash
# Copy plugin files
mkdir -p "$HOME/.openclaw/extensions/higress"
cp -r ./* "$HOME/.openclaw/extensions/higress/"
# Configure provider
openclaw plugins enable higress
openclaw models auth login --provider higress
```
## Usage
After installation, configure Higress as a model provider:
```bash
openclaw models auth login --provider higress
```
The plugin will prompt for:
1. Gateway URL (default: http://localhost:8080)
2. Console URL (default: http://localhost:8001)
3. API Key (optional for local deployments)
4. Model list (auto-detected or manually specified)
5. Auto-routing default model (if using higress/auto)
## Related Resources
- **Parent Skill**: [higress-openclaw-integration](../SKILL.md)
- **Auto-routing Configuration**: [higress-auto-router](../../higress-auto-router/SKILL.md)
## License
Apache-2.0
================================================
FILE: .claude/skills/higress-openclaw-integration/scripts/plugin/index.ts
================================================
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
const DEFAULT_GATEWAY_URL = "http://localhost:8080";
const DEFAULT_CONSOLE_URL = "http://localhost:8001";
// Model-specific context window and max tokens configurations
const MODEL_CONFIG: Record<string, { contextWindow: number; maxTokens: number }> = {
"gpt-5.3-codex": { contextWindow: 400_000, maxTokens: 128_000 },
"gpt-5-mini": { contextWindow: 400_000, maxTokens: 128_000 },
"gpt-5-nano": { contextWindow: 400_000, maxTokens: 128_000 },
"claude-opus-4-6": { contextWindow: 1_000_000, maxTokens: 128_000 },
"claude-sonnet-4-6": { contextWindow: 1_000_000, maxTokens: 64_000 },
"claude-haiku-4-5": { contextWindow: 200_000, maxTokens: 64_000 },
"qwen3.5-plus": { contextWindow: 960_000, maxTokens: 64_000 },
"deepseek-chat": { contextWindow: 256_000, maxTokens: 128_000 },
"deepseek-reasoner": { contextWindow: 256_000, maxTokens: 128_000 },
"kimi-k2.5": { contextWindow: 256_000, maxTokens: 128_000 },
"glm-5": { contextWindow: 200_000, maxTokens: 128_000 },
"MiniMax-M2.5": { contextWindow: 200_000, maxTokens: 128_000 },
};
// Default values for unknown models
const DEFAULT_CONTEXT_WINDOW = 200_000;
const DEFAULT_MAX_TOKENS = 128_000;
// Common models that Higress AI Gateway typically supports
const DEFAULT_MODEL_IDS = [
// Auto-routing special model
"higress/auto",
// Commonly models
"kimi-k2.5",
"glm-5",
"MiniMax-M2.5",
"qwen3.5-plus",
// Anthropic models
"claude-opus-4-6",
"claude-sonnet-4-6",
"claude-haiku-4-5",
// OpenAI models
"gpt-5.3-codex",
"gpt-5-mini",
"gpt-5-nano",
// DeepSeek models
"deepseek-chat",
"deepseek-reasoner",
] as const;
function normalizeBaseUrl(value: string): string {
const trimmed = value.trim();
if (!trimmed) return DEFAULT_GATEWAY_URL;
let normalized = trimmed;
while (normalized.endsWith("/")) normalized = normalized.slice(0, -1);
if (!normalized.endsWith("/v1")) normalized = `${normalized}/v1`;
return normalized;
}
function validateUrl(value: string): string | undefined {
const normalized = normalizeBaseUrl(value);
try {
new URL(normalized);
} catch {
return "Enter a valid URL";
}
return undefined;
}
function parseModelIds(input: string): string[] {
const parsed = input
.split(/[\n,]/)
.map((model) => model.trim())
.filter(Boolean);
return Array.from(new Set(parsed));
}
function buildModelDefinition(modelId: string) {
const isAutoModel = modelId === "higress/auto";
const config = MODEL_CONFIG[modelId] || { contextWindow: DEFAULT_CONTEXT_WINDOW, maxTokens: DEFAULT_MAX_TOKENS };
return {
id: modelId,
name: isAutoModel ? "Higress Auto Router" : modelId,
api: "openai-completions",
reasoning: true,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: config.contextWindow,
maxTokens: config.maxTokens,
};
}
async function testGatewayConnection(gatewayUrl: string): Promise<boolean> {
try {
// gatewayUrl already ends with /v1 from normalizeBaseUrl()
// Use chat/completions endpoint with empty body to test connection
// Higress doesn't support /models endpoint
const response = await fetch(`${gatewayUrl}/chat/completions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
signal: AbortSignal.timeout(5000),
});
// Any response (including 400/401/422) means gateway is reachable
return true;
} catch {
return false;
}
}
async function fetchAvailableModels(consoleUrl: string): Promise<string[]> {
try {
// Try to get models from Higress Console API
const response = await fetch(`${consoleUrl}/v1/ai/routes`, {
method: "GET",
headers: { "Content-Type": "application/json" },
signal: AbortSignal.timeout(5000),
});
if (response.ok) {
const data = (await response.json()) as { data?: { model?: string }[] };
if (data.data && Array.isArray(data.data)) {
return data.data
.map((route: { model?: string }) => route.model)
.filter((m): m is string => typeof m === "string");
}
}
} catch {
// Ignore errors, use defaults
}
return [];
}
const higressPlugin = {
id: "higress",
name: "Higress AI Gateway",
description: "Model provider plugin for Higress AI Gateway with auto-routing support",
configSchema: emptyPluginConfigSchema(),
register(api) {
api.registerProvider({
id: "higress",
label: "Higress AI Gateway",
docsPath: "/providers/models",
aliases: ["higress-gateway", "higress-ai"],
auth: [
{
id: "api-key",
label: "API Key",
hint: "Configure Higress AI Gateway endpoint with optional API key",
kind: "custom",
run: async (ctx) => {
// Step 1: Get Gateway URL
const gatewayUrlInput = await ctx.prompter.text({
message: "Higress AI Gateway URL",
initialValue: DEFAULT_GATEWAY_URL,
validate: validateUrl,
});
const gatewayUrl = normalizeBaseUrl(gatewayUrlInput);
// Step 2: Get Console URL (for auto-router configuration)
const consoleUrlInput = await ctx.prompter.text({
message: "Higress Console URL (for auto-router config)",
initialValue: DEFAULT_CONSOLE_URL,
validate: validateUrl,
});
const consoleUrl = normalizeBaseUrl(consoleUrlInput);
// Step 3: Test connection (create a new spinner)
const spin = ctx.prompter.progress("Testing gateway connection…");
const isConnected = await testGatewayConnection(gatewayUrl);
if (!isConnected) {
spin.stop("Gateway connection failed");
await ctx.prompter.note(
[
"Could not connect to Higress AI Gateway.",
"Make sure the gateway is running and the URL is correct.",
].join("\n"),
"Connection Warning",
);
} else {
spin.stop("Gateway connected");
}
// Step 4: Get API Key (optional for local gateway)
const apiKeyInput = await ctx.prompter.text({
message: "API Key (leave empty if not required)",
initialValue: "",
}) || '';
const apiKey = apiKeyInput.trim() || "higress-local";
// Step 5: Fetch available models (create a new spinner)
const spin2 = ctx.prompter.progress("Fetching available models…");
const fetchedModels = await fetchAvailableModels(consoleUrl);
const defaultModels = fetchedModels.length > 0
? ["higress/auto", ...fetchedModels]
: DEFAULT_MODEL_IDS;
spin2.stop();
// Step 6: Let user customize model list
const modelInput = await ctx.prompter.text({
message: "Model IDs (comma-separated, higress/auto enables auto-routing)",
initialValue: defaultModels.slice(0, 10).join(", "),
validate: (value) =>
parseModelIds(value).length > 0 ? undefined : "Enter at least one model id",
});
const modelIds = parseModelIds(modelInput);
const hasAutoModel = modelIds.includes("higress/auto");
// Always add higress/ provider prefix to create model reference
const defaultModelId = hasAutoModel
? "higress/auto"
: (modelIds[0] ?? "glm-5");
const defaultModelRef = `higress/${defaultModelId}`;
// Step 7: Configure default model for auto-routing
let autoRoutingDefaultModel = "glm-5";
if (hasAutoModel) {
const autoRoutingModelInput = await ctx.prompter.text({
message: "Default model for auto-routing (when no rule matches)",
initialValue: "glm-5",
});
autoRoutingDefaultModel = autoRoutingModelInput.trim(); // FIX: Add trim() here
}
return {
profiles: [
{
profileId: `higress:${apiKey === "higress-local" ? "local" : "default"}`,
credential: {
type: "token",
provider: "higress",
token: apiKey,
},
},
],
configPatch: {
models: {
providers: {
higress: {
// gatewayUrl already ends with /v1 from normalizeBaseUrl()
baseUrl: gatewayUrl,
apiKey: apiKey,
api: "openai-completions",
authHeader: apiKey !== "higress-local",
models: modelIds.map((modelId) => buildModelDefinition(modelId)),
},
},
},
agents: {
defaults: {
models: Object.fromEntries(
modelIds.map((modelId) => {
// Always add higress/ provider prefix to create model reference
const modelRef = `higress/${modelId}`;
return [modelRef, {}];
}),
),
},
},
plugins: {
entries: {
"higress": {
enabled: true,
config: {
gatewayUrl,
consoleUrl,
autoRoutingDefaultModel,
},
},
},
},
},
defaultModel: defaultModelRef,
notes: [
"Higress AI Gateway is now configured as a model provider.",
hasAutoModel
? `Auto-routing enabled: use model "higress/auto" to route based on message content.`
: "Add 'higress/auto' to models to enable auto-routing.",
// gatewayUrl already ends with /v1 from normalizeBaseUrl()
`Gateway endpoint: ${gatewayUrl}/chat/completions`,
`Console: ${consoleUrl}`,
"",
"💡 Future Configuration Updates (No Restart Needed):",
" • Add New Providers: Add LLM providers (DeepSeek, OpenAI, Claude, etc.) dynamically.",
" • Update API Keys: Update existing provider keys without restart.",
" • Configure Auto-Routing: Ask OpenClaw to set up intelligent routing rules.",
" All changes hot-load via Higress — no gateway restart required!",
"",
"🎯 Recommended Skills (install via OpenClaw conversation):",
"",
"1. Auto-Routing Skill:",
" Configure automatic model routing based on message content",
" https://github.com/alibaba/higress/tree/main/.claude/skills/higress-auto-router",
' Say: "Install higress-auto-router skill"',
],
};
},
},
],
});
},
};
export default higressPlugin;
================================================
FILE: .claude/skills/higress-openclaw-integration/scripts/plugin/openclaw.plugin.json
================================================
{
"id": "higress",
"name": "Higress AI Gateway",
"description": "Model provider plugin for Higress AI Gateway with auto-routing support",
"providers": ["higress"],
"configSchema": {
"type": "object",
"additionalProperties": true
}
}
================================================
FILE: .claude/skills/higress-openclaw-integration/scripts/plugin/package.json
================================================
{
"name": "@higress/higress",
"version": "1.0.0",
"description": "Higress AI Gateway model provider plugin for OpenClaw with auto-routing support",
"main": "index.ts",
"openclaw": {
"extensions": ["./index.ts"]
},
"keywords": [
"openclaw",
"higress",
"ai-gateway",
"model-router",
"auto-routing"
],
"author": "Higress Team",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/alibaba/higress"
}
}
================================================
FILE: .claude/skills/higress-wasm-go-plugin/SKILL.md
================================================
---
name: higress-wasm-go-plugin
description: Develop Higress WASM plugins using Go 1.24+. Use when creating, modifying, or debugging Higress gateway plugins for HTTP request/response processing, external service calls, Redis integration, or custom gateway logic.
---
# Higress WASM Go Plugin Development
Develop Higress gateway WASM plugins using Go language with the `wasm-go` SDK.
## Quick Start
### Project Setup
```bash
# Create project directory
mkdir my-plugin && cd my-plugin
# Initialize Go module
go mod init my-plugin
# Set proxy (China)
go env -w GOPROXY=https://proxy.golang.com.cn,direct
# Download dependencies
go get github.com/higress-group/proxy-wasm-go-sdk@go-1.24
go get github.com/higress-group/wasm-go@main
go get github.com/tidwall/gjson
```
### Minimal Plugin Template
```go
package main
import (
"github.com/higress-group/wasm-go/pkg/wrapper"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
"github.com/tidwall/gjson"
)
func main() {}
func init() {
wrapper.SetCtx(
"my-plugin",
wrapper.ParseConfig(parseConfig),
wrapper.ProcessRequestHeaders(onHttpRequestHeaders),
)
}
type MyConfig struct {
Enabled bool
}
func parseConfig(json gjson.Result, config *MyConfig) error {
config.Enabled = json.Get("enabled").Bool()
return nil
}
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
if config.Enabled {
proxywasm.AddHttpRequestHeader("x-my-header", "hello")
}
return types.HeaderContinue
}
```
### Compile
```bash
go mod tidy
GOOS=wasip1 GOARCH=wasm go build -buildmode=c-shared -o main.wasm ./
```
## Core Concepts
### Plugin Lifecycle
1. **init()** - Register plugin with `wrapper.SetCtx()`
2. **parseConfig** - Parse YAML config (auto-converted to JSON)
3. **HTTP processing phases** - Handle requests/responses
### HTTP Processing Phases
| Phase | Trigger | Handler |
|-------|---------|---------|
| Request Headers | Gateway receives client request headers | `ProcessRequestHeaders` |
| Request Body | Gateway receives client request body | `ProcessRequestBody` |
| Response Headers | Gateway receives backend response headers | `ProcessResponseHeaders` |
| Response Body | Gateway receives backend response body | `ProcessResponseBody` |
| Stream Done | HTTP stream completes | `ProcessStreamDone` |
### Action Return Values
| Action | Behavior |
|--------|----------|
| `types.HeaderContinue` | Continue to next filter |
| `types.HeaderStopIteration` | Stop header processing, wait for body |
| `types.HeaderStopAllIterationAndWatermark` | Stop all processing, buffer data, call `proxywasm.ResumeHttpRequest/Response()` to resume |
## API Reference
### HttpContext Methods
```go
// Request info (cached, safe to call in any phase)
ctx.Scheme() // :scheme
ctx.Host() // :authority
ctx.Path() // :path
ctx.Method() // :method
// Body handling
ctx.HasRequestBody() // Check if request has body
ctx.HasResponseBody() // Check if response has body
ctx.DontReadRequestBody() // Skip reading request body
ctx.DontReadResponseBody() // Skip reading response body
ctx.BufferRequestBody() // Buffer instead of stream
ctx.BufferResponseBody() // Buffer instead of stream
// Content detection
ctx.IsWebsocket() // Check WebSocket upgrade
ctx.IsBinaryRequestBody() // Check binary content
ctx.IsBinaryResponseBody() // Check binary content
// Context storage
ctx.SetContext(key, value)
ctx.GetContext(key)
ctx.GetStringContext(key, defaultValue)
ctx.GetBoolContext(key, defaultValue)
// Custom logging
ctx.SetUserAttribute(key, value)
ctx.WriteUserAttributeToLog()
```
### Header/Body Operations (proxywasm)
```go
// Request headers
proxywasm.GetHttpRequestHeader(name)
proxywasm.AddHttpRequestHeader(name, value)
proxywasm.ReplaceHttpRequestHeader(name, value)
proxywasm.RemoveHttpRequestHeader(name)
proxywasm.GetHttpRequestHeaders()
proxywasm.ReplaceHttpRequestHeaders(headers)
// Response headers
proxywasm.GetHttpResponseHeader(name)
proxywasm.AddHttpResponseHeader(name, value)
proxywasm.ReplaceHttpResponseHeader(name, value)
proxywasm.RemoveHttpResponseHeader(name)
proxywasm.GetHttpResponseHeaders()
proxywasm.ReplaceHttpResponseHeaders(headers)
// Request body (only in body phase)
proxywasm.GetHttpRequestBody(start, size)
proxywasm.ReplaceHttpRequestBody(body)
proxywasm.AppendHttpRequestBody(data)
proxywasm.PrependHttpRequestBody(data)
// Response body (only in body phase)
proxywasm.GetHttpResponseBody(start, size)
proxywasm.ReplaceHttpResponseBody(body)
proxywasm.AppendHttpResponseBody(data)
proxywasm.PrependHttpResponseBody(data)
// Direct response
proxywasm.SendHttpResponse(statusCode, headers, body, grpcStatus)
// Flow control
proxywasm.ResumeHttpRequest() // Resume paused request
proxywasm.ResumeHttpResponse() // Resume paused response
```
## Common Patterns
### External HTTP Call
See [references/http-client.md](references/http-client.md) for complete HTTP client patterns.
```go
func parseConfig(json gjson.Result, config *MyConfig) error {
serviceName := json.Get("serviceName").String()
servicePort := json.Get("servicePort").Int()
config.client = wrapper.NewClusterClient(wrapper.FQDNCluster{
FQDN: serviceName,
Port: servicePort,
})
return nil
}
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
err := config.client.Get("/api/check", nil, func(statusCode int, headers http.Header, body []byte) {
if statusCode != 200 {
proxywasm.SendHttpResponse(403, nil, []byte("Forbidden"), -1)
return
}
proxywasm.ResumeHttpRequest()
}, 3000) // timeout ms
if err != nil {
return types.HeaderContinue // fallback on error
}
return types.HeaderStopAllIterationAndWatermark
}
```
### Redis Integration
See [references/redis-client.md](references/redis-client.md) for complete Redis patterns.
```go
func parseConfig(json gjson.Result, config *MyConfig) error {
config.redis = wrapper.NewRedisClusterClient(wrapper.FQDNCluster{
FQDN: json.Get("redisService").String(),
Port: json.Get("redisPort").Int(),
})
return config.redis.Init(
json.Get("username").String(),
json.Get("password").String(),
json.Get("timeout").Int(),
)
}
```
### Multi-level Config
插件配置支持在控制台不同级别设置:全局、域名级、路由级。控制面会自动处理配置的优先级和匹配逻辑,插件代码中通过 `parseConfig` 解析到的就是当前请求匹配到的配置。
## Local Testing
See [references/local-testing.md](references/local-testing.md) for Docker Compose setup.
## Advanced Topics
See [references/advanced-patterns.md](references/advanced-patterns.md) for:
- Streaming body processing
- Route call pattern
- Tick functions (periodic tasks)
- Leader election
- Memory management
- Custom logging
## Best Practices
1. **Never call Resume after SendHttpResponse** - Response auto-resumes
2. **Check HasRequestBody() before returning HeaderStopIteration** - Avoids blocking
3. **Use cached ctx methods** - `ctx.Path()` works in any phase, `GetHttpRequestHeader(":path")` only in header phase
4. **Handle external call failures gracefully** - Return `HeaderContinue` on error to avoid blocking
5. **Set appropriate timeouts** - Default HTTP call timeout is 500ms
================================================
FILE: .claude/skills/higress-wasm-go-plugin/references/advanced-patterns.md
================================================
# Advanced Patterns
## Streaming Body Processing
Process body chunks as they arrive without buffering:
```go
func init() {
wrapper.SetCtx(
"streaming-plugin",
wrapper.ParseConfig(parseConfig),
wrapper.ProcessStreamingRequestBody(onStreamingRequestBody),
wrapper.ProcessStreamingResponseBody(onStreamingResponseBody),
)
}
func onStreamingRequestBody(ctx wrapper.HttpContext, config MyConfig, chunk []byte, isLastChunk bool) []byte {
// Modify chunk and return
modified := bytes.ReplaceAll(chunk, []byte("old"), []byte("new"))
return modified
}
func onStreamingResponseBody(ctx wrapper.HttpContext, config MyConfig, chunk []byte, isLastChunk bool) []byte {
// Can call external services with NeedPauseStreamingResponse()
return chunk
}
```
## Buffered Body Processing
Buffer entire body before processing:
```go
func init() {
wrapper.SetCtx(
"buffered-plugin",
wrapper.ParseConfig(parseConfig),
wrapper.ProcessRequestBody(onRequestBody),
wrapper.ProcessResponseBody(onResponseBody),
)
}
func onRequestBody(ctx wrapper.HttpContext, config MyConfig, body []byte) types.Action {
// Full request body available
var data map[string]interface{}
json.Unmarshal(body, &data)
// Modify and replace
data["injected"] = "value"
newBody, _ := json.Marshal(data)
proxywasm.ReplaceHttpRequestBody(newBody)
return types.ActionContinue
}
```
## Route Call Pattern
Call the current route's upstream with modified request:
```go
func onRequestBody(ctx wrapper.HttpContext, config MyConfig, body []byte) types.Action {
err := ctx.RouteCall("POST", "/modified-path", [][2]string{
{"Content-Type", "application/json"},
{"X-Custom", "header"},
}, body, func(statusCode int, headers [][2]string, body []byte) {
// Handle response from upstream
proxywasm.SendHttpResponse(statusCode, headers, body, -1)
})
if err != nil {
proxywasm.SendHttpResponse(500, nil, []byte("Route call failed"), -1)
}
return types.ActionContinue
}
```
## Tick Functions (Periodic Tasks)
Register periodic background tasks:
```go
func parseConfig(json gjson.Result, config *MyConfig) error {
// Register tick functions during config parsing
wrapper.RegisterTickFunc(1000, func() {
// Executes every 1 second
log.Info("1s tick")
})
wrapper.RegisterTickFunc(5000, func() {
// Executes every 5 seconds
log.Info("5s tick")
})
return nil
}
```
## Leader Election
For tasks that should run on only one VM instance:
```go
func init() {
wrapper.SetCtx(
"leader-plugin",
wrapper.PrePluginStartOrReload(onPluginStart),
wrapper.ParseConfig(parseConfig),
)
}
func onPluginStart(ctx wrapper.PluginContext) error {
ctx.DoLeaderElection()
return nil
}
func parseConfig(json gjson.Result, config *MyConfig) error {
wrapper.RegisterTickFunc(10000, func() {
if ctx.IsLeader() {
// Only leader executes this
log.Info("Leader task")
}
})
return nil
}
```
## Plugin Context Storage
Store data across requests at plugin level:
```go
type MyConfig struct {
// Config fields
}
func init() {
wrapper.SetCtx(
"context-plugin",
wrapper.ParseConfigWithContext(parseConfigWithContext),
wrapper.ProcessRequestHeaders(onHttpRequestHeaders),
)
}
func parseConfigWithContext(ctx wrapper.PluginContext, json gjson.Result, config *MyConfig) error {
// Store in plugin context (survives across requests)
ctx.SetContext("initTime", time.Now().Unix())
return nil
}
```
## Rule-Level Config Isolation
Enable graceful degradation when rule config parsing fails:
```go
func init() {
wrapper.SetCtx(
"isolated-plugin",
wrapper.PrePluginStartOrReload(func(ctx wrapper.PluginContext) error {
ctx.EnableRuleLevelConfigIsolation()
return nil
}),
wrapper.ParseOverrideConfig(parseGlobal, parseRule),
)
}
func parseGlobal(json gjson.Result, config *MyConfig) error {
// Parse global config
return nil
}
func parseRule(json gjson.Result, global MyConfig, config *MyConfig) error {
// Parse per-rule config, inheriting from global
*config = global // Copy global defaults
// Override with rule-specific values
return nil
}
```
## Memory Management
Configure automatic VM rebuild to prevent memory leaks:
```go
func init() {
wrapper.SetCtxWithOptions(
"memory-managed-plugin",
wrapper.ParseConfig(parseConfig),
wrapper.WithRebuildAfterRequests(10000), // Rebuild after 10k requests
wrapper.WithRebuildMaxMemBytes(100*1024*1024), // Rebuild at 100MB
wrapper.WithMaxRequestsPerIoCycle(20), // Limit concurrent requests
)
}
```
## Custom Logging
Add structured fields to access logs:
```go
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
// Set custom attributes
ctx.SetUserAttribute("user_id", "12345")
ctx.SetUserAttribute("request_type", "api")
return types.HeaderContinue
}
func onHttpResponseHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
// Write to access log
ctx.WriteUserAttributeToLog()
// Or write to trace spans
ctx.WriteUserAttributeToTrace()
return types.HeaderContinue
}
```
## Disable Re-routing
Prevent Envoy from recalculating routes after header modification:
```go
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
// Call BEFORE modifying headers
ctx.DisableReroute()
// Now safe to modify headers without triggering re-route
proxywasm.ReplaceHttpRequestHeader(":path", "/new-path")
return types.HeaderContinue
}
```
## Buffer Limits
Set per-request buffer limits to control memory usage:
```go
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
// Allow larger request bodies for this request
ctx.SetRequestBodyBufferLimit(10 * 1024 * 1024) // 10MB
return types.HeaderContinue
}
func onHttpResponseHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
// Allow larger response bodies
ctx.SetResponseBodyBufferLimit(50 * 1024 * 1024) // 50MB
return types.HeaderContinue
}
```
================================================
FILE: .claude/skills/higress-wasm-go-plugin/references/http-client.md
================================================
# HTTP Client Reference
## Cluster Types
### FQDNCluster (Most Common)
For services registered in Higress with FQDN:
```go
wrapper.NewClusterClient(wrapper.FQDNCluster{
FQDN: "my-service.dns", // Service FQDN with suffix
Port: 8080,
Host: "optional-host-header", // Optional
})
```
Common FQDN suffixes:
- `.dns` - DNS service
- `.static` - Static IP service (port defaults to 80)
- `.nacos` - Nacos service
### K8sCluster
For Kubernetes services:
```go
wrapper.NewClusterClient(wrapper.K8sCluster{
ServiceName: "my-service",
Namespace: "default",
Port: 8080,
Version: "", // Optional subset version
})
// Generates: outbound|8080||my-service.default.svc.cluster.local
```
### NacosCluster
For Nacos registry services:
```go
wrapper.NewClusterClient(wrapper.NacosCluster{
ServiceName: "my-service",
Group: "DEFAULT-GROUP",
NamespaceID: "public",
Port: 8080,
IsExtRegistry: false, // true for EDAS/SAE
})
```
### StaticIpCluster
For static IP services:
```go
wrapper.NewClusterClient(wrapper.StaticIpCluster{
ServiceName: "my-service",
Port: 8080,
})
// Generates: outbound|8080||my-service.static
```
### DnsCluster
For DNS-resolved services:
```go
wrapper.NewClusterClient(wrapper.DnsCluster{
ServiceName: "my-service",
Domain: "api.example.com",
Port: 443,
})
```
### RouteCluster
Use current route's upstream:
```go
wrapper.NewClusterClient(wrapper.RouteCluster{
Host: "optional-host-override",
})
```
### TargetCluster
Direct cluster name specification:
```go
wrapper.NewClusterClient(wrapper.TargetCluster{
Cluster: "outbound|8080||my-service.dns",
Host: "api.example.com",
})
```
## HTTP Methods
```go
client.Get(path, headers, callback, timeout...)
client.Post(path, headers, body, callback, timeout...)
client.Put(path, headers, body, callback, timeout...)
client.Patch(path, headers, body, callback, timeout...)
client.Delete(path, headers, body, callback, timeout...)
client.Head(path, headers, callback, timeout...)
client.Options(path, headers, callback, timeout...)
client.Call(method, path, headers, body, callback, timeout...)
```
## Callback Signature
```go
func(statusCode int, responseHeaders http.Header, responseBody []byte)
```
## Complete Example
```go
type MyConfig struct {
client wrapper.HttpClient
requestPath string
tokenHeader string
}
func parseConfig(json gjson.Result, config *MyConfig) error {
config.tokenHeader = json.Get("tokenHeader").String()
if config.tokenHeader == "" {
return errors.New("missing tokenHeader")
}
config.requestPath = json.Get("requestPath").String()
if config.requestPath == "" {
return errors.New("missing requestPath")
}
serviceName := json.Get("serviceName").String()
servicePort := json.Get("servicePort").Int()
if servicePort == 0 {
if strings.HasSuffix(serviceName, ".static") {
servicePort = 80
}
}
config.client = wrapper.NewClusterClient(wrapper.FQDNCluster{
FQDN: serviceName,
Port: servicePort,
})
return nil
}
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
err := config.client.Get(config.requestPath, nil,
func(statusCode int, responseHeaders http.Header, responseBody []byte) {
if statusCode != http.StatusOK {
log.Errorf("http call failed, status: %d", statusCode)
proxywasm.SendHttpResponse(http.StatusInternalServerError, nil,
[]byte("http call failed"), -1)
return
}
token := responseHeaders.Get(config.tokenHeader)
if token != "" {
proxywasm.AddHttpRequestHeader(config.tokenHeader, token)
}
proxywasm.ResumeHttpRequest()
})
if err != nil {
log.Errorf("http call dispatch failed: %v", err)
return types.HeaderContinue
}
return types.HeaderStopAllIterationAndWatermark
}
```
## Important Notes
1. **Cannot use net/http** - Must use wrapper's HTTP client
2. **Default timeout is 500ms** - Pass explicit timeout for longer calls
3. **Callback is async** - Must return `HeaderStopAllIterationAndWatermark` and call `ResumeHttpRequest()` in callback
4. **Error handling** - If dispatch fails, return `HeaderContinue` to avoid blocking
================================================
FILE: .claude/skills/higress-wasm-go-plugin/references/local-testing.md
================================================
# Local Testing with Docker Compose
## Prerequisites
- Docker installed
- Compiled `main.wasm` file
## Setup
Create these files in your plugin directory:
### docker-compose.yaml
```yaml
version: '3.7'
services:
envoy:
image: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/gateway:v2.1.5
entrypoint: /usr/local/bin/envoy
command: -c /etc/envoy/envoy.yaml --component-log-level wasm:debug
depends_on:
- httpbin
networks:
- wasmtest
ports:
- "10000:10000"
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
- ./main.wasm:/etc/envoy/main.wasm
httpbin:
image: kennethreitz/httpbin:latest
networks:
- wasmtest
ports:
- "12345:80"
networks:
wasmtest: {}
```
### envoy.yaml
```yaml
admin:
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: listener_0
address:
socket_address:
protocol: TCP
address: 0.0.0.0
port_value: 10000
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
scheme_header_transformation:
scheme_to_overwrite: https
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: httpbin
http_filters:
- name: wasmdemo
typed_config:
"@type": type.googleapis.com/udpa.type.v1.TypedStruct
type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
value:
config:
name: wasmdemo
vm_config:
runtime: envoy.wasm.runtime.v8
code:
local:
filename: /etc/envoy/main.wasm
configuration:
"@type": "type.googleapis.com/google.protobuf.StringValue"
value: |
{
"mockEnable": false
}
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: httpbin
connect_timeout: 30s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: httpbin
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: httpbin
port_value: 80
```
## Running
```bash
# Start
docker compose up
# Test without gateway (baseline)
curl http://127.0.0.1:12345/get
# Test with gateway (plugin applied)
curl http://127.0.0.1:10000/get
# Stop
docker compose down
```
## Modifying Plugin Config
1. Edit the `configuration.value` section in `envoy.yaml`
2. Restart: `docker compose restart envoy`
## Viewing Logs
```bash
# Follow Envoy logs
docker compose logs -f envoy
# WASM debug logs (enabled by --component-log-level wasm:debug)
```
## Adding External Services
To test external HTTP/Redis calls, add services to docker-compose.yaml:
```yaml
services:
# ... existing services ...
redis:
image: redis:7-alpine
networks:
- wasmtest
ports:
- "6379:6379"
auth-service:
image: your-auth-service:latest
networks:
- wasmtest
```
Then add clusters to envoy.yaml:
```yaml
clusters:
# ... existing clusters ...
- name: outbound|6379||redis.static
connect_timeout: 5s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: redis
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: redis
port_value: 6379
```
================================================
FILE: .claude/skills/higress-wasm-go-plugin/references/redis-client.md
================================================
# Redis Client Reference
## Initialization
```go
type MyConfig struct {
redis wrapper.RedisClient
qpm int
}
func parseConfig(json gjson.Result, config *MyConfig) error {
serviceName := json.Get("serviceName").String()
servicePort := json.Get("servicePort").Int()
if servicePort == 0 {
servicePort = 6379
}
config.redis = wrapper.NewRedisClusterClient(wrapper.FQDNCluster{
FQDN: serviceName,
Port: servicePort,
})
return config.redis.Init(
json.Get("username").String(),
json.Get("password").String(),
json.Get("timeout").Int(), // milliseconds
// Optional settings:
// wrapper.WithDataBase(1),
// wrapper.WithBufferFlushTimeout(3*time.Millisecond),
// wrapper.WithMaxBufferSizeBeforeFlush(1024),
// wrapper.WithDisableBuffer(), // For latency-sensitive scenarios
)
}
```
## Callback Signature
```go
func(response resp.Value)
// Check for errors
if response.Error() != nil {
// Handle error
}
// Get values
response.Integer() // int
response.String() // string
response.Bool() // bool
response.Array() // []resp.Value
response.Bytes() // []byte
```
## Available Commands
### Key Operations
```go
redis.Del(key, callback)
redis.Exists(key, callback)
redis.Expire(key, ttlSeconds, callback)
redis.Persist(key, callback)
```
### String Operations
```go
redis.Get(key, callback)
redis.Set(key, value, callback)
redis.SetEx(key, value, ttlSeconds, callback)
redis.SetNX(key, value, ttlSeconds, callback) // ttl=0 means no expiry
redis.MGet(keys, callback)
redis.MSet(kvMap, callback)
redis.Incr(key, callback)
redis.Decr(key, callback)
redis.IncrBy(key, delta, callback)
redis.DecrBy(key, delta, callback)
```
### List Operations
```go
redis.LLen(key, callback)
redis.RPush(key, values, callback)
redis.RPop(key, callback)
redis.LPush(key, values, callback)
redis.LPop(key, callback)
redis.LIndex(key, index, callback)
redis.LRange(key, start, stop, callback)
redis.LRem(key, count, value, callback)
redis.LInsertBefore(key, pivot, value, callback)
redis.LInsertAfter(key, pivot, value, callback)
```
### Hash Operations
```go
redis.HExists(key, field, callback)
redis.HDel(key, fields, callback)
redis.HLen(key, callback)
redis.HGet(key, field, callback)
redis.HSet(key, field, value, callback)
redis.HMGet(key, fields, callback)
redis.HMSet(key, kvMap, callback)
redis.HKeys(key, callback)
redis.HVals(key, callback)
redis.HGetAll(key, callback)
redis.HIncrBy(key, field, delta, callback)
redis.HIncrByFloat(key, field, delta, callback)
```
### Set Operations
```go
redis.SCard(key, callback)
redis.SAdd(key, values, callback)
redis.SRem(key, values, callback)
redis.SIsMember(key, value, callback)
redis.SMembers(key, callback)
redis.SDiff(key1, key2, callback)
redis.SDiffStore(dest, key1, key2, callback)
redis.SInter(key1, key2, callback)
redis.SInterStore(dest, key1, key2, callback)
redis.SUnion(key1, key2, callback)
redis.SUnionStore(dest, key1, key2, callback)
```
### Sorted Set Operations
```go
redis.ZCard(key, callback)
redis.ZAdd(key, memberScoreMap, callback)
redis.ZCount(key, min, max, callback)
redis.ZIncrBy(key, member, delta, callback)
redis.ZScore(key, member, callback)
redis.ZRank(key, member, callback)
redis.ZRevRank(key, member, callback)
redis.ZRem(key, members, callback)
redis.ZRange(key, start, stop, callback)
redis.ZRevRange(key, start, stop, callback)
```
### Lua Script
```go
redis.Eval(script, numkeys, keys, args, callback)
```
### Raw Command
```go
redis.Command([]interface{}{"SET", "key", "value"}, callback)
```
## Rate Limiting Example
```go
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
now := time.Now()
minuteAligned := now.Truncate(time.Minute)
timeStamp := strconv.FormatInt(minuteAligned.Unix(), 10)
err := config.redis.Incr(timeStamp, func(response resp.Value) {
if response.Error() != nil {
log.Errorf("redis error: %v", response.Error())
proxywasm.ResumeHttpRequest()
return
}
count := response.Integer()
ctx.SetContext("timeStamp", timeStamp)
ctx.SetContext("callTimeLeft", strconv.Itoa(config.qpm - count))
if count == 1 {
// First request in this minute, set expiry
config.redis.Expire(timeStamp, 60, func(response resp.Value) {
if response.Error() != nil {
log.Errorf("expire error: %v", response.Error())
}
proxywasm.ResumeHttpRequest()
})
} else if count > config.qpm {
proxywasm.SendHttpResponse(429, [][2]string{
{"timeStamp", timeStamp},
{"callTimeLeft", "0"},
}, []byte("Too many requests\n"), -1)
} else {
proxywasm.ResumeHttpRequest()
}
})
if err != nil {
log.Errorf("redis call failed: %v", err)
return types.HeaderContinue
}
return types.HeaderStopAllIterationAndWatermark
}
func onHttpResponseHeaders(ctx wrapper.HttpContext, config MyConfig) types.Action {
if ts := ctx.GetContext("timeStamp"); ts != nil {
proxywasm.AddHttpResponseHeader("timeStamp", ts.(string))
}
if left := ctx.GetContext("callTimeLeft"); left != nil {
proxywasm.AddHttpResponseHeader("callTimeLeft", left.(string))
}
return types.HeaderContinue
}
```
## Important Notes
1. **Check Ready()** - `redis.Ready()` returns false if init failed
2. **Auto-reconnect** - Client handles NOAUTH errors and re-authenticates automatically
3. **Buffering** - Default 3ms flush timeout and 1024 byte buffer; use `WithDisableBuffer()` for latency-sensitive scenarios
4. **Error handling** - Always check `response.Error()` in callbacks
================================================
FILE: .claude/skills/nginx-to-higress-migration/README.md
================================================
# Nginx to Higress Migration Skill
Complete end-to-end solution for migrating from ingress-nginx to Higress gateway, featuring intelligent compatibility validation, automated migration toolchain, and AI-driven capability enhancement.
## Overview
This skill is built on real-world production migration experience, providing:
- 🔍 **Configuration Analysis & Compatibility Assessment**: Automated scanning of nginx Ingress configurations to identify migration risks
- 🧪 **Kind Cluster Simulation**: Local fast verification of configuration compatibility to ensure safe migration
- 🚀 **Gradual Migration Strategy**: Phased migration approach to minimize business risk
- 🤖 **AI-Driven Capability Enhancement**: Automated WASM plugin development to fill gaps in Higress functionality
## Core Advantages
### 🎯 Simple Mode: Zero-Configuration Migration
**For standard Ingress resources with common nginx annotations:**
✅ **100% Annotation Compatibility** - All standard `nginx.ingress.kubernetes.io/*` annotations work out-of-the-box
✅ **Zero Configuration Changes** - Apply your existing Ingress YAML directly to Higress
✅ **Instant Migration** - No learning curve, no manual conversion, no risk
✅ **Parallel Deployment** - Install Higress alongside nginx for safe testing
**Example:**
```yaml
# Your existing nginx Ingress - works immediately on Higress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /api/$2
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
spec:
ingressClassName: nginx # Same class name, both controllers watch it
rules:
- host: api.example.com
http:
paths:
- path: /v1(/|$)(.*)
pathType: Prefix
backend:
service:
name: backend
port:
number: 8080
```
**No conversion needed. No manual rewrite. Just deploy and validate.**
### ⚙️ Complex Mode: Full DevOps Automation for Custom Plugins
**When nginx snippets or custom Lua logic require WASM plugins:**
✅ **Automated Requirement Analysis** - AI extracts functionality from nginx snippets
✅ **Code Generation** - Type-safe Go code with proxy-wasm SDK automatically generated
✅ **Build & Validation** - Compile, test, and package as OCI images
✅ **Production Deployment** - Push to registry and deploy WasmPlugin CRD
**Complete workflow automation:**
```
nginx snippet → AI analysis → Go WASM code → Build → Test → Deploy → Validate
↓ ↓ ↓ ↓ ↓ ↓ ↓
minutes seconds seconds seconds 1min instant instant
```
**Example: Custom IP-based routing + HMAC signature validation**
**Original nginx snippet:**
```nginx
location /payment {
access_by_lua_block {
local client_ip = ngx.var.remote_addr
local signature = ngx.req.get_headers()["X-Signature"]
-- Complex IP routing and HMAC validation logic
if not validate_signature(signature) then
ngx.exit(403)
end
}
}
```
**AI-generated WASM plugin** (automatic):
1. Analyze requirement: IP routing + HMAC-SHA256 validation
2. Generate Go code with proper error handling
3. Build, test, deploy - **fully automated**
**Result**: Original functionality preserved, business logic unchanged, zero manual coding required.
## Migration Workflow
### Mode 1: Simple Migration (Standard Ingress)
**Prerequisites**: Your Ingress uses standard annotations (check with `kubectl get ingress -A -o yaml`)
**Steps:**
```bash
# 1. Install Higress alongside nginx (same ingressClass)
helm install higress higress/higress \
-n higress-system --create-namespace \
--set global.ingressClass=nginx \
--set global.enableStatus=false
# 2. Generate validation tests
./scripts/generate-migration-test.sh > test.sh
# 3. Run tests against Higress gateway
./test.sh ${HIGRESS_IP}
# 4. If all tests pass → switch traffic (DNS/LB)
# nginx continues running as fallback
```
**Timeline**: 30 minutes for 50+ Ingress resources (including validation)
### Mode 2: Complex Migration (Custom Snippets/Lua)
**Prerequisites**: Your Ingress uses `server-snippet`, `configuration-snippet`, or Lua logic
**Steps:**
```bash
# 1. Analyze incompatible features
./scripts/analyze-ingress.sh
# 2. For each snippet:
# - AI reads the snippet
# - Designs WASM plugin architecture
# - Generates type-safe Go code
# - Builds and validates
# 3. Deploy plugins
kubectl apply -f generated-wasm-plugins/
# 4. Validate + switch traffic
```
**Timeline**: 1-2 hours including AI-driven plugin development
## AI Execution Example
**User**: "Migrate my nginx Ingress to Higress"
**AI Agent Workflow**:
1. **Discovery**
```bash
kubectl get ingress -A -o yaml > backup.yaml
kubectl get configmap -n ingress-nginx ingress-nginx-controller -o yaml
```
2. **Compatibility Analysis**
- ✅ Standard annotations: direct migration
- ⚠️ Snippet annotations: require WASM plugins
- Identify patterns: rate limiting, auth, routing logic
3. **Parallel Deployment**
```bash
helm install higress higress/higress -n higress-system \
--set global.ingressClass=nginx \
--set global.enableStatus=false
```
4. **Automated Testing**
```bash
./scripts/generate-migration-test.sh > test.sh
./test.sh ${HIGRESS_IP}
# ✅ 60/60 routes passed
```
5. **Plugin Development** (if needed)
- Read `higress-wasm-go-plugin` skill
- Generate Go code for custom logic
- Build, validate, deploy
- Re-test affected routes
6. **Gradual Cutover**
- Phase 1: 10% traffic → validate
- Phase 2: 50% traffic → monitor
- Phase 3: 100% traffic → decommission nginx
## Production Case Studies
### Case 1: E-Commerce API Gateway (60+ Ingress Resources)
**Environment**:
- 60+ Ingress resources
- 3-node HA cluster
- TLS termination for 15+ domains
- Rate limiting, CORS, JWT auth
**Migration**:
```yaml
# Example Ingress (one of 60+)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: product-api
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$2
nginx.ingress.kubernetes.io/rate-limit: "1000"
nginx.ingress.kubernetes.io/cors-allow-origin: "https://shop.example.com"
nginx.ingress.kubernetes.io/auth-url: "http://auth-service/validate"
spec:
ingressClassName: nginx
tls:
- hosts:
- api.example.com
secretName: api-tls
rules:
- host: api.example.com
http:
paths:
- path: /api(/|$)(.*)
pathType: Prefix
backend:
service:
name: product-service
port:
number: 8080
```
**Validation in Kind cluster**:
```bash
# Apply directly without modification
kubectl apply -f product-api-ingress.yaml
# Test all functionality
curl https://api.example.com/api/products/123
# ✅ URL rewrite: /products/123 (correct)
# ✅ Rate limiting: active
# ✅ CORS headers: injected
# ✅ Auth validation: working
# ✅ TLS certificate: valid
```
**Results**:
| Metric | Value | Notes |
|--------|-------|-------|
| Ingress resources migrated | 60+ | Zero modification |
| Annotation types supported | 20+ | 100% compatibility |
| TLS certificates | 15+ | Direct secret reuse |
| Configuration changes | **0** | No YAML edits needed |
| Migration time | **30 min** | Including validation |
| Downtime | **0 sec** | Zero-downtime cutover |
| Rollback needed | **0** | All tests passed |
### Case 2: Financial Services with Custom Auth Logic
**Challenge**: Payment service required custom IP-based routing + HMAC-SHA256 request signing validation (implemented as nginx Lua snippet)
**Original nginx configuration**:
```nginx
location /payment/process {
access_by_lua_block {
local client_ip = ngx.var.remote_addr
local signature = ngx.req.get_headers()["X-Payment-Signature"]
local timestamp = ngx.req.get_headers()["X-Timestamp"]
-- IP allowlist check
if not is_allowed_ip(client_ip) then
ngx.log(ngx.ERR, "Blocked IP: " .. client_ip)
ngx.exit(403)
end
-- HMAC-SHA256 signature validation
local payload = ngx.var.request_uri .. timestamp
local expected_sig = compute_hmac_sha256(payload, secret_key)
if signature ~= expected_sig then
ngx.log(ngx.ERR, "Invalid signature from: " .. client_ip)
ngx.exit(403)
end
}
}
```
**AI-Driven Plugin Development**:
1. **Requirement Analysis** (AI reads snippet)
- IP allowlist validation
- HMAC-SHA256 signature verification
- Request timestamp validation
- Error logging requirements
2. **Auto-Generated WASM Plugin** (Go)
```go
// Auto-generated by AI agent
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
)
type PaymentAuthPlugin struct {
proxywasm.DefaultPluginContext
}
func (ctx *PaymentAuthPlugin) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {
// IP allowlist check
clientIP, _ := proxywasm.GetProperty([]string{"source", "address"})
if !isAllowedIP(string(clientIP)) {
proxywasm.LogError("Blocked IP: " + string(clientIP))
proxywasm.SendHttpResponse(403, nil, []byte("Forbidden"), -1)
return types.ActionPause
}
// HMAC signature validation
signature, _ := proxywasm.GetHttpRequestHeader("X-Payment-Signature")
timestamp, _ := proxywasm.GetHttpRequestHeader("X-Timestamp")
uri, _ := proxywasm.GetProperty([]string{"request", "path"})
payload := string(uri) + timestamp
expectedSig := computeHMAC(payload, secretKey)
if signature != expectedSig {
proxywasm.LogError("Invalid signature from: " + string(clientIP))
proxywasm.SendHttpResponse(403, nil, []byte("Invalid signature"), -1)
return types.ActionPause
}
return types.ActionContinue
}
```
3. **Automated Build & Deployment**
```bash
# AI agent executes automatically:
go mod tidy
GOOS=wasip1 GOARCH=wasm go build -o payment-auth.wasm
docker build -t registry.example.com/payment-auth:v1 .
docker push registry.example.com/payment-auth:v1
kubectl apply -f - <<EOF
apiVersion: extensions.higress.io/v1alpha1
kind: WasmPlugin
metadata:
name: payment-auth
namespace: higress-system
spec:
url: oci://registry.example.com/payment-auth:v1
phase: AUTHN
priority: 100
EOF
```
**Results**:
- ✅ Original functionality preserved (IP check + HMAC validation)
- ✅ Improved security (type-safe code, compiled WASM)
- ✅ Better performance (native WASM vs interpreted Lua)
- ✅ Full automation (requirement → deployment in <10 minutes)
- ✅ Zero business logic changes required
### Case 3: Multi-Tenant SaaS Platform (Custom Routing)
**Challenge**: Route requests to
gitextract__hz1lxah/
├── .claude/
│ └── skills/
│ ├── agent-session-monitor/
│ │ ├── QUICKSTART.md
│ │ ├── README.md
│ │ ├── SKILL.md
│ │ ├── example/
│ │ │ ├── clawdbot_demo.py
│ │ │ ├── demo.sh
│ │ │ ├── demo_v2.sh
│ │ │ ├── test_access.log
│ │ │ ├── test_access_v2.log
│ │ │ └── test_rotation.sh
│ │ ├── main.py
│ │ └── scripts/
│ │ ├── cli.py
│ │ └── webserver.py
│ ├── higress-auto-router/
│ │ └── SKILL.md
│ ├── higress-daily-report/
│ │ ├── README.md
│ │ ├── SKILL.md
│ │ └── scripts/
│ │ └── generate-report.sh
│ ├── higress-openclaw-integration/
│ │ ├── SKILL.md
│ │ ├── references/
│ │ │ └── TROUBLESHOOTING.md
│ │ └── scripts/
│ │ ├── detect-region.sh
│ │ └── plugin/
│ │ ├── README.md
│ │ ├── index.ts
│ │ ├── openclaw.plugin.json
│ │ └── package.json
│ ├── higress-wasm-go-plugin/
│ │ ├── SKILL.md
│ │ └── references/
│ │ ├── advanced-patterns.md
│ │ ├── http-client.md
│ │ ├── local-testing.md
│ │ └── redis-client.md
│ └── nginx-to-higress-migration/
│ ├── README.md
│ ├── README_CN.md
│ ├── SKILL.md
│ ├── references/
│ │ ├── annotation-mapping.md
│ │ ├── builtin-plugins.md
│ │ ├── plugin-deployment.md
│ │ └── snippet-patterns.md
│ └── scripts/
│ ├── analyze-ingress.sh
│ ├── generate-migration-test.sh
│ ├── generate-plugin-scaffold.sh
│ └── install-harbor.sh
├── .cursor/
│ └── rules/
│ └── plugin-development.mdc
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── FEATURE_REQUEST.md
│ │ ├── config.yml
│ │ └── non--crash-security--bug.md
│ ├── PULL_REQUEST_TEMPLATE.md
│ └── workflows/
│ ├── build-and-push-wasm-plugin-image.yaml
│ ├── build-and-test-plugin.yaml
│ ├── build-and-test.yaml
│ ├── build-image-and-push.yaml
│ ├── codeql-analysis.yaml
│ ├── deploy-standalone-to-oss.yaml
│ ├── deploy-to-oss.yaml
│ ├── generate-release-notes.yaml
│ ├── helm-docs.yaml
│ ├── license-checker.yaml
│ ├── release-crd.yaml
│ ├── release-hgctl.yaml
│ ├── sync-crds.yaml
│ ├── sync-skills-to-oss.yaml
│ ├── translate-readme.yaml
│ ├── translate-test.yml
│ └── wasm-plugin-unit-test.yml
├── .gitignore
├── .gitmodules
├── .licenserc.yaml
├── ADOPTERS.md
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING_CN.md
├── CONTRIBUTING_EN.md
├── CONTRIBUTING_JP.md
├── DEP_VERSION
├── LICENSE
├── Makefile
├── Makefile.core.mk
├── Makefile.overrides.mk
├── README.md
├── README_JP.md
├── README_ZH.md
├── SECURITY.md
├── VERSION
├── api/
│ ├── buf.gen.yaml
│ ├── buf.yaml
│ ├── cue.yaml
│ ├── extensions/
│ │ └── v1alpha1/
│ │ ├── wasmplugin.pb.go
│ │ ├── wasmplugin.proto
│ │ ├── wasmplugin_deepcopy.gen.go
│ │ └── wasmplugin_json.gen.go
│ ├── gen.sh
│ ├── kubernetes/
│ │ └── customresourcedefinitions.gen.yaml
│ ├── networking/
│ │ └── v1/
│ │ ├── http_2_rpc.pb.go
│ │ ├── http_2_rpc.proto
│ │ ├── http_2_rpc_deepcopy.gen.go
│ │ ├── http_2_rpc_json.gen.go
│ │ ├── mcp_bridge.pb.go
│ │ ├── mcp_bridge.proto
│ │ ├── mcp_bridge_deepcopy.gen.go
│ │ └── mcp_bridge_json.gen.go
│ └── protocol.yaml
├── client/
│ ├── Makefile
│ ├── header.go.txt
│ └── pkg/
│ ├── apis/
│ │ ├── extensions/
│ │ │ └── v1alpha1/
│ │ │ ├── doc.go
│ │ │ ├── register.gen.go
│ │ │ ├── types.gen.go
│ │ │ └── zz_generated.deepcopy.gen.go
│ │ └── networking/
│ │ └── v1/
│ │ ├── doc.go
│ │ ├── register.gen.go
│ │ ├── types.gen.go
│ │ └── zz_generated.deepcopy.gen.go
│ ├── applyconfiguration/
│ │ ├── extensions/
│ │ │ └── v1alpha1/
│ │ │ └── wasmplugin.go
│ │ ├── internal/
│ │ │ └── internal.go
│ │ ├── meta/
│ │ │ └── v1/
│ │ │ ├── managedfieldsentry.go
│ │ │ ├── objectmeta.go
│ │ │ ├── ownerreference.go
│ │ │ └── typemeta.go
│ │ ├── networking/
│ │ │ └── v1/
│ │ │ ├── http2rpc.go
│ │ │ └── mcpbridge.go
│ │ └── utils.go
│ ├── clientset/
│ │ └── versioned/
│ │ ├── clientset.gen.go
│ │ ├── fake/
│ │ │ ├── clientset_generated.gen.go
│ │ │ ├── doc.go
│ │ │ └── register.gen.go
│ │ ├── scheme/
│ │ │ ├── doc.go
│ │ │ └── register.gen.go
│ │ └── typed/
│ │ ├── extensions/
│ │ │ └── v1alpha1/
│ │ │ ├── doc.go
│ │ │ ├── extensions_client.gen.go
│ │ │ ├── fake/
│ │ │ │ ├── doc.go
│ │ │ │ ├── fake_extensions_client.gen.go
│ │ │ │ └── fake_wasmplugin.gen.go
│ │ │ ├── generated_expansion.gen.go
│ │ │ └── wasmplugin.gen.go
│ │ └── networking/
│ │ └── v1/
│ │ ├── doc.go
│ │ ├── fake/
│ │ │ ├── doc.go
│ │ │ ├── fake_http2rpc.gen.go
│ │ │ ├── fake_mcpbridge.gen.go
│ │ │ └── fake_networking_client.gen.go
│ │ ├── generated_expansion.gen.go
│ │ ├── http2rpc.gen.go
│ │ ├── mcpbridge.gen.go
│ │ └── networking_client.gen.go
│ ├── informers/
│ │ └── externalversions/
│ │ ├── extensions/
│ │ │ ├── interface.gen.go
│ │ │ └── v1alpha1/
│ │ │ ├── interface.gen.go
│ │ │ └── wasmplugin.gen.go
│ │ ├── factory.gen.go
│ │ ├── generic.gen.go
│ │ ├── internalinterfaces/
│ │ │ └── factory_interfaces.gen.go
│ │ └── networking/
│ │ ├── interface.gen.go
│ │ └── v1/
│ │ ├── http2rpc.gen.go
│ │ ├── interface.gen.go
│ │ └── mcpbridge.gen.go
│ └── listers/
│ ├── extensions/
│ │ └── v1alpha1/
│ │ ├── expansion_generated.gen.go
│ │ └── wasmplugin.gen.go
│ └── networking/
│ └── v1/
│ ├── expansion_generated.gen.go
│ ├── http2rpc.gen.go
│ └── mcpbridge.gen.go
├── cmd/
│ └── higress/
│ └── main.go
├── codecov.yml
├── docker/
│ ├── Dockerfile.base
│ ├── Dockerfile.higress
│ ├── docker-copy.sh
│ └── docker.mk
├── docs/
│ └── architecture.md
├── get_helm.sh
├── go.mod
├── go.sum
├── helm/
│ ├── core/
│ │ ├── .helmignore
│ │ ├── Chart.yaml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── charts/
│ │ │ └── redis/
│ │ │ ├── .helmignore
│ │ │ ├── Chart.yaml
│ │ │ ├── templates/
│ │ │ │ ├── _helpers.tpl
│ │ │ │ ├── configmap.yaml
│ │ │ │ ├── pvc.yaml
│ │ │ │ ├── service.yaml
│ │ │ │ └── statefulset.yaml
│ │ │ └── values.yaml
│ │ ├── crds/
│ │ │ ├── customresourcedefinitions.gen.yaml
│ │ │ ├── customresourcedefinitions.gen_lt1.16.yaml
│ │ │ └── istio-envoyfilter.yaml
│ │ ├── templates/
│ │ │ ├── NOTES.txt
│ │ │ ├── _helpers.tpl
│ │ │ ├── _pod.tpl
│ │ │ ├── clusterrole.yaml
│ │ │ ├── configmap.yaml
│ │ │ ├── controller-clusterrole.yaml
│ │ │ ├── controller-clusterrolebinding.yaml
│ │ │ ├── controller-deployment.yaml
│ │ │ ├── controller-role.yaml
│ │ │ ├── controller-rolebinding.yaml
│ │ │ ├── controller-service.yaml
│ │ │ ├── controller-serviceaccont.yaml
│ │ │ ├── daemonset.yaml
│ │ │ ├── deployment.yaml
│ │ │ ├── fallback-envoyfilter.yaml
│ │ │ ├── hpa.yaml
│ │ │ ├── ingressclass.yaml
│ │ │ ├── plugin-server-deployment.yaml
│ │ │ ├── plugin-server-service.yaml
│ │ │ ├── podmonitor.yaml
│ │ │ ├── promtail.yaml
│ │ │ ├── role.yaml
│ │ │ ├── service.yaml
│ │ │ └── serviceaccount.yaml
│ │ └── values.yaml
│ └── higress/
│ ├── Chart.yaml
│ ├── LICENSE
│ ├── README.md
│ ├── README.md.gotmpl
│ └── README.zh.md
├── hgctl/
│ ├── cmd/
│ │ └── hgctl/
│ │ ├── config/
│ │ │ ├── gateway_config.go
│ │ │ ├── gateway_config_test.go
│ │ │ └── testdata/
│ │ │ └── config/
│ │ │ ├── input/
│ │ │ │ └── in.all.json
│ │ │ └── output/
│ │ │ ├── out.all.json
│ │ │ ├── out.all.yaml
│ │ │ ├── out.bootstrap.json
│ │ │ ├── out.bootstrap.yaml
│ │ │ ├── out.cluster.json
│ │ │ ├── out.cluster.yaml
│ │ │ ├── out.endpoints.json
│ │ │ ├── out.endpoints.yaml
│ │ │ ├── out.listener.json
│ │ │ ├── out.listener.yaml
│ │ │ ├── out.route.json
│ │ │ └── out.route.yaml
│ │ └── main.go
│ ├── go.mod
│ ├── go.sum
│ └── pkg/
│ ├── agent/
│ │ ├── README.md
│ │ ├── agent.go
│ │ ├── base.go
│ │ ├── common/
│ │ │ └── base.go
│ │ ├── config.go
│ │ ├── core.go
│ │ ├── deploy.go
│ │ ├── mcp.go
│ │ ├── new.go
│ │ ├── prompt/
│ │ │ ├── agent_guide.md
│ │ │ └── base.go
│ │ ├── services/
│ │ │ ├── client.go
│ │ │ ├── service.go
│ │ │ └── utils.go
│ │ ├── types.go
│ │ └── utils.go
│ ├── code_debug.go
│ ├── common.go
│ ├── completion.go
│ ├── config_bootstrap.go
│ ├── config_cluster.go
│ ├── config_cmd.go
│ ├── config_endpoint.go
│ ├── config_listener.go
│ ├── config_route.go
│ ├── dashboard.go
│ ├── docker/
│ │ └── compose.go
│ ├── helm/
│ │ ├── common.go
│ │ ├── name/
│ │ │ └── name.go
│ │ ├── object/
│ │ │ ├── objects.go
│ │ │ └── objects_test.go
│ │ ├── profile.go
│ │ ├── render.go
│ │ └── tpath/
│ │ ├── tree.go
│ │ ├── tree_test.go
│ │ ├── util.go
│ │ └── util_test.go
│ ├── install.go
│ ├── installer/
│ │ ├── component.go
│ │ ├── gateway_api.go
│ │ ├── helm_agent.go
│ │ ├── higress.go
│ │ ├── installer.go
│ │ ├── installer_docker.go
│ │ ├── installer_k8s.go
│ │ ├── istio.go
│ │ ├── profile_store.go
│ │ ├── server_info.go
│ │ ├── standalone.go
│ │ └── standalone_agent.go
│ ├── kubernetes/
│ │ ├── client.go
│ │ ├── common.go
│ │ ├── port-forwarder.go
│ │ └── wasmplugin.go
│ ├── manifest.go
│ ├── manifests/
│ │ ├── agent/
│ │ │ ├── agents/
│ │ │ │ ├── agentscope-test-runner.md
│ │ │ │ ├── openapi-generator.md
│ │ │ │ └── openapi-to-mcp-generator.md
│ │ │ ├── commands/
│ │ │ │ └── gen-agent.md
│ │ │ └── template/
│ │ │ ├── agent.tmpl
│ │ │ ├── agentrun.tmpl
│ │ │ ├── agentrun_s.tmpl
│ │ │ ├── agentscope.tmpl
│ │ │ └── toolkit.tmpl
│ │ ├── gatewayapi/
│ │ │ └── experimental-install.yaml
│ │ ├── istiobase/
│ │ │ ├── Chart.yaml
│ │ │ ├── README.md
│ │ │ ├── crds/
│ │ │ │ ├── crd-all.gen.yaml
│ │ │ │ └── crd-operator.yaml
│ │ │ ├── templates/
│ │ │ │ ├── NOTES.txt
│ │ │ │ ├── clusterrole.yaml
│ │ │ │ ├── clusterrolebinding.yaml
│ │ │ │ ├── crds.yaml
│ │ │ │ ├── default.yaml
│ │ │ │ ├── endpoints.yaml
│ │ │ │ ├── reader-serviceaccount.yaml
│ │ │ │ ├── role.yaml
│ │ │ │ ├── rolebinding.yaml
│ │ │ │ ├── serviceaccount.yaml
│ │ │ │ └── services.yaml
│ │ │ └── values.yaml
│ │ ├── manifest.go
│ │ └── profiles/
│ │ ├── _all.yaml
│ │ ├── k8s.yaml
│ │ ├── local-docker.yaml
│ │ └── local-k8s.yaml
│ ├── plugin/
│ │ ├── build/
│ │ │ ├── build.go
│ │ │ ├── signal.go
│ │ │ ├── signal_windows.go
│ │ │ └── templates.go
│ │ ├── config/
│ │ │ ├── config.go
│ │ │ ├── create.go
│ │ │ ├── edit.go
│ │ │ └── templates.go
│ │ ├── init/
│ │ │ ├── init.go
│ │ │ └── templates.go
│ │ ├── install/
│ │ │ ├── asker.go
│ │ │ └── install.go
│ │ ├── ls/
│ │ │ └── ls.go
│ │ ├── option/
│ │ │ ├── option.go
│ │ │ └── template.go
│ │ ├── plugin.go
│ │ ├── test/
│ │ │ ├── clean.go
│ │ │ ├── create.go
│ │ │ ├── ls.go
│ │ │ ├── start.go
│ │ │ ├── stop.go
│ │ │ ├── templates.go
│ │ │ └── test.go
│ │ ├── types/
│ │ │ ├── annotation.go
│ │ │ ├── marshal.go
│ │ │ ├── meta.go
│ │ │ ├── model_parser.go
│ │ │ ├── model_parser_test.go
│ │ │ ├── schema.go
│ │ │ └── testdata/
│ │ │ ├── doc_tag/
│ │ │ │ └── main.go
│ │ │ └── types/
│ │ │ ├── ext/
│ │ │ │ ├── ext.go
│ │ │ │ └── nested/
│ │ │ │ └── nested.go
│ │ │ └── main.go
│ │ ├── uninstall/
│ │ │ └── uninstall.go
│ │ └── utils/
│ │ ├── common.go
│ │ ├── debugger.go
│ │ ├── printer.go
│ │ └── survey_wrapper.go
│ ├── profile.go
│ ├── profile_dump.go
│ ├── profile_list.go
│ ├── root.go
│ ├── uninstall.go
│ ├── upgrade.go
│ ├── util/
│ │ ├── env.go
│ │ ├── filter.go
│ │ ├── filter_test.go
│ │ ├── http_fetcher.go
│ │ ├── path.go
│ │ ├── path_test.go
│ │ ├── reflect.go
│ │ ├── util.go
│ │ ├── yaml.go
│ │ └── yaml_test.go
│ ├── utils.go
│ └── version.go
├── pkg/
│ ├── bootstrap/
│ │ ├── server.go
│ │ └── server_test.go
│ ├── cert/
│ │ ├── certmgr.go
│ │ ├── config.go
│ │ ├── config_test.go
│ │ ├── controller.go
│ │ ├── ingress.go
│ │ ├── log.go
│ │ ├── secret.go
│ │ ├── server.go
│ │ ├── storage.go
│ │ ├── storage_test.go
│ │ └── util.go
│ ├── cmd/
│ │ ├── options/
│ │ │ └── global.go
│ │ ├── root.go
│ │ ├── server.go
│ │ ├── server_test.go
│ │ ├── version/
│ │ │ └── version.go
│ │ └── version.go
│ ├── common/
│ │ ├── protocol.go
│ │ ├── proxy.go
│ │ └── symbol.go
│ ├── config/
│ │ ├── constants/
│ │ │ └── constants.go
│ │ └── envs.go
│ ├── ingress/
│ │ ├── config/
│ │ │ ├── ingress_config.go
│ │ │ ├── ingress_config_test.go
│ │ │ ├── ingress_template.go
│ │ │ ├── ingress_template_test.go
│ │ │ ├── kingress_config.go
│ │ │ ├── kingress_config_test.go
│ │ │ ├── secret_config_mgr.go
│ │ │ └── secret_config_mgr_test.go
│ │ ├── kube/
│ │ │ ├── annotations/
│ │ │ │ ├── annotations.go
│ │ │ │ ├── annotations_test.go
│ │ │ │ ├── auth.go
│ │ │ │ ├── canary.go
│ │ │ │ ├── canary_test.go
│ │ │ │ ├── cors.go
│ │ │ │ ├── cors_test.go
│ │ │ │ ├── default_backend.go
│ │ │ │ ├── default_backend_test.go
│ │ │ │ ├── destination.go
│ │ │ │ ├── destination_test.go
│ │ │ │ ├── downstreamtls.go
│ │ │ │ ├── downstreamtls_test.go
│ │ │ │ ├── header_control.go
│ │ │ │ ├── header_control_test.go
│ │ │ │ ├── http2rpc.go
│ │ │ │ ├── http2rpc_test.go
│ │ │ │ ├── ignore_case.go
│ │ │ │ ├── ignore_case_test.go
│ │ │ │ ├── interface.go
│ │ │ │ ├── ip_access_control.go
│ │ │ │ ├── ip_access_control_test.go
│ │ │ │ ├── loadbalance.go
│ │ │ │ ├── loadbalance_test.go
│ │ │ │ ├── local_rate_limit.go
│ │ │ │ ├── local_rate_limit_test.go
│ │ │ │ ├── match.go
│ │ │ │ ├── match_test.go
│ │ │ │ ├── mcpserver.go
│ │ │ │ ├── mcpserver_test.go
│ │ │ │ ├── mirror.go
│ │ │ │ ├── mirror_test.go
│ │ │ │ ├── parser.go
│ │ │ │ ├── redirect.go
│ │ │ │ ├── redirect_test.go
│ │ │ │ ├── retry.go
│ │ │ │ ├── retry_test.go
│ │ │ │ ├── rewrite.go
│ │ │ │ ├── rewrite_test.go
│ │ │ │ ├── timeout.go
│ │ │ │ ├── timeout_test.go
│ │ │ │ ├── upstreamtls.go
│ │ │ │ ├── upstreamtls_test.go
│ │ │ │ ├── util.go
│ │ │ │ └── util_test.go
│ │ │ ├── common/
│ │ │ │ ├── controller.go
│ │ │ │ ├── metrics.go
│ │ │ │ ├── model.go
│ │ │ │ ├── model_test.go
│ │ │ │ ├── schema.go
│ │ │ │ ├── tool.go
│ │ │ │ └── tool_test.go
│ │ │ ├── configmap/
│ │ │ │ ├── config.go
│ │ │ │ ├── controller.go
│ │ │ │ ├── global.go
│ │ │ │ ├── global_test.go
│ │ │ │ ├── gzip.go
│ │ │ │ ├── gzip_test.go
│ │ │ │ ├── mcp_server.go
│ │ │ │ ├── mcp_server_test.go
│ │ │ │ └── tracing.go
│ │ │ ├── controller/
│ │ │ │ └── model.go
│ │ │ ├── gateway/
│ │ │ │ ├── controller.go
│ │ │ │ └── istio/
│ │ │ │ ├── backend_policies.go
│ │ │ │ ├── conditions.go
│ │ │ │ ├── conditions_test.go
│ │ │ │ ├── context.go
│ │ │ │ ├── controller.go
│ │ │ │ ├── controller_test.go
│ │ │ │ ├── conversion.go
│ │ │ │ ├── conversion_test.go
│ │ │ │ ├── deploymentcontroller.go
│ │ │ │ ├── gateway_collection.go
│ │ │ │ ├── gatewayclass.go
│ │ │ │ ├── gatewayclass_collection.go
│ │ │ │ ├── gatewayclass_test.go
│ │ │ │ ├── inferencepool_collection.go
│ │ │ │ ├── inferencepool_status_test.go
│ │ │ │ ├── inferencepool_test.go
│ │ │ │ ├── leak_test.go
│ │ │ │ ├── references.go
│ │ │ │ ├── references_collection.go
│ │ │ │ ├── route_collections.go
│ │ │ │ ├── status_test.go
│ │ │ │ ├── supported_features.go
│ │ │ │ └── testdata/
│ │ │ │ ├── backend-lb-policy.status.yaml.golden
│ │ │ │ ├── backend-lb-policy.yaml
│ │ │ │ ├── backend-lb-policy.yaml.golden
│ │ │ │ ├── backend-tls-policy.status.yaml.golden
│ │ │ │ ├── backend-tls-policy.yaml
│ │ │ │ ├── backend-tls-policy.yaml.golden
│ │ │ │ ├── benchmark-httproute.yaml
│ │ │ │ ├── delegated.status.yaml.golden
│ │ │ │ ├── delegated.yaml
│ │ │ │ ├── delegated.yaml.golden
│ │ │ │ ├── east-west-ambient.status.yaml.golden
│ │ │ │ ├── east-west-ambient.yaml
│ │ │ │ ├── east-west-ambient.yaml.golden
│ │ │ │ ├── eastwest-labelport.status.yaml.golden
│ │ │ │ ├── eastwest-labelport.yaml
│ │ │ │ ├── eastwest-labelport.yaml.golden
│ │ │ │ ├── eastwest-remote.status.yaml.golden
│ │ │ │ ├── eastwest-remote.yaml
│ │ │ │ ├── eastwest-remote.yaml.golden
│ │ │ │ ├── eastwest-tlsoption.status.yaml.golden
│ │ │ │ ├── eastwest-tlsoption.yaml
│ │ │ │ ├── eastwest-tlsoption.yaml.golden
│ │ │ │ ├── eastwest.status.yaml.golden
│ │ │ │ ├── eastwest.yaml
│ │ │ │ ├── eastwest.yaml.golden
│ │ │ │ ├── grpc.status.yaml.golden
│ │ │ │ ├── grpc.yaml
│ │ │ │ ├── grpc.yaml.golden
│ │ │ │ ├── http.status.yaml.golden
│ │ │ │ ├── http.yaml
│ │ │ │ ├── http.yaml.golden
│ │ │ │ ├── invalid.status.yaml.golden
│ │ │ │ ├── invalid.yaml
│ │ │ │ ├── invalid.yaml.golden
│ │ │ │ ├── isolation.status.yaml.golden
│ │ │ │ ├── isolation.yaml
│ │ │ │ ├── isolation.yaml.golden
│ │ │ │ ├── listenerset-cross-namespace.status.yaml.golden
│ │ │ │ ├── listenerset-cross-namespace.yaml
│ │ │ │ ├── listenerset-cross-namespace.yaml.golden
│ │ │ │ ├── listenerset-empty-listeners.status.yaml.golden
│ │ │ │ ├── listenerset-empty-listeners.yaml
│ │ │ │ ├── listenerset-empty-listeners.yaml.golden
│ │ │ │ ├── listenerset-invalid.status.yaml.golden
│ │ │ │ ├── listenerset-invalid.yaml
│ │ │ │ ├── listenerset-invalid.yaml.golden
│ │ │ │ ├── listenerset.status.yaml.golden
│ │ │ │ ├── listenerset.yaml
│ │ │ │ ├── listenerset.yaml.golden
│ │ │ │ ├── mcs.status.yaml.golden
│ │ │ │ ├── mcs.yaml
│ │ │ │ ├── mcs.yaml.golden
│ │ │ │ ├── mesh.status.yaml.golden
│ │ │ │ ├── mesh.yaml
│ │ │ │ ├── mesh.yaml.golden
│ │ │ │ ├── mismatch.status.yaml.golden
│ │ │ │ ├── mismatch.yaml
│ │ │ │ ├── mismatch.yaml.golden
│ │ │ │ ├── mix-backend-policy.status.yaml.golden
│ │ │ │ ├── mix-backend-policy.yaml
│ │ │ │ ├── mix-backend-policy.yaml.golden
│ │ │ │ ├── multi-gateway.status.yaml.golden
│ │ │ │ ├── multi-gateway.yaml
│ │ │ │ ├── multi-gateway.yaml.golden
│ │ │ │ ├── reference-policy-inferencepool.status.yaml.golden
│ │ │ │ ├── reference-policy-inferencepool.yaml
│ │ │ │ ├── reference-policy-inferencepool.yaml.golden
│ │ │ │ ├── reference-policy-service.status.yaml.golden
│ │ │ │ ├── reference-policy-service.yaml
│ │ │ │ ├── reference-policy-service.yaml.golden
│ │ │ │ ├── reference-policy-tcp.status.yaml.golden
│ │ │ │ ├── reference-policy-tcp.yaml
│ │ │ │ ├── reference-policy-tcp.yaml.golden
│ │ │ │ ├── reference-policy-tls.status.yaml.golden
│ │ │ │ ├── reference-policy-tls.yaml
│ │ │ │ ├── reference-policy-tls.yaml.golden
│ │ │ │ ├── route-binding.status.yaml.golden
│ │ │ │ ├── route-binding.yaml
│ │ │ │ ├── route-binding.yaml.golden
│ │ │ │ ├── route-precedence.status.yaml.golden
│ │ │ │ ├── route-precedence.yaml
│ │ │ │ ├── route-precedence.yaml.golden
│ │ │ │ ├── serviceentry.status.yaml.golden
│ │ │ │ ├── serviceentry.yaml
│ │ │ │ ├── serviceentry.yaml.golden
│ │ │ │ ├── status.status.yaml.golden
│ │ │ │ ├── status.yaml
│ │ │ │ ├── status.yaml.golden
│ │ │ │ ├── tcp.status.yaml.golden
│ │ │ │ ├── tcp.yaml
│ │ │ │ ├── tcp.yaml.golden
│ │ │ │ ├── tls.status.yaml.golden
│ │ │ │ ├── tls.yaml
│ │ │ │ ├── tls.yaml.golden
│ │ │ │ ├── valid-invalid-parent-ref.status.yaml.golden
│ │ │ │ ├── valid-invalid-parent-ref.yaml
│ │ │ │ ├── valid-invalid-parent-ref.yaml.golden
│ │ │ │ ├── waypoint.status.yaml.golden
│ │ │ │ ├── waypoint.yaml
│ │ │ │ ├── waypoint.yaml.golden
│ │ │ │ ├── weighted.status.yaml.golden
│ │ │ │ ├── weighted.yaml
│ │ │ │ ├── weighted.yaml.golden
│ │ │ │ ├── zero.status.yaml.golden
│ │ │ │ ├── zero.yaml
│ │ │ │ └── zero.yaml.golden
│ │ │ ├── http2rpc/
│ │ │ │ └── controller.go
│ │ │ ├── ingress/
│ │ │ │ ├── controller.go
│ │ │ │ ├── controller_test.go
│ │ │ │ └── status.go
│ │ │ ├── ingressv1/
│ │ │ │ ├── controller.go
│ │ │ │ ├── controller_test.go
│ │ │ │ └── status.go
│ │ │ ├── kingress/
│ │ │ │ ├── controller.go
│ │ │ │ ├── controller_test.go
│ │ │ │ ├── resources/
│ │ │ │ │ ├── doc.go
│ │ │ │ │ ├── virtual_service.go
│ │ │ │ │ └── virtual_service_test.go
│ │ │ │ └── status.go
│ │ │ ├── mcpbridge/
│ │ │ │ └── controller.go
│ │ │ ├── mcpserver/
│ │ │ │ ├── model.go
│ │ │ │ ├── provider.go
│ │ │ │ └── provider_test.go
│ │ │ ├── secret/
│ │ │ │ ├── controller.go
│ │ │ │ └── controller_test.go
│ │ │ ├── util/
│ │ │ │ ├── transformer.go
│ │ │ │ ├── util.go
│ │ │ │ └── util_test.go
│ │ │ └── wasmplugin/
│ │ │ └── controller.go
│ │ ├── log/
│ │ │ └── log.go
│ │ ├── mcp/
│ │ │ ├── generator.go
│ │ │ └── generator_test.go
│ │ └── translation/
│ │ └── translation.go
│ └── kube/
│ └── client.go
├── plugins/
│ ├── README.md
│ ├── golang-filter/
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── README_en.md
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── main.go
│ │ ├── mcp-server/
│ │ │ ├── README.md
│ │ │ ├── README_en.md
│ │ │ ├── config.go
│ │ │ ├── filter.go
│ │ │ ├── registry/
│ │ │ │ ├── nacos/
│ │ │ │ │ ├── nacos.go
│ │ │ │ │ └── server.go
│ │ │ │ ├── registry.go
│ │ │ │ └── remote.go
│ │ │ └── servers/
│ │ │ ├── gorm/
│ │ │ │ ├── db.go
│ │ │ │ ├── server.go
│ │ │ │ └── tools.go
│ │ │ ├── higress/
│ │ │ │ ├── client.go
│ │ │ │ ├── higress-api/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── README_en.md
│ │ │ │ │ ├── server.go
│ │ │ │ │ └── tools/
│ │ │ │ │ ├── ai_provider.go
│ │ │ │ │ ├── ai_route.go
│ │ │ │ │ ├── mcp_server.go
│ │ │ │ │ ├── plugins/
│ │ │ │ │ │ ├── common.go
│ │ │ │ │ │ ├── custom-response.go
│ │ │ │ │ │ ├── request-block.go
│ │ │ │ │ │ ├── types.go
│ │ │ │ │ │ └── util.go
│ │ │ │ │ ├── route.go
│ │ │ │ │ └── service.go
│ │ │ │ ├── higress-ops/
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── README_en.md
│ │ │ │ │ ├── client.go
│ │ │ │ │ ├── server.go
│ │ │ │ │ └── tools/
│ │ │ │ │ ├── client.go
│ │ │ │ │ ├── envoy.go
│ │ │ │ │ ├── istiod.go
│ │ │ │ │ └── utils.go
│ │ │ │ ├── nginx-migration/
│ │ │ │ │ ├── .gitignore
│ │ │ │ │ ├── Makefile
│ │ │ │ │ ├── QUICKSTART.md
│ │ │ │ │ ├── README.md
│ │ │ │ │ ├── config/
│ │ │ │ │ │ └── rag.json.example
│ │ │ │ │ ├── go.mod
│ │ │ │ │ ├── go.sum
│ │ │ │ │ ├── integration/
│ │ │ │ │ │ ├── mcptools/
│ │ │ │ │ │ │ ├── adapter.go
│ │ │ │ │ │ │ ├── context.go
│ │ │ │ │ │ │ ├── lua_tools.go
│ │ │ │ │ │ │ ├── nginx_tools.go
│ │ │ │ │ │ │ ├── rag_integration.go
│ │ │ │ │ │ │ └── tool_chain.go
│ │ │ │ │ │ └── server.go
│ │ │ │ │ ├── internal/
│ │ │ │ │ │ ├── rag/
│ │ │ │ │ │ │ ├── client.go
│ │ │ │ │ │ │ ├── config.go
│ │ │ │ │ │ │ └── manager.go
│ │ │ │ │ │ └── standalone/
│ │ │ │ │ │ └── server.go
│ │ │ │ │ ├── mcp-tools.json
│ │ │ │ │ ├── standalone/
│ │ │ │ │ │ ├── cmd/
│ │ │ │ │ │ │ └── main.go
│ │ │ │ │ │ ├── config.go
│ │ │ │ │ │ ├── server.go
│ │ │ │ │ │ └── types.go
│ │ │ │ │ └── tools/
│ │ │ │ │ ├── lua_converter.go
│ │ │ │ │ ├── mcp_tools.go
│ │ │ │ │ ├── nginx_parser.go
│ │ │ │ │ └── tool_chain.go
│ │ │ │ └── types.go
│ │ │ ├── rag/
│ │ │ │ ├── README.md
│ │ │ │ ├── common/
│ │ │ │ │ └── httpclient.go
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── embedding/
│ │ │ │ │ ├── openai.go
│ │ │ │ │ └── provider.go
│ │ │ │ ├── llm/
│ │ │ │ │ ├── openai.go
│ │ │ │ │ ├── prompt.go
│ │ │ │ │ └── provider.go
│ │ │ │ ├── rag_client.go
│ │ │ │ ├── rag_client_test.go
│ │ │ │ ├── schema/
│ │ │ │ │ └── document.go
│ │ │ │ ├── server.go
│ │ │ │ ├── server_test.go
│ │ │ │ ├── textsplitter/
│ │ │ │ │ ├── options.go
│ │ │ │ │ ├── recursive_character.go
│ │ │ │ │ ├── recursive_character_test.go
│ │ │ │ │ ├── splitter_document.go
│ │ │ │ │ └── text_splitter.go
│ │ │ │ ├── tools.go
│ │ │ │ └── vectordb/
│ │ │ │ ├── mapper.go
│ │ │ │ ├── milvus.go
│ │ │ │ ├── milvus_test.go
│ │ │ │ └── provider.go
│ │ │ └── tool-search/
│ │ │ ├── README.md
│ │ │ ├── config-example.json
│ │ │ ├── embedding.go
│ │ │ ├── milvus.go
│ │ │ ├── search.go
│ │ │ ├── server.go
│ │ │ ├── server_test.go
│ │ │ └── tools.go
│ │ └── mcp-session/
│ │ ├── common/
│ │ │ ├── auth.go
│ │ │ ├── crypto.go
│ │ │ ├── match.go
│ │ │ ├── redis.go
│ │ │ ├── registry.go
│ │ │ ├── server.go
│ │ │ ├── sse.go
│ │ │ └── utils.go
│ │ ├── config.go
│ │ ├── filter.go
│ │ ├── filter_test.go
│ │ └── handler/
│ │ ├── config_handler.go
│ │ ├── config_store.go
│ │ └── rate_limit_handler.go
│ ├── wasm-assemblyscript/
│ │ ├── README.md
│ │ ├── asconfig.json
│ │ ├── assembly/
│ │ │ ├── cluster_wrapper.ts
│ │ │ ├── http_wrapper.ts
│ │ │ ├── index.ts
│ │ │ ├── log_wrapper.ts
│ │ │ ├── plugin_wrapper.ts
│ │ │ ├── request_wrapper.ts
│ │ │ ├── rule_matcher.ts
│ │ │ └── tsconfig.json
│ │ ├── extensions/
│ │ │ ├── custom-response/
│ │ │ │ ├── README.md
│ │ │ │ ├── asconfig.json
│ │ │ │ ├── assembly/
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── tsconfig.json
│ │ │ │ └── package.json
│ │ │ └── hello-world/
│ │ │ ├── asconfig.json
│ │ │ ├── assembly/
│ │ │ │ ├── index.ts
│ │ │ │ └── tsconfig.json
│ │ │ └── package.json
│ │ └── package.json
│ ├── wasm-cpp/
│ │ ├── .bazelrc
│ │ ├── .bazelversion
│ │ ├── .clang-format
│ │ ├── BUILD
│ │ ├── Dockerfile
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── README_EN.md
│ │ ├── WORKSPACE
│ │ ├── bazel/
│ │ │ ├── BUILD
│ │ │ ├── absl.patch
│ │ │ ├── boringssl.patch
│ │ │ ├── re2.patch
│ │ │ ├── third_party.bzl
│ │ │ └── wasm.bzl
│ │ ├── common/
│ │ │ ├── BUILD
│ │ │ ├── base64.h
│ │ │ ├── common_util.h
│ │ │ ├── crypt_blowfish.c
│ │ │ ├── crypto_util.cc
│ │ │ ├── crypto_util.h
│ │ │ ├── http_util.cc
│ │ │ ├── http_util.h
│ │ │ ├── json_util.cc
│ │ │ ├── json_util.h
│ │ │ ├── nlohmann_json.hpp
│ │ │ ├── regex.h
│ │ │ └── route_rule_matcher.h
│ │ ├── extensions/
│ │ │ ├── basic_auth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── bot_detect/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── custom_response/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── hmac_auth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── jwt_auth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── extractor.cc
│ │ │ │ ├── extractor.h
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── key_auth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── key_rate_limit/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── bucket.cc
│ │ │ │ ├── bucket.h
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── model_mapper/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── model_router/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── oauth/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ ├── request_block/
│ │ │ │ ├── BUILD
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── plugin.cc
│ │ │ │ ├── plugin.h
│ │ │ │ └── plugin_test.cc
│ │ │ └── sni_misdirect/
│ │ │ ├── BUILD
│ │ │ ├── README.md
│ │ │ ├── VERSION
│ │ │ ├── plugin.cc
│ │ │ ├── plugin.h
│ │ │ └── plugin_test.cc
│ │ └── scripts/
│ │ └── build_and_push.sh
│ ├── wasm-go/
│ │ ├── .devcontainer/
│ │ │ ├── Dockerfile
│ │ │ ├── devcontainer.json
│ │ │ └── gen_config.py
│ │ ├── Dockerfile
│ │ ├── DockerfileBuilder
│ │ ├── Makefile
│ │ ├── README.md
│ │ ├── README_EN.md
│ │ ├── examples/
│ │ │ ├── custom-log/
│ │ │ │ ├── config.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── custom-span-attribute/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ └── test-foreign-function/
│ │ │ ├── README.md
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ │ └── main.go
│ │ ├── extensions/
│ │ │ ├── ai-agent/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config.go
│ │ │ │ ├── dashscope/
│ │ │ │ │ ├── message.go
│ │ │ │ │ └── types.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── promptTpl/
│ │ │ │ └── prompt.go
│ │ │ ├── ai-cache/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── cache/
│ │ │ │ │ ├── provider.go
│ │ │ │ │ └── redis.go
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── core.go
│ │ │ │ ├── embedding/
│ │ │ │ │ ├── azure.go
│ │ │ │ │ ├── cohere.go
│ │ │ │ │ ├── dashscope.go
│ │ │ │ │ ├── huggingface.go
│ │ │ │ │ ├── ollama.go
│ │ │ │ │ ├── openai.go
│ │ │ │ │ ├── provider.go
│ │ │ │ │ ├── textin.go
│ │ │ │ │ └── xfyun.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── option.yaml
│ │ │ │ ├── util.go
│ │ │ │ └── vector/
│ │ │ │ ├── chroma.go
│ │ │ │ ├── dashvector.go
│ │ │ │ ├── elasticsearch.go
│ │ │ │ ├── milvus.go
│ │ │ │ ├── pinecone.go
│ │ │ │ ├── provider.go
│ │ │ │ ├── qdrant.go
│ │ │ │ └── weaviate.go
│ │ │ ├── ai-history/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── option.yaml
│ │ │ ├── ai-image-reader/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── dashscope.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── provider.go
│ │ │ ├── ai-intent/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-json-resp/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── model.go
│ │ │ │ └── util.go
│ │ │ ├── ai-load-balancer/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── cluster_metrics/
│ │ │ │ │ └── lb_policy.go
│ │ │ │ ├── endpoint_metrics/
│ │ │ │ │ ├── backend/
│ │ │ │ │ │ ├── types.go
│ │ │ │ │ │ └── vllm/
│ │ │ │ │ │ └── metrics.go
│ │ │ │ │ ├── lb_policy.go
│ │ │ │ │ └── scheduling/
│ │ │ │ │ ├── filter.go
│ │ │ │ │ ├── scheduler.go
│ │ │ │ │ └── types.go
│ │ │ │ ├── global_least_request/
│ │ │ │ │ ├── lb_policy.go
│ │ │ │ │ ├── lb_script_test.lua
│ │ │ │ │ └── rate_limit.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── prefix_cache/
│ │ │ │ │ └── lb_policy.go
│ │ │ │ └── utils/
│ │ │ │ ├── queue.go
│ │ │ │ └── utils.go
│ │ │ ├── ai-prompt-decorator/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-prompt-template/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-proxy/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── README_dev.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── option.yaml
│ │ │ │ ├── provider/
│ │ │ │ │ ├── ai360.go
│ │ │ │ │ ├── azure.go
│ │ │ │ │ ├── baichuan.go
│ │ │ │ │ ├── baidu.go
│ │ │ │ │ ├── bedrock.go
│ │ │ │ │ ├── bedrock_sigv4_path_test.go
│ │ │ │ │ ├── claude.go
│ │ │ │ │ ├── claude_test.go
│ │ │ │ │ ├── claude_to_openai.go
│ │ │ │ │ ├── claude_to_openai_test.go
│ │ │ │ │ ├── cloudflare.go
│ │ │ │ │ ├── cohere.go
│ │ │ │ │ ├── context.go
│ │ │ │ │ ├── coze.go
│ │ │ │ │ ├── custom_setting.go
│ │ │ │ │ ├── deepl.go
│ │ │ │ │ ├── deepseek.go
│ │ │ │ │ ├── dify.go
│ │ │ │ │ ├── doubao.go
│ │ │ │ │ ├── failover.go
│ │ │ │ │ ├── fireworks.go
│ │ │ │ │ ├── gemini.go
│ │ │ │ │ ├── generic.go
│ │ │ │ │ ├── github.go
│ │ │ │ │ ├── grok.go
│ │ │ │ │ ├── groq.go
│ │ │ │ │ ├── hunyuan.go
│ │ │ │ │ ├── longcat.go
│ │ │ │ │ ├── longcat_test.go
│ │ │ │ │ ├── minimax.go
│ │ │ │ │ ├── mistral.go
│ │ │ │ │ ├── model.go
│ │ │ │ │ ├── moonshot.go
│ │ │ │ │ ├── multipart_helper.go
│ │ │ │ │ ├── ollama.go
│ │ │ │ │ ├── openai.go
│ │ │ │ │ ├── openrouter.go
│ │ │ │ │ ├── provider.go
│ │ │ │ │ ├── provider_test.go
│ │ │ │ │ ├── qwen.go
│ │ │ │ │ ├── request_helper.go
│ │ │ │ │ ├── request_helper_test.go
│ │ │ │ │ ├── retry.go
│ │ │ │ │ ├── spark.go
│ │ │ │ │ ├── stepfun.go
│ │ │ │ │ ├── together_ai.go
│ │ │ │ │ ├── triton.go
│ │ │ │ │ ├── vertex.go
│ │ │ │ │ ├── vllm.go
│ │ │ │ │ ├── yi.go
│ │ │ │ │ └── zhipuai.go
│ │ │ │ ├── test/
│ │ │ │ │ ├── ai360.go
│ │ │ │ │ ├── api_paths.go
│ │ │ │ │ ├── azure.go
│ │ │ │ │ ├── bedrock.go
│ │ │ │ │ ├── claude-test/
│ │ │ │ │ │ └── claude-message-api.yaml
│ │ │ │ │ ├── claude.go
│ │ │ │ │ ├── consumer_affinity.go
│ │ │ │ │ ├── fireworks.go
│ │ │ │ │ ├── gemini.go
│ │ │ │ │ ├── generic.go
│ │ │ │ │ ├── minimax.go
│ │ │ │ │ ├── mock_context.go
│ │ │ │ │ ├── openai.go
│ │ │ │ │ ├── qwen.go
│ │ │ │ │ ├── util.go
│ │ │ │ │ └── vertex.go
│ │ │ │ └── util/
│ │ │ │ ├── http.go
│ │ │ │ ├── json.go
│ │ │ │ ├── json_test.go
│ │ │ │ ├── ptr.go
│ │ │ │ ├── string.go
│ │ │ │ └── string_test.go
│ │ │ ├── ai-quota/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── plugin.yaml
│ │ │ │ └── util/
│ │ │ │ ├── http.go
│ │ │ │ └── http_test.go
│ │ │ ├── ai-rag/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── dashscope/
│ │ │ │ │ └── types.go
│ │ │ │ ├── dashvector/
│ │ │ │ │ └── types.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-search/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── engine/
│ │ │ │ │ ├── arxiv/
│ │ │ │ │ │ └── arxiv.go
│ │ │ │ │ ├── bing/
│ │ │ │ │ │ └── bing.go
│ │ │ │ │ ├── elasticsearch/
│ │ │ │ │ │ └── elasticsearch.go
│ │ │ │ │ ├── google/
│ │ │ │ │ │ └── google.go
│ │ │ │ │ ├── quark/
│ │ │ │ │ │ └── quark.go
│ │ │ │ │ └── types.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── guide.md
│ │ │ │ ├── main.go
│ │ │ │ └── prompts/
│ │ │ │ ├── arxiv.md
│ │ │ │ ├── chinese-internet.md
│ │ │ │ ├── full.md
│ │ │ │ ├── internet.md
│ │ │ │ ├── private.md
│ │ │ │ └── test_ai_search.py
│ │ │ ├── ai-security-guard/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── lvwang/
│ │ │ │ │ ├── common/
│ │ │ │ │ │ ├── request_builder.go
│ │ │ │ │ │ ├── request_builder_test.go
│ │ │ │ │ │ └── text/
│ │ │ │ │ │ └── openai.go
│ │ │ │ │ ├── multi_modal_guard/
│ │ │ │ │ │ ├── handler.go
│ │ │ │ │ │ ├── image/
│ │ │ │ │ │ │ ├── common.go
│ │ │ │ │ │ │ ├── openai.go
│ │ │ │ │ │ │ └── qwen.go
│ │ │ │ │ │ ├── mcp/
│ │ │ │ │ │ │ └── mcp.go
│ │ │ │ │ │ └── text/
│ │ │ │ │ │ └── openai.go
│ │ │ │ │ └── text_moderation_plus/
│ │ │ │ │ ├── handler.go
│ │ │ │ │ └── text/
│ │ │ │ │ └── openai.go
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── utils/
│ │ │ │ └── utils.go
│ │ │ ├── ai-statistics/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── fix_tool_calls.patch
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ai-token-ratelimit/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ └── utils.go
│ │ │ ├── ai-transformer/
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── api-workflow/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── README.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── utils/
│ │ │ │ │ ├── conditional.go
│ │ │ │ │ ├── conditional_test.go
│ │ │ │ │ ├── http.go
│ │ │ │ │ └── tools.go
│ │ │ │ └── workflow/
│ │ │ │ └── workflow.go
│ │ │ ├── basic-auth/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── bot-detect/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── botdetect.yaml
│ │ │ │ ├── config/
│ │ │ │ │ ├── bot_detect_config.go
│ │ │ │ │ └── bot_detect_config_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── cache-control/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── chatgpt-proxy/
│ │ │ │ ├── README.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── cluster-key-rate-limit/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ └── utils.go
│ │ │ ├── cors/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── cors_config.go
│ │ │ │ │ └── cors_config_test.go
│ │ │ │ ├── cors.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── custom-response/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── de-graphql/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── degraphql_config.go
│ │ │ │ │ └── degraphql_config_test.go
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── graphql.yaml
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ext-auth/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── expr/
│ │ │ │ │ ├── match_rules.go
│ │ │ │ │ ├── match_rules_test.go
│ │ │ │ │ ├── matcher.go
│ │ │ │ │ ├── matcher_test.go
│ │ │ │ │ ├── repeated_string_matcher.go
│ │ │ │ │ └── repeated_string_matcher_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ └── utils.go
│ │ │ ├── frontend-gray/
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ ├── gc-test/
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── geo-ip/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── generateCidr/
│ │ │ │ │ ├── ip.merge.txt
│ │ │ │ │ ├── ipRange2Cidr.go
│ │ │ │ │ └── ipRange2Cidr_test.go
│ │ │ │ ├── geoCidr.txt
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── gw-error-format/
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── gw-error-format.yaml
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── hello-world/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── hmac-auth-apisix/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── config/
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── config_test.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── http-call/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── ip-restriction/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ ├── jsonrpc-converter/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── jwt-auth/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── Makefile
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ ├── checker.go
│ │ │ │ │ ├── config.go
│ │ │ │ │ └── parser.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── go.work.sum
│ │ │ │ ├── handler/
│ │ │ │ │ ├── claims.go
│ │ │ │ │ ├── extractor.go
│ │ │ │ │ ├── handler.go
│ │ │ │ │ ├── verify.go
│ │ │ │ │ └── verify_test.go
│ │ │ │ ├── main.go
│ │ │ │ ├── option.yaml
│ │ │ │ └── test/
│ │ │ │ ├── jwt_test.go
│ │ │ │ ├── jwts.json
│ │ │ │ └── keys.json
│ │ │ ├── key-auth/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── keyauth.yaml
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── log-request-response/
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── mcp-router/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── mcp-server/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── model-mapper/
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── model-router/
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── oidc/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── main.go
│ │ │ ├── opa/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config.go
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── replay-protection/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── util/
│ │ │ │ └── utils.go
│ │ │ ├── request-block/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── Makefile
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── request-validation/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── response-cache/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── cache/
│ │ │ │ │ ├── provider.go
│ │ │ │ │ └── redis.go
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── core.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── option.yaml
│ │ │ ├── simple-jwt-auth/
│ │ │ │ ├── README.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── sni-misdirect/
│ │ │ │ ├── VERSION
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── streaming-body-example/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── main_test.go
│ │ │ ├── traffic-editor/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── config.go
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── http.go
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ └── pkg/
│ │ │ │ ├── command.go
│ │ │ │ ├── command_test.go
│ │ │ │ ├── condition.go
│ │ │ │ ├── condition_test.go
│ │ │ │ ├── context.go
│ │ │ │ ├── context_test.go
│ │ │ │ ├── mock_test.go
│ │ │ │ └── ref.go
│ │ │ ├── traffic-tag/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── SampleConfig.yaml
│ │ │ │ ├── VERSION
│ │ │ │ ├── config.yaml
│ │ │ │ ├── content.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── main_test.go
│ │ │ │ ├── parse.go
│ │ │ │ ├── utils.go
│ │ │ │ └── weight.go
│ │ │ ├── transformer/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_EN.md
│ │ │ │ ├── VERSION
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ ├── envoy.yaml
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ ├── utils.go
│ │ │ │ └── utils_test.go
│ │ │ └── waf/
│ │ │ ├── Dockerfile
│ │ │ ├── README.md
│ │ │ ├── README_EN.md
│ │ │ ├── VERSION
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ │ ├── init_tinygo.go
│ │ │ ├── local/
│ │ │ │ ├── Dockerfile
│ │ │ │ ├── app.py
│ │ │ │ ├── docker-compose.yaml
│ │ │ │ └── envoy-config.yaml
│ │ │ ├── mage.go
│ │ │ ├── magefiles/
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ └── magefile.go
│ │ │ ├── main.go
│ │ │ └── wasmplugin/
│ │ │ ├── fs.go
│ │ │ ├── logger.go
│ │ │ ├── plugin.go
│ │ │ ├── rules/
│ │ │ │ ├── coraza-demo.conf
│ │ │ │ ├── coraza.conf-recommended.conf
│ │ │ │ ├── crs/
│ │ │ │ │ ├── REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf.example
│ │ │ │ │ ├── REQUEST-901-INITIALIZATION.conf
│ │ │ │ │ ├── REQUEST-905-COMMON-EXCEPTIONS.conf
│ │ │ │ │ ├── REQUEST-911-METHOD-ENFORCEMENT.conf
│ │ │ │ │ ├── REQUEST-913-SCANNER-DETECTION.conf
│ │ │ │ │ ├── REQUEST-920-PROTOCOL-ENFORCEMENT.conf
│ │ │ │ │ ├── REQUEST-921-PROTOCOL-ATTACK.conf
│ │ │ │ │ ├── REQUEST-922-MULTIPART-ATTACK.conf
│ │ │ │ │ ├── REQUEST-930-APPLICATION-ATTACK-LFI.conf
│ │ │ │ │ ├── REQUEST-931-APPLICATION-ATTACK-RFI.conf
│ │ │ │ │ ├── REQUEST-932-APPLICATION-ATTACK-RCE.conf
│ │ │ │ │ ├── REQUEST-933-APPLICATION-ATTACK-PHP.conf
│ │ │ │ │ ├── REQUEST-934-APPLICATION-ATTACK-GENERIC.conf
│ │ │ │ │ ├── REQUEST-941-APPLICATION-ATTACK-XSS.conf
│ │ │ │ │ ├── REQUEST-942-APPLICATION-ATTACK-SQLI.conf
│ │ │ │ │ ├── REQUEST-943-APPLICATION-ATTACK-SESSION-FIXATION.conf
│ │ │ │ │ ├── REQUEST-944-APPLICATION-ATTACK-JAVA.conf
│ │ │ │ │ ├── REQUEST-949-BLOCKING-EVALUATION.conf
│ │ │ │ │ ├── RESPONSE-950-DATA-LEAKAGES.conf
│ │ │ │ │ ├── RESPONSE-951-DATA-LEAKAGES-SQL.conf
│ │ │ │ │ ├── RESPONSE-952-DATA-LEAKAGES-JAVA.conf
│ │ │ │ │ ├── RESPONSE-953-DATA-LEAKAGES-PHP.conf
│ │ │ │ │ ├── RESPONSE-954-DATA-LEAKAGES-IIS.conf
│ │ │ │ │ ├── RESPONSE-955-WEB-SHELLS.conf
│ │ │ │ │ ├── RESPONSE-959-BLOCKING-EVALUATION.conf
│ │ │ │ │ ├── RESPONSE-980-CORRELATION.conf
│ │ │ │ │ ├── RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf.example
│ │ │ │ │ ├── crawlers-user-agents.data
│ │ │ │ │ ├── iis-errors.data
│ │ │ │ │ ├── java-classes.data
│ │ │ │ │ ├── java-code-leakages.data
│ │ │ │ │ ├── java-errors.data
│ │ │ │ │ ├── lfi-os-files.data
│ │ │ │ │ ├── php-config-directives.data
│ │ │ │ │ ├── php-errors-pl2.data
│ │ │ │ │ ├── php-errors.data
│ │ │ │ │ ├── php-function-names-933150.data
│ │ │ │ │ ├── php-function-names-933151.data
│ │ │ │ │ ├── php-variables.data
│ │ │ │ │ ├── restricted-files.data
│ │ │ │ │ ├── restricted-upload.data
│ │ │ │ │ ├── scanners-headers.data
│ │ │ │ │ ├── scanners-urls.data
│ │ │ │ │ ├── scanners-user-agents.data
│ │ │ │ │ ├── scripting-user-agents.data
│ │ │ │ │ ├── sql-errors.data
│ │ │ │ │ ├── ssrf.data
│ │ │ │ │ ├── unix-shell.data
│ │ │ │ │ ├── web-shells-php.data
│ │ │ │ │ └── windows-powershell-commands.data
│ │ │ │ ├── crs-setup-demo.conf
│ │ │ │ ├── crs-setup.conf.example
│ │ │ │ └── ftw-config.conf
│ │ │ └── utils.go
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── mcp-servers/
│ │ │ ├── Dockerfile
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── README_zh.md
│ │ │ ├── amap-tools/
│ │ │ │ ├── config/
│ │ │ │ │ └── config.go
│ │ │ │ ├── go.mod
│ │ │ │ ├── go.sum
│ │ │ │ ├── main.go
│ │ │ │ └── tools/
│ │ │ │ ├── load_tools.go
│ │ │ │ ├── maps_around_search.go
│ │ │ │ ├── maps_bicycling.go
│ │ │ │ ├── maps_direction_driving.go
│ │ │ │ ├── maps_direction_transit_integrated.go
│ │ │ │ ├── maps_direction_walking.go
│ │ │ │ ├── maps_distance.go
│ │ │ │ ├── maps_geo.go
│ │ │ │ ├── maps_ip_location.go
│ │ │ │ ├── maps_regeocode.go
│ │ │ │ ├── maps_search_detail.go
│ │ │ │ ├── maps_text_search.go
│ │ │ │ └── maps_weather.go
│ │ │ ├── mcp-agricultural-product-price-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-bid-tools/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-blockscout/
│ │ │ │ ├── README.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-book-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-bravesearch/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-business-credit-rating/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-business-info-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-business-patent-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-calendar-holiday-helper/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-chatppt/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-context7/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-deadbeat-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-document-conversion/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-e2bdev/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-exchange-rate-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-firecrawl/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-fund-data-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-github/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-global-financial-news/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-hackmd/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-heavenly-stems-and-earthly-branches-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-hot-news/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-invoice-verification/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-ip-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-jd-hot-words/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-librechat/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-logistics-tracking-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-national-bid-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-notion/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-oil-price-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-openweather/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-parking-lot-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-plate-quote/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-product-barcode-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-recipe-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-resume-analysis/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-route-planning/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-scripts/
│ │ │ │ ├── create_api_directories.sh
│ │ │ │ ├── mcp-server-docs.md
│ │ │ │ ├── translate_readme.py
│ │ │ │ ├── yaml_to_markdown.py
│ │ │ │ └── yunmarket-tmpl.yaml
│ │ │ ├── mcp-shebao-tools/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── city_data.xls
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-stock-helper/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-stock-history-data/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-taobao-hot-words/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-time/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-today-in-history/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-tourist-attraction-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-traditional-chinese-medicine-tongue-diagnosis/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-train-ticket-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-vehicle-info-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-vehicle-restriction-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-weather-query/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-wolframalpha/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-yuque/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ └── mcp-server.yaml
│ │ │ ├── mcp-zodiac-analysis/
│ │ │ │ ├── README.md
│ │ │ │ ├── README_ZH.md
│ │ │ │ ├── api.json
│ │ │ │ └── mcp-server.yaml
│ │ │ └── quark-search/
│ │ │ ├── config/
│ │ │ │ └── config.go
│ │ │ ├── go.mod
│ │ │ ├── go.sum
│ │ │ ├── main.go
│ │ │ └── tools/
│ │ │ ├── load_tools.go
│ │ │ ├── web_search.go
│ │ │ └── web_search_test.go
│ │ └── pkg/
│ │ └── mcp/
│ │ ├── consts/
│ │ │ └── vars.go
│ │ ├── filter/
│ │ │ └── plugin.go
│ │ ├── go.mod
│ │ ├── mcp.go
│ │ ├── server/
│ │ │ ├── auth_utils.go
│ │ │ ├── base_server.go
│ │ │ ├── composed_server.go
│ │ │ ├── config_validator_test.go
│ │ │ ├── plugin.go
│ │ │ ├── proxy_auth_test.go
│ │ │ ├── proxy_integration_test.go
│ │ │ ├── proxy_server.go
│ │ │ ├── proxy_server_test.go
│ │ │ ├── proxy_tool.go
│ │ │ ├── proxy_tools_test.go
│ │ │ ├── rest_server.go
│ │ │ ├── rest_server_test.go
│ │ │ ├── sse_proxy.go
│ │ │ └── sse_proxy_test.go
│ │ ├── utils/
│ │ │ ├── json_rpc.go
│ │ │ ├── json_rpc_test.go
│ │ │ ├── log.go
│ │ │ ├── mcp_rpc.go
│ │ │ └── session.go
│ │ └── validator/
│ │ ├── README.md
│ │ ├── config_validator.go
│ │ ├── config_validator_test.go
│ │ └── example_usage.go
│ └── wasm-rust/
│ ├── .dockerignore
│ ├── Cargo.toml
│ ├── Dockerfile
│ ├── DockerfileBuilder
│ ├── Makefile
│ ├── README.md
│ ├── example/
│ │ ├── sse-timing/
│ │ │ ├── Cargo.toml
│ │ │ ├── Makefile
│ │ │ ├── README.md
│ │ │ ├── docker-compose.yaml
│ │ │ ├── envoy.yaml
│ │ │ ├── src/
│ │ │ │ └── lib.rs
│ │ │ └── sse-server/
│ │ │ ├── Dockerfile
│ │ │ ├── go.mod
│ │ │ └── main.go
│ │ └── wrapper-say-hello/
│ │ ├── Cargo.toml
│ │ ├── docker-compose.yaml
│ │ ├── envoy.yaml
│ │ └── src/
│ │ └── lib.rs
│ ├── extensions/
│ │ ├── ai-data-masking/
│ │ │ ├── .prebuild
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ ├── README_EN.md
│ │ │ ├── res/
│ │ │ │ └── sensitive_word_dict.txt
│ │ │ ├── src/
│ │ │ │ ├── ai_data_masking.rs
│ │ │ │ ├── deny_word.rs
│ │ │ │ ├── lib.rs
│ │ │ │ ├── msg_win_openai.rs
│ │ │ │ ├── msg_window.rs
│ │ │ │ └── number_merge.rs
│ │ │ └── test/
│ │ │ └── raw_message.txt
│ │ ├── ai-intent/
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ ├── README_EN.md
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── demo-wasm/
│ │ │ ├── Cargo.toml
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ ├── request-block/
│ │ │ ├── Cargo.toml
│ │ │ ├── README.md
│ │ │ └── src/
│ │ │ └── lib.rs
│ │ └── say-hello/
│ │ ├── Cargo.toml
│ │ ├── docker-compose.yaml
│ │ ├── envoy.yaml
│ │ └── src/
│ │ └── lib.rs
│ └── src/
│ ├── cluster_wrapper.rs
│ ├── error.rs
│ ├── event_stream.rs
│ ├── internal.rs
│ ├── lib.rs
│ ├── log.rs
│ ├── plugin_wrapper.rs
│ ├── redis_wrapper.rs
│ ├── request_wrapper.rs
│ └── rule_matcher.rs
├── registry/
│ ├── auth_option.go
│ ├── consul/
│ │ └── watcher.go
│ ├── direct/
│ │ └── watcher.go
│ ├── eureka/
│ │ ├── client/
│ │ │ ├── http_client.go
│ │ │ ├── plan.go
│ │ │ └── struct.go
│ │ └── watcher.go
│ ├── mcp_model.go
│ ├── memory/
│ │ └── cache.go
│ ├── nacos/
│ │ ├── address/
│ │ │ ├── address_discovery.go
│ │ │ └── address_discovery_test.go
│ │ ├── mcpserver/
│ │ │ ├── client.go
│ │ │ ├── client_test.go
│ │ │ ├── watcher.go
│ │ │ └── watcher_test.go
│ │ ├── v2/
│ │ │ ├── watcher.go
│ │ │ └── watcher_test.go
│ │ ├── watcher.go
│ │ └── watcher_test.go
│ ├── proxy/
│ │ └── factory.go
│ ├── reconcile/
│ │ └── reconcile.go
│ ├── watcher.go
│ └── zookeeper/
│ ├── types.go
│ ├── watcher.go
│ └── watcher_test.go
├── release-notes/
│ ├── 2.1.10/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.11/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.4/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.5/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.6/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.7/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.8/
│ │ ├── README.md
│ │ └── README_ZH.md
│ ├── 2.1.9/
│ │ ├── README.md
│ │ └── README_ZH.md
│ └── 2.2.0/
│ ├── README.md
│ └── README_ZH.md
├── samples/
│ ├── gateway-api/
│ │ └── demo.yaml
│ ├── hello-world/
│ │ └── quickstart.yaml
│ ├── loadbalance/
│ │ └── useSourceIp-example.yaml
│ ├── nacos-discovery/
│ │ ├── canary.yaml
│ │ ├── multi-destination.yaml
│ │ └── quickstart.yaml
│ ├── quickstart.yaml
│ └── wasmplugin/
│ ├── default-config.yaml
│ ├── ingress-level-config.yaml
│ └── waf.yaml
├── test/
│ ├── README.md
│ ├── README_CN.md
│ ├── e2e/
│ │ ├── conformance/
│ │ │ ├── base/
│ │ │ │ ├── consul.yaml
│ │ │ │ ├── dubbo.yaml
│ │ │ │ ├── eureka.yaml
│ │ │ │ ├── llm-mock.yaml
│ │ │ │ ├── manifests.yaml
│ │ │ │ ├── nacos.yaml
│ │ │ │ └── opa.yaml
│ │ │ ├── embed.go
│ │ │ ├── tests/
│ │ │ │ ├── configmap-global.go
│ │ │ │ ├── configmap-global.yaml
│ │ │ │ ├── configmap-gzip.go
│ │ │ │ ├── configmap-gzip.yaml
│ │ │ │ ├── configmap-https.go
│ │ │ │ ├── configmap-https.yaml
│ │ │ │ ├── configmap-mcp-redis-secret.go
│ │ │ │ ├── configmap-mcp-redis-secret.yaml
│ │ │ │ ├── cpp-wasm-basic-auth.go
│ │ │ │ ├── cpp-wasm-basic-auth.yaml
│ │ │ │ ├── cpp-wasm-key-auth.go
│ │ │ │ ├── cpp-wasm-key-auth.yaml
│ │ │ │ ├── cpp-wasm-request-block.go
│ │ │ │ ├── cpp-wasm-request-block.yaml
│ │ │ │ ├── go-wasm-ai-cache.go
│ │ │ │ ├── go-wasm-ai-cache.yaml
│ │ │ │ ├── go-wasm-ai-proxy.go
│ │ │ │ ├── go-wasm-ai-proxy.yaml
│ │ │ │ ├── go-wasm-basic-auth-template.go
│ │ │ │ ├── go-wasm-basic-auth-template.yaml
│ │ │ │ ├── go-wasm-basic-auth.go
│ │ │ │ ├── go-wasm-basic-auth.yaml
│ │ │ │ ├── go-wasm-bot-detect.go
│ │ │ │ ├── go-wasm-bot-detect.yaml
│ │ │ │ ├── go-wasm-cache-control.go
│ │ │ │ ├── go-wasm-cache-control.yaml
│ │ │ │ ├── go-wasm-custom-response.go
│ │ │ │ ├── go-wasm-custom-response.yaml
│ │ │ │ ├── go-wasm-geo-ip.go
│ │ │ │ ├── go-wasm-geo-ip.yaml
│ │ │ │ ├── go-wasm-ip-restriction-allow.yaml
│ │ │ │ ├── go-wasm-ip-restriction-deny.yaml
│ │ │ │ ├── go-wasm-ip-restriction.go
│ │ │ │ ├── go-wasm-jwt-auth-allow.yaml
│ │ │ │ ├── go-wasm-jwt-auth-deny.yaml
│ │ │ │ ├── go-wasm-jwt-auth-single-consumer.yaml
│ │ │ │ ├── go-wasm-jwt-auth.go
│ │ │ │ ├── go-wasm-key-auth.go
│ │ │ │ ├── go-wasm-key-auth.yaml
│ │ │ │ ├── go-wasm-opa.go
│ │ │ │ ├── go-wasm-opa.yaml
│ │ │ │ ├── go-wasm-replay-protection.go
│ │ │ │ ├── go-wasm-replay-protection.yaml
│ │ │ │ ├── go-wasm-request-block.go
│ │ │ │ ├── go-wasm-request-block.yaml
│ │ │ │ ├── go-wasm-request-validation.go
│ │ │ │ ├── go-wasm-request-validation.yaml
│ │ │ │ ├── go-wasm-simple-jwt-auth.go
│ │ │ │ ├── go-wasm-simple-jwt-auth.yaml
│ │ │ │ ├── go-wasm-sni-misdirect.go
│ │ │ │ ├── go-wasm-sni-misdirect.yaml
│ │ │ │ ├── go-wasm-transformer.go
│ │ │ │ ├── go-wasm-transformer.yaml
│ │ │ │ ├── httproute-app-root.go
│ │ │ │ ├── httproute-app-root.yaml
│ │ │ │ ├── httproute-canary-header-with-customized-header.go
│ │ │ │ ├── httproute-canary-header-with-customized-header.yaml
│ │ │ │ ├── httproute-canary-header.go
│ │ │ │ ├── httproute-canary-header.yaml
│ │ │ │ ├── httproute-canary-weight.go
│ │ │ │ ├── httproute-canary-weight.yaml
│ │ │ │ ├── httproute-consul-httpbin.go
│ │ │ │ ├── httproute-consul-httpbin.yaml
│ │ │ │ ├── httproute-default-backend.go
│ │ │ │ ├── httproute-default-backend.yaml
│ │ │ │ ├── httproute-dns-registry.go
│ │ │ │ ├── httproute-dns-registry.yaml
│ │ │ │ ├── httproute-downstream-encryption.go
│ │ │ │ ├── httproute-downstream-encryption.yaml
│ │ │ │ ├── httproute-enable-cors.go
│ │ │ │ ├── httproute-enable-cors.yaml
│ │ │ │ ├── httproute-enable-ignore-case.go
│ │ │ │ ├── httproute-enable-ignore-case.yaml
│ │ │ │ ├── httproute-eureka-registry.go
│ │ │ │ ├── httproute-eureka-registry.yaml
│ │ │ │ ├── httproute-exact-domain-fallback.go
│ │ │ │ ├── httproute-exact-domain-fallback.yaml
│ │ │ │ ├── httproute-force-redirect-https.go
│ │ │ │ ├── httproute-force-redirect-https.yaml
│ │ │ │ ├── httproute-full-path-regex.go
│ │ │ │ ├── httproute-full-path-regex.yaml
│ │ │ │ ├── httproute-hostname-same-namespace.go
│ │ │ │ ├── httproute-hostname-same-namespace.yaml
│ │ │ │ ├── httproute-http2rpc-0-create.yaml
│ │ │ │ ├── httproute-http2rpc-1-update.yaml
│ │ │ │ ├── httproute-http2rpc.go
│ │ │ │ ├── httproute-https-without-sni.go
│ │ │ │ ├── httproute-https-without-sni.yaml
│ │ │ │ ├── httproute-limit.go
│ │ │ │ ├── httproute-limit.yaml
│ │ │ │ ├── httproute-match-headers.go
│ │ │ │ ├── httproute-match-headers.yaml
│ │ │ │ ├── httproute-match-methods.go
│ │ │ │ ├── httproute-match-methods.yaml
│ │ │ │ ├── httproute-match-path.go
│ │ │ │ ├── httproute-match-path.yaml
│ │ │ │ ├── httproute-match-pseudo-headers.go
│ │ │ │ ├── httproute-match-pseudo-headers.yaml
│ │ │ │ ├── httproute-match-query-params.go
│ │ │ │ ├── httproute-match-query-params.yaml
│ │ │ │ ├── httproute-mirror-target-service.go
│ │ │ │ ├── httproute-mirror-target-service.yaml
│ │ │ │ ├── httproute-permanent-redirect-code.go
│ │ │ │ ├── httproute-permanent-redirect-code.yaml
│ │ │ │ ├── httproute-permanent-redirect.go
│ │ │ │ ├── httproute-permanent-redirect.yaml
│ │ │ │ ├── httproute-redirct-as-https.yaml
│ │ │ │ ├── httproute-redirect-as-https.go
│ │ │ │ ├── httproute-request-header-control.go
│ │ │ │ ├── httproute-request-header-control.yaml
│ │ │ │ ├── httproute-response-header-control.go
│ │ │ │ ├── httproute-response-header-control.yaml
│ │ │ │ ├── httproute-rewrite-host.go
│ │ │ │ ├── httproute-rewrite-host.yaml
│ │ │ │ ├── httproute-rewrite-path.go
│ │ │ │ ├── httproute-rewrite-path.yaml
│ │ │ │ ├── httproute-same-host-and-path.go
│ │ │ │ ├── httproute-same-host-and-path.yaml
│ │ │ │ ├── httproute-simple-same-namespace.go
│ │ │ │ ├── httproute-simple-same-namespace.yaml
│ │ │ │ ├── httproute-static-registry.go
│ │ │ │ ├── httproute-static-registry.yaml
│ │ │ │ ├── httproute-temporal-redirect.go
│ │ │ │ ├── httproute-temporal-redirect.yaml
│ │ │ │ ├── httproute-timeout.go
│ │ │ │ ├── httproute-timeout.yaml
│ │ │ │ ├── httproute-whitelist-source-range.go
│ │ │ │ ├── httproute-whitelist-source-range.yaml
│ │ │ │ ├── ingress-loadbalance-mcp-sse.go
│ │ │ │ ├── ingress-loadbalance-mcp-sse.yaml
│ │ │ │ ├── rust-wasm-ai-data-masking.go
│ │ │ │ ├── rust-wasm-ai-data-masking.yaml
│ │ │ │ ├── rust-wasm-request-block.go
│ │ │ │ ├── rust-wasm-request-block.yaml
│ │ │ │ └── tests.go
│ │ │ └── utils/
│ │ │ ├── cert/
│ │ │ │ └── cert.go
│ │ │ ├── config/
│ │ │ │ └── timeout.go
│ │ │ ├── envoy/
│ │ │ │ ├── envoy.go
│ │ │ │ └── envoy_test.go
│ │ │ ├── flags/
│ │ │ │ └── flags.go
│ │ │ ├── http/
│ │ │ │ ├── http.go
│ │ │ │ └── http_test.go
│ │ │ ├── kubernetes/
│ │ │ │ ├── apply.go
│ │ │ │ ├── apply_test.go
│ │ │ │ ├── cert.go
│ │ │ │ └── helpers.go
│ │ │ ├── roundtripper/
│ │ │ │ ├── roundtripper.go
│ │ │ │ └── roundtripper_test.go
│ │ │ └── suite/
│ │ │ ├── features.go
│ │ │ └── suite.go
│ │ └── e2e_test.go
│ └── gateway/
│ ├── e2e.go
│ └── e2e_test.go
└── tools/
├── hack/
│ ├── build-envoy.patch
│ ├── build-envoy.sh
│ ├── build-golang-filters.sh
│ ├── build-istio-image.sh
│ ├── build-istio-pilot.sh
│ ├── build-wasm-plugins.sh
│ ├── create-cluster.sh
│ ├── docker-pull-image.sh
│ ├── get-hgctl.sh
│ ├── gobuild.sh
│ ├── kind-load-image.sh
│ ├── prebuild.sh
│ ├── report_build_info.sh
│ ├── run.sh
│ ├── setup-istio-env.sh
│ └── setup_env.sh
├── lint.mk
├── linter/
│ ├── codespell/
│ │ ├── .codespell.ignorewords
│ │ ├── .codespell.skip
│ │ └── matcher.json
│ ├── golangci-lint/
│ │ └── .golangci.yml
│ └── yamllint/
│ └── .yamllint
├── src/
│ ├── codespell/
│ │ └── requirements.txt
│ ├── controller-gen/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ ├── golangci-lint/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ ├── kind/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ ├── kustomize/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ ├── setup-envtest/
│ │ ├── go.mod
│ │ ├── go.sum
│ │ └── pin.go
│ └── yamllint/
│ └── requirements.txt
└── tools.mk
Copy disabled (too large)
Download .txt
Showing preview only (38,352K chars total). Download the full file to get everything.
SYMBOL INDEX (11408 symbols across 957 files)
FILE: .claude/skills/agent-session-monitor/example/clawdbot_demo.py
function generate_session_url (line 8) | def generate_session_url(session_id: str, base_url: str = "http://localh...
function format_response_message (line 31) | def format_response_message(session_id: str, base_url: str = "http://loc...
FILE: .claude/skills/agent-session-monitor/main.py
class SessionManager (line 88) | class SessionManager:
method __init__ (line 91) | def __init__(self, output_dir: str, load_existing: bool = True):
method _load_existing_sessions (line 100) | def _load_existing_sessions(self):
method update_session (line 117) | def update_session(self, session_id: str, ai_log: dict) -> dict:
method _save_session (line 218) | def _save_session(self, session: dict):
method get_all_sessions (line 224) | def get_all_sessions(self) -> List[dict]:
method get_session (line 228) | def get_session(self, session_id: str) -> Optional[dict]:
method get_summary (line 232) | def get_summary(self) -> dict:
class LogParser (line 284) | class LogParser:
method __init__ (line 287) | def __init__(self, state_file: str = None):
method _load_state (line 292) | def _load_state(self):
method _save_state (line 301) | def _save_state(self):
method parse_log_line (line 311) | def parse_log_line(self, line: str) -> Optional[dict]:
method parse_rotated_logs (line 330) | def parse_rotated_logs(self, log_pattern: str, session_manager) -> None:
method _parse_file_incremental (line 368) | def _parse_file_incremental(self, file_path: str, session_manager) -> ...
class RealtimeMonitor (line 422) | class RealtimeMonitor:
method __init__ (line 425) | def __init__(self, session_manager: SessionManager, log_parser=None, l...
method start (line 433) | def start(self):
method _display_status (line 458) | def _display_status(self):
method _display_summary (line 495) | def _display_summary(self):
function main (line 521) | def main():
FILE: .claude/skills/agent-session-monitor/scripts/cli.py
class SessionAnalyzer (line 78) | class SessionAnalyzer:
method __init__ (line 81) | def __init__(self, data_dir: str):
method load_session (line 86) | def load_session(self, session_id: str) -> Optional[dict]:
method load_all_sessions (line 95) | def load_all_sessions(self) -> List[dict]:
method display_session_detail (line 107) | def display_session_detail(self, session_id: str, show_messages: bool ...
method _calculate_cost (line 224) | def _calculate_cost(self, session: dict) -> float:
method stats_by_model (line 250) | def stats_by_model(self) -> Dict[str, dict]:
method stats_by_date (line 272) | def stats_by_date(self, days: int = 30) -> Dict[str, dict]:
method display_model_stats (line 306) | def display_model_stats(self):
method display_date_stats (line 342) | def display_date_stats(self, days: int = 30):
method list_sessions (line 383) | def list_sessions(self, limit: int = 20, sort_by: str = 'updated'):
method export_finops_report (line 414) | def export_finops_report(self, output_file: str, format: str = 'json'):
function main (line 475) | def main():
FILE: .claude/skills/agent-session-monitor/scripts/webserver.py
class SessionMonitorHandler (line 30) | class SessionMonitorHandler(BaseHTTPRequestHandler):
method __init__ (line 33) | def __init__(self, *args, data_dir=None, **kwargs):
method do_GET (line 37) | def do_GET(self):
method serve_index (line 64) | def serve_index(self):
method serve_session_detail (line 69) | def serve_session_detail(self, session_id: str):
method serve_api_sessions (line 74) | def serve_api_sessions(self):
method serve_api_session (line 95) | def serve_api_session(self, session_id: str):
method serve_api_stats (line 104) | def serve_api_stats(self):
method load_session (line 160) | def load_session(self, session_id: str):
method load_all_sessions (line 168) | def load_all_sessions(self):
method calculate_cost (line 179) | def calculate_cost(self, session: dict) -> float:
method send_html (line 205) | def send_html(self, html: str):
method send_json (line 212) | def send_json(self, data):
method generate_index_html (line 220) | def generate_index_html(self) -> str:
method generate_session_html (line 456) | def generate_session_html(self, session_id: str) -> str:
method escape_html (line 678) | def escape_html(self, text: str) -> str:
method log_message (line 686) | def log_message(self, format, *args):
function create_handler (line 691) | def create_handler(data_dir):
function main (line 698) | def main():
FILE: .claude/skills/higress-openclaw-integration/scripts/plugin/index.ts
constant DEFAULT_GATEWAY_URL (line 3) | const DEFAULT_GATEWAY_URL = "http://localhost:8080";
constant DEFAULT_CONSOLE_URL (line 4) | const DEFAULT_CONSOLE_URL = "http://localhost:8001";
constant MODEL_CONFIG (line 7) | const MODEL_CONFIG: Record<string, { contextWindow: number; maxTokens: n...
constant DEFAULT_CONTEXT_WINDOW (line 23) | const DEFAULT_CONTEXT_WINDOW = 200_000;
constant DEFAULT_MAX_TOKENS (line 24) | const DEFAULT_MAX_TOKENS = 128_000;
constant DEFAULT_MODEL_IDS (line 27) | const DEFAULT_MODEL_IDS = [
function normalizeBaseUrl (line 48) | function normalizeBaseUrl(value: string): string {
function validateUrl (line 57) | function validateUrl(value: string): string | undefined {
function parseModelIds (line 67) | function parseModelIds(input: string): string[] {
function buildModelDefinition (line 75) | function buildModelDefinition(modelId: string) {
function testGatewayConnection (line 91) | async function testGatewayConnection(gatewayUrl: string): Promise<boolea...
function fetchAvailableModels (line 109) | async function fetchAvailableModels(consoleUrl: string): Promise<string[...
method register (line 136) | register(api) {
FILE: api/extensions/v1alpha1/wasmplugin.pb.go
constant _ (line 39) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 41) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type RouteType (line 46) | type RouteType
method Enum (line 67) | func (x RouteType) Enum() *RouteType {
method String (line 73) | func (x RouteType) String() string {
method Descriptor (line 77) | func (RouteType) Descriptor() protoreflect.EnumDescriptor {
method Type (line 81) | func (RouteType) Type() protoreflect.EnumType {
method Number (line 85) | func (x RouteType) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 90) | func (RouteType) EnumDescriptor() ([]byte, []int) {
constant RouteType_HTTP (line 50) | RouteType_HTTP RouteType = 0
constant RouteType_GRPC (line 52) | RouteType_GRPC RouteType = 1
type PluginPhase (line 95) | type PluginPhase
method Enum (line 126) | func (x PluginPhase) Enum() *PluginPhase {
method String (line 132) | func (x PluginPhase) String() string {
method Descriptor (line 136) | func (PluginPhase) Descriptor() protoreflect.EnumDescriptor {
method Type (line 140) | func (PluginPhase) Type() protoreflect.EnumType {
method Number (line 144) | func (x PluginPhase) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 149) | func (PluginPhase) EnumDescriptor() ([]byte, []int) {
constant PluginPhase_UNSPECIFIED_PHASE (line 101) | PluginPhase_UNSPECIFIED_PHASE PluginPhase = 0
constant PluginPhase_AUTHN (line 103) | PluginPhase_AUTHN PluginPhase = 1
constant PluginPhase_AUTHZ (line 105) | PluginPhase_AUTHZ PluginPhase = 2
constant PluginPhase_STATS (line 107) | PluginPhase_STATS PluginPhase = 3
type PullPolicy (line 159) | type PullPolicy
method Enum (line 188) | func (x PullPolicy) Enum() *PullPolicy {
method String (line 194) | func (x PullPolicy) String() string {
method Descriptor (line 198) | func (PullPolicy) Descriptor() protoreflect.EnumDescriptor {
method Type (line 202) | func (PullPolicy) Type() protoreflect.EnumType {
method Number (line 206) | func (x PullPolicy) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 211) | func (PullPolicy) EnumDescriptor() ([]byte, []int) {
constant PullPolicy_UNSPECIFIED_POLICY (line 164) | PullPolicy_UNSPECIFIED_POLICY PullPolicy = 0
constant PullPolicy_IfNotPresent (line 168) | PullPolicy_IfNotPresent PullPolicy = 1
constant PullPolicy_Always (line 171) | PullPolicy_Always PullPolicy = 2
type EnvValueSource (line 215) | type EnvValueSource
method Enum (line 236) | func (x EnvValueSource) Enum() *EnvValueSource {
method String (line 242) | func (x EnvValueSource) String() string {
method Descriptor (line 246) | func (EnvValueSource) Descriptor() protoreflect.EnumDescriptor {
method Type (line 250) | func (EnvValueSource) Type() protoreflect.EnumType {
method Number (line 254) | func (x EnvValueSource) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 259) | func (EnvValueSource) EnumDescriptor() ([]byte, []int) {
constant EnvValueSource_INLINE (line 219) | EnvValueSource_INLINE EnvValueSource = 0
constant EnvValueSource_HOST (line 221) | EnvValueSource_HOST EnvValueSource = 1
type FailStrategy (line 263) | type FailStrategy
method Enum (line 288) | func (x FailStrategy) Enum() *FailStrategy {
method String (line 294) | func (x FailStrategy) String() string {
method Descriptor (line 298) | func (FailStrategy) Descriptor() protoreflect.EnumDescriptor {
method Type (line 302) | func (FailStrategy) Type() protoreflect.EnumType {
method Number (line 306) | func (x FailStrategy) Number() protoreflect.EnumNumber {
method EnumDescriptor (line 311) | func (FailStrategy) EnumDescriptor() ([]byte, []int) {
constant FailStrategy_FAIL_CLOSE (line 268) | FailStrategy_FAIL_CLOSE FailStrategy = 0
constant FailStrategy_FAIL_OPEN (line 273) | FailStrategy_FAIL_OPEN FailStrategy = 1
type WasmPlugin (line 336) | type WasmPlugin struct
method Reset (line 397) | func (x *WasmPlugin) Reset() {
method String (line 406) | func (x *WasmPlugin) String() string {
method ProtoMessage (line 410) | func (*WasmPlugin) ProtoMessage() {}
method ProtoReflect (line 412) | func (x *WasmPlugin) ProtoReflect() protoreflect.Message {
method Descriptor (line 425) | func (*WasmPlugin) Descriptor() ([]byte, []int) {
method GetUrl (line 429) | func (x *WasmPlugin) GetUrl() string {
method GetSha256 (line 436) | func (x *WasmPlugin) GetSha256() string {
method GetImagePullPolicy (line 443) | func (x *WasmPlugin) GetImagePullPolicy() PullPolicy {
method GetImagePullSecret (line 450) | func (x *WasmPlugin) GetImagePullSecret() string {
method GetVerificationKey (line 457) | func (x *WasmPlugin) GetVerificationKey() string {
method GetPluginConfig (line 464) | func (x *WasmPlugin) GetPluginConfig() *_struct.Struct {
method GetPluginName (line 471) | func (x *WasmPlugin) GetPluginName() string {
method GetPhase (line 478) | func (x *WasmPlugin) GetPhase() PluginPhase {
method GetPriority (line 485) | func (x *WasmPlugin) GetPriority() *wrappers.Int32Value {
method GetFailStrategy (line 492) | func (x *WasmPlugin) GetFailStrategy() FailStrategy {
method GetVmConfig (line 499) | func (x *WasmPlugin) GetVmConfig() *VmConfig {
method GetDefaultConfig (line 506) | func (x *WasmPlugin) GetDefaultConfig() *_struct.Struct {
method GetMatchRules (line 513) | func (x *WasmPlugin) GetMatchRules() []*MatchRule {
method GetDefaultConfigDisable (line 520) | func (x *WasmPlugin) GetDefaultConfigDisable() *wrappers.BoolValue {
type MatchRule (line 528) | type MatchRule struct
method Reset (line 542) | func (x *MatchRule) Reset() {
method String (line 551) | func (x *MatchRule) String() string {
method ProtoMessage (line 555) | func (*MatchRule) ProtoMessage() {}
method ProtoReflect (line 557) | func (x *MatchRule) ProtoReflect() protoreflect.Message {
method Descriptor (line 570) | func (*MatchRule) Descriptor() ([]byte, []int) {
method GetIngress (line 574) | func (x *MatchRule) GetIngress() []string {
method GetDomain (line 581) | func (x *MatchRule) GetDomain() []string {
method GetConfig (line 588) | func (x *MatchRule) GetConfig() *_struct.Struct {
method GetConfigDisable (line 595) | func (x *MatchRule) GetConfigDisable() *wrappers.BoolValue {
method GetService (line 602) | func (x *MatchRule) GetService() []string {
method GetRouteType (line 609) | func (x *MatchRule) GetRouteType() RouteType {
type VmConfig (line 618) | type VmConfig struct
method Reset (line 628) | func (x *VmConfig) Reset() {
method String (line 637) | func (x *VmConfig) String() string {
method ProtoMessage (line 641) | func (*VmConfig) ProtoMessage() {}
method ProtoReflect (line 643) | func (x *VmConfig) ProtoReflect() protoreflect.Message {
method Descriptor (line 656) | func (*VmConfig) Descriptor() ([]byte, []int) {
method GetEnv (line 660) | func (x *VmConfig) GetEnv() []*EnvVar {
type EnvVar (line 667) | type EnvVar struct
method Reset (line 684) | func (x *EnvVar) Reset() {
method String (line 693) | func (x *EnvVar) String() string {
method ProtoMessage (line 697) | func (*EnvVar) ProtoMessage() {}
method ProtoReflect (line 699) | func (x *EnvVar) ProtoReflect() protoreflect.Message {
method Descriptor (line 712) | func (*EnvVar) Descriptor() ([]byte, []int) {
method GetName (line 716) | func (x *EnvVar) GetName() string {
method GetValueFrom (line 723) | func (x *EnvVar) GetValueFrom() EnvValueSource {
method GetValue (line 730) | func (x *EnvVar) GetValue() string {
function file_extensions_v1alpha1_wasmplugin_proto_rawDescGZIP (line 856) | func file_extensions_v1alpha1_wasmplugin_proto_rawDescGZIP() []byte {
function init (line 901) | func init() { file_extensions_v1alpha1_wasmplugin_proto_init() }
function file_extensions_v1alpha1_wasmplugin_proto_init (line 902) | func file_extensions_v1alpha1_wasmplugin_proto_init() {
FILE: api/extensions/v1alpha1/wasmplugin_deepcopy.gen.go
method DeepCopyInto (line 9) | func (in *WasmPlugin) DeepCopyInto(out *WasmPlugin) {
method DeepCopy (line 15) | func (in *WasmPlugin) DeepCopy() *WasmPlugin {
method DeepCopyInterface (line 25) | func (in *WasmPlugin) DeepCopyInterface() interface{} {
method DeepCopyInto (line 30) | func (in *MatchRule) DeepCopyInto(out *MatchRule) {
method DeepCopy (line 36) | func (in *MatchRule) DeepCopy() *MatchRule {
method DeepCopyInterface (line 46) | func (in *MatchRule) DeepCopyInterface() interface{} {
method DeepCopyInto (line 51) | func (in *VmConfig) DeepCopyInto(out *VmConfig) {
method DeepCopy (line 57) | func (in *VmConfig) DeepCopy() *VmConfig {
method DeepCopyInterface (line 67) | func (in *VmConfig) DeepCopyInterface() interface{} {
method DeepCopyInto (line 72) | func (in *EnvVar) DeepCopyInto(out *EnvVar) {
method DeepCopy (line 78) | func (in *EnvVar) DeepCopy() *EnvVar {
method DeepCopyInterface (line 88) | func (in *EnvVar) DeepCopyInterface() interface{} {
FILE: api/extensions/v1alpha1/wasmplugin_json.gen.go
method MarshalJSON (line 10) | func (this *WasmPlugin) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 16) | func (this *WasmPlugin) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 21) | func (this *MatchRule) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 27) | func (this *MatchRule) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 32) | func (this *VmConfig) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 38) | func (this *VmConfig) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 43) | func (this *EnvVar) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 49) | func (this *EnvVar) UnmarshalJSON(b []byte) error {
FILE: api/networking/v1/http_2_rpc.pb.go
constant _ (line 38) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 40) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type Http2Rpc (line 60) | type Http2Rpc struct
method Reset (line 72) | func (x *Http2Rpc) Reset() {
method String (line 81) | func (x *Http2Rpc) String() string {
method ProtoMessage (line 85) | func (*Http2Rpc) ProtoMessage() {}
method ProtoReflect (line 87) | func (x *Http2Rpc) ProtoReflect() protoreflect.Message {
method Descriptor (line 100) | func (*Http2Rpc) Descriptor() ([]byte, []int) {
method GetDestination (line 104) | func (m *Http2Rpc) GetDestination() isHttp2Rpc_Destination {
method GetDubbo (line 111) | func (x *Http2Rpc) GetDubbo() *DubboService {
method GetGrpc (line 118) | func (x *Http2Rpc) GetGrpc() *GrpcService {
type isHttp2Rpc_Destination (line 125) | type isHttp2Rpc_Destination interface
type Http2Rpc_Dubbo (line 129) | type Http2Rpc_Dubbo struct
method isHttp2Rpc_Destination (line 137) | func (*Http2Rpc_Dubbo) isHttp2Rpc_Destination() {}
type Http2Rpc_Grpc (line 133) | type Http2Rpc_Grpc struct
method isHttp2Rpc_Destination (line 139) | func (*Http2Rpc_Grpc) isHttp2Rpc_Destination() {}
type DubboService (line 141) | type DubboService struct
method Reset (line 152) | func (x *DubboService) Reset() {
method String (line 161) | func (x *DubboService) String() string {
method ProtoMessage (line 165) | func (*DubboService) ProtoMessage() {}
method ProtoReflect (line 167) | func (x *DubboService) ProtoReflect() protoreflect.Message {
method Descriptor (line 180) | func (*DubboService) Descriptor() ([]byte, []int) {
method GetService (line 184) | func (x *DubboService) GetService() string {
method GetVersion (line 191) | func (x *DubboService) GetVersion() string {
method GetGroup (line 198) | func (x *DubboService) GetGroup() string {
method GetMethods (line 205) | func (x *DubboService) GetMethods() []*Method {
type Method (line 212) | type Method struct
method Reset (line 225) | func (x *Method) Reset() {
method String (line 234) | func (x *Method) String() string {
method ProtoMessage (line 238) | func (*Method) ProtoMessage() {}
method ProtoReflect (line 240) | func (x *Method) ProtoReflect() protoreflect.Message {
method Descriptor (line 253) | func (*Method) Descriptor() ([]byte, []int) {
method GetServiceMethod (line 257) | func (x *Method) GetServiceMethod() string {
method GetHeadersAttach (line 264) | func (x *Method) GetHeadersAttach() string {
method GetHttpPath (line 271) | func (x *Method) GetHttpPath() string {
method GetHttpMethods (line 278) | func (x *Method) GetHttpMethods() []string {
method GetParams (line 285) | func (x *Method) GetParams() []*Param {
method GetParamFromEntireBody (line 292) | func (x *Method) GetParamFromEntireBody() *ParamFromEntireBody {
type Param (line 299) | type Param struct
method Reset (line 309) | func (x *Param) Reset() {
method String (line 318) | func (x *Param) String() string {
method ProtoMessage (line 322) | func (*Param) ProtoMessage() {}
method ProtoReflect (line 324) | func (x *Param) ProtoReflect() protoreflect.Message {
method Descriptor (line 337) | func (*Param) Descriptor() ([]byte, []int) {
method GetParamSource (line 341) | func (x *Param) GetParamSource() string {
method GetParamKey (line 348) | func (x *Param) GetParamKey() string {
method GetParamType (line 355) | func (x *Param) GetParamType() string {
type ParamFromEntireBody (line 362) | type ParamFromEntireBody struct
method Reset (line 370) | func (x *ParamFromEntireBody) Reset() {
method String (line 379) | func (x *ParamFromEntireBody) String() string {
method ProtoMessage (line 383) | func (*ParamFromEntireBody) ProtoMessage() {}
method ProtoReflect (line 385) | func (x *ParamFromEntireBody) ProtoReflect() protoreflect.Message {
method Descriptor (line 398) | func (*ParamFromEntireBody) Descriptor() ([]byte, []int) {
method GetParamType (line 402) | func (x *ParamFromEntireBody) GetParamType() string {
type GrpcService (line 409) | type GrpcService struct
method Reset (line 415) | func (x *GrpcService) Reset() {
method String (line 424) | func (x *GrpcService) String() string {
method ProtoMessage (line 428) | func (*GrpcService) ProtoMessage() {}
method ProtoReflect (line 430) | func (x *GrpcService) ProtoReflect() protoreflect.Message {
method Descriptor (line 443) | func (*GrpcService) Descriptor() ([]byte, []int) {
function file_networking_v1_http_2_rpc_proto_rawDescGZIP (line 519) | func file_networking_v1_http_2_rpc_proto_rawDescGZIP() []byte {
function init (line 548) | func init() { file_networking_v1_http_2_rpc_proto_init() }
function file_networking_v1_http_2_rpc_proto_init (line 549) | func file_networking_v1_http_2_rpc_proto_init() {
FILE: api/networking/v1/http_2_rpc_deepcopy.gen.go
method DeepCopyInto (line 9) | func (in *Http2Rpc) DeepCopyInto(out *Http2Rpc) {
method DeepCopy (line 15) | func (in *Http2Rpc) DeepCopy() *Http2Rpc {
method DeepCopyInterface (line 25) | func (in *Http2Rpc) DeepCopyInterface() interface{} {
method DeepCopyInto (line 30) | func (in *DubboService) DeepCopyInto(out *DubboService) {
method DeepCopy (line 36) | func (in *DubboService) DeepCopy() *DubboService {
method DeepCopyInterface (line 46) | func (in *DubboService) DeepCopyInterface() interface{} {
method DeepCopyInto (line 51) | func (in *Method) DeepCopyInto(out *Method) {
method DeepCopy (line 57) | func (in *Method) DeepCopy() *Method {
method DeepCopyInterface (line 67) | func (in *Method) DeepCopyInterface() interface{} {
method DeepCopyInto (line 72) | func (in *Param) DeepCopyInto(out *Param) {
method DeepCopy (line 78) | func (in *Param) DeepCopy() *Param {
method DeepCopyInterface (line 88) | func (in *Param) DeepCopyInterface() interface{} {
method DeepCopyInto (line 93) | func (in *ParamFromEntireBody) DeepCopyInto(out *ParamFromEntireBody) {
method DeepCopy (line 99) | func (in *ParamFromEntireBody) DeepCopy() *ParamFromEntireBody {
method DeepCopyInterface (line 109) | func (in *ParamFromEntireBody) DeepCopyInterface() interface{} {
method DeepCopyInto (line 114) | func (in *GrpcService) DeepCopyInto(out *GrpcService) {
method DeepCopy (line 120) | func (in *GrpcService) DeepCopy() *GrpcService {
method DeepCopyInterface (line 130) | func (in *GrpcService) DeepCopyInterface() interface{} {
FILE: api/networking/v1/http_2_rpc_json.gen.go
method MarshalJSON (line 10) | func (this *Http2Rpc) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 16) | func (this *Http2Rpc) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 21) | func (this *DubboService) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 27) | func (this *DubboService) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 32) | func (this *Method) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 38) | func (this *Method) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 43) | func (this *Param) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 49) | func (this *Param) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 54) | func (this *ParamFromEntireBody) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 60) | func (this *ParamFromEntireBody) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 65) | func (this *GrpcService) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 71) | func (this *GrpcService) UnmarshalJSON(b []byte) error {
FILE: api/networking/v1/mcp_bridge.pb.go
constant _ (line 40) | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
constant _ (line 42) | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
type McpBridge (line 62) | type McpBridge struct
method Reset (line 71) | func (x *McpBridge) Reset() {
method String (line 80) | func (x *McpBridge) String() string {
method ProtoMessage (line 84) | func (*McpBridge) ProtoMessage() {}
method ProtoReflect (line 86) | func (x *McpBridge) ProtoReflect() protoreflect.Message {
method Descriptor (line 99) | func (*McpBridge) Descriptor() ([]byte, []int) {
method GetRegistries (line 103) | func (x *McpBridge) GetRegistries() []*RegistryConfig {
method GetProxies (line 110) | func (x *McpBridge) GetProxies() []*ProxyConfig {
type RegistryConfig (line 117) | type RegistryConfig struct
method Reset (line 151) | func (x *RegistryConfig) Reset() {
method String (line 160) | func (x *RegistryConfig) String() string {
method ProtoMessage (line 164) | func (*RegistryConfig) ProtoMessage() {}
method ProtoReflect (line 166) | func (x *RegistryConfig) ProtoReflect() protoreflect.Message {
method Descriptor (line 179) | func (*RegistryConfig) Descriptor() ([]byte, []int) {
method GetType (line 183) | func (x *RegistryConfig) GetType() string {
method GetName (line 190) | func (x *RegistryConfig) GetName() string {
method GetDomain (line 197) | func (x *RegistryConfig) GetDomain() string {
method GetPort (line 204) | func (x *RegistryConfig) GetPort() uint32 {
method GetNacosAddressServer (line 211) | func (x *RegistryConfig) GetNacosAddressServer() string {
method GetNacosAccessKey (line 218) | func (x *RegistryConfig) GetNacosAccessKey() string {
method GetNacosSecretKey (line 225) | func (x *RegistryConfig) GetNacosSecretKey() string {
method GetNacosNamespaceId (line 232) | func (x *RegistryConfig) GetNacosNamespaceId() string {
method GetNacosNamespace (line 239) | func (x *RegistryConfig) GetNacosNamespace() string {
method GetNacosGroups (line 246) | func (x *RegistryConfig) GetNacosGroups() []string {
method GetNacosRefreshInterval (line 253) | func (x *RegistryConfig) GetNacosRefreshInterval() int64 {
method GetConsulNamespace (line 260) | func (x *RegistryConfig) GetConsulNamespace() string {
method GetZkServicesPath (line 267) | func (x *RegistryConfig) GetZkServicesPath() []string {
method GetConsulDatacenter (line 274) | func (x *RegistryConfig) GetConsulDatacenter() string {
method GetConsulServiceTag (line 281) | func (x *RegistryConfig) GetConsulServiceTag() string {
method GetConsulRefreshInterval (line 288) | func (x *RegistryConfig) GetConsulRefreshInterval() int64 {
method GetAuthSecretName (line 295) | func (x *RegistryConfig) GetAuthSecretName() string {
method GetProtocol (line 302) | func (x *RegistryConfig) GetProtocol() string {
method GetSni (line 309) | func (x *RegistryConfig) GetSni() string {
method GetMcpServerExportDomains (line 316) | func (x *RegistryConfig) GetMcpServerExportDomains() []string {
method GetMcpServerBaseUrl (line 323) | func (x *RegistryConfig) GetMcpServerBaseUrl() string {
method GetEnableMCPServer (line 330) | func (x *RegistryConfig) GetEnableMCPServer() *wrappers.BoolValue {
method GetEnableScopeMcpServers (line 337) | func (x *RegistryConfig) GetEnableScopeMcpServers() *wrappers.BoolValue {
method GetAllowMcpServers (line 344) | func (x *RegistryConfig) GetAllowMcpServers() []string {
method GetMetadata (line 351) | func (x *RegistryConfig) GetMetadata() map[string]*InnerMap {
method GetProxyName (line 358) | func (x *RegistryConfig) GetProxyName() string {
method GetVport (line 365) | func (x *RegistryConfig) GetVport() *RegistryConfig_VPort {
type ProxyConfig (line 372) | type ProxyConfig struct
method Reset (line 385) | func (x *ProxyConfig) Reset() {
method String (line 394) | func (x *ProxyConfig) String() string {
method ProtoMessage (line 398) | func (*ProxyConfig) ProtoMessage() {}
method ProtoReflect (line 400) | func (x *ProxyConfig) ProtoReflect() protoreflect.Message {
method Descriptor (line 413) | func (*ProxyConfig) Descriptor() ([]byte, []int) {
method GetType (line 417) | func (x *ProxyConfig) GetType() string {
method GetName (line 424) | func (x *ProxyConfig) GetName() string {
method GetServerAddress (line 431) | func (x *ProxyConfig) GetServerAddress() string {
method GetServerPort (line 438) | func (x *ProxyConfig) GetServerPort() uint32 {
method GetListenerPort (line 445) | func (x *ProxyConfig) GetListenerPort() uint32 {
method GetConnectTimeout (line 452) | func (x *ProxyConfig) GetConnectTimeout() uint32 {
type InnerMap (line 459) | type InnerMap struct
method Reset (line 467) | func (x *InnerMap) Reset() {
method String (line 476) | func (x *InnerMap) String() string {
method ProtoMessage (line 480) | func (*InnerMap) ProtoMessage() {}
method ProtoReflect (line 482) | func (x *InnerMap) ProtoReflect() protoreflect.Message {
method Descriptor (line 495) | func (*InnerMap) Descriptor() ([]byte, []int) {
method GetInnerMap (line 499) | func (x *InnerMap) GetInnerMap() map[string]string {
type RegistryConfig_VPort (line 506) | type RegistryConfig_VPort struct
method Reset (line 515) | func (x *RegistryConfig_VPort) Reset() {
method String (line 524) | func (x *RegistryConfig_VPort) String() string {
method ProtoMessage (line 528) | func (*RegistryConfig_VPort) ProtoMessage() {}
method ProtoReflect (line 530) | func (x *RegistryConfig_VPort) ProtoReflect() protoreflect.Message {
method Descriptor (line 543) | func (*RegistryConfig_VPort) Descriptor() ([]byte, []int) {
method GetDefault (line 547) | func (x *RegistryConfig_VPort) GetDefault() uint32 {
method GetServices (line 554) | func (x *RegistryConfig_VPort) GetServices() []*RegistryConfig_VPort_S...
type RegistryConfig_VPort_Services (line 561) | type RegistryConfig_VPort_Services struct
method Reset (line 570) | func (x *RegistryConfig_VPort_Services) Reset() {
method String (line 579) | func (x *RegistryConfig_VPort_Services) String() string {
method ProtoMessage (line 583) | func (*RegistryConfig_VPort_Services) ProtoMessage() {}
method ProtoReflect (line 585) | func (x *RegistryConfig_VPort_Services) ProtoReflect() protoreflect.Me...
method Descriptor (line 598) | func (*RegistryConfig_VPort_Services) Descriptor() ([]byte, []int) {
method GetName (line 602) | func (x *RegistryConfig_VPort_Services) GetName() string {
method GetValue (line 609) | func (x *RegistryConfig_VPort_Services) GetValue() uint32 {
function file_networking_v1_mcp_bridge_proto_rawDescGZIP (line 763) | func file_networking_v1_mcp_bridge_proto_rawDescGZIP() []byte {
function init (line 799) | func init() { file_networking_v1_mcp_bridge_proto_init() }
function file_networking_v1_mcp_bridge_proto_init (line 800) | func file_networking_v1_mcp_bridge_proto_init() {
FILE: api/networking/v1/mcp_bridge_deepcopy.gen.go
method DeepCopyInto (line 9) | func (in *McpBridge) DeepCopyInto(out *McpBridge) {
method DeepCopy (line 15) | func (in *McpBridge) DeepCopy() *McpBridge {
method DeepCopyInterface (line 25) | func (in *McpBridge) DeepCopyInterface() interface{} {
method DeepCopyInto (line 30) | func (in *RegistryConfig) DeepCopyInto(out *RegistryConfig) {
method DeepCopy (line 36) | func (in *RegistryConfig) DeepCopy() *RegistryConfig {
method DeepCopyInterface (line 46) | func (in *RegistryConfig) DeepCopyInterface() interface{} {
method DeepCopyInto (line 51) | func (in *RegistryConfig_VPort) DeepCopyInto(out *RegistryConfig_VPort) {
method DeepCopy (line 57) | func (in *RegistryConfig_VPort) DeepCopy() *RegistryConfig_VPort {
method DeepCopyInterface (line 67) | func (in *RegistryConfig_VPort) DeepCopyInterface() interface{} {
method DeepCopyInto (line 72) | func (in *RegistryConfig_VPort_Services) DeepCopyInto(out *RegistryConfi...
method DeepCopy (line 78) | func (in *RegistryConfig_VPort_Services) DeepCopy() *RegistryConfig_VPor...
method DeepCopyInterface (line 88) | func (in *RegistryConfig_VPort_Services) DeepCopyInterface() interface{} {
method DeepCopyInto (line 93) | func (in *ProxyConfig) DeepCopyInto(out *ProxyConfig) {
method DeepCopy (line 99) | func (in *ProxyConfig) DeepCopy() *ProxyConfig {
method DeepCopyInterface (line 109) | func (in *ProxyConfig) DeepCopyInterface() interface{} {
method DeepCopyInto (line 114) | func (in *InnerMap) DeepCopyInto(out *InnerMap) {
method DeepCopy (line 120) | func (in *InnerMap) DeepCopy() *InnerMap {
method DeepCopyInterface (line 130) | func (in *InnerMap) DeepCopyInterface() interface{} {
FILE: api/networking/v1/mcp_bridge_json.gen.go
method MarshalJSON (line 10) | func (this *McpBridge) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 16) | func (this *McpBridge) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 21) | func (this *RegistryConfig) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 27) | func (this *RegistryConfig) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 32) | func (this *RegistryConfig_VPort) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 38) | func (this *RegistryConfig_VPort) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 43) | func (this *RegistryConfig_VPort_Services) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 49) | func (this *RegistryConfig_VPort_Services) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 54) | func (this *ProxyConfig) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 60) | func (this *ProxyConfig) UnmarshalJSON(b []byte) error {
method MarshalJSON (line 65) | func (this *InnerMap) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 71) | func (this *InnerMap) UnmarshalJSON(b []byte) error {
FILE: client/pkg/apis/extensions/v1alpha1/register.gen.go
constant GroupName (line 35) | GroupName = "extensions.higress.io"
function Resource (line 38) | func Resource(resource string) schema.GroupResource {
function addKnownTypes (line 42) | func addKnownTypes(scheme *runtime.Scheme) error {
FILE: client/pkg/apis/extensions/v1alpha1/types.gen.go
type WasmPlugin (line 49) | type WasmPlugin struct
type WasmPluginList (line 64) | type WasmPluginList struct
FILE: client/pkg/apis/extensions/v1alpha1/zz_generated.deepcopy.gen.go
method DeepCopyInto (line 27) | func (in *WasmPlugin) DeepCopyInto(out *WasmPlugin) {
method DeepCopy (line 37) | func (in *WasmPlugin) DeepCopy() *WasmPlugin {
method DeepCopyObject (line 47) | func (in *WasmPlugin) DeepCopyObject() runtime.Object {
method DeepCopyInto (line 55) | func (in *WasmPluginList) DeepCopyInto(out *WasmPluginList) {
method DeepCopy (line 74) | func (in *WasmPluginList) DeepCopy() *WasmPluginList {
method DeepCopyObject (line 84) | func (in *WasmPluginList) DeepCopyObject() runtime.Object {
FILE: client/pkg/apis/networking/v1/register.gen.go
constant GroupName (line 35) | GroupName = "networking.higress.io"
function Resource (line 38) | func Resource(resource string) schema.GroupResource {
function addKnownTypes (line 42) | func addKnownTypes(scheme *runtime.Scheme) error {
FILE: client/pkg/apis/networking/v1/types.gen.go
type Http2Rpc (line 45) | type Http2Rpc struct
type Http2RpcList (line 60) | type Http2RpcList struct
type McpBridge (line 87) | type McpBridge struct
type McpBridgeList (line 102) | type McpBridgeList struct
FILE: client/pkg/apis/networking/v1/zz_generated.deepcopy.gen.go
method DeepCopyInto (line 27) | func (in *Http2Rpc) DeepCopyInto(out *Http2Rpc) {
method DeepCopy (line 37) | func (in *Http2Rpc) DeepCopy() *Http2Rpc {
method DeepCopyObject (line 47) | func (in *Http2Rpc) DeepCopyObject() runtime.Object {
method DeepCopyInto (line 55) | func (in *Http2RpcList) DeepCopyInto(out *Http2RpcList) {
method DeepCopy (line 74) | func (in *Http2RpcList) DeepCopy() *Http2RpcList {
method DeepCopyObject (line 84) | func (in *Http2RpcList) DeepCopyObject() runtime.Object {
method DeepCopyInto (line 92) | func (in *McpBridge) DeepCopyInto(out *McpBridge) {
method DeepCopy (line 102) | func (in *McpBridge) DeepCopy() *McpBridge {
method DeepCopyObject (line 112) | func (in *McpBridge) DeepCopyObject() runtime.Object {
method DeepCopyInto (line 120) | func (in *McpBridgeList) DeepCopyInto(out *McpBridgeList) {
method DeepCopy (line 139) | func (in *McpBridgeList) DeepCopy() *McpBridgeList {
method DeepCopyObject (line 149) | func (in *McpBridgeList) DeepCopyObject() runtime.Object {
FILE: client/pkg/applyconfiguration/extensions/v1alpha1/wasmplugin.go
type WasmPluginApplyConfiguration (line 29) | type WasmPluginApplyConfiguration struct
method WithKind (line 50) | func (b *WasmPluginApplyConfiguration) WithKind(value string) *WasmPlu...
method WithAPIVersion (line 58) | func (b *WasmPluginApplyConfiguration) WithAPIVersion(value string) *W...
method WithName (line 66) | func (b *WasmPluginApplyConfiguration) WithName(value string) *WasmPlu...
method WithGenerateName (line 75) | func (b *WasmPluginApplyConfiguration) WithGenerateName(value string) ...
method WithNamespace (line 84) | func (b *WasmPluginApplyConfiguration) WithNamespace(value string) *Wa...
method WithUID (line 93) | func (b *WasmPluginApplyConfiguration) WithUID(value types.UID) *WasmP...
method WithResourceVersion (line 102) | func (b *WasmPluginApplyConfiguration) WithResourceVersion(value strin...
method WithGeneration (line 111) | func (b *WasmPluginApplyConfiguration) WithGeneration(value int64) *Wa...
method WithCreationTimestamp (line 120) | func (b *WasmPluginApplyConfiguration) WithCreationTimestamp(value met...
method WithDeletionTimestamp (line 129) | func (b *WasmPluginApplyConfiguration) WithDeletionTimestamp(value met...
method WithDeletionGracePeriodSeconds (line 138) | func (b *WasmPluginApplyConfiguration) WithDeletionGracePeriodSeconds(...
method WithLabels (line 148) | func (b *WasmPluginApplyConfiguration) WithLabels(entries map[string]s...
method WithAnnotations (line 163) | func (b *WasmPluginApplyConfiguration) WithAnnotations(entries map[str...
method WithOwnerReferences (line 177) | func (b *WasmPluginApplyConfiguration) WithOwnerReferences(values ...*...
method WithFinalizers (line 191) | func (b *WasmPluginApplyConfiguration) WithFinalizers(values ...string...
method ensureObjectMetaApplyConfigurationExists (line 199) | func (b *WasmPluginApplyConfiguration) ensureObjectMetaApplyConfigurat...
method WithSpec (line 208) | func (b *WasmPluginApplyConfiguration) WithSpec(value v1alpha1.WasmPlu...
method WithStatus (line 216) | func (b *WasmPluginApplyConfiguration) WithStatus(value metav1alpha1.I...
function WasmPlugin (line 38) | func WasmPlugin(name, namespace string) *WasmPluginApplyConfiguration {
FILE: client/pkg/applyconfiguration/internal/internal.go
function Parser (line 26) | func Parser() *typed.Parser {
FILE: client/pkg/applyconfiguration/meta/v1/managedfieldsentry.go
type ManagedFieldsEntryApplyConfiguration (line 25) | type ManagedFieldsEntryApplyConfiguration struct
method WithManager (line 44) | func (b *ManagedFieldsEntryApplyConfiguration) WithManager(value strin...
method WithOperation (line 52) | func (b *ManagedFieldsEntryApplyConfiguration) WithOperation(value v1....
method WithAPIVersion (line 60) | func (b *ManagedFieldsEntryApplyConfiguration) WithAPIVersion(value st...
method WithTime (line 68) | func (b *ManagedFieldsEntryApplyConfiguration) WithTime(value v1.Time)...
method WithFieldsType (line 76) | func (b *ManagedFieldsEntryApplyConfiguration) WithFieldsType(value st...
method WithFieldsV1 (line 84) | func (b *ManagedFieldsEntryApplyConfiguration) WithFieldsV1(value v1.F...
method WithSubresource (line 92) | func (b *ManagedFieldsEntryApplyConfiguration) WithSubresource(value s...
function ManagedFieldsEntry (line 37) | func ManagedFieldsEntry() *ManagedFieldsEntryApplyConfiguration {
FILE: client/pkg/applyconfiguration/meta/v1/objectmeta.go
type ObjectMetaApplyConfiguration (line 26) | type ObjectMetaApplyConfiguration struct
method WithName (line 51) | func (b *ObjectMetaApplyConfiguration) WithName(value string) *ObjectM...
method WithGenerateName (line 59) | func (b *ObjectMetaApplyConfiguration) WithGenerateName(value string) ...
method WithNamespace (line 67) | func (b *ObjectMetaApplyConfiguration) WithNamespace(value string) *Ob...
method WithUID (line 75) | func (b *ObjectMetaApplyConfiguration) WithUID(value types.UID) *Objec...
method WithResourceVersion (line 83) | func (b *ObjectMetaApplyConfiguration) WithResourceVersion(value strin...
method WithGeneration (line 91) | func (b *ObjectMetaApplyConfiguration) WithGeneration(value int64) *Ob...
method WithCreationTimestamp (line 99) | func (b *ObjectMetaApplyConfiguration) WithCreationTimestamp(value v1....
method WithDeletionTimestamp (line 107) | func (b *ObjectMetaApplyConfiguration) WithDeletionTimestamp(value v1....
method WithDeletionGracePeriodSeconds (line 115) | func (b *ObjectMetaApplyConfiguration) WithDeletionGracePeriodSeconds(...
method WithLabels (line 124) | func (b *ObjectMetaApplyConfiguration) WithLabels(entries map[string]s...
method WithAnnotations (line 138) | func (b *ObjectMetaApplyConfiguration) WithAnnotations(entries map[str...
method WithOwnerReferences (line 151) | func (b *ObjectMetaApplyConfiguration) WithOwnerReferences(values ...*...
method WithFinalizers (line 164) | func (b *ObjectMetaApplyConfiguration) WithFinalizers(values ...string...
function ObjectMeta (line 44) | func ObjectMeta() *ObjectMetaApplyConfiguration {
FILE: client/pkg/applyconfiguration/meta/v1/ownerreference.go
type OwnerReferenceApplyConfiguration (line 25) | type OwnerReferenceApplyConfiguration struct
method WithAPIVersion (line 43) | func (b *OwnerReferenceApplyConfiguration) WithAPIVersion(value string...
method WithKind (line 51) | func (b *OwnerReferenceApplyConfiguration) WithKind(value string) *Own...
method WithName (line 59) | func (b *OwnerReferenceApplyConfiguration) WithName(value string) *Own...
method WithUID (line 67) | func (b *OwnerReferenceApplyConfiguration) WithUID(value types.UID) *O...
method WithController (line 75) | func (b *OwnerReferenceApplyConfiguration) WithController(value bool) ...
method WithBlockOwnerDeletion (line 83) | func (b *OwnerReferenceApplyConfiguration) WithBlockOwnerDeletion(valu...
function OwnerReference (line 36) | func OwnerReference() *OwnerReferenceApplyConfiguration {
FILE: client/pkg/applyconfiguration/meta/v1/typemeta.go
type TypeMetaApplyConfiguration (line 21) | type TypeMetaApplyConfiguration struct
method WithKind (line 35) | func (b *TypeMetaApplyConfiguration) WithKind(value string) *TypeMetaA...
method WithAPIVersion (line 43) | func (b *TypeMetaApplyConfiguration) WithAPIVersion(value string) *Typ...
function TypeMeta (line 28) | func TypeMeta() *TypeMetaApplyConfiguration {
FILE: client/pkg/applyconfiguration/networking/v1/http2rpc.go
type Http2RpcApplyConfiguration (line 29) | type Http2RpcApplyConfiguration struct
method WithKind (line 50) | func (b *Http2RpcApplyConfiguration) WithKind(value string) *Http2RpcA...
method WithAPIVersion (line 58) | func (b *Http2RpcApplyConfiguration) WithAPIVersion(value string) *Htt...
method WithName (line 66) | func (b *Http2RpcApplyConfiguration) WithName(value string) *Http2RpcA...
method WithGenerateName (line 75) | func (b *Http2RpcApplyConfiguration) WithGenerateName(value string) *H...
method WithNamespace (line 84) | func (b *Http2RpcApplyConfiguration) WithNamespace(value string) *Http...
method WithUID (line 93) | func (b *Http2RpcApplyConfiguration) WithUID(value types.UID) *Http2Rp...
method WithResourceVersion (line 102) | func (b *Http2RpcApplyConfiguration) WithResourceVersion(value string)...
method WithGeneration (line 111) | func (b *Http2RpcApplyConfiguration) WithGeneration(value int64) *Http...
method WithCreationTimestamp (line 120) | func (b *Http2RpcApplyConfiguration) WithCreationTimestamp(value metav...
method WithDeletionTimestamp (line 129) | func (b *Http2RpcApplyConfiguration) WithDeletionTimestamp(value metav...
method WithDeletionGracePeriodSeconds (line 138) | func (b *Http2RpcApplyConfiguration) WithDeletionGracePeriodSeconds(va...
method WithLabels (line 148) | func (b *Http2RpcApplyConfiguration) WithLabels(entries map[string]str...
method WithAnnotations (line 163) | func (b *Http2RpcApplyConfiguration) WithAnnotations(entries map[strin...
method WithOwnerReferences (line 177) | func (b *Http2RpcApplyConfiguration) WithOwnerReferences(values ...*v1...
method WithFinalizers (line 191) | func (b *Http2RpcApplyConfiguration) WithFinalizers(values ...string) ...
method ensureObjectMetaApplyConfigurationExists (line 199) | func (b *Http2RpcApplyConfiguration) ensureObjectMetaApplyConfiguratio...
method WithSpec (line 208) | func (b *Http2RpcApplyConfiguration) WithSpec(value networkingv1.Http2...
method WithStatus (line 216) | func (b *Http2RpcApplyConfiguration) WithStatus(value v1alpha1.IstioSt...
function Http2Rpc (line 38) | func Http2Rpc(name, namespace string) *Http2RpcApplyConfiguration {
FILE: client/pkg/applyconfiguration/networking/v1/mcpbridge.go
type McpBridgeApplyConfiguration (line 29) | type McpBridgeApplyConfiguration struct
method WithKind (line 50) | func (b *McpBridgeApplyConfiguration) WithKind(value string) *McpBridg...
method WithAPIVersion (line 58) | func (b *McpBridgeApplyConfiguration) WithAPIVersion(value string) *Mc...
method WithName (line 66) | func (b *McpBridgeApplyConfiguration) WithName(value string) *McpBridg...
method WithGenerateName (line 75) | func (b *McpBridgeApplyConfiguration) WithGenerateName(value string) *...
method WithNamespace (line 84) | func (b *McpBridgeApplyConfiguration) WithNamespace(value string) *Mcp...
method WithUID (line 93) | func (b *McpBridgeApplyConfiguration) WithUID(value types.UID) *McpBri...
method WithResourceVersion (line 102) | func (b *McpBridgeApplyConfiguration) WithResourceVersion(value string...
method WithGeneration (line 111) | func (b *McpBridgeApplyConfiguration) WithGeneration(value int64) *Mcp...
method WithCreationTimestamp (line 120) | func (b *McpBridgeApplyConfiguration) WithCreationTimestamp(value meta...
method WithDeletionTimestamp (line 129) | func (b *McpBridgeApplyConfiguration) WithDeletionTimestamp(value meta...
method WithDeletionGracePeriodSeconds (line 138) | func (b *McpBridgeApplyConfiguration) WithDeletionGracePeriodSeconds(v...
method WithLabels (line 148) | func (b *McpBridgeApplyConfiguration) WithLabels(entries map[string]st...
method WithAnnotations (line 163) | func (b *McpBridgeApplyConfiguration) WithAnnotations(entries map[stri...
method WithOwnerReferences (line 177) | func (b *McpBridgeApplyConfiguration) WithOwnerReferences(values ...*v...
method WithFinalizers (line 191) | func (b *McpBridgeApplyConfiguration) WithFinalizers(values ...string)...
method ensureObjectMetaApplyConfigurationExists (line 199) | func (b *McpBridgeApplyConfiguration) ensureObjectMetaApplyConfigurati...
method WithSpec (line 208) | func (b *McpBridgeApplyConfiguration) WithSpec(value networkingv1.McpB...
method WithStatus (line 216) | func (b *McpBridgeApplyConfiguration) WithStatus(value v1alpha1.IstioS...
function McpBridge (line 38) | func McpBridge(name, namespace string) *McpBridgeApplyConfiguration {
FILE: client/pkg/applyconfiguration/utils.go
function ForKind (line 31) | func ForKind(kind schema.GroupVersionKind) interface{} {
FILE: client/pkg/clientset/versioned/clientset.gen.go
type Interface (line 30) | type Interface interface
type Clientset (line 37) | type Clientset struct
method ExtensionsV1alpha1 (line 44) | func (c *Clientset) ExtensionsV1alpha1() extensionsv1alpha1.Extensions...
method NetworkingV1 (line 49) | func (c *Clientset) NetworkingV1() networkingv1.NetworkingV1Interface {
method Discovery (line 54) | func (c *Clientset) Discovery() discovery.DiscoveryInterface {
function NewForConfig (line 66) | func NewForConfig(c *rest.Config) (*Clientset, error) {
function NewForConfigAndClient (line 86) | func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Cl...
function NewForConfigOrDie (line 115) | func NewForConfigOrDie(c *rest.Config) *Clientset {
function New (line 124) | func New(c rest.Interface) *Clientset {
FILE: client/pkg/clientset/versioned/fake/clientset_generated.gen.go
function NewSimpleClientset (line 36) | func NewSimpleClientset(objects ...runtime.Object) *Clientset {
type Clientset (line 63) | type Clientset struct
method Discovery (line 69) | func (c *Clientset) Discovery() discovery.DiscoveryInterface {
method Tracker (line 73) | func (c *Clientset) Tracker() testing.ObjectTracker {
method ExtensionsV1alpha1 (line 83) | func (c *Clientset) ExtensionsV1alpha1() extensionsv1alpha1.Extensions...
method NetworkingV1 (line 88) | func (c *Clientset) NetworkingV1() networkingv1.NetworkingV1Interface {
FILE: client/pkg/clientset/versioned/fake/register.gen.go
function init (line 55) | func init() {
FILE: client/pkg/clientset/versioned/scheme/register.gen.go
function init (line 55) | func init() {
FILE: client/pkg/clientset/versioned/typed/extensions/v1alpha1/extensions_client.gen.go
type ExtensionsV1alpha1Interface (line 27) | type ExtensionsV1alpha1Interface interface
type ExtensionsV1alpha1Client (line 33) | type ExtensionsV1alpha1Client struct
method WasmPlugins (line 37) | func (c *ExtensionsV1alpha1Client) WasmPlugins(namespace string) WasmP...
method RESTClient (line 100) | func (c *ExtensionsV1alpha1Client) RESTClient() rest.Interface {
function NewForConfig (line 44) | func NewForConfig(c *rest.Config) (*ExtensionsV1alpha1Client, error) {
function NewForConfigAndClient (line 58) | func NewForConfigAndClient(c *rest.Config, h *http.Client) (*ExtensionsV...
function NewForConfigOrDie (line 72) | func NewForConfigOrDie(c *rest.Config) *ExtensionsV1alpha1Client {
function New (line 81) | func New(c rest.Interface) *ExtensionsV1alpha1Client {
function setConfigDefaults (line 85) | func setConfigDefaults(config *rest.Config) error {
FILE: client/pkg/clientset/versioned/typed/extensions/v1alpha1/fake/fake_extensions_client.gen.go
type FakeExtensionsV1alpha1 (line 25) | type FakeExtensionsV1alpha1 struct
method WasmPlugins (line 29) | func (c *FakeExtensionsV1alpha1) WasmPlugins(namespace string) v1alpha...
method RESTClient (line 35) | func (c *FakeExtensionsV1alpha1) RESTClient() rest.Interface {
FILE: client/pkg/clientset/versioned/typed/extensions/v1alpha1/fake/fake_wasmplugin.gen.go
type FakeWasmPlugins (line 34) | type FakeWasmPlugins struct
method Get (line 44) | func (c *FakeWasmPlugins) Get(ctx context.Context, name string, option...
method List (line 55) | func (c *FakeWasmPlugins) List(ctx context.Context, opts v1.ListOption...
method Watch (line 77) | func (c *FakeWasmPlugins) Watch(ctx context.Context, opts v1.ListOptio...
method Create (line 83) | func (c *FakeWasmPlugins) Create(ctx context.Context, wasmPlugin *v1al...
method Update (line 94) | func (c *FakeWasmPlugins) Update(ctx context.Context, wasmPlugin *v1al...
method UpdateStatus (line 106) | func (c *FakeWasmPlugins) UpdateStatus(ctx context.Context, wasmPlugin...
method Delete (line 117) | func (c *FakeWasmPlugins) Delete(ctx context.Context, name string, opt...
method DeleteCollection (line 125) | func (c *FakeWasmPlugins) DeleteCollection(ctx context.Context, opts v...
method Patch (line 133) | func (c *FakeWasmPlugins) Patch(ctx context.Context, name string, pt t...
method Apply (line 144) | func (c *FakeWasmPlugins) Apply(ctx context.Context, wasmPlugin *exten...
method ApplyStatus (line 167) | func (c *FakeWasmPlugins) ApplyStatus(ctx context.Context, wasmPlugin ...
FILE: client/pkg/clientset/versioned/typed/extensions/v1alpha1/generated_expansion.gen.go
type WasmPluginExpansion (line 19) | type WasmPluginExpansion interface
FILE: client/pkg/clientset/versioned/typed/extensions/v1alpha1/wasmplugin.gen.go
type WasmPluginsGetter (line 36) | type WasmPluginsGetter interface
type WasmPluginInterface (line 41) | type WasmPluginInterface interface
type wasmPlugins (line 57) | type wasmPlugins struct
method Get (line 71) | func (c *wasmPlugins) Get(ctx context.Context, name string, options v1...
method List (line 84) | func (c *wasmPlugins) List(ctx context.Context, opts v1.ListOptions) (...
method Watch (line 101) | func (c *wasmPlugins) Watch(ctx context.Context, opts v1.ListOptions) ...
method Create (line 116) | func (c *wasmPlugins) Create(ctx context.Context, wasmPlugin *v1alpha1...
method Update (line 129) | func (c *wasmPlugins) Update(ctx context.Context, wasmPlugin *v1alpha1...
method UpdateStatus (line 144) | func (c *wasmPlugins) UpdateStatus(ctx context.Context, wasmPlugin *v1...
method Delete (line 159) | func (c *wasmPlugins) Delete(ctx context.Context, name string, opts v1...
method DeleteCollection (line 170) | func (c *wasmPlugins) DeleteCollection(ctx context.Context, opts v1.De...
method Patch (line 186) | func (c *wasmPlugins) Patch(ctx context.Context, name string, pt types...
method Apply (line 201) | func (c *wasmPlugins) Apply(ctx context.Context, wasmPlugin *extension...
method ApplyStatus (line 228) | func (c *wasmPlugins) ApplyStatus(ctx context.Context, wasmPlugin *ext...
function newWasmPlugins (line 63) | func newWasmPlugins(c *ExtensionsV1alpha1Client, namespace string) *wasm...
FILE: client/pkg/clientset/versioned/typed/networking/v1/fake/fake_http2rpc.gen.go
type FakeHttp2Rpcs (line 34) | type FakeHttp2Rpcs struct
method Get (line 44) | func (c *FakeHttp2Rpcs) Get(ctx context.Context, name string, options ...
method List (line 55) | func (c *FakeHttp2Rpcs) List(ctx context.Context, opts metav1.ListOpti...
method Watch (line 77) | func (c *FakeHttp2Rpcs) Watch(ctx context.Context, opts metav1.ListOpt...
method Create (line 83) | func (c *FakeHttp2Rpcs) Create(ctx context.Context, http2Rpc *v1.Http2...
method Update (line 94) | func (c *FakeHttp2Rpcs) Update(ctx context.Context, http2Rpc *v1.Http2...
method UpdateStatus (line 106) | func (c *FakeHttp2Rpcs) UpdateStatus(ctx context.Context, http2Rpc *v1...
method Delete (line 117) | func (c *FakeHttp2Rpcs) Delete(ctx context.Context, name string, opts ...
method DeleteCollection (line 125) | func (c *FakeHttp2Rpcs) DeleteCollection(ctx context.Context, opts met...
method Patch (line 133) | func (c *FakeHttp2Rpcs) Patch(ctx context.Context, name string, pt typ...
method Apply (line 144) | func (c *FakeHttp2Rpcs) Apply(ctx context.Context, http2Rpc *networkin...
method ApplyStatus (line 167) | func (c *FakeHttp2Rpcs) ApplyStatus(ctx context.Context, http2Rpc *net...
FILE: client/pkg/clientset/versioned/typed/networking/v1/fake/fake_mcpbridge.gen.go
type FakeMcpBridges (line 34) | type FakeMcpBridges struct
method Get (line 44) | func (c *FakeMcpBridges) Get(ctx context.Context, name string, options...
method List (line 55) | func (c *FakeMcpBridges) List(ctx context.Context, opts metav1.ListOpt...
method Watch (line 77) | func (c *FakeMcpBridges) Watch(ctx context.Context, opts metav1.ListOp...
method Create (line 83) | func (c *FakeMcpBridges) Create(ctx context.Context, mcpBridge *v1.Mcp...
method Update (line 94) | func (c *FakeMcpBridges) Update(ctx context.Context, mcpBridge *v1.Mcp...
method UpdateStatus (line 106) | func (c *FakeMcpBridges) UpdateStatus(ctx context.Context, mcpBridge *...
method Delete (line 117) | func (c *FakeMcpBridges) Delete(ctx context.Context, name string, opts...
method DeleteCollection (line 125) | func (c *FakeMcpBridges) DeleteCollection(ctx context.Context, opts me...
method Patch (line 133) | func (c *FakeMcpBridges) Patch(ctx context.Context, name string, pt ty...
method Apply (line 144) | func (c *FakeMcpBridges) Apply(ctx context.Context, mcpBridge *network...
method ApplyStatus (line 167) | func (c *FakeMcpBridges) ApplyStatus(ctx context.Context, mcpBridge *n...
FILE: client/pkg/clientset/versioned/typed/networking/v1/fake/fake_networking_client.gen.go
type FakeNetworkingV1 (line 25) | type FakeNetworkingV1 struct
method Http2Rpcs (line 29) | func (c *FakeNetworkingV1) Http2Rpcs(namespace string) v1.Http2RpcInte...
method McpBridges (line 33) | func (c *FakeNetworkingV1) McpBridges(namespace string) v1.McpBridgeIn...
method RESTClient (line 39) | func (c *FakeNetworkingV1) RESTClient() rest.Interface {
FILE: client/pkg/clientset/versioned/typed/networking/v1/generated_expansion.gen.go
type Http2RpcExpansion (line 19) | type Http2RpcExpansion interface
type McpBridgeExpansion (line 21) | type McpBridgeExpansion interface
FILE: client/pkg/clientset/versioned/typed/networking/v1/http2rpc.gen.go
type Http2RpcsGetter (line 36) | type Http2RpcsGetter interface
type Http2RpcInterface (line 41) | type Http2RpcInterface interface
type http2Rpcs (line 57) | type http2Rpcs struct
method Get (line 71) | func (c *http2Rpcs) Get(ctx context.Context, name string, options meta...
method List (line 84) | func (c *http2Rpcs) List(ctx context.Context, opts metav1.ListOptions)...
method Watch (line 101) | func (c *http2Rpcs) Watch(ctx context.Context, opts metav1.ListOptions...
method Create (line 116) | func (c *http2Rpcs) Create(ctx context.Context, http2Rpc *v1.Http2Rpc,...
method Update (line 129) | func (c *http2Rpcs) Update(ctx context.Context, http2Rpc *v1.Http2Rpc,...
method UpdateStatus (line 144) | func (c *http2Rpcs) UpdateStatus(ctx context.Context, http2Rpc *v1.Htt...
method Delete (line 159) | func (c *http2Rpcs) Delete(ctx context.Context, name string, opts meta...
method DeleteCollection (line 170) | func (c *http2Rpcs) DeleteCollection(ctx context.Context, opts metav1....
method Patch (line 186) | func (c *http2Rpcs) Patch(ctx context.Context, name string, pt types.P...
method Apply (line 201) | func (c *http2Rpcs) Apply(ctx context.Context, http2Rpc *networkingv1....
method ApplyStatus (line 228) | func (c *http2Rpcs) ApplyStatus(ctx context.Context, http2Rpc *network...
function newHttp2Rpcs (line 63) | func newHttp2Rpcs(c *NetworkingV1Client, namespace string) *http2Rpcs {
FILE: client/pkg/clientset/versioned/typed/networking/v1/mcpbridge.gen.go
type McpBridgesGetter (line 36) | type McpBridgesGetter interface
type McpBridgeInterface (line 41) | type McpBridgeInterface interface
type mcpBridges (line 57) | type mcpBridges struct
method Get (line 71) | func (c *mcpBridges) Get(ctx context.Context, name string, options met...
method List (line 84) | func (c *mcpBridges) List(ctx context.Context, opts metav1.ListOptions...
method Watch (line 101) | func (c *mcpBridges) Watch(ctx context.Context, opts metav1.ListOption...
method Create (line 116) | func (c *mcpBridges) Create(ctx context.Context, mcpBridge *v1.McpBrid...
method Update (line 129) | func (c *mcpBridges) Update(ctx context.Context, mcpBridge *v1.McpBrid...
method UpdateStatus (line 144) | func (c *mcpBridges) UpdateStatus(ctx context.Context, mcpBridge *v1.M...
method Delete (line 159) | func (c *mcpBridges) Delete(ctx context.Context, name string, opts met...
method DeleteCollection (line 170) | func (c *mcpBridges) DeleteCollection(ctx context.Context, opts metav1...
method Patch (line 186) | func (c *mcpBridges) Patch(ctx context.Context, name string, pt types....
method Apply (line 201) | func (c *mcpBridges) Apply(ctx context.Context, mcpBridge *networkingv...
method ApplyStatus (line 228) | func (c *mcpBridges) ApplyStatus(ctx context.Context, mcpBridge *netwo...
function newMcpBridges (line 63) | func newMcpBridges(c *NetworkingV1Client, namespace string) *mcpBridges {
FILE: client/pkg/clientset/versioned/typed/networking/v1/networking_client.gen.go
type NetworkingV1Interface (line 27) | type NetworkingV1Interface interface
type NetworkingV1Client (line 34) | type NetworkingV1Client struct
method Http2Rpcs (line 38) | func (c *NetworkingV1Client) Http2Rpcs(namespace string) Http2RpcInter...
method McpBridges (line 42) | func (c *NetworkingV1Client) McpBridges(namespace string) McpBridgeInt...
method RESTClient (line 105) | func (c *NetworkingV1Client) RESTClient() rest.Interface {
function NewForConfig (line 49) | func NewForConfig(c *rest.Config) (*NetworkingV1Client, error) {
function NewForConfigAndClient (line 63) | func NewForConfigAndClient(c *rest.Config, h *http.Client) (*NetworkingV...
function NewForConfigOrDie (line 77) | func NewForConfigOrDie(c *rest.Config) *NetworkingV1Client {
function New (line 86) | func New(c rest.Interface) *NetworkingV1Client {
function setConfigDefaults (line 90) | func setConfigDefaults(config *rest.Config) error {
FILE: client/pkg/informers/externalversions/extensions/interface.gen.go
type Interface (line 25) | type Interface interface
type group (line 30) | type group struct
method V1alpha1 (line 42) | func (g *group) V1alpha1() v1alpha1.Interface {
function New (line 37) | func New(f internalinterfaces.SharedInformerFactory, namespace string, t...
FILE: client/pkg/informers/externalversions/extensions/v1alpha1/interface.gen.go
type Interface (line 24) | type Interface interface
type version (line 29) | type version struct
method WasmPlugins (line 41) | func (v *version) WasmPlugins() WasmPluginInformer {
function New (line 36) | func New(f internalinterfaces.SharedInformerFactory, namespace string, t...
FILE: client/pkg/informers/externalversions/extensions/v1alpha1/wasmplugin.gen.go
type WasmPluginInformer (line 35) | type WasmPluginInformer interface
type wasmPluginInformer (line 40) | type wasmPluginInformer struct
method defaultInformer (line 78) | func (f *wasmPluginInformer) defaultInformer(client versioned.Interfac...
method Informer (line 82) | func (f *wasmPluginInformer) Informer() cache.SharedIndexInformer {
method Lister (line 86) | func (f *wasmPluginInformer) Lister() v1alpha1.WasmPluginLister {
function NewWasmPluginInformer (line 49) | func NewWasmPluginInformer(client versioned.Interface, namespace string,...
function NewFilteredWasmPluginInformer (line 56) | func NewFilteredWasmPluginInformer(client versioned.Interface, namespace...
FILE: client/pkg/informers/externalversions/factory.gen.go
type SharedInformerOption (line 35) | type SharedInformerOption
type sharedInformerFactory (line 37) | type sharedInformerFactory struct
method Start (line 114) | func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
method Shutdown (line 138) | func (f *sharedInformerFactory) Shutdown() {
method WaitForCacheSync (line 147) | func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{...
method InformerFor (line 170) | func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFun...
method Extensions (line 249) | func (f *sharedInformerFactory) Extensions() extensions.Interface {
method Networking (line 253) | func (f *sharedInformerFactory) Networking() networking.Interface {
function WithCustomResyncConfig (line 57) | func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) Sh...
function WithTweakListOptions (line 67) | func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListO...
function WithNamespace (line 75) | func WithNamespace(namespace string) SharedInformerOption {
function NewSharedInformerFactory (line 83) | func NewSharedInformerFactory(client versioned.Interface, defaultResync ...
function NewFilteredSharedInformerFactory (line 91) | func NewFilteredSharedInformerFactory(client versioned.Interface, defaul...
function NewSharedInformerFactoryWithOptions (line 96) | func NewSharedInformerFactoryWithOptions(client versioned.Interface, def...
type SharedInformerFactory (line 215) | type SharedInformerFactory interface
FILE: client/pkg/informers/externalversions/generic.gen.go
type GenericInformer (line 30) | type GenericInformer interface
type genericInformer (line 35) | type genericInformer struct
method Informer (line 41) | func (f *genericInformer) Informer() cache.SharedIndexInformer {
method Lister (line 46) | func (f *genericInformer) Lister() cache.GenericLister {
method ForResource (line 52) | func (f *sharedInformerFactory) ForResource(resource schema.GroupVersion...
FILE: client/pkg/informers/externalversions/internalinterfaces/factory_interfaces.gen.go
type NewInformerFunc (line 29) | type NewInformerFunc
type SharedInformerFactory (line 32) | type SharedInformerFactory interface
type TweakListOptionsFunc (line 38) | type TweakListOptionsFunc
FILE: client/pkg/informers/externalversions/networking/interface.gen.go
type Interface (line 25) | type Interface interface
type group (line 30) | type group struct
method V1 (line 42) | func (g *group) V1() v1.Interface {
function New (line 37) | func New(f internalinterfaces.SharedInformerFactory, namespace string, t...
FILE: client/pkg/informers/externalversions/networking/v1/http2rpc.gen.go
type Http2RpcInformer (line 35) | type Http2RpcInformer interface
type http2RpcInformer (line 40) | type http2RpcInformer struct
method defaultInformer (line 78) | func (f *http2RpcInformer) defaultInformer(client versioned.Interface,...
method Informer (line 82) | func (f *http2RpcInformer) Informer() cache.SharedIndexInformer {
method Lister (line 86) | func (f *http2RpcInformer) Lister() v1.Http2RpcLister {
function NewHttp2RpcInformer (line 49) | func NewHttp2RpcInformer(client versioned.Interface, namespace string, r...
function NewFilteredHttp2RpcInformer (line 56) | func NewFilteredHttp2RpcInformer(client versioned.Interface, namespace s...
FILE: client/pkg/informers/externalversions/networking/v1/interface.gen.go
type Interface (line 24) | type Interface interface
type version (line 31) | type version struct
method Http2Rpcs (line 43) | func (v *version) Http2Rpcs() Http2RpcInformer {
method McpBridges (line 48) | func (v *version) McpBridges() McpBridgeInformer {
function New (line 38) | func New(f internalinterfaces.SharedInformerFactory, namespace string, t...
FILE: client/pkg/informers/externalversions/networking/v1/mcpbridge.gen.go
type McpBridgeInformer (line 35) | type McpBridgeInformer interface
type mcpBridgeInformer (line 40) | type mcpBridgeInformer struct
method defaultInformer (line 78) | func (f *mcpBridgeInformer) defaultInformer(client versioned.Interface...
method Informer (line 82) | func (f *mcpBridgeInformer) Informer() cache.SharedIndexInformer {
method Lister (line 86) | func (f *mcpBridgeInformer) Lister() v1.McpBridgeLister {
function NewMcpBridgeInformer (line 49) | func NewMcpBridgeInformer(client versioned.Interface, namespace string, ...
function NewFilteredMcpBridgeInformer (line 56) | func NewFilteredMcpBridgeInformer(client versioned.Interface, namespace ...
FILE: client/pkg/listers/extensions/v1alpha1/expansion_generated.gen.go
type WasmPluginListerExpansion (line 21) | type WasmPluginListerExpansion interface
type WasmPluginNamespaceListerExpansion (line 25) | type WasmPluginNamespaceListerExpansion interface
FILE: client/pkg/listers/extensions/v1alpha1/wasmplugin.gen.go
type WasmPluginLister (line 28) | type WasmPluginLister interface
type wasmPluginLister (line 38) | type wasmPluginLister struct
method List (line 48) | func (s *wasmPluginLister) List(selector labels.Selector) (ret []*v1al...
method WasmPlugins (line 56) | func (s *wasmPluginLister) WasmPlugins(namespace string) WasmPluginNam...
function NewWasmPluginLister (line 43) | func NewWasmPluginLister(indexer cache.Indexer) WasmPluginLister {
type WasmPluginNamespaceLister (line 62) | type WasmPluginNamespaceLister interface
type wasmPluginNamespaceLister (line 74) | type wasmPluginNamespaceLister struct
method List (line 80) | func (s wasmPluginNamespaceLister) List(selector labels.Selector) (ret...
method Get (line 88) | func (s wasmPluginNamespaceLister) Get(name string) (*v1alpha1.WasmPlu...
FILE: client/pkg/listers/networking/v1/expansion_generated.gen.go
type Http2RpcListerExpansion (line 21) | type Http2RpcListerExpansion interface
type Http2RpcNamespaceListerExpansion (line 25) | type Http2RpcNamespaceListerExpansion interface
type McpBridgeListerExpansion (line 29) | type McpBridgeListerExpansion interface
type McpBridgeNamespaceListerExpansion (line 33) | type McpBridgeNamespaceListerExpansion interface
FILE: client/pkg/listers/networking/v1/http2rpc.gen.go
type Http2RpcLister (line 28) | type Http2RpcLister interface
type http2RpcLister (line 38) | type http2RpcLister struct
method List (line 48) | func (s *http2RpcLister) List(selector labels.Selector) (ret []*v1.Htt...
method Http2Rpcs (line 56) | func (s *http2RpcLister) Http2Rpcs(namespace string) Http2RpcNamespace...
function NewHttp2RpcLister (line 43) | func NewHttp2RpcLister(indexer cache.Indexer) Http2RpcLister {
type Http2RpcNamespaceLister (line 62) | type Http2RpcNamespaceLister interface
type http2RpcNamespaceLister (line 74) | type http2RpcNamespaceLister struct
method List (line 80) | func (s http2RpcNamespaceLister) List(selector labels.Selector) (ret [...
method Get (line 88) | func (s http2RpcNamespaceLister) Get(name string) (*v1.Http2Rpc, error) {
FILE: client/pkg/listers/networking/v1/mcpbridge.gen.go
type McpBridgeLister (line 28) | type McpBridgeLister interface
type mcpBridgeLister (line 38) | type mcpBridgeLister struct
method List (line 48) | func (s *mcpBridgeLister) List(selector labels.Selector) (ret []*v1.Mc...
method McpBridges (line 56) | func (s *mcpBridgeLister) McpBridges(namespace string) McpBridgeNamesp...
function NewMcpBridgeLister (line 43) | func NewMcpBridgeLister(indexer cache.Indexer) McpBridgeLister {
type McpBridgeNamespaceLister (line 62) | type McpBridgeNamespaceLister interface
type mcpBridgeNamespaceLister (line 74) | type mcpBridgeNamespaceLister struct
method List (line 80) | func (s mcpBridgeNamespaceLister) List(selector labels.Selector) (ret ...
method Get (line 88) | func (s mcpBridgeNamespaceLister) Get(name string) (*v1.McpBridge, err...
FILE: cmd/higress/main.go
function main (line 26) | func main() {
FILE: hgctl/cmd/hgctl/config/gateway_config.go
constant defaultProxyAdminPort (line 43) | defaultProxyAdminPort = 15000
type EnvoyConfigType (line 46) | type EnvoyConfigType
type GetEnvoyConfigOptions (line 48) | type GetEnvoyConfigOptions struct
function init (line 57) | func init() {
function NewDefaultGetEnvoyConfigOptions (line 62) | func NewDefaultGetEnvoyConfigOptions() *GetEnvoyConfigOptions {
function setupConfigdumpEnvoyConfigWriter (line 73) | func setupConfigdumpEnvoyConfigWriter(debug []byte, stdout io.Writer) (*...
function GetEnvoyConfigWriter (line 82) | func GetEnvoyConfigWriter(config *GetEnvoyConfigOptions, stdout io.Write...
function GetEnvoyConfig (line 90) | func GetEnvoyConfig(config *GetEnvoyConfigOptions) ([]byte, error) {
function retrieveConfigDump (line 105) | func retrieveConfigDump(podName, podNamespace, bindAddress string, inclu...
function portForwarder (line 146) | func portForwarder(nn types.NamespacedName, bindAddress string) (kuberne...
function formatGatewayConfig (line 168) | func formatGatewayConfig(configDump any, output string) ([]byte, error) {
function fetchGatewayConfig (line 182) | func fetchGatewayConfig(fw kubernetes.PortForwarder, includeEds bool) ([...
function configDumpRequest (line 191) | func configDumpRequest(address string, includeEds bool) ([]byte, error) {
function getXDSResource (line 212) | func getXDSResource(resourceType EnvoyConfigType, configDump []byte) (an...
FILE: hgctl/cmd/hgctl/config/gateway_config_test.go
type fakePortForwarder (line 32) | type fakePortForwarder struct
method WaitForStop (line 59) | func (fw *fakePortForwarder) WaitForStop() {
method Start (line 63) | func (fw *fakePortForwarder) Start() error {
method Stop (line 79) | func (fw *fakePortForwarder) Stop() {}
method Address (line 81) | func (fw *fakePortForwarder) Address() string {
function newFakePortForwarder (line 40) | func newFakePortForwarder(b []byte) (kubernetes.PortForwarder, error) {
function TestExtractAllConfigDump (line 85) | func TestExtractAllConfigDump(t *testing.T) {
function TestExtractSubResourcesConfigDump (line 129) | func TestExtractSubResourcesConfigDump(t *testing.T) {
function readInputConfig (line 215) | func readInputConfig(filename string) ([]byte, error) {
function readOutputConfig (line 223) | func readOutputConfig(filename string) ([]byte, error) {
FILE: hgctl/cmd/hgctl/main.go
function main (line 24) | func main() {
FILE: hgctl/pkg/agent/agent.go
constant A2A (line 28) | A2A = "a2a"
constant REST (line 29) | REST = "restful"
constant MODEL (line 30) | MODEL = "model"
function NewAgentCmd (line 33) | func NewAgentCmd() *cobra.Command {
function invokeAgentCore (line 49) | func invokeAgentCore(w io.Writer) error {
type AgentAddArg (line 57) | type AgentAddArg struct
function newAgentAddCmd (line 70) | func newAgentAddCmd() *cobra.Command {
function handleAddAgent (line 97) | func handleAddAgent(writer io.Writer, arg AgentAddArg) error {
function publishAgentAPIToHigress (line 123) | func publishAgentAPIToHigress(arg AgentAddArg) error {
function validateArg (line 170) | func validateArg(arg AgentAddArg) error {
FILE: hgctl/pkg/agent/base.go
constant NodeLeastVersion (line 35) | NodeLeastVersion = 18
type HimarketAdminAuthArg (line 38) | type HimarketAdminAuthArg struct
method validate (line 51) | func (h *HimarketAdminAuthArg) validate() error {
type HimarketDevAuthArg (line 45) | type HimarketDevAuthArg struct
type HigressConsoleAuthArg (line 58) | type HigressConsoleAuthArg struct
method validate (line 65) | func (h *HigressConsoleAuthArg) validate() error {
function init (line 73) | func init() {
function resolveHimarketAdminAuth (line 78) | func resolveHimarketAdminAuth(arg *HimarketAdminAuthArg) {
function resolveHigressConsoleAuth (line 91) | func resolveHigressConsoleAuth(arg *HigressConsoleAuthArg) {
function parseTypeToAPIProductType (line 112) | func parseTypeToAPIProductType(typ string) string {
function publishAPIToHimarket (line 128) | func publishAPIToHimarket(typ, name string, arg HimarketAdminAuthArg) er...
function generateAgentPromptByCore (line 177) | func generateAgentPromptByCore(desc string) (string, error) {
type EnvProvisioner (line 186) | type EnvProvisioner struct
method init (line 207) | func (p *EnvProvisioner) init() {
method check (line 221) | func (p *EnvProvisioner) check() error {
method checkNodeInstall (line 238) | func (p *EnvProvisioner) checkNodeInstall() bool {
method promptNodeInstall (line 259) | func (p *EnvProvisioner) promptNodeInstall() error {
method installNodeAutomatically (line 313) | func (p *EnvProvisioner) installNodeAutomatically() error {
method showNodeManualInstallation (line 364) | func (p *EnvProvisioner) showNodeManualInstallation() {
method checkAgentInstall (line 393) | func (p *EnvProvisioner) checkAgentInstall() bool {
method promptAgentInstall (line 401) | func (p *EnvProvisioner) promptAgentInstall() error {
method installAgentAutomatically (line 453) | func (p *EnvProvisioner) installAgentAutomatically() error {
method showAgentManualInstallation (line 475) | func (p *EnvProvisioner) showAgentManualInstallation() {
function getCore (line 195) | func getCore() (*AgenticCore, error) {
FILE: hgctl/pkg/agent/common/base.go
type ProductType (line 18) | type ProductType
constant MCP_SERVER (line 21) | MCP_SERVER ProductType = "MCP_SERVER"
constant MODEL_API (line 22) | MODEL_API ProductType = "MODEL_API"
constant REST_API (line 23) | REST_API ProductType = "REST_API"
constant AGENT_API (line 24) | AGENT_API ProductType = "AGENT_API"
FILE: hgctl/pkg/agent/config.go
type CoreType (line 26) | type CoreType
constant CORE_CLAUDE (line 29) | CORE_CLAUDE CoreType = "claude"
constant CORE_QODERCLI (line 30) | CORE_QODERCLI CoreType = "qodercli"
constant HGCTL_AGENT_CORE (line 41) | HGCTL_AGENT_CORE = "hgctl-agent-core"
constant AGENT_MODEL_PROVIDER (line 42) | AGENT_MODEL_PROVIDER = "agent-model-provider"
constant AGENT_CHAT_MODEL (line 43) | AGENT_CHAT_MODEL = "agent-chat-model"
constant HIGRESS_CONSOLE_URL (line 44) | HIGRESS_CONSOLE_URL = "higress-console-url"
constant HIGRESS_CONSOLE_USER (line 45) | HIGRESS_CONSOLE_USER = "higress-console-user"
constant HIGRESS_CONSOLE_PASSWORD (line 46) | HIGRESS_CONSOLE_PASSWORD = "higress-console-password"
constant HIGRESS_GATEWAY_URL (line 47) | HIGRESS_GATEWAY_URL = "higress-gateway-url"
constant HIMARKET_ADMIN_URL (line 49) | HIMARKET_ADMIN_URL = "himarket-admin-url"
constant HIMARKET_ADMIN_USER (line 50) | HIMARKET_ADMIN_USER = "himarket-admin-user"
constant HIMARKET_ADMIN_PASSWORD (line 51) | HIMARKET_ADMIN_PASSWORD = "himarket-admin-password"
constant HIMARKET_TARGET_HIGRESS_ID (line 52) | HIMARKET_TARGET_HIGRESS_ID = "himarket-target-higress-id"
constant HIMARKET_DEVELOPER_URL (line 54) | HIMARKET_DEVELOPER_URL = "himarket-developer-url"
constant HIMARKET_DEVELOPER_USER (line 55) | HIMARKET_DEVELOPER_USER = "himarket-developer-user"
constant HIMARKET_DEVELOPER_PASSWORD (line 56) | HIMARKET_DEVELOPER_PASSWORD = "himarket-developer-password"
constant AGENTRUN_MODEL_NAME (line 59) | AGENTRUN_MODEL_NAME = "agentrun-model-name"
constant AGENTRUN_SANDBOX_NAME (line 60) | AGENTRUN_SANDBOX_NAME = "agentrun-sandbox-name"
constant ALIBABA_CLOUD_ACCESS_KEY_ID (line 61) | ALIBABA_CLOUD_ACCESS_KEY_ID = "alibaba-cloud-access-key-id"
constant ALIBABA_CLOUD_ACCESS_KEY_SECRET (line 62) | ALIBABA_CLOUD_ACCESS_KEY_SECRET = "alibaba-cloud-access-key-secret"
constant ALIBABA_CLOUD_SECURITY_TOK (line 63) | ALIBABA_CLOUD_SECURITY_TOK = "alibaba-cloud-security-tok"
constant AGENTRUN_ACCOUNT_ID (line 64) | AGENTRUN_ACCOUNT_ID = "agentrun-account-id"
constant AGENTRUN_REGION (line 65) | AGENTRUN_REGION = "agentrun-region"
constant AGENTRUN_SDK_DEB (line 66) | AGENTRUN_SDK_DEB = "agentrun-sdk-deb"
type HgctlAgentConfig (line 71) | type HgctlAgentConfig struct
function InitConfig (line 102) | func InitConfig() {
FILE: hgctl/pkg/agent/core.go
type AgenticCore (line 32) | type AgenticCore struct
method GetPromptFileName (line 44) | func (c *AgenticCore) GetPromptFileName() string {
method GetCoreDirName (line 54) | func (c *AgenticCore) GetCoreDirName() string {
method ImproveNewAgent (line 65) | func (c *AgenticCore) ImproveNewAgent(config *AgentConfig) error {
method runInTargetDir (line 73) | func (c *AgenticCore) runInTargetDir(dir string, args ...string) error {
method runWithResult (line 83) | func (c *AgenticCore) runWithResult(args ...string) (string, error) {
method run (line 98) | func (c *AgenticCore) run(args ...string) error {
method Setup (line 108) | func (c *AgenticCore) Setup() {
method addPredefinedMCP (line 146) | func (c *AgenticCore) addPredefinedMCP() error {
method addHigressAPIMCP (line 161) | func (c *AgenticCore) addHigressAPIMCP() error {
method Start (line 231) | func (c *AgenticCore) Start() error {
method AddMCPServer (line 236) | func (c *AgenticCore) AddMCPServer(arg MCPAddArg) error {
function NewAgenticCore (line 36) | func NewAgenticCore() *AgenticCore {
FILE: hgctl/pkg/agent/deploy.go
type DeployType (line 30) | type DeployType
constant AgentRun (line 33) | AgentRun DeployType = "agent-run"
constant Local (line 34) | Local DeployType = "local"
constant InstallServerlessCmd (line 44) | InstallServerlessCmd = "npm install @serverless-devs/s -g"
constant BuildAgentCmd (line 45) | BuildAgentCmd = "s build"
constant ServerlessCliDocs (line 46) | ServerlessCliDocs = "https://serverless-devs.com/docs/user-guide/inst...
type DeployHandler (line 49) | type DeployHandler struct
method validate (line 74) | func (h *DeployHandler) validate() error {
method RunCmd (line 81) | func (h *DeployHandler) RunCmd(showOutput bool, cmd string, targetDir ...
method RunPythonCmd (line 104) | func (h *DeployHandler) RunPythonCmd(showOutput bool, args ...string) ...
method checkAgentRunEnvironment (line 119) | func (h *DeployHandler) checkAgentRunEnvironment() error {
method checkLocalEnvironment (line 134) | func (h *DeployHandler) checkLocalEnvironment() error {
method createLocalPyVenv (line 185) | func (h *DeployHandler) createLocalPyVenv() error {
method installLocalRequiredDeps (line 196) | func (h *DeployHandler) installLocalRequiredDeps(missingDeps []string)...
method activateLocalPythonVenv (line 228) | func (h *DeployHandler) activateLocalPythonVenv() error {
method checkRequiredEnvironment (line 246) | func (h *DeployHandler) checkRequiredEnvironment() error {
method GetRequiredDeps (line 257) | func (h *DeployHandler) GetRequiredDeps() ([]string, error) {
method getAgentType (line 273) | func (h *DeployHandler) getAgentType() error {
method Deploy (line 290) | func (h *DeployHandler) Deploy() error {
method HandleAgentRun (line 322) | func (h *DeployHandler) HandleAgentRun() error {
method CheckServerlessAccessKey (line 348) | func (h *DeployHandler) CheckServerlessAccessKey() error {
method HandleLocal (line 367) | func (h *DeployHandler) HandleLocal() error {
method startAgentProcess (line 379) | func (h *DeployHandler) startAgentProcess() error {
method runUnixAgent (line 390) | func (h *DeployHandler) runUnixAgent() error {
method runWindowsAgent (line 399) | func (h *DeployHandler) runWindowsAgent() error {
function deployAgentCmd (line 55) | func deployAgentCmd() *cobra.Command {
FILE: hgctl/pkg/agent/mcp.go
type MCPType (line 32) | type MCPType
constant OPENAPI (line 35) | OPENAPI string = "openapi"
constant HTTP (line 36) | HTTP string = "http"
constant STREAMABLE (line 38) | STREAMABLE string = "streamable"
constant SSE (line 39) | SSE string = "sse"
constant DIRECT_ROUTE (line 41) | DIRECT_ROUTE string = "DIRECT_ROUTE"
constant OPEN_API (line 42) | OPEN_API string = "OPEN_API"
type MCPAddArg (line 45) | type MCPAddArg struct
type MCPAddHandler (line 61) | type MCPAddHandler struct
method validateArg (line 130) | func (h *MCPAddHandler) validateArg() error {
method addHTTPMCP (line 138) | func (h *MCPAddHandler) addHTTPMCP() error {
method addOpenAPIMCP (line 151) | func (h *MCPAddHandler) addOpenAPIMCP() error {
method parseOpenapiSpec (line 179) | func (h *MCPAddHandler) parseOpenapiSpec() *models.MCPConfig {
function NewMCPCmd (line 67) | func NewMCPCmd() *cobra.Command {
function newMCPAddCmd (line 78) | func newMCPAddCmd() *cobra.Command {
function newHanlder (line 126) | func newHanlder(c *AgenticCore, arg MCPAddArg, w io.Writer) *MCPAddHandl...
function handleAddMCP (line 183) | func handleAddMCP(w io.Writer, arg MCPAddArg) error {
function publishMCPToHigress (line 228) | func publishMCPToHigress(arg MCPAddArg, transport string, config *models...
function addMCPToolConfig (line 297) | func addMCPToolConfig(client *services.HigressClient, config *models.MCP...
function tryToGetLocalCredential (line 320) | func tryToGetLocalCredential(arg *HigressConsoleAuthArg) error {
FILE: hgctl/pkg/agent/new.go
constant ASRuntimeMainPyFile (line 33) | ASRuntimeMainPyFile = "as_runtime_main.py"
constant AgentRunMainPyFile (line 34) | AgentRunMainPyFile = "agentrun_main.py"
constant ToolKitPyFile (line 35) | ToolKitPyFile = "toolkit.py"
constant AgentClassFile (line 36) | AgentClassFile = "agent.py"
constant CorePromptFile (line 37) | CorePromptFile = "claude.md"
constant SConfigYAML (line 38) | SConfigYAML = "s.yaml"
constant ARTemplate (line 40) | ARTemplate = "agentrun.tmpl"
constant ASTemplate (line 41) | ASTemplate = "agentscope.tmpl"
constant AgentClassTemplate (line 42) | AgentClassTemplate = "agent.tmpl"
constant ToolKitTemplate (line 43) | ToolKitTemplate = "toolkit.tmpl"
constant SConfigTemplate (line 44) | SConfigTemplate = "agentrun_s.tmpl"
constant MinPythonVersion (line 65) | MinPythonVersion = "3.12"
constant DefaultServerLessAccessKey (line 67) | DefaultServerLessAccessKey = "hgctl-credential"
type PostAgentAction (line 71) | type PostAgentAction
type MCPServerConfig (line 73) | type MCPServerConfig struct
type ServerlessConfig (line 80) | type ServerlessConfig struct
type AgentConfig (line 94) | type AgentConfig struct
function createAgentCmd (line 113) | func createAgentCmd() *cobra.Command {
function afterCreatedAgent (line 160) | func afterCreatedAgent(config *AgentConfig) error {
function runAgenticCoreImprovement (line 183) | func runAgenticCoreImprovement(cfg *AgentConfig) error {
function promptAfterCreatedAgent (line 195) | func promptAfterCreatedAgent(options []string, config *AgentConfig, call...
function createAgentTemplate (line 219) | func createAgentTemplate(config *AgentConfig) error {
function renderTemplateFile (line 304) | func renderTemplateFile(templateStr string, targetPath string, data inte...
function get_template (line 332) | func get_template(templatePath string) (string, error) {
FILE: hgctl/pkg/agent/services/client.go
type HigressClient (line 27) | type HigressClient struct
method Get (line 86) | func (c *HigressClient) Get(path string) ([]byte, error) {
method Post (line 90) | func (c *HigressClient) Post(path string, data interface{}) ([]byte, e...
method Put (line 94) | func (c *HigressClient) Put(path string, data interface{}) ([]byte, er...
method Delete (line 98) | func (c *HigressClient) Delete(path string) ([]byte, error) {
method request (line 228) | func (c *HigressClient) request(method, path string, data interface{})...
type HimarketClient (line 34) | type HimarketClient struct
method getJWTToken (line 102) | func (c *HimarketClient) getJWTToken() error {
method Get (line 157) | func (c *HimarketClient) Get(path string) ([]byte, error) {
method Post (line 161) | func (c *HimarketClient) Post(path string, data interface{}) ([]byte, ...
method Put (line 165) | func (c *HimarketClient) Put(path string, data interface{}) ([]byte, e...
method request (line 169) | func (c *HimarketClient) request(method, path string, data interface{}...
function NewHigressClient (line 59) | func NewHigressClient(baseURL, username, password string) *HigressClient {
function NewHimarketClient (line 73) | func NewHimarketClient(baseURL, username, password string) *HimarketClie...
FILE: hgctl/pkg/agent/services/service.go
function HandleAddServiceSource (line 25) | func HandleAddServiceSource(client *HigressClient, body interface{}) ([]...
function HandleAddMCPServer (line 78) | func HandleAddMCPServer(client *HigressClient, body interface{}) ([]byte...
function GetExistingMCPServers (line 109) | func GetExistingMCPServers(client *HigressClient) (map[string]string, er...
function HandleListMCPServers (line 135) | func HandleListMCPServers(client *HigressClient) ([]byte, error) {
function HandleAddOpenAPITool (line 169) | func HandleAddOpenAPITool(client *HigressClient, body interface{}) ([]by...
function HandleAddAIProviderService (line 173) | func HandleAddAIProviderService(client *HigressClient, body interface{})...
function HandleAddAIRoute (line 178) | func HandleAddAIRoute(client *HigressClient, body interface{}) ([]byte, ...
function HandleAddRoute (line 182) | func HandleAddRoute(client *HigressClient, body interface{}) ([]byte, er...
function HandleAddHigressInstance (line 187) | func HandleAddHigressInstance(client *HimarketClient, body interface{}) ...
method getProduct (line 192) | func (c *HimarketClient) getProduct(typ common.ProductType) ([]byte, err...
method extractGetProductResponse (line 196) | func (c *HimarketClient) extractGetProductResponse(typ common.ProductTyp...
method GetDevModelProduct (line 273) | func (c *HimarketClient) GetDevModelProduct() (map[string]string, error) {
method GetDevMCPServerProduct (line 286) | func (c *HimarketClient) GetDevMCPServerProduct() (map[string]string, er...
function HandleListHimarketMCPServers (line 299) | func HandleListHimarketMCPServers(client *HimarketClient) ([]byte, error) {
function HandleAddAPIProduct (line 303) | func HandleAddAPIProduct(client *HimarketClient, body interface{}) ([]by...
function HandleRefAPIProduct (line 321) | func HandleRefAPIProduct(client *HimarketClient, product_id string, body...
FILE: hgctl/pkg/agent/services/utils.go
function BuildAIProviderServiceBody (line 23) | func BuildAIProviderServiceBody(name, url string) map[string]interface{} {
function BuildAddAIRouteBody (line 42) | func BuildAddAIRouteBody(name, _url string) map[string]interface{} {
function BuildServiceBodyAndSrv (line 81) | func BuildServiceBodyAndSrv(name, urlStr string) (map[string]interface{}...
function BuildAPIRouteBody (line 119) | func BuildAPIRouteBody(name, srv string) map[string]interface{} {
function BuildAddHigressInstanceBody (line 138) | func BuildAddHigressInstanceBody(name, addr, username, password string) ...
function BuildAPIProductBody (line 150) | func BuildAPIProductBody(name, desc, typ string) map[string]interface{} {
function BuildRefModelAPIProductBody (line 156) | func BuildRefModelAPIProductBody(gateway_id, product_id, target_route st...
function BuildRefMCPAPIProductBody (line 168) | func BuildRefMCPAPIProductBody(gateway_id, product_id, mcp_name string) ...
FILE: hgctl/pkg/agent/types.go
type Message (line 17) | type Message struct
type Request (line 22) | type Request struct
type Choice (line 32) | type Choice struct
type Usage (line 38) | type Usage struct
type Response (line 44) | type Response struct
type ToolsParam (line 53) | type ToolsParam struct
type Info (line 62) | type Info struct
type Server (line 68) | type Server struct
type Parameter (line 72) | type Parameter struct
type Items (line 84) | type Items struct
type Property (line 89) | type Property struct
type Schema (line 98) | type Schema struct
type MediaType (line 104) | type MediaType struct
type RequestBody (line 108) | type RequestBody struct
type PathItem (line 113) | type PathItem struct
type Paths (line 122) | type Paths
type Components (line 124) | type Components struct
type API (line 128) | type API struct
FILE: hgctl/pkg/agent/utils.go
constant SecretConsoleUser (line 48) | SecretConsoleUser = "adminUsername"
constant SecretConsolePwd (line 49) | SecretConsolePwd = "adminPassword"
function addHigressConsoleAuthFlag (line 60) | func addHigressConsoleAuthFlag(cmd *cobra.Command, arg *HigressConsoleAu...
function addHimarketAdminAuthFlag (line 69) | func addHimarketAdminAuthFlag(cmd *cobra.Command, arg *HimarketAdminAuth...
function parseOpenapi2MCP (line 79) | func parseOpenapi2MCP(arg MCPAddArg) *models.MCPConfig {
function convertMCPConfigToStr (line 111) | func convertMCPConfigToStr(cfg *models.MCPConfig) string {
function GetHigressGatewayServiceIP (line 141) | func GetHigressGatewayServiceIP() (string, error) {
function extractServiceIP (line 174) | func extractServiceIP(clientset *k8s.Clientset, namespace string, svc *v...
function promptForServiceKubeSettingsAndRetry (line 194) | func promptForServiceKubeSettingsAndRetry() (string, error) {
function getConsoleCredentials (line 240) | func getConsoleCredentials(profile *helm.Profile) (username, password st...
function getAllProfiles (line 258) | func getAllProfiles() ([]*installer.ProfileContext, error) {
function getAgentConfig (line 289) | func getAgentConfig(config *AgentConfig) error {
function getAgentCoreSubAgents (line 315) | func getAgentCoreSubAgents() (map[string]string, []string, error) {
function importAgentFromCore (line 356) | func importAgentFromCore(config *AgentConfig) error {
function queryAgentSysPrompt (line 418) | func queryAgentSysPrompt(config *AgentConfig) error {
function queryAgentTools (line 501) | func queryAgentTools(config *AgentConfig) error {
function queryAgentModel (line 521) | func queryAgentModel(config *AgentConfig) error {
function queryAgentRunModel (line 532) | func queryAgentRunModel(config *AgentConfig) error {
function queryLocalModel (line 551) | func queryLocalModel(config *AgentConfig) error {
function queryAgentMCP (line 615) | func queryAgentMCP(config *AgentConfig) error {
function queryDeploySettings (line 736) | func queryDeploySettings(config *AgentConfig) error {
function queryAgentRunDeploySettings (line 747) | func queryAgentRunDeploySettings(config *AgentConfig) error {
function queryLocalDeploySettings (line 824) | func queryLocalDeploySettings(config *AgentConfig) error {
function createAgentStepByStep (line 853) | func createAgentStepByStep(config *AgentConfig) error {
function writeAgentPromptFile (line 914) | func writeAgentPromptFile(dir, name, prompt string) error {
function getHimarketMCPServer (line 926) | func getHimarketMCPServer() (map[string]string, []string, error) {
function getHigressMCPServers (line 953) | func getHigressMCPServers() (map[string]string, []string, error) {
function showConfigSummary (line 985) | func showConfigSummary(config *AgentConfig) {
FILE: hgctl/pkg/code_debug.go
constant DefaultIp (line 34) | DefaultIp = "127.0.0.1"
constant DefaultPort (line 35) | DefaultPort = ":15051"
function newCodeDebugCmd (line 38) | func newCodeDebugCmd() *cobra.Command {
function getStartCodeDebugCmd (line 50) | func getStartCodeDebugCmd() *cobra.Command {
function getStopCodeDebugCmd (line 131) | func getStopCodeDebugCmd() *cobra.Command {
function getNonLoopbackIPv4 (line 204) | func getNonLoopbackIPv4() (string, error) {
function updateXdsIpAndRollout (line 240) | func updateXdsIpAndRollout(c *kubernetes.Clientset, ip string, port stri...
function triggerRollout (line 283) | func triggerRollout(clientset *kubernetes.Clientset, deploymentName stri...
function replaceXDSAddress (line 305) | func replaceXDSAddress(configString, newIP, newPort string) (string, err...
function promptCodeDebug (line 324) | func promptCodeDebug(writer io.Writer, t string) bool {
FILE: hgctl/pkg/common.go
constant summaryOutput (line 18) | summaryOutput = "short"
constant yamlOutput (line 19) | yamlOutput = "yaml"
constant jsonOutput (line 20) | jsonOutput = "json"
constant flagsOutput (line 21) | flagsOutput = "flags"
FILE: hgctl/pkg/completion.go
constant completionDesc (line 26) | completionDesc = `
constant bashCompDesc (line 30) | bashCompDesc = `
constant zshCompDesc (line 53) | zshCompDesc = `
constant fishCompDesc (line 78) | fishCompDesc = `
constant powershellCompDesc (line 92) | powershellCompDesc = `
constant noDescFlagName (line 104) | noDescFlagName = "no-descriptions"
constant noDescFlagText (line 105) | noDescFlagText = "disable completion descriptions"
function newCompletionCmd (line 111) | func newCompletionCmd(out io.Writer) *cobra.Command {
function runCompletionBash (line 172) | func runCompletionBash(out io.Writer, cmd *cobra.Command) error {
function runCompletionZsh (line 193) | func runCompletionZsh(out io.Writer, cmd *cobra.Command) error {
function runCompletionFish (line 218) | func runCompletionFish(out io.Writer, cmd *cobra.Command) error {
function runCompletionPowershell (line 222) | func runCompletionPowershell(out io.Writer, cmd *cobra.Command) error {
function noCompletions (line 230) | func noCompletions(cmd *cobra.Command, args []string, toComplete string)...
FILE: hgctl/pkg/config_bootstrap.go
function bootstrapConfigCmd (line 25) | func bootstrapConfigCmd() *cobra.Command {
function runBootstrapConfig (line 48) | func runBootstrapConfig(c *cobra.Command, args []string) error {
FILE: hgctl/pkg/config_cluster.go
function clusterConfigCmd (line 26) | func clusterConfigCmd() *cobra.Command {
function runClusterConfig (line 49) | func runClusterConfig(c *cobra.Command, args []string) error {
FILE: hgctl/pkg/config_cmd.go
constant defaultProxyAdminPort (line 33) | defaultProxyAdminPort = 15000
constant containerName (line 34) | containerName = "envoy"
function newConfigCommand (line 37) | func newConfigCommand() *cobra.Command {
function allConfigCmd (line 61) | func allConfigCmd() *cobra.Command {
function runAllConfig (line 83) | func runAllConfig(c *cobra.Command, args []string) error {
FILE: hgctl/pkg/config_endpoint.go
function endpointConfigCmd (line 25) | func endpointConfigCmd() *cobra.Command {
function runEndpointConfig (line 48) | func runEndpointConfig(c *cobra.Command, args []string) error {
FILE: hgctl/pkg/config_listener.go
function listenerConfigCmd (line 26) | func listenerConfigCmd() *cobra.Command {
function runListenerConfig (line 49) | func runListenerConfig(c *cobra.Command, args []string) error {
FILE: hgctl/pkg/config_route.go
function routeConfigCmd (line 26) | func routeConfigCmd() *cobra.Command {
function runRouteConfig (line 49) | func runRouteConfig(c *cobra.Command, args []string) error {
FILE: hgctl/pkg/dashboard.go
constant defaultPrometheusPort (line 63) | defaultPrometheusPort = 9090
constant defaultGrafanaPort (line 64) | defaultGrafanaPort = 3000
constant defaultConsolePort (line 65) | defaultConsolePort = 8080
constant defaultControllerPort (line 66) | defaultControllerPort = 8888
function newDashboardCmd (line 69) | func newDashboardCmd() *cobra.Command {
function promDashCmd (line 123) | func promDashCmd() *cobra.Command {
function consoleDashCmd (line 158) | func consoleDashCmd() *cobra.Command {
function accessDockerCompose (line 198) | func accessDockerCompose(cmd *cobra.Command) error {
function grafanaDashCmd (line 223) | func grafanaDashCmd() *cobra.Command {
function envoyDashCmd (line 257) | func envoyDashCmd() *cobra.Command {
function controllerDebugCmd (line 316) | func controllerDebugCmd() *cobra.Command {
function portForward (line 351) | func portForward(podName, namespace, flavor, urlFormat, localAddress str...
function ClosePortForwarderOnInterrupt (line 393) | func ClosePortForwarderOnInterrupt(fw kubernetes.PortForwarder) {
function openBrowser (line 403) | func openBrowser(url string, writer io.Writer, browser bool) {
function openCommand (line 423) | func openCommand(writer io.Writer, command string, args ...string) {
FILE: hgctl/pkg/docker/compose.go
type Compose (line 30) | type Compose struct
method Up (line 56) | func (c Compose) Up(ctx context.Context, name string, configs []string...
method List (line 104) | func (c Compose) List(ctx context.Context) ([]api.Stack, error) {
method Down (line 108) | func (c Compose) Down(ctx context.Context, name string) error {
method Ps (line 112) | func (c Compose) Ps(ctx context.Context, name string) ([]api.Container...
function NewCompose (line 35) | func NewCompose(w io.Writer) (*Compose, error) {
FILE: hgctl/pkg/helm/common.go
function GetProfileFromFlags (line 30) | func GetProfileFromFlags(setFlags []string) (string, error) {
function GetValuesOverylayFromFiles (line 40) | func GetValuesOverylayFromFiles(inFilenames []string) (string, error) {
function GetUninstallProfileName (line 65) | func GetUninstallProfileName() string {
function ReadLayeredYAMLs (line 69) | func ReadLayeredYAMLs(filenames []string) (string, error) {
function readLayeredYAMLs (line 73) | func readLayeredYAMLs(filenames []string, stdinReader io.Reader) (string...
function GetValueForSetFlag (line 102) | func GetValueForSetFlag(setFlags []string, path string) string {
function getPV (line 115) | func getPV(setFlag string) (path string, value string) {
function GenerateConfig (line 124) | func GenerateConfig(inFilenames []string, setFlags []string) (string, *P...
function validateSetFlags (line 148) | func validateSetFlags(setFlags []string) error {
function overlaySetFlagValues (line 158) | func overlaySetFlagValues(iopYAML string, setFlags []string) (string, er...
function getInstallPackagePath (line 189) | func getInstallPackagePath(profileYAML string) (string, error) {
function GetProfileYAML (line 202) | func GetProfileYAML(installPackagePath, profileOrPath string) (string, e...
function IsDefaultProfile (line 236) | func IsDefaultProfile(profile string) bool {
function DefaultFilenameForProfile (line 241) | func DefaultFilenameForProfile(profile string) string {
function ReadProfileYAML (line 252) | func ReadProfileYAML(profile, manifestsPath string) (string, error) {
function readFile (line 271) | func readFile(path string) (string, error) {
function UnmarshalProfile (line 277) | func UnmarshalProfile(profileYAML string) (*Profile, error) {
function GenProfile (line 287) | func GenProfile(profileOrPath, fileOverlayYAML string, setFlags []string...
function GenProfileFromProfileContent (line 330) | func GenProfileFromProfileContent(profileContent, fileOverlayYAML string...
FILE: hgctl/pkg/helm/name/name.go
constant CRDStr (line 19) | CRDStr = "CustomResourceDefinition"
constant ClusterRoleStr (line 20) | ClusterRoleStr = "ClusterRole"
constant ClusterRoleBindingStr (line 21) | ClusterRoleBindingStr = "ClusterRoleBinding"
constant CMStr (line 22) | CMStr = "ConfigMap"
constant DaemonSetStr (line 23) | DaemonSetStr = "DaemonSet"
constant DeploymentStr (line 24) | DeploymentStr = "Deployment"
constant EndpointStr (line 25) | EndpointStr = "Endpoints"
constant HPAStr (line 26) | HPAStr = "HorizontalPodAutoscaler"
constant IngressStr (line 27) | IngressStr = "Ingress"
constant IstioOperator (line 28) | IstioOperator = "IstioOperator"
constant MutatingWebhookConfigurationStr (line 29) | MutatingWebhookConfigurationStr = "MutatingWebhookConfiguration"
constant NamespaceStr (line 30) | NamespaceStr = "Namespace"
constant PVCStr (line 31) | PVCStr = "PersistentVolumeClaim"
constant PodStr (line 32) | PodStr = "Pod"
constant PDBStr (line 33) | PDBStr = "PodDisruptionBudget"
constant ReplicationControllerStr (line 34) | ReplicationControllerStr = "ReplicationController"
constant ReplicaSetStr (line 35) | ReplicaSetStr = "ReplicaSet"
constant RoleStr (line 36) | RoleStr = "Role"
constant RoleBindingStr (line 37) | RoleBindingStr = "RoleBinding"
constant SAStr (line 38) | SAStr = "ServiceAccount"
constant ServiceStr (line 39) | ServiceStr = "Service"
constant SecretStr (line 40) | SecretStr = "Secret"
constant StatefulSetStr (line 41) | StatefulSetStr = "StatefulSet"
constant ValidatingWebhookConfigurationStr (line 42) | ValidatingWebhookConfigurationStr = "ValidatingWebhookConfiguration"
constant EnvoyFilterStr (line 47) | EnvoyFilterStr = "EnvoyFilter"
constant GatewayStr (line 48) | GatewayStr = "Gateway"
constant DestinationRuleStr (line 49) | DestinationRuleStr = "DestinationRule"
constant MeshPolicyStr (line 50) | MeshPolicyStr = "MeshPolicy"
constant PeerAuthenticationStr (line 51) | PeerAuthenticationStr = "PeerAuthentication"
constant VirtualServiceStr (line 52) | VirtualServiceStr = "VirtualService"
constant IstioOperatorStr (line 53) | IstioOperatorStr = "IstioOperator"
constant AuthenticationAPIGroupName (line 58) | AuthenticationAPIGroupName = "authentication.istio.io"
constant ConfigAPIGroupName (line 59) | ConfigAPIGroupName = "config.istio.io"
constant NetworkingAPIGroupName (line 60) | NetworkingAPIGroupName = "networking.istio.io"
constant OperatorAPIGroupName (line 61) | OperatorAPIGroupName = "operator.istio.io"
constant SecurityAPIGroupName (line 62) | SecurityAPIGroupName = "security.istio.io"
FILE: hgctl/pkg/helm/object/objects.go
constant YAMLSeparator (line 36) | YAMLSeparator = "\n---\n"
type K8sObject (line 41) | type K8sObject struct
method UnstructuredObject (line 123) | func (o *K8sObject) UnstructuredObject() *unstructured.Unstructured {
method ResolveK8sConflict (line 130) | func (o *K8sObject) ResolveK8sConflict() *K8sObject {
method Unstructured (line 138) | func (o *K8sObject) Unstructured() map[string]any {
method Container (line 143) | func (o *K8sObject) Container(name string) map[string]any {
method GroupVersionKind (line 155) | func (o *K8sObject) GroupVersionKind() schema.GroupVersionKind {
method Version (line 160) | func (o *K8sObject) Version() string {
method Hash (line 165) | func (o *K8sObject) Hash() string {
method HashNameKind (line 170) | func (o *K8sObject) HashNameKind() string {
method JSON (line 175) | func (o *K8sObject) JSON() ([]byte, error) {
method YAML (line 188) | func (o *K8sObject) YAML() ([]byte, error) {
method YAMLDebugString (line 209) | func (o *K8sObject) YAMLDebugString() string {
method Valid (line 381) | func (o *K8sObject) Valid() bool {
method FullName (line 386) | func (o *K8sObject) FullName() string {
method Equal (line 391) | func (o *K8sObject) Equal(other *K8sObject) bool {
function NewK8sObject (line 54) | func NewK8sObject(u *unstructured.Unstructured, json, yaml []byte) *K8sO...
function Hash (line 71) | func Hash(kind, namespace, name string) string {
function FromHash (line 80) | func FromHash(hash string) (kind, namespace, name string) {
function HashNameKind (line 90) | func HashNameKind(kind, name string) string {
function ParseJSONToK8sObject (line 95) | func ParseJSONToK8sObject(json []byte) (*K8sObject, error) {
function ParseYAMLToK8sObject (line 110) | func ParseYAMLToK8sObject(yaml []byte) (*K8sObject, error) {
type K8sObjects (line 218) | type K8sObjects
method String (line 221) | func (os K8sObjects) String() string {
method Keys (line 230) | func (os K8sObjects) Keys() []string {
method UnstructuredItems (line 239) | func (os K8sObjects) UnstructuredItems() []unstructured.Unstructured {
method YAMLManifest (line 314) | func (os K8sObjects) YAMLManifest() (string, error) {
method Sort (line 341) | func (os K8sObjects) Sort(score func(o *K8sObject) int) {
method ToMap (line 359) | func (os K8sObjects) ToMap() map[string]*K8sObject {
method ToNameKindMap (line 370) | func (os K8sObjects) ToNameKindMap() map[string]*K8sObject {
function ParseK8sObjectsFromYAMLManifest (line 248) | func ParseK8sObjectsFromYAMLManifest(manifest string) (K8sObjects, error) {
function ParseK8sObjectsFromYAMLManifestFailOption (line 254) | func ParseK8sObjectsFromYAMLManifestFailOption(manifest string, failOnEr...
function removeNonYAMLLines (line 299) | func removeNonYAMLLines(yms string) string {
function istioCustomResources (line 411) | func istioCustomResources(group string) bool {
function DefaultObjectOrder (line 423) | func DefaultObjectOrder() func(o *K8sObject) int {
function ObjectsNotInLists (line 468) | func ObjectsNotInLists(objects K8sObjects, lists ...K8sObjects) K8sObjec...
function KindObjects (line 487) | func KindObjects(objs K8sObjects, kind string) K8sObjects {
function AllObjectHashes (line 514) | func AllObjectHashes(m string) map[string]bool {
function resolvePDBConflict (line 530) | func resolvePDBConflict(o *K8sObject) *K8sObject {
FILE: hgctl/pkg/helm/object/objects_test.go
function TestHash (line 25) | func TestHash(t *testing.T) {
function TestFromHash (line 48) | func TestFromHash(t *testing.T) {
function TestHashNameKind (line 72) | func TestHashNameKind(t *testing.T) {
function TestParseJSONToK8sObject (line 94) | func TestParseJSONToK8sObject(t *testing.T) {
function TestParseYAMLToK8sObject (line 276) | func TestParseYAMLToK8sObject(t *testing.T) {
function TestParseK8sObjectsFromYAMLManifest (line 405) | func TestParseK8sObjectsFromYAMLManifest(t *testing.T) {
function TestK8sObject_Equal (line 532) | func TestK8sObject_Equal(t *testing.T) {
function TestK8sObject_ResolveK8sConflict (line 590) | func TestK8sObject_ResolveK8sConflict(t *testing.T) {
FILE: hgctl/pkg/helm/profile.go
type InstallMode (line 27) | type InstallMode
constant InstallK8s (line 30) | InstallK8s InstallMode = "k8s"
constant InstallLocalK8s (line 31) | InstallLocalK8s InstallMode = "local-k8s"
constant InstallLocalDocker (line 32) | InstallLocalDocker InstallMode = "local-docker"
constant InstallLocal (line 33) | InstallLocal InstallMode = "local"
type Profile (line 36) | type Profile struct
method ValuesYaml (line 286) | func (p *Profile) ValuesYaml() (string, error) {
method IstioEnabled (line 373) | func (p *Profile) IstioEnabled() bool {
method GatewayAPIEnabled (line 380) | func (p *Profile) GatewayAPIEnabled() bool {
method GetIstioNamespace (line 387) | func (p *Profile) GetIstioNamespace() string {
method Validate (line 400) | func (p *Profile) Validate() error {
type ProfileGlobal (line 49) | type ProfileGlobal struct
method SetFlags (line 57) | func (p ProfileGlobal) SetFlags(install InstallMode) ([]string, error) {
method Validate (line 70) | func (p ProfileGlobal) Validate(install InstallMode) []error {
type ProfileConsole (line 87) | type ProfileConsole struct
method SetFlags (line 94) | func (p ProfileConsole) SetFlags(install InstallMode) ([]string, error) {
method Validate (line 103) | func (p ProfileConsole) Validate(install InstallMode) []error {
type ProfileGateway (line 136) | type ProfileGateway struct
method SetFlags (line 144) | func (p ProfileGateway) SetFlags(install InstallMode) ([]string, error) {
method Validate (line 152) | func (p ProfileGateway) Validate(install InstallMode) []error {
type ProfileController (line 191) | type ProfileController struct
method SetFlags (line 196) | func (p ProfileController) SetFlags(install InstallMode) ([]string, er...
method Validate (line 204) | func (p ProfileController) Validate(install InstallMode) []error {
type ProfileStorage (line 231) | type ProfileStorage struct
method Validate (line 239) | func (p ProfileStorage) Validate(install InstallMode) []error {
type Chart (line 269) | type Chart struct
type ProfileCharts (line 275) | type ProfileCharts struct
method Validate (line 280) | func (p ProfileCharts) Validate(install InstallMode) []error {
function ToString (line 435) | func ToString(errors []error, separator string) string {
type Resource (line 449) | type Resource struct
method Validate (line 464) | func (r Resource) Validate() []error {
type Requests (line 454) | type Requests struct
type Limits (line 459) | type Limits struct
function isValidK8SResourceFormat (line 487) | func isValidK8SResourceFormat(resource string) bool {
FILE: hgctl/pkg/helm/render.go
constant DefaultProfileName (line 47) | DefaultProfileName = "local-k8s"
constant DefaultProfileFilename (line 49) | DefaultProfileFilename = "local-k8s.yaml"
constant DefaultUninstallProfileName (line 51) | DefaultUninstallProfileName = "local-k8s"
constant profilesRoot (line 54) | profilesRoot = "profiles"
constant RepoLatestVersion (line 56) | RepoLatestVersion = "latest"
constant RepoChartIndexYamlHigressIndex (line 57) | RepoChartIndexYamlHigressIndex = "higress"
constant YAMLSeparator (line 59) | YAMLSeparator = "\n---\n"
constant NotesFileNameSuffix (line 60) | NotesFileNameSuffix = ".txt"
function LoadValues (line 63) | func LoadValues(profileName string, chartsDir string) (string, error) {
function readProfiles (line 72) | func readProfiles(chartsDir string) (map[string]bool, error) {
function builtinProfileToFilename (line 91) | func builtinProfileToFilename(name string) string {
function stripPrefix (line 99) | func stripPrefix(path, prefix string) string {
function ListProfiles (line 106) | func ListProfiles(charts string) ([]string, error) {
type Renderer (line 121) | type Renderer interface
type RendererOptions (line 127) | type RendererOptions struct
type RendererOption (line 146) | type RendererOption
function WithName (line 148) | func WithName(name string) RendererOption {
function WithNamespace (line 154) | func WithNamespace(ns string) RendererOption {
function WithFS (line 160) | func WithFS(f fs.FS) RendererOption {
function WithDir (line 166) | func WithDir(dir string) RendererOption {
function WithVersion (line 172) | func WithVersion(version string) RendererOption {
function WithRepoURL (line 178) | func WithRepoURL(repo string) RendererOption {
function WithCapabilities (line 184) | func WithCapabilities(capabilities *chartutil.Capabilities) RendererOpti...
function WithRestConfig (line 190) | func WithRestConfig(config *rest.Config) RendererOption {
type LocalFileRenderer (line 197) | type LocalFileRenderer struct
method Init (line 215) | func (l *LocalFileRenderer) Init() error {
method RenderManifest (line 235) | func (l *LocalFileRenderer) RenderManifest(valsYaml string) (string, e...
method SetVersion (line 262) | func (l *LocalFileRenderer) SetVersion(version string) {
function NewLocalFileRenderer (line 203) | func NewLocalFileRenderer(opts ...RendererOption) (Renderer, error) {
type LocalChartRenderer (line 267) | type LocalChartRenderer struct
method Init (line 273) | func (lr *LocalChartRenderer) Init() error {
method RenderManifest (line 304) | func (lr *LocalChartRenderer) RenderManifest(valsYaml string) (string,...
method SetVersion (line 311) | func (lr *LocalChartRenderer) SetVersion(version string) {
function NewLocalChartRenderer (line 315) | func NewLocalChartRenderer(opts ...RendererOption) (Renderer, error) {
type RemoteRenderer (line 329) | type RemoteRenderer struct
method initChartPathOptions (line 335) | func (rr *RemoteRenderer) initChartPathOptions() *action.ChartPathOpti...
method Init (line 342) | func (rr *RemoteRenderer) Init() error {
method SetVersion (line 367) | func (rr *RemoteRenderer) SetVersion(version string) {
method RenderManifest (line 371) | func (rr *RemoteRenderer) RenderManifest(valsYaml string) (string, err...
function NewRemoteRenderer (line 378) | func NewRemoteRenderer(opts ...RendererOption) (Renderer, error) {
function verifyRendererOptions (line 389) | func verifyRendererOptions(opts *RendererOptions) error {
function getFileNames (line 406) | func getFileNames(f fs.FS, root string) ([]string, error) {
function verifyInstallable (line 423) | func verifyInstallable(cht *chart.Chart) error {
function renderManifest (line 431) | func renderManifest(valsYaml string, cht *chart.Chart, builtIn bool, opt...
function locateChart (line 502) | func locateChart(cpOpts *action.ChartPathOptions, name string, settings ...
function ParseLatestVersion (line 587) | func ParseLatestVersion(repoUrl string, version string, devel bool) (str...
function loadIndex (line 651) | func loadIndex(data []byte) (*repo.IndexFile, error) {
function jsonOrYamlUnmarshal (line 686) | func jsonOrYamlUnmarshal(b []byte, i interface{}) error {
FILE: hgctl/pkg/helm/tpath/tree.go
type PathContext (line 32) | type PathContext struct
method String (line 42) | func (nc *PathContext) String() string {
function GetPathContext (line 60) | func GetPathContext(root any, path util.Path, createMissing bool) (*Path...
function WritePathContext (line 65) | func WritePathContext(nc *PathContext, value any, merge bool) error {
function WriteNode (line 92) | func WriteNode(root any, path util.Path, value any) error {
function MergeNode (line 101) | func MergeNode(root any, path util.Path, value any) error {
function Find (line 112) | func Find(inputTree map[string]any, path util.Path) (any, bool, error) {
function Delete (line 121) | func Delete(root map[string]any, path util.Path) (bool, error) {
function getPathContext (line 131) | func getPathContext(nc *PathContext, fullPath, remainPath util.Path, cre...
function setPathContext (line 296) | func setPathContext(nc *PathContext, value any, merge bool) error {
function setValueContext (line 311) | func setValueContext(nc *PathContext, value any, merge bool) (bool, erro...
function mergeConditional (line 400) | func mergeConditional(newVal, originalVal any, merge bool) (any, error) {
function find (line 441) | func find(treeNode any, path util.Path) (any, bool) {
function stringsEqual (line 480) | func stringsEqual(a, b any) bool {
function matchesRegex (line 485) | func matchesRegex(pattern, str any) bool {
function isSliceOrPtrInterface (line 494) | func isSliceOrPtrInterface(v any) bool {
function isMapOrInterface (line 506) | func isMapOrInterface(v any) bool {
function tryToUnmarshalStringToYAML (line 516) | func tryToUnmarshalStringToYAML(s any) (any, bool) {
function getTreeRoot (line 542) | func getTreeRoot(m map[string]any) string {
FILE: hgctl/pkg/helm/tpath/tree_test.go
function TestWritePathContext (line 24) | func TestWritePathContext(t *testing.T) {
function TestWriteNode (line 367) | func TestWriteNode(t *testing.T) {
function TestMergeNode (line 595) | func TestMergeNode(t *testing.T) {
function errToString (line 676) | func errToString(err error) string {
function TestSecretVolumes (line 684) | func TestSecretVolumes(t *testing.T) {
function TestWriteEscapedPathContext (line 787) | func TestWriteEscapedPathContext(t *testing.T) {
FILE: hgctl/pkg/helm/tpath/util.go
function AddSpecRoot (line 24) | func AddSpecRoot(tree string) (string, error) {
function GetSpecSubtree (line 38) | func GetSpecSubtree(yml string) (string, error) {
function GetConfigSubtree (line 43) | func GetConfigSubtree(manifest, path string) (string, error) {
FILE: hgctl/pkg/helm/tpath/util_test.go
function TestAddSpecRoot (line 22) | func TestAddSpecRoot(t *testing.T) {
function TestGetConfigSubtree (line 65) | func TestGetConfigSubtree(t *testing.T) {
FILE: hgctl/pkg/install.go
constant setFlagHelpStr (line 30) | setFlagHelpStr = `Override an higress profile value, e.g. to choose a pr...
constant manifestsFlagHelpStr (line 33) | manifestsFlagHelpStr = `Specify a path to a directory of profiles
constant filenameFlagHelpStr (line 35) | filenameFlagHelpStr = "Path to file containing helm custom values"
constant outputHelpstr (line 36) | outputHelpstr = "Specify a file to write profile yaml"
constant profileNameK8s (line 38) | profileNameK8s = "k8s"
constant profileNameLocalK8s (line 39) | profileNameLocalK8s = "local-k8s"
constant profileNameLocalDocker (line 40) | profileNameLocalDocker = "local-docker"
type InstallArgs (line 43) | type InstallArgs struct
method String (line 59) | func (a *InstallArgs) String() string {
function addInstallFlags (line 68) | func addInstallFlags(cmd *cobra.Command, args *InstallArgs) {
function applyFlagAliases (line 76) | func applyFlagAliases(flags []string, manifestsPath string) []string {
function newInstallCmd (line 84) | func newInstallCmd() *cobra.Command {
function install (line 122) | func install(writer io.Writer, iArgs *InstallArgs) error {
function promptInstall (line 160) | func promptInstall(writer io.Writer, profileName string) bool {
function promptProfileName (line 176) | func promptProfileName(writer io.Writer) string {
function installManifests (line 197) | func installManifests(profile *helm.Profile, writer io.Writer, devel boo...
FILE: hgctl/pkg/installer/component.go
type ComponentName (line 24) | type ComponentName
type Component (line 31) | type Component interface
type ComponentOptions (line 43) | type ComponentOptions struct
type ComponentOption (line 59) | type ComponentOption
function WithComponentNamespace (line 61) | func WithComponentNamespace(namespace string) ComponentOption {
function WithComponentChartPath (line 67) | func WithComponentChartPath(path string) ComponentOption {
function WithComponentChartName (line 73) | func WithComponentChartName(chartName string) ComponentOption {
function WithComponentRepoURL (line 79) | func WithComponentRepoURL(url string) ComponentOption {
function WithComponentVersion (line 85) | func WithComponentVersion(version string) ComponentOption {
function WithComponentCapabilities (line 91) | func WithComponentCapabilities(capabilities *chartutil.Capabilities) Com...
function WithQuiet (line 97) | func WithQuiet() ComponentOption {
function WithDevel (line 103) | func WithDevel(devel bool) ComponentOption {
function renderComponentManifest (line 109) | func renderComponentManifest(spec any, renderer helm.Renderer, addOn boo...
FILE: hgctl/pkg/installer/gateway_api.go
constant GatewayAPI (line 29) | GatewayAPI ComponentName = "gatewayAPI"
type GatewayAPIComponent (line 32) | type GatewayAPIComponent struct
method ComponentName (line 77) | func (i *GatewayAPIComponent) ComponentName() ComponentName {
method Namespace (line 81) | func (i *GatewayAPIComponent) Namespace() string {
method Enabled (line 85) | func (i *GatewayAPIComponent) Enabled() bool {
method Run (line 89) | func (i *GatewayAPIComponent) Run() error {
method RenderManifest (line 100) | func (i *GatewayAPIComponent) RenderManifest() (string, error) {
function NewGatewayAPIComponent (line 41) | func NewGatewayAPIComponent(kubeCli kubernetes.CLIClient, profile *helm....
FILE: hgctl/pkg/installer/helm_agent.go
type HelmRelease (line 28) | type HelmRelease struct
type HelmAgent (line 38) | type HelmAgent struct
method IsHigressInstalled (line 54) | func (h *HelmAgent) IsHigressInstalled() (bool, error) {
function NewHelmAgent (line 45) | func NewHelmAgent(profile *helm.Profile, writer io.Writer, quiet bool) *...
FILE: hgctl/pkg/installer/higress.go
constant Higress (line 27) | Higress ComponentName = "higress"
type HigressComponent (line 30) | type HigressComponent struct
method ComponentName (line 39) | func (h *HigressComponent) ComponentName() ComponentName {
method Namespace (line 43) | func (h *HigressComponent) Namespace() string {
method Enabled (line 47) | func (h *HigressComponent) Enabled() bool {
method Run (line 51) | func (h *HigressComponent) Run() error {
method RenderManifest (line 78) | func (h *HigressComponent) RenderManifest() (string, error) {
function NewHigressComponent (line 96) | func NewHigressComponent(kubeCli kubernetes.CLIClient, profile *helm.Pro...
FILE: hgctl/pkg/installer/installer.go
type InstallerMode (line 31) | type InstallerMode
constant HgctlHomeDirPath (line 34) | HgctlHomeDirPath = ".hgctl"
constant StandaloneInstalledPath (line 35) | StandaloneInstalledPath = "higress-standalone"
constant ProfileInstalledPath (line 36) | ProfileInstalledPath = "profiles"
constant InstalledYamlFileName (line 37) | InstalledYamlFileName = "install.yaml"
constant DefaultGatewayAPINamespace (line 38) | DefaultGatewayAPINamespace = "gateway-system"
constant DefaultIstioNamespace (line 39) | DefaultIstioNamespace = "istio-system"
constant InstallInstallerMode (line 43) | InstallInstallerMode InstallerMode = iota
constant UpgradeInstallerMode (line 44) | UpgradeInstallerMode
constant UninstallInstallerMode (line 45) | UninstallInstallerMode
type Installer (line 48) | type Installer interface
function NewInstaller (line 54) | func NewInstaller(profile *helm.Profile, writer io.Writer, quiet bool, d...
function GetHomeDir (line 71) | func GetHomeDir() (string, error) {
function GetHgctlPath (line 80) | func GetHgctlPath() (string, error) {
function GetDefaultInstallPackagePath (line 96) | func GetDefaultInstallPackagePath() (string, error) {
function GetProfileInstalledPath (line 112) | func GetProfileInstalledPath() (string, error) {
function GetInstalledYamlPath (line 128) | func GetInstalledYamlPath() (string, bool) {
FILE: hgctl/pkg/installer/installer_docker.go
type DockerInstaller (line 25) | type DockerInstaller struct
method Install (line 33) | func (d *DockerInstaller) Install() error {
method UnInstall (line 50) | func (d *DockerInstaller) UnInstall() error {
method Upgrade (line 67) | func (d *DockerInstaller) Upgrade() error {
function NewDockerInstaller (line 78) | func NewDockerInstaller(profile *helm.Profile, writer io.Writer, quiet b...
FILE: hgctl/pkg/installer/installer_k8s.go
type K8sInstaller (line 31) | type K8sInstaller struct
method Install (line 40) | func (o *K8sInstaller) Install() error {
method UnInstall (line 79) | func (o *K8sInstaller) UnInstall() error {
method Upgrade (line 109) | func (o *K8sInstaller) Upgrade() error {
method Run (line 114) | func (o *K8sInstaller) Run() error {
method RenderManifests (line 128) | func (o *K8sInstaller) RenderManifests() (map[ComponentName]string, er...
method GenerateManifests (line 147) | func (o *K8sInstaller) GenerateManifests(manifestMap map[ComponentName...
method ApplyManifests (line 158) | func (o *K8sInstaller) ApplyManifests(manifestMap map[ComponentName]st...
method applyManifest (line 171) | func (o *K8sInstaller) applyManifest(manifest string, ns string) error {
method DeleteManifests (line 198) | func (o *K8sInstaller) DeleteManifests(manifestMap map[ComponentName]s...
method WriteManifests (line 212) | func (o *K8sInstaller) WriteManifests(manifestMap map[ComponentName]st...
method deleteManifest (line 225) | func (o *K8sInstaller) deleteManifest(manifest string, ns string) error {
method isNamespacedObject (line 249) | func (o *K8sInstaller) isNamespacedObject(obj *object.K8sObject) bool {
function NewK8sInstaller (line 257) | func NewK8sInstaller(profile *helm.Profile, cli kubernetes.CLIClient, wr...
FILE: hgctl/pkg/installer/istio.go
constant Istio (line 28) | Istio ComponentName = "istio"
type IstioCRDComponent (line 31) | type IstioCRDComponent struct
method ComponentName (line 89) | func (i *IstioCRDComponent) ComponentName() ComponentName {
method Namespace (line 93) | func (i *IstioCRDComponent) Namespace() string {
method Enabled (line 97) | func (i *IstioCRDComponent) Enabled() bool {
method Run (line 101) | func (i *IstioCRDComponent) Run() error {
method RenderManifest (line 112) | func (i *IstioCRDComponent) RenderManifest() (string, error) {
function NewIstioCRDComponent (line 40) | func NewIstioCRDComponent(kubeCli kubernetes.CLIClient, profile *helm.Pr...
FILE: hgctl/pkg/installer/profile_store.go
constant ProfileConfigmapKey (line 34) | ProfileConfigmapKey = "profile"
constant ProfileConfigmapName (line 35) | ProfileConfigmapName = "higress-profile"
constant ProfileConfigmapAnnotation (line 36) | ProfileConfigmapAnnotation = "higress.io/install"
constant ProfileFilePrefix (line 37) | ProfileFilePrefix = "install"
type ProfileContext (line 40) | type ProfileContext struct
type ProfileStore (line 49) | type ProfileStore interface
type FileDirProfileStore (line 55) | type FileDirProfileStore struct
method Save (line 59) | func (f *FileDirProfileStore) Save(profile *helm.Profile) (string, err...
method List (line 74) | func (f *FileDirProfileStore) List() ([]*ProfileContext, error) {
method Delete (line 109) | func (f *FileDirProfileStore) Delete(profile *helm.Profile) (string, e...
function NewFileDirProfileStore (line 124) | func NewFileDirProfileStore(profilesPath string) (ProfileStore, error) {
type ConfigmapProfileStore (line 137) | type ConfigmapProfileStore struct
method Save (line 141) | func (c *ConfigmapProfileStore) Save(profile *helm.Profile) (string, e...
method List (line 165) | func (c *ConfigmapProfileStore) List() ([]*ProfileContext, error) {
method Delete (line 191) | func (c *ConfigmapProfileStore) Delete(profile *helm.Profile) (string,...
method listConfigmaps (line 205) | func (c *ConfigmapProfileStore) listConfigmaps(name string, namespace ...
method applyConfigmap (line 219) | func (c *ConfigmapProfileStore) applyConfigmap(configmap *corev1.Confi...
method deleteConfigmap (line 232) | func (c *ConfigmapProfileStore) deleteConfigmap(configmap *corev1.Conf...
function NewConfigmapProfileStore (line 242) | func NewConfigmapProfileStore(kubeCli kubernetes.CLIClient) (ProfileStor...
FILE: hgctl/pkg/installer/server_info.go
type ServerInfo (line 25) | type ServerInfo struct
method GetCapabilities (line 29) | func (c *ServerInfo) GetCapabilities() (*chartutil.Capabilities, error) {
function NewServerInfo (line 61) | func NewServerInfo(kubCli kubernetes.CLIClient) (*ServerInfo, error) {
FILE: hgctl/pkg/installer/standalone.go
constant defaultHttpRequestTimeout (line 30) | defaultHttpRequestTimeout = 15 * time.Second
constant defaultHttpMaxTry (line 31) | defaultHttpMaxTry = 3
constant defaultHttpBufferSize (line 32) | defaultHttpBufferSize = 1024 * 1024 * 2
type StandaloneComponent (line 35) | type StandaloneComponent struct
method Install (line 44) | func (s *StandaloneComponent) Install() error {
method UnInstall (line 68) | func (s *StandaloneComponent) UnInstall() error {
method Upgrade (line 75) | func (s *StandaloneComponent) Upgrade() error {
function NewStandaloneComponent (line 99) | func NewStandaloneComponent(profile *helm.Profile, writer io.Writer, opt...
function prepareProfile (line 120) | func prepareProfile(profile *helm.Profile) error {
FILE: hgctl/pkg/installer/standalone_agent.go
type RunSudoState (line 31) | type RunSudoState
constant NoSudo (line 34) | NoSudo RunSudoState = "NoSudo"
constant SudoWithoutPassword (line 35) | SudoWithoutPassword RunSudoState = "SudoWithoutPassword"
constant SudoWithPassword (line 36) | SudoWithPassword RunSudoState = "SudoWithPassword"
type Agent (line 39) | type Agent struct
method profileArgs (line 72) | func (a *Agent) profileArgs() []string {
method run (line 88) | func (a *Agent) run(binaryName string, args []string, autoSudo bool) e...
method checkSudoPermission (line 124) | func (a *Agent) checkSudoPermission() error {
method Install (line 200) | func (a *Agent) Install() error {
method Uninstall (line 222) | func (a *Agent) Uninstall() error {
method Upgrade (line 241) | func (a *Agent) Upgrade() error {
method Version (line 289) | func (a *Agent) Version() (string, error) {
method promptSudo (line 298) | func (a *Agent) promptSudo() bool {
method promptRestart (line 314) | func (a *Agent) promptRestart() bool {
method Startup (line 330) | func (a *Agent) Startup() error {
method Shutdown (line 337) | func (a *Agent) Shutdown() error {
method Reset (line 344) | func (a *Agent) Reset() error {
method hasConfigured (line 351) | func (a *Agent) hasConfigured() bool {
function NewAgent (line 54) | func NewAgent(profile *helm.Profile, writer io.Writer, quiet bool) *Agent {
FILE: hgctl/pkg/kubernetes/client.go
type CLIClient (line 39) | type CLIClient interface
type client (line 67) | type client struct
method RESTConfig (line 107) | func (c *client) RESTConfig() *rest.Config {
method PodsForSelector (line 115) | func (c *client) PodsForSelector(namespace string, podSelectors ...str...
method Pod (line 121) | func (c *client) Pod(namespacedName types.NamespacedName) (*corev1.Pod...
method PodExec (line 125) | func (c *client) PodExec(namespacedName types.NamespacedName, containe...
method DeleteObject (line 172) | func (c *client) DeleteObject(obj *unstructured.Unstructured) error {
method ApplyObject (line 183) | func (c *client) ApplyObject(obj *unstructured.Unstructured) error {
method CreateNamespace (line 229) | func (c *client) CreateNamespace(namespace string) error {
method KubernetesInterface (line 254) | func (c *client) KubernetesInterface() kubernetes.Interface {
function NewCLIClient (line 74) | func NewCLIClient(clientConfig clientcmd.ClientConfig) (CLIClient, error) {
function newClientInternal (line 78) | func newClientInternal(clientConfig clientcmd.ClientConfig) (*client, er...
FILE: hgctl/pkg/kubernetes/common.go
function applyOverlay (line 33) | func applyOverlay(current, overlay *unstructured.Unstructured) error {
function createPortMap (line 66) | func createPortMap(current *unstructured.Unstructured) map[string]uint32 {
function savePersistentVolumeClaim (line 79) | func savePersistentVolumeClaim(current, overlay *unstructured.Unstructur...
function saveNodePorts (line 98) | func saveNodePorts(current, overlay *unstructured.Unstructured) {
function saveClusterIP (line 121) | func saveClusterIP(current, overlay *unstructured.Unstructured) error {
function setRestDefaults (line 135) | func setRestDefaults(config *rest.Config) *rest.Config {
FILE: hgctl/pkg/kubernetes/port-forwarder.go
function LocalAvailablePort (line 31) | func LocalAvailablePort(localAddress string) (int, error) {
type PortForwarder (line 40) | type PortForwarder interface
type localForwarder (line 54) | type localForwarder struct
method Start (line 86) | func (f *localForwarder) Start() error {
method buildKubernetesPortForwarder (line 121) | func (f *localForwarder) buildKubernetesPortForwarder(readyCh chan str...
method Stop (line 150) | func (f *localForwarder) Stop() {
method Address (line 154) | func (f *localForwarder) Address() string {
method WaitForStop (line 158) | func (f *localForwarder) WaitForStop() {
function NewLocalPortForwarder (line 65) | func NewLocalPortForwarder(client CLIClient, namespacedName types.Namesp...
FILE: hgctl/pkg/kubernetes/wasmplugin.go
constant DefaultHigressNamespace (line 30) | DefaultHigressNamespace = "higress-system"
constant HigressExtGroup (line 31) | HigressExtGroup = "extensions.higress.io"
constant HigressExtVersion (line 32) | HigressExtVersion = "v1alpha1"
constant HigressExtAPIVersion (line 33) | HigressExtAPIVersion = HigressExtGroup + "/" + HigressExtVersion
constant WasmPluginKind (line 35) | WasmPluginKind = "WasmPlugin"
constant WasmPluginResource (line 36) | WasmPluginResource = "wasmplugins"
function AddHigressNamespaceFlags (line 45) | func AddHigressNamespaceFlags(flags *pflag.FlagSet) {
type WasmPluginClient (line 50) | type WasmPluginClient struct
method Get (line 58) | func (c WasmPluginClient) Get(ctx context.Context, name string) (*unst...
method List (line 62) | func (c WasmPluginClient) List(ctx context.Context) (*unstructured.Uns...
method Create (line 66) | func (c WasmPluginClient) Create(ctx context.Context, obj *unstructure...
method Delete (line 70) | func (c WasmPluginClient) Delete(ctx context.Context, name string) (*u...
method Update (line 74) | func (c WasmPluginClient) Update(ctx context.Context, obj *unstructure...
function NewWasmPluginClient (line 54) | func NewWasmPluginClient(dynClient *DynamicClient) *WasmPluginClient {
type DynamicClient (line 79) | type DynamicClient struct
method Get (line 103) | func (c DynamicClient) Get(ctx context.Context, gvr schema.GroupVersio...
method List (line 107) | func (c DynamicClient) List(ctx context.Context, gvr schema.GroupVersi...
method Create (line 111) | func (c DynamicClient) Create(ctx context.Context, gvr schema.GroupVer...
method Delete (line 115) | func (c DynamicClient) Delete(ctx context.Context, gvr schema.GroupVer...
method Update (line 127) | func (c DynamicClient) Update(ctx context.Context, gvr schema.GroupVer...
function NewDynamicClient (line 84) | func NewDynamicClient(clientConfig clientcmd.ClientConfig) (*DynamicClie...
FILE: hgctl/pkg/manifest.go
type ManifestArgs (line 29) | type ManifestArgs struct
method String (line 44) | func (a *ManifestArgs) String() string {
function newManifestCmd (line 54) | func newManifestCmd() *cobra.Command {
function addManifestFlags (line 71) | func addManifestFlags(cmd *cobra.Command, args *ManifestArgs) {
function newManifestGenerateCmd (line 79) | func newManifestGenerateCmd(iArgs *ManifestArgs) *cobra.Command {
function generate (line 100) | func generate(writer io.Writer, iArgs *ManifestArgs) error {
function genManifests (line 126) | func genManifests(profile *helm.Profile, writer io.Writer, devel bool) e...
FILE: hgctl/pkg/manifests/manifest.go
function BuiltinOrDir (line 35) | func BuiltinOrDir(dir string) fs.FS {
function ExtractEmbedFiles (line 43) | func ExtractEmbedFiles(fsys fs.FS, srcDir, targetDir string) error {
FILE: hgctl/pkg/plugin/build/build.go
constant DefaultBuilderRepository (line 43) | DefaultBuilderRepository = "higress-registry.cn-hangzhou.cr.aliyuncs.com...
constant DefaultBuilderGo (line 44) | DefaultBuilderGo = "1.19"
constant DefaultBuilderTinyGo (line 45) | DefaultBuilderTinyGo = "0.28.1"
constant DefaultBuilderOras (line 46) | DefaultBuilderOras = "1.0.0"
constant MediaTypeSpec (line 48) | MediaTypeSpec = "application/vnd.module.wasm.spec.v1+yaml"
constant MediaTypeREADME (line 49) | MediaTypeREADME = "application/vnd.module.wasm.doc.v1+markdown"
constant MediaTypeREADME_ZH (line 50) | MediaTypeREADME_ZH = "application/vnd.module.wasm.doc.v1.zh+markdown"
constant MediaTypeREADME_EN (line 51) | MediaTypeREADME_EN = "application/vnd.module.wasm.doc.v1.en+markdown"
constant MediaTypeIcon (line 52) | MediaTypeIcon = "application/vnd.module.wasm.icon.v1+png"
constant MediaTypePlugin (line 53) | MediaTypePlugin = "application/vnd.oci.image.layer.v1.tar+gzip"
constant HostTempDirPattern (line 55) | HostTempDirPattern = "higress-wasm-go-build-*"
constant HostDockerEntryPattern (line 56) | HostDockerEntryPattern = "higress-wasm-go-build-docker-entrypoint-*.sh"
constant ContainerWorkDir (line 58) | ContainerWorkDir = "/workspace"
constant ContainerTempDir (line 59) | ContainerTempDir = "/higress_temp"
constant ContainerOutDir (line 60) | ContainerOutDir = "/output"
constant ContainerDockerAuth (line 61) | ContainerDockerAuth = "/root/.docker/config.json"
constant ContainerEntryFile (line 62) | ContainerEntryFile = "docker-entrypoint.sh"
constant ContainerEntryFilePath (line 63) | ContainerEntryFilePath = "/" + ContainerEntryFile
type Builder (line 66) | type Builder struct
method bindFlags (line 132) | func (b *Builder) bindFlags(v *viper.Viper, flags *pflag.FlagSet) {
method Build (line 181) | func (b *Builder) Build() (err error) {
method doBuild (line 223) | func (b *Builder) doBuild() (err error) {
method generateMetadata (line 265) | func (b *Builder) generateMetadata() error {
method imagePull (line 308) | func (b *Builder) imagePull(ctx context.Context) error {
method addContainerConfByOutType (line 325) | func (b *Builder) addContainerConfByOutType() error {
method containerCreate (line 346) | func (b *Builder) containerCreate(ctx context.Context) error {
method containerStart (line 361) | func (b *Builder) containerStart(ctx context.Context) error {
method filesHandler (line 402) | func (b *Builder) filesHandler() error {
method imageHandler (line 433) | func (b *Builder) imageHandler() error {
method config (line 483) | func (b *Builder) config(f ConfigFunc) (err error) {
method parseOptions (line 645) | func (b *Builder) parseOptions(v *viper.Viper, cmd *cobra.Command) err...
method finish (line 657) | func (b *Builder) finish() {
method waitForFinished (line 665) | func (b *Builder) waitForFinished() {
method interrupt (line 669) | func (b *Builder) interrupt() {
method isInterrupted (line 677) | func (b *Builder) isInterrupted() bool {
method WithManualClean (line 691) | func (b *Builder) WithManualClean() {
method WithWriter (line 695) | func (b *Builder) WithWriter(w io.Writer) {
method CleanupForError (line 700) | func (b *Builder) CleanupForError() {
method Cleanup (line 706) | func (b *Builder) Cleanup() {
method removeOutputDest (line 713) | func (b *Builder) removeOutputDest() {
method removeTempDir (line 720) | func (b *Builder) removeTempDir() {
method removeDockerEntrypoint (line 727) | func (b *Builder) removeDockerEntrypoint() {
method removeBuilderContainer (line 734) | func (b *Builder) removeBuilderContainer() {
method closeDockerCli (line 745) | func (b *Builder) closeDockerCli() {
method builderImageRef (line 752) | func (b *Builder) builderImageRef() string {
method SpecYAMLPath (line 756) | func (b *Builder) SpecYAMLPath() string {
method TempDir (line 760) | func (b *Builder) TempDir() string {
method String (line 764) | func (b *Builder) String() string {
function NewBuilder (line 89) | func NewBuilder(f ConfigFunc) (*Builder, error) {
function NewCommand (line 98) | func NewCommand() *cobra.Command {
type ConfigFunc (line 481) | type ConfigFunc
FILE: hgctl/pkg/plugin/build/signal.go
function signalNotify (line 25) | func signalNotify(b *Builder) {
FILE: hgctl/pkg/plugin/build/signal_windows.go
function signalNotify (line 25) | func signalNotify(b *Builder) {
FILE: hgctl/pkg/plugin/build/templates.go
constant filesDockerEntrypoint (line 25) | filesDockerEntrypoint = `#!/bin/bash
constant imageDockerEntrypoint (line 37) | imageDockerEntrypoint = `#!/bin/bash
type FilesTmplFields (line 62) | type FilesTmplFields struct
type ImageTmplFields (line 70) | type ImageTmplFields struct
function genFilesDockerEntrypoint (line 81) | func genFilesDockerEntrypoint(ft *FilesTmplFields, target string) error {
function genImageDockerEntrypoint (line 95) | func genImageDockerEntrypoint(it *ImageTmplFields, target string) error {
constant readme_zh_CN (line 110) | readme_zh_CN = `> 该插件用法文件根据源代码自动生成,请根据需求自行修改!
constant readme_en_US (line 131) | readme_en_US = `> THIS PLUGIN USAGE FILE IS AUTOMATICALLY GENERATED BASE...
function genMarkdownUsage (line 153) | func genMarkdownUsage(u *types.WasmUsage, dir string, suffix bool) error {
function i18n2MD (line 167) | func i18n2MD(i18n types.I18nType) string {
function i18n2MDTitle (line 178) | func i18n2MDTitle(i18n types.I18nType, dir string, suffix bool) string {
FILE: hgctl/pkg/plugin/config/config.go
function NewCommand (line 19) | func NewCommand() *cobra.Command {
FILE: hgctl/pkg/plugin/config/create.go
function newCreateCommand (line 29) | func newCreateCommand() *cobra.Command {
function create (line 47) | func create(w io.Writer, target string) error {
FILE: hgctl/pkg/plugin/config/edit.go
function newEditCommand (line 37) | func newEditCommand() *cobra.Command {
function edit (line 60) | func edit(w io.Writer, name string) error {
function editorEnvs (line 120) | func editorEnvs() []string {
function keepSameMeta (line 128) | func keepSameMeta(edited, original *unstructured.Unstructured) bool {
FILE: hgctl/pkg/plugin/config/templates.go
constant pluginConfYAML (line 31) | pluginConfYAML = `# File generated by hgctl. Modify as required.
type PluginConf (line 57) | type PluginConf struct
method String (line 71) | func (pc *PluginConf) String() string {
method withDefaultValue (line 134) | func (pc *PluginConf) withDefaultValue() {
function GenPluginConfYAML (line 80) | func GenPluginConfYAML(p *PluginConf, dir string) error {
function ExtractPluginConfFrom (line 97) | func ExtractPluginConfFrom(spec *types.WasmPluginMeta, config, url strin...
FILE: hgctl/pkg/plugin/init/init.go
function NewCommand (line 32) | func NewCommand() *cobra.Command {
function runInit (line 50) | func runInit(w io.Writer, target string) (err error) {
FILE: hgctl/pkg/plugin/init/templates.go
constant goMain (line 27) | goMain = `// File generated by hgctl. Modify as required.
constant goMod (line 90) | goMod = `// File generated by hgctl. Modify as required.
constant gitIgnore (line 103) | gitIgnore = `# File generated by hgctl. Modify as required.
function genGoMain (line 125) | func genGoMain(ans *answer, dir string) error {
function genGoMod (line 140) | func genGoMod(ans *answer, dir string) error {
function genGitIgnore (line 155) | func genGitIgnore(dir string) error {
type answer (line 171) | type answer struct
FILE: hgctl/pkg/plugin/install/asker.go
constant askInterrupted (line 32) | askInterrupted = "X Interrupted."
constant invalidSyntax (line 33) | invalidSyntax = "X Invalid syntax."
constant failedToValidate (line 34) | failedToValidate = "X Failed to validate: not satisfied with schema."
constant addConfSuccessful (line 35) | addConfSuccessful = "√ Successful to add configuration."
type Asker (line 40) | type Asker interface
type WasmPluginSpecConfAsker (line 44) | type WasmPluginSpecConfAsker struct
method Ask (line 63) | func (p *WasmPluginSpecConfAsker) Ask() error {
function NewWasmPluginSpecConfAsker (line 54) | func NewWasmPluginSpecConfAsker(ingAsk *IngressAsker, domAsk *DomainAske...
type IngressAsker (line 179) | type IngressAsker struct
method Ask (line 199) | func (i *IngressAsker) Ask() error {
function NewIngressAsker (line 190) | func NewIngressAsker(structName string, schema *types.JSONSchemaProps, v...
type DomainAsker (line 246) | type DomainAsker struct
method Ask (line 266) | func (d *DomainAsker) Ask() error {
function NewDomainAsker (line 257) | func NewDomainAsker(structName string, schema *types.JSONSchemaProps, vl...
type GlobalConfAsker (line 313) | type GlobalConfAsker struct
method Ask (line 333) | func (g *GlobalConfAsker) Ask() error {
function NewGlobalConfAsker (line 324) | func NewGlobalConfAsker(structName string, schema *types.JSONSchemaProps...
type continueAsker (line 351) | type continueAsker struct
method Ask (line 361) | func (c *continueAsker) Ask() error {
function newContinueAsker (line 357) | func newContinueAsker(printer *utils.YesOrNoPrinter) *continueAsker {
type rewriteAsker (line 375) | type rewriteAsker struct
method Ask (line 385) | func (r *rewriteAsker) Ask() error {
function newRewriteAsker (line 381) | func newRewriteAsker(printer *utils.YesOrNoPrinter) *rewriteAsker {
type scopeAsker (line 399) | type scopeAsker struct
method Ask (line 409) | func (s *scopeAsker) Ask() error {
function newScopeAsker (line 405) | func newScopeAsker(printer *utils.YesOrNoPrinter) *scopeAsker {
type ruleAsker (line 429) | type ruleAsker struct
method Ask (line 439) | func (r *ruleAsker) Ask() error {
function newRuleAsker (line 435) | func newRuleAsker(printer *utils.YesOrNoPrinter) *ruleAsker {
type WasmPluginSpecConf (line 457) | type WasmPluginSpecConf struct
method String (line 468) | func (p *WasmPluginSpecConf) String() string {
function NewPluginSpecConf (line 462) | func NewPluginSpecConf() *WasmPluginSpecConf {
type MatchRule (line 477) | type MatchRule interface
type IngressMatchRule (line 481) | type IngressMatchRule struct
method String (line 486) | func (i IngressMatchRule) String() string {
function decodeIngressMatchRule (line 491) | func decodeIngressMatchRule(obj map[string]interface{}) (*IngressMatchRu...
type DomainMatchRule (line 500) | type DomainMatchRule struct
method String (line 505) | func (d DomainMatchRule) String() string {
function decodeDomainMatchRule (line 510) | func decodeDomainMatchRule(obj map[string]interface{}) (*DomainMatchRule...
type Rule (line 519) | type Rule
constant ruleIngress (line 522) | ruleIngress Rule = "Ingress"
constant ruleDomain (line 523) | ruleDomain Rule = "Domain"
function recursivePrompt (line 526) | func recursivePrompt(structName string, schema *types.JSONSchemaProps, s...
function doPrompt (line 532) | func doPrompt(fieldName string, parent, schema *types.JSONSchemaProps, o...
function matchesScope (line 669) | func matchesScope(oriScope, selScope, scope types.Scope) bool {
function fieldTips (line 675) | func fieldTips(fieldName string, parent, schema *types.JSONSchemaProps, ...
function isRequired (line 689) | func isRequired(name string, required []string) bool {
function validate (line 700) | func validate(schema *jsonschema.Schema, v interface{}) (bool, error) {
function convertValidationError (line 708) | func convertValidationError(ve *jsonschema.ValidationError) error {
function doConvertValidationError (line 734) | func doConvertValidationError(de []jsonschema.Detailed, errs []error) []...
FILE: hgctl/pkg/plugin/install/install.go
type installer (line 45) | type installer struct
method config (line 111) | func (ins *installer) config(v *viper.Viper, cmd *cobra.Command) error {
method install (line 131) | func (ins *installer) install(flags *pflag.FlagSet) (err error) {
method yamlHandler (line 142) | func (ins *installer) yamlHandler() error {
method goHandler (line 146) | func (ins *installer) goHandler() error {
method doInstall (line 228) | func (ins *installer) doInstall(validate bool) error {
method validateWasmPluginConfig (line 299) | func (ins *installer) validateWasmPluginConfig(wps map[string]interfac...
method String (line 377) | func (ins *installer) String() string {
function NewCommand (line 55) | func NewCommand() *cobra.Command {
function isValidAPIVersion (line 287) | func isValidAPIVersion(obj *unstructured.Unstructured) bool {
function isValidKind (line 291) | func isValidKind(obj *unstructured.Unstructured) bool {
function isValidNamespace (line 295) | func isValidNamespace(obj *unstructured.Unstructured) bool {
function buildSchemaValidator (line 351) | func buildSchemaValidator(spec *types.WasmPluginMeta) (*jsonschema.Schem...
FILE: hgctl/pkg/plugin/ls/ls.go
function NewCommand (line 33) | func NewCommand() *cobra.Command {
function runLs (line 51) | func runLs(w io.Writer) error {
function getAge (line 76) | func getAge(now time.Time, create time.Time) string {
FILE: hgctl/pkg/plugin/option/option.go
type Option (line 25) | type Option struct
type BuildOptions (line 32) | type BuildOptions struct
type TestOptions (line 42) | type TestOptions struct
type InstallOptions (line 50) | type InstallOptions struct
type BuilderVersion (line 58) | type BuilderVersion struct
type Output (line 64) | type Output struct
function ParseOptions (line 70) | func ParseOptions(optionFile string, v *viper.Viper, flags *pflag.FlagSe...
function AddOptionFileFlag (line 93) | func AddOptionFileFlag(optionFile *string, flags *pflag.FlagSet) {
FILE: hgctl/pkg/plugin/option/template.go
constant optionYAML (line 22) | optionYAML = `# File generated by hgctl. Modify as required.
function GenOptionYAML (line 76) | func GenOptionYAML(dir string) error {
FILE: hgctl/pkg/plugin/plugin.go
function NewCommand (line 29) | func NewCommand() *cobra.Command {
FILE: hgctl/pkg/plugin/test/clean.go
type cleaner (line 33) | type cleaner struct
method config (line 73) | func (c *cleaner) config(v *viper.Viper, cmd *cobra.Command) error {
method clean (line 85) | func (c *cleaner) clean() error {
function newCleanCommand (line 40) | func newCleanCommand() *cobra.Command {
FILE: hgctl/pkg/plugin/test/create.go
type creator (line 36) | type creator struct
method config (line 83) | func (c *creator) config(v *viper.Viper, cmd *cobra.Command) error {
method create (line 95) | func (c *creator) create() (err error) {
method genTestConfFiles (line 160) | func (c *creator) genTestConfFiles(fields testTmplFields) (err error) {
function newCreateCommand (line 43) | func newCreateCommand() *cobra.Command {
type testTmplFields (line 154) | type testTmplFields struct
FILE: hgctl/pkg/plugin/test/ls.go
function newLsCommand (line 30) | func newLsCommand() *cobra.Command {
function runLs (line 44) | func runLs(w io.Writer) error {
FILE: hgctl/pkg/plugin/test/start.go
type starter (line 32) | type starter struct
method config (line 85) | func (s *starter) config(v *viper.Viper, cmd *cobra.Command) error {
method start (line 97) | func (s *starter) start() error {
function newStartCommand (line 39) | func newStartCommand() *cobra.Command {
FILE: hgctl/pkg/plugin/test/stop.go
type stopper (line 31) | type stopper struct
method config (line 70) | func (s *stopper) config(v *viper.Viper, cmd *cobra.Command) error {
method stop (line 82) | func (s *stopper) stop() error {
function newStopCommand (line 38) | func newStopCommand() *cobra.Command {
FILE: hgctl/pkg/plugin/test/templates.go
constant dockerComposeYAML (line 24) | dockerComposeYAML = `# File generated by hgctl. Modify as required.
constant envoyYAML (line 52) | envoyYAML = `# File generated by hgctl. Modify as required.
type DockerCompose (line 138) | type DockerCompose struct
type Envoy (line 143) | type Envoy struct
function genDockerComposeYAML (line 147) | func genDockerComposeYAML(d *DockerCompose, dir string) error {
function genEnvoyYAML (line 162) | func genEnvoyYAML(e *Envoy, dir string) error {
FILE: hgctl/pkg/plugin/test/test.go
function NewCommand (line 21) | func NewCommand() *cobra.Command {
FILE: hgctl/pkg/plugin/types/annotation.go
type Annotation (line 24) | type Annotation struct
type AnnotationType (line 30) | type AnnotationType
constant ACategory (line 34) | ACategory AnnotationType = iota
constant AName (line 35) | AName
constant ATitle (line 36) | ATitle
constant ADescription (line 37) | ADescription
constant AIconUrl (line 38) | AIconUrl
constant AVersion (line 39) | AVersion
constant AContactName (line 40) | AContactName
constant AContactUrl (line 41) | AContactUrl
constant AContactEmail (line 42) | AContactEmail
constant APhase (line 45) | APhase
constant APriority (line 46) | APriority
constant AScope (line 49) | AScope
constant AExample (line 50) | AExample
constant AEnd (line 51) | AEnd
constant AUnknown (line 53) | AUnknown
function str2AnnotationType (line 56) | func str2AnnotationType(typ string) AnnotationType {
function GetAnnotations (line 92) | func GetAnnotations(comment string) []Annotation {
function getAnnotationFrom (line 118) | func getAnnotationFrom(c string) (Annotation, error) {
FILE: hgctl/pkg/plugin/types/marshal.go
method MarshalJSON (line 25) | func (s JSON) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 37) | func (s *JSON) UnmarshalJSON(data []byte) error {
method MarshalYAML (line 44) | func (s JSON) MarshalYAML() (interface{}, error) {
method MarshalJSON (line 56) | func (s JSONSchemaPropsOrArray) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 63) | func (s *JSONSchemaPropsOrArray) UnmarshalJSON(data []byte) error {
method MarshalYAML (line 85) | func (s JSONSchemaPropsOrArray) MarshalYAML() (interface{}, error) {
method MarshalJSON (line 92) | func (s JSONSchemaPropsOrBool) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 103) | func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error {
method MarshalYAML (line 125) | func (s JSONSchemaPropsOrBool) MarshalYAML() (interface{}, error) {
method MarshalJSON (line 136) | func (s JSONSchemaPropsOrStringArray) MarshalJSON() ([]byte, error) {
method UnmarshalJSON (line 146) | func (s *JSONSchemaPropsOrStringArray) UnmarshalJSON(data []byte) error {
method MarshalYAML (line 168) | func (s JSONSchemaPropsOrStringArray) MarshalYAML() (interface{}, error) {
FILE: hgctl/pkg/plugin/types/meta.go
type WasmPluginMeta (line 30) | type WasmPluginMeta struct
method setByConfigModel (line 85) | func (meta *WasmPluginMeta) setByConfigModel(model *Model) {
method setModelAnnotations (line 126) | func (meta *WasmPluginMeta) setModelAnnotations(comment string) {
method GetConfigExample (line 280) | func (meta *WasmPluginMeta) GetConfigExample() string {
method getLanguageUnionOrderMap (line 290) | func (meta *WasmPluginMeta) getLanguageUnionOrderMap() *orderedmap.Ord...
method GetUsages (line 324) | func (meta *WasmPluginMeta) GetUsages() ([]WasmUsage, error) {
function defaultWasmPluginMeta (line 36) | func defaultWasmPluginMeta() *WasmPluginMeta {
function ParseSpecYAML (line 54) | func ParseSpecYAML(spec string) (*WasmPluginMeta, error) {
function ParseGoSrc (line 71) | func ParseGoSrc(dir, model string) (*WasmPluginMeta, error) {
function recursiveSetSchema (line 91) | func recursiveSetSchema(model *Model, parent *JSONSchemaProps) (string, ...
function recursiveObjectProperties (line 119) | func recursiveObjectProperties(parent *JSONSchemaProps, model *Model) {
type WasmPluginInfo (line 175) | type WasmPluginInfo struct
type Category (line 187) | type Category
constant CategoryAuth (line 190) | CategoryAuth Category = "auth"
constant CategorySecurity (line 191) | CategorySecurity Category = "security"
constant CategoryProtocol (line 192) | CategoryProtocol Category = "protocol"
constant CategoryFlowControl (line 193) | CategoryFlowControl Category = "flow-control"
constant CategoryFlowMonitor (line 194) | CategoryFlowMonitor Category = "flow-monitor"
constant CategoryCustom (line 195) | CategoryCustom Category = "custom"
constant CategoryDefault (line 196) | CategoryDefault = CategoryCustom
constant IconAuth (line 200) | IconAuth = "https://img.alicdn.com/imgextra/i4/O1CN01BPFGlT1pGZ2V...
constant IconSecurity (line 201) | IconSecurity = "https://img.alicdn.com/imgextra/i1/O1CN01jKT9vC1O059v...
constant IconProtocol (line 202) | IconProtocol = "https://img.alicdn.com/imgextra/i2/O1CN01xIywow1mVGuR...
constant IconFlowControl (line 203) | IconFlowControl = "https://img.alicdn.com/imgextra/i3/O1CN01bAFa9k1t1gdQ...
constant IconFlowMonitor (line 204) | IconFlowMonitor = "https://img.alicdn.com/imgextra/i4/O1CN01aet3s61MoLOE...
constant IconCustom (line 205) | IconCustom = "https://img.alicdn.com/imgextra/i1/O1CN018iKKih1iVx28...
constant IconDefault (line 206) | IconDefault = IconCustom
function Category2IconUrl (line 209) | func Category2IconUrl(category Category) string {
type I18nType (line 228) | type I18nType
constant I18nZH_CN (line 231) | I18nZH_CN I18nType = "zh-CN"
constant I18nEN_US (line 232) | I18nEN_US I18nType = "en-US"
constant I18nUndefined (line 233) | I18nUndefined I18nType = "undefined"
constant I18nUnknown (line 234) | I18nUnknown I18nType = "unknown"
constant I18nDefault (line 235) | I18nDefault = I18nEN_US
function str2I18nType (line 238) | func str2I18nType(typ string) I18nType {
type Contact (line 249) | type Contact struct
type WasmPluginSpec (line 255) | type WasmPluginSpec struct
type Phase (line 265) | type Phase
constant PhaseUnspecified (line 268) | PhaseUnspecified Phase = "UNSPECIFIED_PHASE"
constant PhaseAuthn (line 269) | PhaseAuthn Phase = "AUTHN"
constant PhaseAuthz (line 270) | PhaseAuthz Phase = "AUTHZ"
constant PhaseStats (line 271) | PhaseStats Phase = "STATS"
constant PhaseDefault (line 272) | PhaseDefault = PhaseUnspecified
type ConfigSchema (line 275) | type ConfigSchema struct
type WasmUsage (line 308) | type WasmUsage struct
type ConfigEntry (line 315) | type ConfigEntry struct
function getConfigEntries (line 347) | func getConfigEntries(schema *JSONSchemaProps, entries *[]ConfigEntry, i...
function doGetConfigEntries (line 351) | func doGetConfigEntries(schema *JSONSchemaProps, entries *[]ConfigEntry,...
function constructName (line 390) | func constructName(parent, name string) string {
FILE: hgctl/pkg/plugin/types/model_parser.go
constant ArrayPrefix (line 32) | ArrayPrefix = "array of "
constant MapPrefix (line 33) | MapPrefix = "map of "
constant ObjectSuffix (line 34) | ObjectSuffix = "object"
function IsArray (line 38) | func IsArray(typ string) bool {
function GetItemType (line 43) | func GetItemType(typ string) string {
function IsMap (line 51) | func IsMap(typ string) bool {
function GetValueType (line 56) | func GetValueType(typ string) string {
function IsObject (line 64) | func IsObject(typ string) bool {
type ModelParser (line 73) | type ModelParser struct
method recursiveAlias (line 207) | func (p *ModelParser) recursiveAlias(alias string) *astNode {
method GetModel (line 224) | func (p *ModelParser) GetModel(model string) (*Model, error) {
method parseModelFields (line 239) | func (p *ModelParser) parseModelFields(model string) (fields []Model, ...
method getModelName (line 323) | func (p *ModelParser) getModelName(typ ast.Expr) (string, error) {
method doGetModelName (line 327) | func (p *ModelParser) doGetModelName(pkgName string, typ ast.Expr) (st...
method parseFieldType (line 349) | func (p *ModelParser) parseFieldType(pkgName string, typ ast.Expr) (st...
type Model (line 81) | type Model struct
method Inspect (line 95) | func (m *Model) Inspect(f func(model *Model) bool) {
method setDoc (line 298) | func (m *Model) setDoc(str string) {
method setTag (line 302) | func (m *Model) setTag(str string) (bool, error) {
type astNode (line 89) | type astNode struct
function NewModelParser (line 107) | func NewModelParser(dir string) (*ModelParser, error) {
function walkGoSrc (line 177) | func walkGoSrc(dir string) (map[string]*ast.Package, error) {
function skipField (line 293) | func skipField(field *ast.Field) bool {
function convert2JsonType (line 393) | func convert2JsonType(typ string) (JsonType, error) {
type JsonType (line 411) | type JsonType
constant JsonTypeInteger (line 414) | JsonTypeInteger JsonType = "integer"
constant JsonTypeNumber (line 415) | JsonTypeNumber JsonType = "number"
constant JsonTypeBoolean (line 416) | JsonTypeBoolean JsonType = "boolean"
constant JsonTypeString (line 417) | JsonTypeString JsonType = "string"
constant JsonTypeObject (line 418) | JsonTypeObject JsonType = "object"
constant JsonTypeArray (line 419) | JsonTypeArray JsonType = "array"
constant JsonTypeMap (line 420) | JsonTypeMap JsonType = "map"
FILE: hgctl/pkg/plugin/types/model_parser_test.go
function TestGetModel (line 23) | func TestGetModel(t *testing.T) {
function TestParseStructAndAlias (line 255) | func TestParseStructAndAlias(t *testing.T) {
function TestStructFieldDocAndTag (line 311) | func TestStructFieldDocAndTag(t *testing.T) {
FILE: hgctl/pkg/plugin/types/schema.go
type JSONSchemaProps (line 32) | type JSONSchemaProps struct
method IsRequired (line 134) | func (s *JSONSchemaProps) IsRequired(name string) bool {
method GetDefaultValue (line 146) | func (s *JSONSchemaProps) GetDefaultValue() string {
method GetExample (line 158) | func (s *JSONSchemaProps) GetExample() string {
method GetPropertiesOrderMap (line 182) | func (s *JSONSchemaProps) GetPropertiesOrderMap() *orderedmap.OrderedM...
method HandleFieldAnnotations (line 193) | func (s *JSONSchemaProps) HandleFieldAnnotations(comment string) {
method HandleFieldTags (line 217) | func (s *JSONSchemaProps) HandleFieldTags(tags string, parent *JSONSch...
method JoinRequirementsBy (line 287) | func (s *JSONSchemaProps) JoinRequirementsBy(i18n I18nType, required b...
method getRequirements (line 299) | func (s *JSONSchemaProps) getRequirements(required bool) map[I18nType]...
method GetMinimum (line 337) | func (s *JSONSchemaProps) GetMinimum() map[I18nType]string {
method GetMaximum (line 348) | func (s *JSONSchemaProps) GetMaximum() map[I18nType]string {
method GetMinLength (line 359) | func (s *JSONSchemaProps) GetMinLength() map[I18nType]string {
method GetMaxLength (line 370) | func (s *JSONSchemaProps) GetMaxLength() map[I18nType]string {
method GetPattern (line 381) | func (s *JSONSchemaProps) GetPattern() map[I18nType]string {
method GetMinItems (line 392) | func (s *JSONSchemaProps) GetMinItems() map[I18nType]string {
method GetMaxItems (line 403) | func (s *JSONSchemaProps) GetMaxItems() map[I18nType]string {
method GetRequired (line 414) | func (s *JSONSchemaProps) GetRequired(req bool) map[I18nType]string {
type Scope (line 75) | type Scope
constant ScopeGlobal (line 78) | ScopeGlobal Scope = "GLOBAL"
constant ScopeInstance (line 79) | ScopeInstance Scope = "INSTANCE"
constant ScopeAll (line 80) | ScopeAll Scope = "ALL"
constant ScopeDefault (line 81) | ScopeDefault = ScopeInstance
type JSON (line 86) | type JSON struct
type JSONSchemaPropsOrArray (line 92) | type JSONSchemaPropsOrArray struct
type JSONSchemaPropsOrBool (line 99) | type JSONSchemaPropsOrBool struct
type JSONSchemaDependencies (line 105) | type JSONSchemaDependencies
type JSONSchemaPropsOrStringArray (line 108) | type JSONSchemaPropsOrStringArray struct
type JSONSchemaURL (line 114) | type JSONSchemaURL
type JSONSchemaDefinitions (line 117) | type JSONSchemaDefinitions
type ExternalDocumentation (line 120) | type ExternalDocumentation struct
function NewJSONSchemaProps (line 125) | func NewJSONSchemaProps() *JSONSchemaProps {
FILE: hgctl/pkg/plugin/types/testdata/doc_tag/main.go
type TestBasicDocTag (line 18) | type TestBasicDocTag struct
type TestNestedStructDocTag (line 42) | type TestNestedStructDocTag struct
FILE: hgctl/pkg/plugin/types/testdata/types/ext/ext.go
type TestExStruct (line 19) | type TestExStruct struct
type ExPointerInt (line 26) | type ExPointerInt
type ExBool (line 27) | type ExBool
type ExSlice (line 28) | type ExSlice
type ExAlias (line 29) | type ExAlias
type TestNestedStruct (line 32) | type TestNestedStruct struct
FILE: hgctl/pkg/plugin/types/testdata/types/ext/nested/nested.go
type TestNestedStruct (line 17) | type TestNestedStruct struct
type NestedInt (line 22) | type NestedInt
type NestedString (line 23) | type NestedString
FILE: hgctl/pkg/plugin/types/testdata/types/main.go
type TestBasicStruct (line 19) | type TestBasicStruct struct
type TestComplexStruct (line 26) | type TestComplexStruct struct
type TestAliasStruct (line 41) | type TestAliasStruct struct
type MyString (line 48) | type MyString
type MyPointerInt (line 49) | type MyPointerInt
type MyStruct (line 50) | type MyStruct
type NestedAlias (line 51) | type NestedAlias
type NestedBasicAlias (line 52) | type NestedBasicAlias
type TestExternalStruct (line 55) | type TestExternalStruct struct
type TestNestedStruct (line 63) | type TestNestedStruct struct
type MyInterface (line 67) | type MyInterface interface
FILE: hgctl/pkg/plugin/uninstall/uninstall.go
function NewCommand (line 31) | func NewCommand() *cobra.Command {
function uninstall (line 61) | func uninstall(w io.Writer, name string, all bool) error {
function deleteOne (line 92) | func deleteOne(ctx context.Context, w io.Writer, cli *k8s.WasmPluginClie...
FILE: hgctl/pkg/plugin/utils/common.go
function GetAbsolutePath (line 33) | func GetAbsolutePath(path string) (newPath string, err error) {
function AddIndent (line 55) | func AddIndent(str, indent string) string {
function MarshalYamlWithIndent (line 70) | func MarshalYamlWithIndent(v interface{}, spaces int) ([]byte, error) {
function MarshalYamlWithIndentTo (line 83) | func MarshalYamlWithIndentTo(w io.Writer, v interface{}, spaces int) err...
FILE: hgctl/pkg/plugin/utils/debugger.go
type Debugger (line 22) | type Debugger interface
type DefaultDebugger (line 27) | type DefaultDebugger struct
method Debugf (line 36) | func (d DefaultDebugger) Debugf(format string, a ...any) (int, error) {
method Debugln (line 48) | func (d DefaultDebugger) Debugln(a ...any) (int, error) {
function NewDefaultDebugger (line 32) | func NewDefaultDebugger(debug bool, w io.Writer) *DefaultDebugger {
FILE: hgctl/pkg/plugin/utils/printer.go
type YesOrNoPrinter (line 26) | type YesOrNoPrinter struct
method Printf (line 52) | func (p *YesOrNoPrinter) Printf(format string, a ...interface{}) (int,...
method Println (line 56) | func (p *YesOrNoPrinter) Println(a ...interface{}) (int, error) {
method PrintWithIndentf (line 60) | func (p *YesOrNoPrinter) PrintWithIndentf(format string, a ...interfac...
method PrintWithIndentln (line 65) | func (p *YesOrNoPrinter) PrintWithIndentln(a ...interface{}) (int, err...
method Yesf (line 77) | func (p *YesOrNoPrinter) Yesf(format string, a ...interface{}) (int, e...
method Yesln (line 81) | func (p *YesOrNoPrinter) Yesln(a ...interface{}) (int, error) {
method YesWithIndentf (line 85) | func (p *YesOrNoPrinter) YesWithIndentf(format string, a ...interface{...
method YesWithIndentln (line 90) | func (p *YesOrNoPrinter) YesWithIndentln(a ...interface{}) (int, error) {
method Nof (line 102) | func (p *YesOrNoPrinter) Nof(format string, a ...interface{}) (int, er...
method Noln (line 106) | func (p *YesOrNoPrinter) Noln(a ...interface{}) (int, error) {
method NoWithIndentf (line 110) | func (p *YesOrNoPrinter) NoWithIndentf(format string, a ...interface{}...
method NoWithIndentln (line 115) | func (p *YesOrNoPrinter) NoWithIndentln(a ...interface{}) (int, error) {
method Ident (line 127) | func (p *YesOrNoPrinter) Ident() string { return p.indent.String() }
method IncIdentRepeat (line 129) | func (p *YesOrNoPrinter) IncIdentRepeat() { p.indent.IncRepeat() }
method DecIndentRepeat (line 131) | func (p *YesOrNoPrinter) DecIndentRepeat() { p.indent.DecRepeat() }
method SetIdentRepeat (line 133) | func (p *YesOrNoPrinter) SetIdentRepeat(v int) { p.indent.SetRepeat(v) }
function NewPrinter (line 39) | func NewPrinter(out io.Writer, indent *Indent, yes, no *color.Color) *Ye...
function DefaultPrinter (line 48) | func DefaultPrinter() *YesOrNoPrinter {
type Indent (line 135) | type Indent struct
method String (line 147) | func (i *Indent) String() string {
method IncRepeat (line 151) | func (i *Indent) IncRepeat() { i.repeat++ }
method DecRepeat (line 153) | func (i *Indent) DecRepeat() {
method SetRepeat (line 160) | func (i *Indent) SetRepeat(v int) {
function NewIndent (line 140) | func NewIndent(format string, repeat int) *Indent {
FILE: hgctl/pkg/plugin/utils/survey_wrapper.go
function Ask (line 19) | func Ask(qs []*survey.Question, response interface{}, opts ...survey.Ask...
function AskOne (line 26) | func AskOne(p survey.Prompt, response interface{}, opts ...survey.AskOpt...
FILE: hgctl/pkg/profile.go
function newProfileCmd (line 22) | func newProfileCmd() *cobra.Command {
FILE: hgctl/pkg/profile_dump.go
type profileDumpArgs (line 25) | type profileDumpArgs struct
function addProfileDumpFlags (line 32) | func addProfileDumpFlags(cmd *cobra.Command, args *profileDumpArgs) {
function profileDumpCmd (line 37) | func profileDumpCmd(pdArgs *profileDumpArgs) *cobra.Command {
function profileDump (line 54) | func profileDump(cmd *cobra.Command, args []string, pdArgs *profileDumpA...
FILE: hgctl/pkg/profile_list.go
type profileListArgs (line 24) | type profileListArgs struct
function addProfileListFlags (line 29) | func addProfileListFlags(cmd *cobra.Command, args *profileListArgs) {
function profileListCmd (line 33) | func profileListCmd(plArgs *profileListArgs) *cobra.Command {
function profileList (line 46) | func profileList(cmd *cobra.Command, plArgs *profileListArgs) error {
FILE: hgctl/pkg/root.go
function GetRootCommand (line 27) | func GetRootCommand() *cobra.Command {
FILE: hgctl/pkg/uninstall.go
type uninstallArgs (line 30) | type uninstallArgs struct
function addUninstallFlags (line 35) | func addUninstallFlags(cmd *cobra.Command, args *uninstallArgs) {
function newUninstallCmd (line 41) | func newUninstallCmd() *cobra.Command {
function uninstall (line 64) | func uninstall(writer io.Writer, uiArgs *uninstallArgs) error {
function promptUninstall (line 112) | func promptUninstall(writer io.Writer) bool {
function uninstallManifests (line 128) | func uninstallManifests(profile *helm.Profile, writer io.Writer, uiArgs ...
FILE: hgctl/pkg/upgrade.go
type upgradeArgs (line 32) | type upgradeArgs struct
function addUpgradeFlags (line 36) | func addUpgradeFlags(cmd *cobra.Command, args *upgradeArgs) {
function newUpgradeCmd (line 44) | func newUpgradeCmd() *cobra.Command {
function upgrade (line 64) | func upgrade(writer io.Writer, iArgs *InstallArgs) error {
function promptUpgrade (line 108) | func promptUpgrade(writer io.Writer) bool {
function upgradeManifests (line 124) | func upgradeManifests(profile *helm.Profile, writer io.Writer, devel boo...
function getAllProfiles (line 138) | func getAllProfiles() ([]*installer.ProfileContext, error) {
function promptProfileContexts (line 169) | func promptProfileContexts(writer io.Writer, profileContexts []*installe...
FILE: hgctl/pkg/util/env.go
function GetPythonVersion (line 25) | func GetPythonVersion() (string, error) {
function CompareVersions (line 50) | func CompareVersions(v1, v2 string) int {
FILE: hgctl/pkg/util/filter.go
type FilterFunc (line 37) | type FilterFunc
function ApplyFilters (line 39) | func ApplyFilters(input string, filters ...FilterFunc) string {
function LicenseFilter (line 48) | func LicenseFilter(input string) string {
function SpaceFilter (line 64) | func SpaceFilter(input string) string {
function SpaceLineFilter (line 69) | func SpaceLineFilter(input string) string {
function FormatterFilter (line 84) | func FormatterFilter(input string) string {
FILE: hgctl/pkg/util/filter_test.go
function TestLicenseFilter (line 21) | func TestLicenseFilter(t *testing.T) {
function TestSpaceFilter (line 52) | func TestSpaceFilter(t *testing.T) {
function TestFormatterFilter (line 73) | func TestFormatterFilter(t *testing.T) {
FILE: hgctl/pkg/util/http_fetcher.go
constant defaultInitialInterval (line 27) | defaultInitialInterval = 500 * time.Millisecond
constant defaultMaxInterval (line 28) | defaultMaxInterval = 60 * time.Second
type HTTPFetcher (line 31) | type HTTPFetcher struct
method Fetch (line 58) | func (f *HTTPFetcher) Fetch(ctx context.Context, url string) ([]byte, ...
function NewHTTPFetcher (line 39) | func NewHTTPFetcher(requestTimeout time.Duration, requestMaxRetry int, b...
function retryable (line 118) | func retryable(code int) bool {
FILE: hgctl/pkg/util/path.go
constant PathSeparator (line 27) | PathSeparator = "."
constant KVSeparator (line 29) | KVSeparator = string(kvSeparatorRune)
constant kvSeparatorRune (line 30) | kvSeparatorRune = ':'
constant InsertIndex (line 33) | InsertIndex = -1
constant pathSeparatorRune (line 36) | pathSeparatorRune = '.'
constant EscapedPathSeparator (line 38) | EscapedPathSeparator = "\\" + PathSeparator
type Path (line 45) | type Path
method String (line 71) | func (p Path) String() string {
method Equals (line 75) | func (p Path) Equals(p2 Path) bool {
function PathFromString (line 48) | func PathFromString(path string) Path {
function ToYAMLPath (line 88) | func ToYAMLPath(path string) Path {
function ToYAMLPathString (line 97) | func ToYAMLPathString(path string) string {
function IsValidPathElement (line 102) | func IsValidPathElement(pe string) bool {
function IsKVPathElement (line 107) | func IsKVPathElement(pe string) bool {
function IsVPathElement (line 121) | func IsVPathElement(pe string) bool {
function IsNPathElement (line 131) | func IsNPathElement(pe string) bool {
function PathKV (line 143) | func PathKV(pe string) (k, v string, err error) {
function PathV (line 154) | func PathV(pe string) (string, error) {
function PathN (line 171) | func PathN(pe string) (int, error) {
function RemoveBrackets (line 181) | func RemoveBrackets(pe string) (string, bool) {
function splitEscaped (line 189) | func splitEscaped(s string, r rune) []string {
function firstCharToLowerCase (line 207) | func firstCharToLowerCase(s string) string {
FILE: hgctl/pkg/util/path_test.go
function TestSplitEscaped (line 22) | func TestSplitEscaped(t *testing.T) {
function TestIsNPathElement (line 68) | func TestIsNPathElement(t *testing.T) {
function stringSlicesEqual (line 105) | func stringSlicesEqual(a, b []string) bool {
function TestPathFromString (line 117) | func TestPathFromString(t *testing.T) {
function TestToYAMLPath (line 149) | func TestToYAMLPath(t *testing.T) {
function TestIsKVPathElement (line 171) | func TestIsKVPathElement(t *testing.T) {
function TestIsVPathElement (line 218) | func TestIsVPathElement(t *testing.T) {
function TestPathKV (line 255) | func TestPathKV(t *testing.T) {
function TestPathV (line 291) | func TestPathV(t *testing.T) {
function TestRemoveBrackets (line 333) | func TestRemoveBrackets(t *testing.T) {
function errNilCheck (line 381) | func errNilCheck(err1, err2 error) bool {
FILE: hgctl/pkg/util/reflect.go
function kindOf (line 24) | func kindOf(value any) reflect.Kind {
function IsString (line 32) | func IsString(value any) bool {
function IsPtr (line 37) | func IsPtr(value any) bool {
function IsMap (line 42) | func IsMap(value any) bool {
function IsMapPtr (line 47) | func IsMapPtr(v any) bool {
function IsSlice (line 53) | func IsSlice(value any) bool {
function IsStruct (line 58) | func IsStruct(value any) bool {
function IsSlicePtr (line 63) | func IsSlicePtr(v any) bool {
function IsSliceInterfacePtr (line 68) | func IsSliceInterfacePtr(v any) bool {
function IsTypeStructPtr (line 75) | func IsTypeStructPtr(t reflect.Type) bool {
function IsTypeSlicePtr (line 83) | func IsTypeSlicePtr(t reflect.Type) bool {
function IsTypeMap (line 91) | func IsTypeMap(t reflect.Type) bool {
function IsTypeInterface (line 99) | func IsTypeInterface(t reflect.Type) bool {
function IsTypeSliceOfInterface (line 107) | func IsTypeSliceOfInterface(t reflect.Type) bool {
function IsNilOrInvalidValue (line 115) | func IsNilOrInvalidValue(v reflect.Value) bool {
function IsValueNil (line 121) | func IsValueNil(value any) bool {
function IsValueNilOrDefault (line 134) | func IsValueNilOrDefault(value any) bool {
function IsValuePtr (line 146) | func IsValuePtr(v reflect.Value) bool {
function IsValueInterface (line 151) | func IsValueInterface(v reflect.Value) bool {
function IsValueStruct (line 156) | func IsValueStruct(v reflect.Value) bool {
function IsValueStructPtr (line 161) | func IsValueStructPtr(v reflect.Value) bool {
function IsValueMap (line 166) | func IsValueMap(v reflect.Value) bool {
function IsValueSlice (line 171) | func IsValueSlice(v reflect.Value) bool {
function IsValueScalar (line 176) | func IsValueScalar(v reflect.Value) bool {
function ValuesAreSameType (line 191) | func ValuesAreSameType(v1 reflect.Value, v2 reflect.Value) bool {
function IsEmptyString (line 196) | func IsEmptyString(value any) bool {
function DeleteFromSlicePtr (line 210) | func DeleteFromSlicePtr(parentSlice any, index int) error {
function UpdateSlicePtr (line 228) | func UpdateSlicePtr(parentSlice any, index int, value any) error {
function InsertIntoMap (line 247) | func InsertIntoMap(parentMap any, key any, value any) error {
function DeleteFromMap (line 269) | func DeleteFromMap(parentMap any, key any) error {
function ToIntValue (line 281) | func ToIntValue(val any) (int, bool) {
function IsIntKind (line 296) | func IsIntKind(k reflect.Kind) bool {
function IsUintKind (line 305) | func IsUintKind(k reflect.Kind) bool {
FILE: hgctl/pkg/util/util.go
function StripPrefix (line 29) | func StripPrefix(path, prefix string) string {
function SplitSetFlag (line 35) | func SplitSetFlag(flag string) (string, string) {
function IsFilePath (line 44) | func IsFilePath(path string) bool {
function IsHTTPURL (line 49) | func IsHTTPURL(path string) (bool, error) {
function StringBoolMapToSlice (line 59) | func StringBoolMapToSlice(m map[string]bool) []string {
function ParseValue (line 70) | func ParseValue(valueStr string) any {
function WriteFileString (line 85) | func WriteFileString(fileName string, content string, perm os.FileMode) ...
function GetHomeHgctlDir (line 100) | func GetHomeHgctlDir() string {
function GetSpecificAgentDir (line 106) | func GetSpecificAgentDir(name string) (string, error) {
FILE: hgctl/pkg/util/yaml.go
function ToYAML (line 68) | func ToYAML(val any) string {
function OverlayTrees (line 122) | func OverlayTrees(base map[string]any, overlays ...map[string]any) (map[...
function OverlayYAML (line 162) | func OverlayYAML(base, overlay string) (string, error) {
function yamlDiff (line 197) | func yamlDiff(a, b string) string {
function yamlStringsToList (line 219) | func yamlStringsToList(str string) []string {
function multiYamlDiffOutput (line 239) | func multiYamlDiffOutput(res, diff string) string {
function diffStringList (line 250) | func diffStringList(l1, l2 []string) string {
function YAMLDiff (line 282) | func YAMLDiff(a, b string) string {
function IsYAMLEqual (line 291) | func IsYAMLEqual(a, b string) bool {
function IsYAMLEmpty (line 308) | func IsYAMLEmpty(y string) bool {
FILE: hgctl/pkg/util/yaml_test.go
function TestToYAML (line 23) | func TestToYAML(t *testing.T) {
function TestOverlayTrees (line 67) | func TestOverlayTrees(t *testing.T) {
function TestOverlayYAML (line 129) | func TestOverlayYAML(t *testing.T) {
function TestYAMLDiff (line 174) | func TestYAMLDiff(t *testing.T) {
function TestMultipleYAMLDiff (line 219) | func TestMultipleYAMLDiff(t *testing.T) {
function TestIsYAMLEqual (line 273) | func TestIsYAMLEqual(t *testing.T) {
function TestIsYAMLEmpty (line 318) | func TestIsYAMLEmpty(t *testing.T) {
FILE: hgctl/pkg/utils.go
type envoyConfigType (line 22) | type envoyConfigType
function GetXDSResource (line 33) | func GetXDSResource(resourceType envoyConfigType, configDump []byte) (an...
FILE: hgctl/pkg/version.go
constant higressCoreContainerName (line 37) | higressCoreContainerName = "higress-core"
constant higressGatewayContainerName (line 38) | higressGatewayContainerName = "higress-gateway"
function newVersionCommand (line 41) | func newVersionCommand() *cobra.Command {
type VersionInfo (line 75) | type VersionInfo struct
type ServerVersion (line 80) | type ServerVersion struct
function Get (line 85) | func Get() VersionInfo {
function retrieveVersion (line 92) | func retrieveVersion(w io.Writer, v *VersionInfo, containerName string, ...
type versionFunc (line 128) | type versionFunc
function versions (line 130) | func versions(w io.Writer, output string, client bool) error {
FILE: pkg/bootstrap/server.go
type XdsOptions (line 59) | type XdsOptions struct
type RegistryOptions (line 78) | type RegistryOptions struct
type ServerArgs (line 97) | type ServerArgs struct
type readinessProbe (line 128) | type readinessProbe
type ServerInterface (line 130) | type ServerInterface interface
type Server (line 135) | type Server struct
method initRegistryEventHandlers (line 197) | func (s *Server) initRegistryEventHandlers() error {
method initConfigController (line 219) | func (s *Server) initConfigController() error {
method Start (line 262) | func (s *Server) Start(stop <-chan struct{}) error {
method waitForShutDown (line 305) | func (s *Server) waitForShutDown(stop <-chan struct{}) {
method WaitUntilCompletion (line 336) | func (s *Server) WaitUntilCompletion() {
method initXdsServer (line 340) | func (s *Server) initXdsServer() error {
method initGrpcServer (line 367) | func (s *Server) initGrpcServer() error {
method initAuthenticators (line 379) | func (s *Server) initAuthenticators() error {
method initAutomaticHttps (line 391) | func (s *Server) initAutomaticHttps() error {
method initKubeClient (line 411) | func (s *Server) initKubeClient() error {
method initHttpServer (line 431) | func (s *Server) initHttpServer() error {
method withConditionalAuth (line 444) | func (s *Server) withConditionalAuth(handler http.HandlerFunc) http.Ha...
method readyHandler (line 452) | func (s *Server) readyHandler(w http.ResponseWriter, _ *http.Request) {
method registryWatcherStatusHandler (line 463) | func (s *Server) registryWatcherStatusHandler(w http.ResponseWriter, _...
method cachesSynced (line 501) | func (s *Server) cachesSynced() bool {
method waitForCacheSync (line 505) | func (s *Server) waitForCacheSync(stop <-chan struct{}) bool {
method pushContextReady (line 528) | func (s *Server) pushContextReady(expected int64) bool {
function NewServer (line 151) | func NewServer(args *ServerArgs) (*Server, error) {
function writeJSON (line 486) | func writeJSON(w http.ResponseWriter, obj interface{}) {
FILE: pkg/bootstrap/server_test.go
function TestStartWithNoError (line 30) | func TestStartWithNoError(t *testing.T) {
function newServerArgs (line 94) | func newServerArgs() *ServerArgs {
FILE: pkg/cert/certmgr.go
constant EventCertObtained (line 33) | EventCertObtained = "cert_obtained"
type CertMgr (line 40) | type CertMgr struct
method Reconcile (line 122) | func (s *CertMgr) Reconcile(ctx context.Context, oldConfig *Config, ne...
method manageSync (line 198) | func (s *CertMgr) manageSync(ctx context.Context, domainNames []string...
method cleanSync (line 203) | func (s *CertMgr) cleanSync(ctx context.Context, domainNames []string)...
method OnEvent (line 209) | func (s *CertMgr) OnEvent(ctx context.Context, event string, data map[...
function InitCertMgr (line 54) | func InitCertMgr(opts *Option, clientSet kubernetes.Interface, config *C...
FILE: pkg/cert/config.go
constant ConfigmapCertName (line 33) | ConfigmapCertName = "higress-https"
constant ConfigmapCertConfigKey (line 34) | ConfigmapCertConfigKey = "cert"
constant DefaultRenewBeforeDays (line 35) | DefaultRenewBeforeDays = 30
constant RenewMaxDays (line 36) | RenewMaxDays = 90
type IssuerName (line 39) | type IssuerName
constant IssuerTypeAliyunSSL (line 42) | IssuerTypeAliyunSSL IssuerName = "aliyunssl"
constant IssuerTypeLetsencrypt (line 43) | IssuerTypeLetsencrypt IssuerName = "letsencrypt"
type Config (line 47) | type Config struct
method GetIssuer (line 56) | func (c *Config) GetIssuer(issuerName IssuerName) *ACMEIssuerEntry {
method MatchSecretNameByDomain (line 65) | func (c *Config) MatchSecretNameByDomain(domain string) string {
method GetSecretNameByDomain (line 76) | func (c *Config) GetSecretNameByDomain(issuerName IssuerName, domain s...
method Validate (line 100) | func (c *Config) Validate() error {
function ParseTLSSecret (line 89) | func ParseTLSSecret(tlsSecret string) (string, string) {
type CredentialEntry (line 154) | type CredentialEntry struct
type ACMEIssuerEntry (line 161) | type ACMEIssuerEntry struct
type ConfigMgr (line 167) | type ConfigMgr struct
method SetConfig (line 173) | func (c *ConfigMgr) SetConfig(config *Config) {
method GetConfig (line 177) | func (c *ConfigMgr) GetConfig() *Config {
method InitConfig (line 187) | func (c *ConfigMgr) InitConfig(email string) (*Config, error) {
method ParseConfigFromConfigmap (line 211) | func (c *ConfigMgr) ParseConfigFromConfigmap(configmap *v1.ConfigMap) ...
method GetConfigFromConfigmap (line 227) | func (c *ConfigMgr) GetConfigFromConfigmap() (*Config, error) {
method GetConfigmap (line 241) | func (c *ConfigMgr) GetConfigmap() (configmap *v1.ConfigMap, err error) {
method ApplyConfigmap (line 247) | func (c *ConfigMgr) ApplyConfigmap(config *Config) error {
function NewConfigMgr (line 279) | func NewConfigMgr(namespace string, client kubernetes.Interface) (*Confi...
function newDefaultConfig (line 287) | func newDefaultConfig(email string) *Config {
function getRandEmail (line 307) | func getRandEmail() string {
FILE: pkg/cert/config_test.go
function TestMatchSecretNameByDomain (line 23) | func TestMatchSecretNameByDomain(t *testing.T) {
function TestParseTLSSecret (line 124) | func TestParseTLSSecret(t *testing.T) {
FILE: pkg/cert/controller.go
constant workNum (line 33) | workNum = 1
constant maxRetry (line 34) | maxRetry = 2
constant configMapName (line 35) | configMapName = "higress-https"
type Controller (line 38) | type Controller struct
method addConfigmap (line 49) | func (c *Controller) addConfigmap(obj interface{}) {
method updateConfigmap (line 61) | func (c *Controller) updateConfigmap(oldObj interface{}, newObj interf...
method enqueue (line 76) | func (c *Controller) enqueue(name string) {
method cachesSynced (line 80) | func (c *Controller) cachesSynced() bool {
method Run (line 84) | func (c *Controller) Run(stopCh <-chan struct{}) error {
method worker (line 104) | func (c *Controller) worker() {
method processNextItem (line 110) | func (c *Controller) processNextItem() bool {
method syncConfigmap (line 125) | func (c *Controller) syncConfigmap(key string) error {
method handleError (line 139) | func (c *Controller) handleError(key string, err error) {
function NewController (line 145) | func NewController(client kubernetes.Interface, namespace string, certMg...
FILE: pkg/cert/ingress.go
constant IngressClassName (line 33) | IngressClassName = "higress"
constant IngressServiceName (line 34) | IngressServiceName = "higress-controller"
constant IngressNamePefix (line 35) | IngressNamePefix = "higress-http-solver-"
constant IngressPathPrefix (line 36) | IngressPathPrefix = "/.well-known/acme-challenge/"
constant IngressServicePort (line 37) | IngressServicePort = 8889
type IngressSolver (line 40) | type IngressSolver struct
method Present (line 58) | func (s *IngressSolver) Present(_ context.Context, challenge acme.Chal...
method Wait (line 81) | func (s *IngressSolver) Wait(ctx context.Context, challenge acme.Chall...
method CleanUp (line 95) | func (s *IngressSolver) CleanUp(_ context.Context, challenge acme.Chal...
method Delete (line 108) | func (s *IngressSolver) Delete(_ context.Context, challenge acme.Chall...
method getIngressName (line 118) | func (s *IngressSolver) getIngressName(challenge acme.Challenge) string {
method constructIngress (line 122) | func (s *IngressSolver) constructIngress(challenge acme.Challenge) *v1...
function NewIngressSolver (line 48) | func NewIngressSolver(namespace string, client kubernetes.Interface, acm...
FILE: pkg/cert/secret.go
type SecretMgr (line 29) | type SecretMgr struct
method Update (line 43) | func (s *SecretMgr) Update(domain string, secretName string, privateKe...
method constructSecret (line 75) | func (s *SecretMgr) constructSecret(domain string, name string, namesp...
function NewSecretMgr (line 34) | func NewSecretMgr(namespace string, client kubernetes.Interface) (*Secre...
FILE: pkg/cert/server.go
type Option (line 29) | type Option struct
type Server (line 35) | type Server struct
method InitDefaultConfig (line 53) | func (s *Server) InitDefaultConfig() error {
method InitServer (line 63) | func (s *Server) InitServer() error {
method initHttpServer (line 81) | func (s *Server) initHttpServer() error {
method Run (line 108) | func (s *Server) Run(stopCh <-chan struct{}) error {
function NewServer (line 44) | func NewServer(clientSet kubernetes.Interface, XDSUpdater model.XDSUpdat...
FILE: pkg/cert/storage.go
constant CertificatesPrefix (line 35) | CertificatesPrefix = "certificates"
constant ConfigmapStoreCertficatesPrefix (line 36) | ConfigmapStoreCertficatesPrefix = "higress-cert-store-certificates-"
constant ConfigmapStoreDefaultName (line 37) | ConfigmapStoreDefaultName = "higress-cert-store-default"
type ConfigmapStorage (line 42) | type ConfigmapStorage struct
method Exists (line 62) | func (s *ConfigmapStorage) Exists(_ context.Context, key string) bool {
method Store (line 81) | func (s *ConfigmapStorage) Store(_ context.Context, key string, value ...
method Load (line 106) | func (s *ConfigmapStorage) Load(_ context.Context, key string) ([]byte...
method Delete (line 131) | func (s *ConfigmapStorage) Delete(_ context.Context, key string) error {
method List (line 148) | func (s *ConfigmapStorage) List(ctx context.Context, prefix string, re...
method Stat (line 232) | func (s *ConfigmapStorage) Stat(_ context.Context, key string) (certma...
method Lock (line 279) | func (s *ConfigmapStorage) Lock(ctx context.Context, name string) error {
method Unlock (line 284) | func (s *ConfigmapStorage) Unlock(_ context.Context, name string) error {
method String (line 288) | func (s *ConfigmapStorage) String() string {
method getConfigmapStoreNameByKey (line 307) | func (s *ConfigmapStorage) getConfigmapStoreNameByKey(key string) stri...
method getConfigmapStoreByKey (line 319) | func (s *ConfigmapStorage) getConfigmapStoreByKey(key string) (*v1.Con...
method updateConfigmap (line 344) | func (s *ConfigmapStorage) updateConfigmap(configmap *v1.ConfigMap) er...
type HashValue (line 48) | type HashValue struct
function NewConfigmapStorage (line 53) | func NewConfigmapStorage(namespace string, client kubernetes.Interface) ...
FILE: pkg/cert/storage_test.go
function TestGetConfigmapStoreNameByKey (line 26) | func TestGetConfigmapStoreNameByKey(t *testing.T) {
function TestExists (line 82) | func TestExists(t *testing.T) {
function TestLoad (line 129) | func TestLoad(t *testing.T) {
function TestStore (line 181) | func TestStore(t *testing.T) {
function TestList (line 254) | func TestList(t *testing.T) {
FILE: pkg/cert/util.go
function parseCertsFromPEMBundle (line 30) | func parseCertsFromPEMBundle(bundle []byte) ([]*x509.Certificate, error) {
function notAfter (line 52) | func notAfter(cert *x509.Certificate) time.Time {
function notBefore (line 59) | func notBefore(cert *x509.Certificate) time.Time {
function hostOnly (line 69) | func hostOnly(hostport string) string {
function rangeRandom (line 77) | func rangeRandom(min, max int) (number int) {
function ValidateEmail (line 83) | func ValidateEmail(email string) bool {
function fastHash (line 93) | func fastHash(input []byte) string {
FILE: pkg/cmd/options/global.go
function AddKubeConfigFlags (line 24) | func AddKubeConfigFlags(flags *pflag.FlagSet) {
FILE: pkg/cmd/root.go
function GetRootCommand (line 21) | func GetRootCommand() *cobra.Command {
FILE: pkg/cmd/server.go
function getServerCommand (line 59) | func getServerCommand() *cobra.Command {
FILE: pkg/cmd/server_test.go
function TestServe (line 27) | func TestServe(t *testing.T) {
type delayedServer (line 69) | type delayedServer struct
method Start (line 75) | func (d *delayedServer) Start(stop <-chan struct{}) error {
method WaitUntilCompletion (line 80) | func (d *delayedServer) WaitUntilCompletion() {
FILE: pkg/cmd/version.go
function getVersionCommand (line 23) | func getVersionCommand() *cobra.Command {
FILE: pkg/cmd/version/version.go
type Info (line 25) | type Info struct
function Get (line 32) | func Get() Info {
function Print (line 45) | func Print(w io.Writer, format string) error {
FILE: pkg/common/protocol.go
type Protocol (line 19) | type Protocol
method IsTCP (line 52) | func (p Protocol) IsTCP() bool {
method IsHTTP (line 61) | func (p Protocol) IsHTTP() bool {
method IsGRPC (line 70) | func (p Protocol) IsGRPC() bool {
method IsHTTPS (line 79) | func (i Protocol) IsHTTPS() bool {
method IsDubbo (line 88) | func (p Protocol) IsDubbo() bool {
method IsUnsupported (line 92) | func (p Protocol) IsUnsupported() bool {
method IsSupportedByProxy (line 96) | func (p Protocol) IsSupportedByProxy() bool {
method String (line 105) | func (p Protocol) String() string {
constant TCP (line 22) | TCP Protocol = "TCP"
constant HTTP (line 23) | HTTP Protocol = "HTTP"
constant HTTP2 (line 24) | HTTP2 Protocol = "HTTP2"
constant HTTPS (line 25) | HTTPS Protocol = "HTTPS"
constant GRPC (line 26) | GRPC Protocol = "GRPC"
constant GRPCS (line 27) | GRPCS Protocol = "GRPCS"
constant Dubbo (line 28) | Dubbo Protocol = "Dubbo"
constant Unsupported (line 29) | Unsupported Protocol = "UnsupportedProtocol"
function ParseProtocol (line 32) | func ParseProtocol(s string) Protocol {
FILE: pkg/common/proxy.go
type ProxyType (line 21) | type ProxyType
method GetTransportProtocol (line 45) | func (p ProxyType) GetTransportProtocol() Protocol {
method String (line 57) | func (p ProxyType) String() string {
constant ProxyType_Unknown (line 24) | ProxyType_Unknown ProxyType = "Unknown"
constant ProxyType_HTTP (line 25) | ProxyType_HTTP ProxyType = "HTTP"
constant ProxyType_HTTPS (line 26) | ProxyType_HTTPS ProxyType = "HTTPS"
constant ProxyType_SOCKS4 (line 27) | ProxyType_SOCKS4 ProxyType = "SOCKS4"
constant ProxyType_SOCKS5 (line 28) | ProxyType_SOCKS5 ProxyType = "SOCKS5"
function ParseProxyType (line 31) | func ParseProxyType(s string) ProxyType {
FILE: pkg/common/symbol.go
constant DotSeparator (line 18) | DotSeparator = "."
constant ColonSeparator (line 19) | ColonSeparator = ":"
constant CommaSeparator (line 20) | CommaSeparator = ","
constant SpecialSeparator (line 21) | SpecialSeparator = "#@"
constant JsonMarshalPrefix (line 22) | JsonMarshalPrefix = ""
constant JsonMarshalIndent (line 23) | JsonMarshalIndent = " "
constant Hyphen (line 24) | Hyphen = "-"
constant Underscore (line 25) | Underscore = "_"
constant Slash (line 26) | Slash = "/"
function GenerateKeyBy (line 29) | func GenerateKeyBy(namespace, name string) string {
FILE: pkg/config/constants/constants.go
constant DefaultIngressClass (line 17) | DefaultIngressClass = "higress"
constant DefaultGatewayClass (line 19) | DefaultGatewayClass = "higress"
constant KnativeIngressCRDName (line 21) | KnativeIngressCRDName = "ingresses.networking.internal.knative.dev"
constant KnativeServicesCRDName (line 23) | KnativeServicesCRDName = "services.serving.knative.dev"
constant ManagedGatewayController (line 25) | ManagedGatewayController = "higress.io/gateway-controller"
constant RegistryTypeLabelKey (line 27) | RegistryTypeLabelKey = "higress-registry-type"
constant RegistryN
Copy disabled (too large)
Download .json
Condensed preview — 2130 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (19,134K chars).
[
{
"path": ".claude/skills/agent-session-monitor/QUICKSTART.md",
"chars": 2790,
"preview": "# Agent Session Monitor - Quick Start\n\n实时Agent对话观测程序,用于监控Higress访问日志,追踪多轮对话的token开销和模型使用情况。\n\n## 快速开始\n\n### 1. 运行Demo\n\n```"
},
{
"path": ".claude/skills/agent-session-monitor/README.md",
"chars": 1969,
"preview": "# Agent Session Monitor\n\nReal-time agent conversation monitoring for Clawdbot, designed to monitor Higress access logs a"
},
{
"path": ".claude/skills/agent-session-monitor/SKILL.md",
"chars": 13139,
"preview": "---\nname: agent-session-monitor\ndescription: Real-time agent conversation monitoring - monitors Higress access logs, agg"
},
{
"path": ".claude/skills/agent-session-monitor/example/clawdbot_demo.py",
"chars": 2293,
"preview": "#!/usr/bin/env python3\n\"\"\"\n演示如何在Clawdbot中生成Session观测URL\n\"\"\"\n\nfrom urllib.parse import quote\n\ndef generate_session_url(se"
},
{
"path": ".claude/skills/agent-session-monitor/example/demo.sh",
"chars": 2807,
"preview": "#!/bin/bash\n# Agent Session Monitor - 演示脚本\n\nset -e\n\nSKILL_DIR=\"$(dirname \"$(dirname \"$(realpath \"$0\")\")\")\"\nEXAMPLE_DIR=\""
},
{
"path": ".claude/skills/agent-session-monitor/example/demo_v2.sh",
"chars": 2297,
"preview": "#!/bin/bash\n# Agent Session Monitor - Demo for PR #3424 token details\n\nset -e\n\nSKILL_DIR=\"$(dirname \"$(dirname \"$(realpa"
},
{
"path": ".claude/skills/agent-session-monitor/example/test_access.log",
"chars": 2324,
"preview": "{\"__file_offset__\":\"1000\",\"timestamp\":\"2026-02-01T09:30:15Z\",\"ai_log\":\"{\\\"session_id\\\":\\\"agent:main:discord:146536799301"
},
{
"path": ".claude/skills/agent-session-monitor/example/test_access_v2.log",
"chars": 2662,
"preview": "{\"__file_offset__\":\"1000\",\"timestamp\":\"2026-02-01T10:00:00Z\",\"ai_log\":\"{\\\"session_id\\\":\\\"agent:main:discord:146536799301"
},
{
"path": ".claude/skills/agent-session-monitor/example/test_rotation.sh",
"chars": 4024,
"preview": "#!/bin/bash\n# 测试日志轮转功能\n\nset -e\n\nSKILL_DIR=\"$(dirname \"$(dirname \"$(realpath \"$0\")\")\")\"\nEXAMPLE_DIR=\"$SKILL_DIR/example\"\n"
},
{
"path": ".claude/skills/agent-session-monitor/main.py",
"chars": 22767,
"preview": "#!/usr/bin/env python3\n\"\"\"\nAgent Session Monitor - 实时Agent对话观测程序\n监控Higress访问日志,按session聚合对话,追踪token开销\n\"\"\"\n\nimport argpar"
},
{
"path": ".claude/skills/agent-session-monitor/scripts/cli.py",
"chars": 21277,
"preview": "#!/usr/bin/env python3\n\"\"\"\nAgent Session Monitor CLI - 查询和分析agent对话数据\n支持:\n1. 实时查询指定session的完整llm请求和响应\n2. 按模型统计token开销\n3."
},
{
"path": ".claude/skills/agent-session-monitor/scripts/webserver.py",
"chars": 27619,
"preview": "#!/usr/bin/env python3\n\"\"\"\nAgent Session Monitor - Web Server\n提供浏览器访问的观测界面\n\"\"\"\n\nimport argparse\nimport json\nimport sys\nf"
},
{
"path": ".claude/skills/higress-auto-router/SKILL.md",
"chars": 3813,
"preview": "---\nname: higress-auto-router\ndescription: \"Configure automatic model routing using the get-ai-gateway.sh CLI tool for H"
},
{
"path": ".claude/skills/higress-daily-report/README.md",
"chars": 3544,
"preview": "# Higress 社区治理日报 - Clawdbot Skill\n\n这个 skill 让 AI 助手通过 Clawdbot 自动追踪 Higress 项目的 GitHub 活动,并生成结构化的每日社区治理报告。\n\n## 架构概览\n\n```"
},
{
"path": ".claude/skills/higress-daily-report/SKILL.md",
"chars": 4291,
"preview": "---\nname: higress-daily-report\ndescription: 生成 Higress 项目每日报告,追踪 issue/PR 动态,沉淀问题处理经验,驱动社区问题闭环。用于生成日报、跟进 issue、记录解决方案。\n-"
},
{
"path": ".claude/skills/higress-daily-report/scripts/generate-report.sh",
"chars": 7544,
"preview": "#!/bin/bash\n# Higress Daily Report Generator\n# Generates daily report for alibaba/higress repository\n\n# set -e # 临时禁用以调"
},
{
"path": ".claude/skills/higress-openclaw-integration/SKILL.md",
"chars": 9958,
"preview": "---\nname: higress-openclaw-integration\ndescription: \"Deploy and configure Higress AI Gateway for OpenClaw integration. U"
},
{
"path": ".claude/skills/higress-openclaw-integration/references/TROUBLESHOOTING.md",
"chars": 6079,
"preview": "# Higress AI Gateway - Troubleshooting\n\nCommon issues and solutions for Higress AI Gateway deployment and operation.\n\n##"
},
{
"path": ".claude/skills/higress-openclaw-integration/scripts/detect-region.sh",
"chars": 509,
"preview": "#!/bin/bash\n# Detect if user is in China region based on timezone\n# Returns: \"china\" or \"international\"\n\nTIMEZONE=$(cat "
},
{
"path": ".claude/skills/higress-openclaw-integration/scripts/plugin/README.md",
"chars": 1847,
"preview": "# Higress AI Gateway Plugin\n\nOpenClaw model provider plugin for Higress AI Gateway with auto-routing support.\n\n## What i"
},
{
"path": ".claude/skills/higress-openclaw-integration/scripts/plugin/index.ts",
"chars": 11444,
"preview": "import { emptyPluginConfigSchema } from \"openclaw/plugin-sdk\";\n\nconst DEFAULT_GATEWAY_URL = \"http://localhost:8080\";\ncon"
},
{
"path": ".claude/skills/higress-openclaw-integration/scripts/plugin/openclaw.plugin.json",
"chars": 253,
"preview": "{\n \"id\": \"higress\",\n \"name\": \"Higress AI Gateway\",\n \"description\": \"Model provider plugin for Higress AI Gateway with"
},
{
"path": ".claude/skills/higress-openclaw-integration/scripts/plugin/package.json",
"chars": 485,
"preview": "{\n \"name\": \"@higress/higress\",\n \"version\": \"1.0.0\",\n \"description\": \"Higress AI Gateway model provider plugin for Ope"
},
{
"path": ".claude/skills/higress-wasm-go-plugin/SKILL.md",
"chars": 7365,
"preview": "---\nname: higress-wasm-go-plugin\ndescription: Develop Higress WASM plugins using Go 1.24+. Use when creating, modifying,"
},
{
"path": ".claude/skills/higress-wasm-go-plugin/references/advanced-patterns.md",
"chars": 6448,
"preview": "# Advanced Patterns\n\n## Streaming Body Processing\n\nProcess body chunks as they arrive without buffering:\n\n```go\nfunc ini"
},
{
"path": ".claude/skills/higress-wasm-go-plugin/references/http-client.md",
"chars": 4473,
"preview": "# HTTP Client Reference\n\n## Cluster Types\n\n### FQDNCluster (Most Common)\n\nFor services registered in Higress with FQDN:\n"
},
{
"path": ".claude/skills/higress-wasm-go-plugin/references/local-testing.md",
"chars": 4587,
"preview": "# Local Testing with Docker Compose\n\n## Prerequisites\n\n- Docker installed\n- Compiled `main.wasm` file\n\n## Setup\n\nCreate "
},
{
"path": ".claude/skills/higress-wasm-go-plugin/references/redis-client.md",
"chars": 5876,
"preview": "# Redis Client Reference\n\n## Initialization\n\n```go\ntype MyConfig struct {\n redis wrapper.RedisClient\n qpm int\n}\n"
},
{
"path": ".claude/skills/nginx-to-higress-migration/README.md",
"chars": 15145,
"preview": "# Nginx to Higress Migration Skill\n\nComplete end-to-end solution for migrating from ingress-nginx to Higress gateway, fe"
},
{
"path": ".claude/skills/nginx-to-higress-migration/README_CN.md",
"chars": 10379,
"preview": "# Nginx 到 Higress 迁移技能\n\n一站式 ingress-nginx 到 Higress 网关迁移解决方案,提供智能兼容性验证、自动化迁移工具链和 AI 驱动的能力增强。\n\n## 概述\n\n本技能基于真实生产环境迁移经验构建,提"
},
{
"path": ".claude/skills/nginx-to-higress-migration/SKILL.md",
"chars": 15398,
"preview": "---\nname: nginx-to-higress-migration\ndescription: \"Migrate from ingress-nginx to Higress in Kubernetes environments. Use"
},
{
"path": ".claude/skills/nginx-to-higress-migration/references/annotation-mapping.md",
"chars": 7742,
"preview": "# Nginx to Higress Annotation Compatibility\n\n## ⚠️ Important: Do NOT Modify Your Ingress Resources!\n\n**Higress natively "
},
{
"path": ".claude/skills/nginx-to-higress-migration/references/builtin-plugins.md",
"chars": 4121,
"preview": "# Higress Built-in Plugins\n\nBefore writing custom WASM plugins, check if Higress has a built-in plugin that meets your n"
},
{
"path": ".claude/skills/nginx-to-higress-migration/references/plugin-deployment.md",
"chars": 5503,
"preview": "# WASM Plugin Build and Deployment\n\n## Plugin Project Structure\n\n```\nmy-plugin/\n├── main.go # Plugin entry poin"
},
{
"path": ".claude/skills/nginx-to-higress-migration/references/snippet-patterns.md",
"chars": 8309,
"preview": "# Common Nginx Snippet to WASM Plugin Patterns\n\n## Header Manipulation\n\n### Add Response Header\n\n**Nginx snippet:**\n```n"
},
{
"path": ".claude/skills/nginx-to-higress-migration/scripts/analyze-ingress.sh",
"chars": 6217,
"preview": "#!/bin/bash\n# Analyze nginx Ingress resources and identify migration requirements\n\nset -e\n\nNAMESPACE=\"${1:-}\"\nOUTPUT_FOR"
},
{
"path": ".claude/skills/nginx-to-higress-migration/scripts/generate-migration-test.sh",
"chars": 7293,
"preview": "#!/bin/bash\n# Generate test script for all Ingress routes\n# Tests each route against Higress gateway to validate migrati"
},
{
"path": ".claude/skills/nginx-to-higress-migration/scripts/generate-plugin-scaffold.sh",
"chars": 6658,
"preview": "#!/bin/bash\n# Generate WASM plugin scaffold for nginx snippet migration\n\nset -e\n\nif [ \"$#\" -lt 1 ]; then\n echo \"Usage"
},
{
"path": ".claude/skills/nginx-to-higress-migration/scripts/install-harbor.sh",
"chars": 5020,
"preview": "#!/bin/bash\n# Install Harbor registry for WASM plugin images\n# Only use this if you don't have an existing image registr"
},
{
"path": ".cursor/rules/plugin-development.mdc",
"chars": 4374,
"preview": "---\ndescription: Plugin Development Standards - Applies to all new wasm and golang-filter plugins\nglobs:\n - \"plugins/wa"
},
{
"path": ".github/ISSUE_TEMPLATE/FEATURE_REQUEST.md",
"chars": 448,
"preview": "---\nname: Feature Request\nabout: Suggest an idea for Higress\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n## Why do you need"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 189,
"preview": "blank_issues_enabled: true\ncontact_links:\n - name: Ask a question 💬\n url: https://github.com/alibaba/higress/discuss"
},
{
"path": ".github/ISSUE_TEMPLATE/non--crash-security--bug.md",
"chars": 1264,
"preview": "---\nname: Non-{crash,security} bug\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 1609,
"preview": "<!-- Please make sure you have read and understood the contributing guidelines -->\n\n## Ⅰ. Describe what this PR did\n\n\n##"
},
{
"path": ".github/workflows/build-and-push-wasm-plugin-image.yaml",
"chars": 6242,
"preview": "name: Build and Push Wasm Plugin Image\n\non:\n push:\n tags:\n - \"wasm-*-*-v*.*.*\" # 匹配 wasm-{go|rust}-{pluginName}"
},
{
"path": ".github/workflows/build-and-test-plugin.yaml",
"chars": 2449,
"preview": "name: \"Build and Test Plugins\"\n\non:\n push:\n branches: [main]\n paths:\n - \"plugins/**\"\n - \"test/**\"\n "
},
{
"path": ".github/workflows/build-and-test.yaml",
"chars": 3961,
"preview": "name: \"Build and Test\"\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [\"*\"]\n\nenv:\n GO_VERSION: 1.24\njo"
},
{
"path": ".github/workflows/build-image-and-push.yaml",
"chars": 8114,
"preview": "name: Build Docker Images and Push to Image Registry\n\non:\n push:\n tags:\n - \"v*.*.*\"\n workflow_dispatch: ~\n\njobs:"
},
{
"path": ".github/workflows/codeql-analysis.yaml",
"chars": 2420,
"preview": "# For most projects, this workflow file will not need changing; you simply need\n# to commit it to your repository.\n#\n# Y"
},
{
"path": ".github/workflows/deploy-standalone-to-oss.yaml",
"chars": 1504,
"preview": "name: Deploy Standalone to OSS\r\n\r\non:\r\n push:\r\n tags:\r\n - \"v*.*.*\"\r\n workflow_dispatch: ~\r\n\r\njobs:\r\n deploy-to-"
},
{
"path": ".github/workflows/deploy-to-oss.yaml",
"chars": 2160,
"preview": "name: Deploy Artifacts to OSS\r\n\r\non:\r\n push:\r\n tags:\r\n - \"v*.*.*\"\r\n workflow_dispatch: ~\r\n\r\njobs:\r\n deploy-to-o"
},
{
"path": ".github/workflows/generate-release-notes.yaml",
"chars": 9953,
"preview": "name: Generate Release Notes\n\non:\n push:\n tags:\n - \"v*.*.*\"\n workflow_dispatch: ~\n\njobs:\n generate-release-no"
},
{
"path": ".github/workflows/helm-docs.yaml",
"chars": 1056,
"preview": "name: \"Helm Docs\"\n\non:\n pull_request:\n branches:\n - \"*\"\n paths:\n - 'helm/**'\n - '!helm/higress/REA"
},
{
"path": ".github/workflows/license-checker.yaml",
"chars": 672,
"preview": "name: License checker\n\non:\n pull_request:\n branches: [ develop, main ]\n\njobs:\n check-license:\n runs-on: ubuntu"
},
{
"path": ".github/workflows/release-crd.yaml",
"chars": 565,
"preview": "name: Release CRD to GitHub\n\non:\n push:\n tags:\n - \"v*.*.*\"\n workflow_dispatch: ~\n\njobs:\n release-crd:\n runs-"
},
{
"path": ".github/workflows/release-hgctl.yaml",
"chars": 2756,
"preview": "name: Release hgctl to GitHub\r\n\r\non:\r\n push:\r\n tags:\r\n - \"v*.*.*\"\r\n workflow_dispatch: ~\r\n\r\njobs:\r\n release-hgc"
},
{
"path": ".github/workflows/sync-crds.yaml",
"chars": 988,
"preview": "name: \"Sync CRDs to Helm Chart\"\n\non:\n workflow_dispatch: ~\n push:\n branches: [ main ]\n paths:\n - 'api/kuber"
},
{
"path": ".github/workflows/sync-skills-to-oss.yaml",
"chars": 1570,
"preview": "name: Sync Skills to OSS\n\non:\n push:\n branches:\n - main\n paths:\n - '.claude/skills/**'\n workflow_dispa"
},
{
"path": ".github/workflows/translate-readme.yaml",
"chars": 4620,
"preview": "name: \"Helm Docs\"\n\non:\n workflow_dispatch: ~\n push:\n branches: [ main ]\n paths:\n - 'helm/higress/README.md'"
},
{
"path": ".github/workflows/translate-test.yml",
"chars": 686,
"preview": "name: 'Translate GitHub content into English'\non:\n issues:\n types: [opened, edited]\n issue_comment:\n types: [cre"
},
{
"path": ".github/workflows/wasm-plugin-unit-test.yml",
"chars": 16078,
"preview": "name: Wasm Plugin Unit Tests(GO)\n\non:\n push:\n branches: [ main ]\n paths:\n - 'plugins/wasm-go/extensions/**'\n"
},
{
"path": ".gitignore",
"chars": 209,
"preview": "out\n*.out\n*.tgz\n*.wasm\n.DS_Store\ncoverage.xml\n.idea/\n.vscode/\nbazel-bin\nbazel-out\nbazel-testlogs\nbazel-wasm-cpp\nexternal"
},
{
"path": ".gitmodules",
"chars": 936,
"preview": "[submodule \"istio/api\"]\n\tpath = istio/api\n\turl = https://github.com/higress-group/api\n\tbranch = istio-1.27\n\tshallow = tr"
},
{
"path": ".licenserc.yaml",
"chars": 815,
"preview": "header:\n license:\n spdx-id: Apache-2.0\n copyright-owner: alibaba\n\n paths-ignore:\n - '.gitignore'\n - '*.md'"
},
{
"path": "ADOPTERS.md",
"chars": 1588,
"preview": "# Adopters of Higress\n\nBelow are the adopters of the Higress project. If you are using Higress in your organization, ple"
},
{
"path": "CODEOWNERS",
"chars": 390,
"preview": "/api @johnlanni @CH3CHO\n/envoy @gengleilei @johnlanni\n/istio @SpecialYang @johnlanni\n/pkg @SpecialYang @johnlanni @CH3CH"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3359,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "CONTRIBUTING_CN.md",
"chars": 5274,
"preview": "# 为 Higress 做贡献\n\n如果你有兴趣寻找关于Higress的漏洞,我们会热烈欢迎。首先,我们非常鼓励这种意愿。这是为您提供的贡献指南列表。\n\n[[English Contributing Document](./CONTRIBUT"
},
{
"path": "CONTRIBUTING_EN.md",
"chars": 10909,
"preview": "# Contributing to Higress\n\nYour interest in contributing to Higress is warmly welcomed. First, we encourage this kind of"
},
{
"path": "CONTRIBUTING_JP.md",
"chars": 6521,
"preview": "# Higress への貢献\n\nHigress のハッキングに興味がある場合は、温かく歓迎します。まず、このような意欲を非常に奨励します。そして、以下は貢献ガイドのリストです。\n\n[[中文](./CONTRIBUTING.md)] | [["
},
{
"path": "DEP_VERSION",
"chars": 23,
"preview": "higress-console: v2.1.9"
},
{
"path": "LICENSE",
"chars": 21758,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Makefile",
"chars": 2338,
"preview": "# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY\n#\n# The original version of this file is located in the https://git"
},
{
"path": "Makefile.core.mk",
"chars": 21333,
"preview": "SHELL := /bin/bash -o pipefail\n\nexport HIGRESS_BASE_VERSION ?= 2023-07-20T20-50-43\n\nexport HUB ?= higress-registry.cn-ha"
},
{
"path": "Makefile.overrides.mk",
"chars": 1251,
"preview": "# Copyright 2019 Istio Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use thi"
},
{
"path": "README.md",
"chars": 12405,
"preview": "<a name=\"readme-top\"></a>\n<h1 align=\"center\">\n <img src=\"https://img.alicdn.com/imgextra/i2/O1CN01NwxLDd20nxfGBjxmZ_!"
},
{
"path": "README_JP.md",
"chars": 8129,
"preview": "<a name=\"readme-top\"></a>\n<h1 align=\"center\">\n <img src=\"https://img.alicdn.com/imgextra/i2/O1CN01NwxLDd20nxfGBjxmZ_!"
},
{
"path": "README_ZH.md",
"chars": 8847,
"preview": "<a name=\"readme-top\"></a>\n<h1 align=\"center\">\n <img src=\"https://img.alicdn.com/imgextra/i2/O1CN01NwxLDd20nxfGBjxmZ_!"
},
{
"path": "SECURITY.md",
"chars": 478,
"preview": "# Security Policy\n\n## Supported Versions\n\n| Version | Supported |\n| ------- | ------------------ |\n| 2.x.x | "
},
{
"path": "VERSION",
"chars": 6,
"preview": "v2.2.1"
},
{
"path": "api/buf.gen.yaml",
"chars": 476,
"preview": "# buf.gen.yaml sets up the generation configuration for all of our plugins.\n# Note: buf does not allow multi roots that "
},
{
"path": "api/buf.yaml",
"chars": 141,
"preview": "version: v1beta1\nlint:\n use:\n - BASIC\n except:\n - FIELD_LOWER_SNAKE_CASE\n - PACKAGE_DIRECTORY_MATCH\n allow_c"
},
{
"path": "api/cue.yaml",
"chars": 448,
"preview": "# Cuelang configuration to generate OpenAPI schema for Higress configs.\n\nmodule: github.com/alibaba/higress/v2/api\n\nopen"
},
{
"path": "api/extensions/v1alpha1/wasmplugin.pb.go",
"chars": 38860,
"preview": "// Copyright Istio Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use "
},
{
"path": "api/extensions/v1alpha1/wasmplugin.proto",
"chars": 8348,
"preview": "// Copyright Istio Authors\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use "
},
{
"path": "api/extensions/v1alpha1/wasmplugin_deepcopy.gen.go",
"chars": 2796,
"preview": "// Code generated by protoc-gen-deepcopy. DO NOT EDIT.\npackage v1alpha1\n\nimport (\n\tproto \"google.golang.org/protobuf/pro"
},
{
"path": "api/extensions/v1alpha1/wasmplugin_json.gen.go",
"chars": 1728,
"preview": "// Code generated by protoc-gen-jsonshim. DO NOT EDIT.\npackage v1alpha1\n\nimport (\n\tbytes \"bytes\"\n\tjsonpb \"github.com/gol"
},
{
"path": "api/gen.sh",
"chars": 163,
"preview": "#!/bin/bash\n\nset -eu\n\n# Generate all protos\nbuf generate \\\n --path networking \\\n --path extensions\n\n# Generate CRD"
},
{
"path": "api/kubernetes/customresourcedefinitions.gen.yaml",
"chars": 11740,
"preview": "# DO NOT EDIT - Generated by Cue OpenAPI generator based on Istio APIs.\napiVersion: apiextensions.k8s.io/v1\nkind: Custom"
},
{
"path": "api/networking/v1/http_2_rpc.pb.go",
"chars": 22479,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "api/networking/v1/http_2_rpc.proto",
"chars": 2651,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "api/networking/v1/http_2_rpc_deepcopy.gen.go",
"chars": 4240,
"preview": "// Code generated by protoc-gen-deepcopy. DO NOT EDIT.\npackage v1\n\nimport (\n\tproto \"google.golang.org/protobuf/proto\"\n)\n"
},
{
"path": "api/networking/v1/http_2_rpc_json.gen.go",
"chars": 2484,
"preview": "// Code generated by protoc-gen-jsonshim. DO NOT EDIT.\npackage v1\n\nimport (\n\tbytes \"bytes\"\n\tjsonpb \"github.com/golang/pr"
},
{
"path": "api/networking/v1/mcp_bridge.pb.go",
"chars": 36349,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "api/networking/v1/mcp_bridge.proto",
"chars": 3252,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "api/networking/v1/mcp_bridge_deepcopy.gen.go",
"chars": 4540,
"preview": "// Code generated by protoc-gen-deepcopy. DO NOT EDIT.\npackage v1\n\nimport (\n\tproto \"google.golang.org/protobuf/proto\"\n)\n"
},
{
"path": "api/networking/v1/mcp_bridge_json.gen.go",
"chars": 2604,
"preview": "// Code generated by protoc-gen-jsonshim. DO NOT EDIT.\npackage v1\n\nimport (\n\tbytes \"bytes\"\n\tjsonpb \"github.com/golang/pr"
},
{
"path": "api/protocol.yaml",
"chars": 151,
"preview": "protoc:\n # This is ignored because we always run with\n # --protoc-bin-path=/usr/bin/protoc to use the protoc from our\n"
},
{
"path": "client/Makefile",
"chars": 4798,
"preview": "# Copyright Istio Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this fil"
},
{
"path": "client/header.go.txt",
"chars": 608,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/apis/extensions/v1alpha1/doc.go",
"chars": 829,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/apis/extensions/v1alpha1/register.gen.go",
"chars": 1539,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/apis/extensions/v1alpha1/types.gen.go",
"chars": 2796,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/apis/extensions/v1alpha1/zz_generated.deepcopy.gen.go",
"chars": 2608,
"preview": "//go:build !ignore_autogenerated\n// +build !ignore_autogenerated\n\n// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n//"
},
{
"path": "client/pkg/apis/networking/v1/doc.go",
"chars": 823,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/apis/networking/v1/register.gen.go",
"chars": 1567,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/apis/networking/v1/types.gen.go",
"chars": 3564,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/apis/networking/v1/zz_generated.deepcopy.gen.go",
"chars": 4366,
"preview": "//go:build !ignore_autogenerated\n// +build !ignore_autogenerated\n\n// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n//"
},
{
"path": "client/pkg/applyconfiguration/extensions/v1alpha1/wasmplugin.go",
"chars": 10491,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/applyconfiguration/internal/internal.go",
"chars": 1535,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/applyconfiguration/meta/v1/managedfieldsentry.go",
"chars": 4699,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/applyconfiguration/meta/v1/objectmeta.go",
"chars": 8673,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/applyconfiguration/meta/v1/ownerreference.go",
"chars": 3998,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/applyconfiguration/meta/v1/typemeta.go",
"chars": 1932,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/applyconfiguration/networking/v1/http2rpc.go",
"chars": 10377,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/applyconfiguration/networking/v1/mcpbridge.go",
"chars": 10424,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/applyconfiguration/utils.go",
"chars": 2423,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/clientset.gen.go",
"chars": 4460,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/fake/clientset_generated.gen.go",
"chars": 3307,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/fake/doc.go",
"chars": 733,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/fake/register.gen.go",
"chars": 2017,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/scheme/doc.go",
"chars": 749,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/scheme/register.gen.go",
"chars": 2098,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/extensions/v1alpha1/doc.go",
"chars": 736,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/extensions/v1alpha1/extensions_client.gen.go",
"chars": 3297,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/extensions/v1alpha1/fake/doc.go",
"chars": 726,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/extensions/v1alpha1/fake/fake_extensions_client.gen.go",
"chars": 1254,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/extensions/v1alpha1/fake/fake_wasmplugin.gen.go",
"chars": 7234,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/extensions/v1alpha1/generated_expansion.gen.go",
"chars": 711,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/extensions/v1alpha1/wasmplugin.gen.go",
"chars": 9207,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/doc.go",
"chars": 730,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/fake/doc.go",
"chars": 726,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/fake/fake_http2rpc.gen.go",
"chars": 6862,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/fake/fake_mcpbridge.gen.go",
"chars": 6954,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/fake/fake_networking_client.gen.go",
"chars": 1333,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/generated_expansion.gen.go",
"chars": 740,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/http2rpc.gen.go",
"chars": 8849,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/mcpbridge.gen.go",
"chars": 8958,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/clientset/versioned/typed/networking/v1/networking_client.gen.go",
"chars": 3311,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/extensions/interface.gen.go",
"chars": 1686,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/extensions/v1alpha1/interface.gen.go",
"chars": 1620,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/extensions/v1alpha1/wasmplugin.gen.go",
"chars": 3775,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/factory.gen.go",
"chars": 9136,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/generic.gen.go",
"chars": 2538,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/internalinterfaces/factory_interfaces.gen.go",
"chars": 1471,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/networking/interface.gen.go",
"chars": 1620,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/networking/v1/http2rpc.gen.go",
"chars": 3671,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/networking/v1/interface.gen.go",
"chars": 1878,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/informers/externalversions/networking/v1/mcpbridge.gen.go",
"chars": 3693,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/listers/extensions/v1alpha1/expansion_generated.gen.go",
"chars": 962,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/listers/extensions/v1alpha1/wasmplugin.gen.go",
"chars": 3626,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/listers/networking/v1/expansion_generated.gen.go",
"chars": 1227,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/listers/networking/v1/http2rpc.gen.go",
"chars": 3452,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "client/pkg/listers/networking/v1/mcpbridge.gen.go",
"chars": 3500,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "cmd/higress/main.go",
"chars": 864,
"preview": "// Copyright (c) 2022 Alibaba Group Holding Ltd.\n//\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n/"
},
{
"path": "codecov.yml",
"chars": 455,
"preview": "codecov:\n require_ci_to_pass: yes\ncoverage:\n status:\n patch: \n default:\n target: 50%\n threshold:"
},
{
"path": "docker/Dockerfile.base",
"chars": 961,
"preview": "FROM ubuntu:22.04\n\nENV DEBIAN_FRONTEND=noninteractive\n\n# Do not add more stuff to this list that isn't small or critical"
},
{
"path": "docker/Dockerfile.higress",
"chars": 588,
"preview": "# BASE_DISTRIBUTION is used to switch between the old base distribution and distroless base images\nARG BASE_DISTRIBUTION"
},
{
"path": "docker/docker-copy.sh",
"chars": 2133,
"preview": "#!/bin/bash\n\n# Copyright 2019 Istio Authors\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you ma"
},
{
"path": "docker/docker.mk",
"chars": 3563,
"preview": "## Copyright 2018 Istio Authors\n##\n## Licensed under the Apache License, Version 2.0 (the \"License\");\n## you may not use"
},
{
"path": "docs/architecture.md",
"chars": 6258,
"preview": "# Higress 核心组件和原理\n\nHigress 是基于 Envoy 和 Istio 进行二次定制化开发构建和功能增强,同时利用 Envoy 和 Istio 一些插件机制,实现了一个轻量级的网关服务。其包括 3 个核心组件:Higres"
},
{
"path": "get_helm.sh",
"chars": 11694,
"preview": "#!/usr/bin/env bash\n\n# Copyright The Helm Authors.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n#"
},
{
"path": "go.mod",
"chars": 14628,
"preview": "module github.com/alibaba/higress/v2\n\ngo 1.24.4\n\nreplace github.com/spf13/viper => github.com/istio/viper v1.3.3-0.20190"
},
{
"path": "go.sum",
"chars": 563072,
"preview": "cel.dev/expr v0.15.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg=\ncel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/"
},
{
"path": "helm/core/.helmignore",
"chars": 46,
"preview": "crds/customresourcedefinitions.gen_lt1.16.yaml"
},
{
"path": "helm/core/Chart.yaml",
"chars": 416,
"preview": "apiVersion: v2\nappVersion: 2.2.0\ndescription: Helm chart for deploying higress gateways\nicon: https://higress.io/img/hig"
},
{
"path": "helm/core/LICENSE",
"chars": 21758,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "helm/core/README.md",
"chars": 254,
"preview": "# Higress Core Helm Chart\n\nInstalls the core components of cloud-native gateway [Higress](http://higress.io/)\n\n**Note:**"
},
{
"path": "helm/core/charts/redis/.helmignore",
"chars": 349,
"preview": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation"
},
{
"path": "helm/core/charts/redis/Chart.yaml",
"chars": 1142,
"preview": "apiVersion: v2\nname: redis\ndescription: A Helm chart for Kubernetes\n\n# A chart can be either an 'application' or a 'libr"
},
{
"path": "helm/core/charts/redis/templates/_helpers.tpl",
"chars": 820,
"preview": "{{/*\nExpand the name of the chart.\n*/}}\n\n{{- define \"redis.name\" -}}\n{{- .Values.redis.name | default \"redis-stack-serve"
},
{
"path": "helm/core/charts/redis/templates/configmap.yaml",
"chars": 240,
"preview": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: {{ include \"redis.name\" . }}\n namespace: {{ .Release.Namespace }}\ndata"
},
{
"path": "helm/core/charts/redis/templates/pvc.yaml",
"chars": 443,
"preview": "{{- if .Values.redis.persistence.enabled }}\napiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n name: {{ include \"red"
},
{
"path": "helm/core/charts/redis/templates/service.yaml",
"chars": 383,
"preview": "apiVersion: v1\nkind: Service\nmetadata:\n name: {{ include \"redis.name\" . }}\n namespace: {{ .Release.Namespace }}\n labe"
},
{
"path": "helm/core/charts/redis/templates/statefulset.yaml",
"chars": 2343,
"preview": "apiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: {{ include \"redis.name\" . }}\n namespace: {{ .Release.Namespace "
},
{
"path": "helm/core/charts/redis/values.yaml",
"chars": 1462,
"preview": "# Default values for redis.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates.\ngloba"
},
{
"path": "helm/core/crds/customresourcedefinitions.gen.yaml",
"chars": 11740,
"preview": "# DO NOT EDIT - Generated by Cue OpenAPI generator based on Istio APIs.\napiVersion: apiextensions.k8s.io/v1\nkind: Custom"
},
{
"path": "helm/core/crds/customresourcedefinitions.gen_lt1.16.yaml",
"chars": 5495,
"preview": "# DO NOT EDIT - Generated by Cue OpenAPI generator based on Istio APIs.\r\napiVersion: apiextensions.k8s.io/v1beta1\r\nkind:"
},
{
"path": "helm/core/crds/istio-envoyfilter.yaml",
"chars": 10186,
"preview": "---\napiVersion: apiextensions.k8s.io/v1\nkind: CustomResourceDefinition\nmetadata:\n annotations:\n \"helm.sh/resource-po"
},
{
"path": "helm/core/templates/NOTES.txt",
"chars": 200,
"preview": "Higress successfully installed!\n\nTo learn more about the release, try:\n $ helm status {{ .Release.Name }} -n {{ .Releas"
},
{
"path": "helm/core/templates/_helpers.tpl",
"chars": 4730,
"preview": "{{- define \"gateway.name\" -}}\n{{- .Values.gateway.name | default \"higress-gateway\" -}}\n{{- end }}\n\n{{/*\nCreate chart nam"
},
{
"path": "helm/core/templates/_pod.tpl",
"chars": 11095,
"preview": "\n{{/*\nRendering the pod template of gateway component.\n*/}}\n{{- define \"gateway.podTemplate\" -}}\n{{- $o11y := .Values.gl"
},
{
"path": "helm/core/templates/clusterrole.yaml",
"chars": 708,
"preview": "{{- if .Values.gateway.rbac.enabled }}\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n name: {{ i"
},
{
"path": "helm/core/templates/configmap.yaml",
"chars": 7619,
"preview": "{{- define \"mesh\" }}\n # The trust domain corresponds to the trust root of a system.\n # Refer to https://github.com"
},
{
"path": "helm/core/templates/controller-clusterrole.yaml",
"chars": 5352,
"preview": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n name: {{ include \"controller.serviceAccountNa"
},
{
"path": "helm/core/templates/controller-clusterrolebinding.yaml",
"chars": 509,
"preview": "---\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n name: {{ include \"controller.serviceAc"
},
{
"path": "helm/core/templates/controller-deployment.yaml",
"chars": 13064,
"preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: {{ include \"controller.name\" . }}\n namespace: {{ .Release.Namesp"
},
{
"path": "helm/core/templates/controller-role.yaml",
"chars": 436,
"preview": "apiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n name: {{ include \"controller.serviceAccountName\" . }}\n "
},
{
"path": "helm/core/templates/controller-rolebinding.yaml",
"chars": 475,
"preview": "apiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n name: {{ include \"controller.serviceAccountName\" "
},
{
"path": "helm/core/templates/controller-service.yaml",
"chars": 728,
"preview": "apiVersion: v1\nkind: Service\nmetadata:\n name: {{ include \"controller.name\" . }}\n namespace: {{ .Release.Namespace }}\n "
},
{
"path": "helm/core/templates/controller-serviceaccont.yaml",
"chars": 385,
"preview": "{{- if .Values.controller.serviceAccount.create }}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n name: {{ include \"con"
},
{
"path": "helm/core/templates/daemonset.yaml",
"chars": 1124,
"preview": "{{- if eq .Values.gateway.kind \"DaemonSet\" -}}\n{{- $o11y := .Values.global.o11y }}\n{{- if eq .Values.gateway.unprivileg"
},
{
"path": "helm/core/templates/deployment.yaml",
"chars": 1575,
"preview": "{{- if eq .Values.gateway.kind \"Deployment\" -}}\n{{- if eq .Values.gateway.unprivilegedPortSupported nil -}}\n {{- $unpri"
},
{
"path": "helm/core/templates/fallback-envoyfilter.yaml",
"chars": 775,
"preview": "apiVersion: networking.istio.io/v1alpha3\nkind: EnvoyFilter\nmetadata:\n name: {{ include \"gateway.name\" . }}-global-custo"
},
{
"path": "helm/core/templates/hpa.yaml",
"chars": 1639,
"preview": "{{- if .Values.gateway.autoscaling.enabled }}\n{{- if not .Values.global.autoscalingv2API }}\napiVersion: autoscaling/v2be"
},
{
"path": "helm/core/templates/ingressclass.yaml",
"chars": 211,
"preview": "{{- if .Values.global.ingressClass }}\r\napiVersion: networking.k8s.io/v1\r\nkind: IngressClass\r\nmetadata:\r\n name: {{ .Valu"
},
{
"path": "helm/core/templates/plugin-server-deployment.yaml",
"chars": 1466,
"preview": "{{- if .Values.global.enablePluginServer }}\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: {{ include \"pluginSer"
},
{
"path": "helm/core/templates/plugin-server-service.yaml",
"chars": 425,
"preview": "{{- if .Values.global.enablePluginServer }}\napiVersion: v1\nkind: Service\nmetadata:\n name: {{ include \"pluginServer.name"
},
{
"path": "helm/core/templates/podmonitor.yaml",
"chars": 1914,
"preview": "{{- if .Values.gateway.metrics.enabled }}\n{{- include \"gateway.podMonitor.gvk\" . }}\nmetadata:\n name: {{ printf \"%s-metr"
},
{
"path": "helm/core/templates/promtail.yaml",
"chars": 1538,
"preview": "{{- $o11y := .Values.global.o11y }}\n{{- if $o11y.enabled }}\n{{- $config := $o11y.promtail }}\napiVersion: v1\nkind: Confi"
}
]
// ... and 1930 more files (download for full content)
About this extraction
This page contains the full source code of the alibaba/higress GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 2130 files (100.7 MB), approximately 4.5M tokens, and a symbol index with 11408 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.