`
+ 在 PR 描述中说明:
+ - 优化的动机与改进点
+ - 改进前后的对比或预期收益
+ - 验证优化是否生效的测试方法
+6. 在原 Issue 下使用用户提问的语言进行回复,说明已提交 PR、优化思路及预期的提升效果。
+
+如果功能改进可能带来重大的破坏性变更(Breaking Changes)或者现有代码结构不支持盲目优化,在 Issue 下用中文说明原因,保持维持原状,不创建 PR。
\ No newline at end of file
diff --git a/.github/workflows/issue-triage.lock.yml b/.github/workflows/issue-triage.lock.yml
index 4dd0549..c4c7adb 100644
--- a/.github/workflows/issue-triage.lock.yml
+++ b/.github/workflows/issue-triage.lock.yml
@@ -1,5 +1,5 @@
-# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"49f1529d95cbf3c8e3d0da1df4b6cee935245532511b98ca9ecd7a44f1d0bb68","compiler_version":"v0.71.5","agent_id":"copilot"}
-# gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"b8068426813005612b960b5ab0b8bd2c27142323","version":"v0.71.5"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.0.3","digest":"sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959","pinned_image":"ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]}
+# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"01651461ea771a40a1d9a25bbf950f25e913d6b556796467343b77b45eabdd15","body_hash":"b17fdb8754e311cfac38664fbaa575804386c0027689ce0def213670917f77f0","compiler_version":"v0.79.6","agent_id":"copilot","engine_versions":{"copilot":"1.0.60"}}
+# gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN","OPENAI_API_KEY"],"actions":[{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"5c2fe865bb4dc46e1450f6ee0d0541d759aea73a","version":"v0.79.6"}],"containers":[{"image":"ghcr.io/github/github-mcp-server:v1.1.2","digest":"sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c","pinned_image":"ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c"}]}
# ___ _ _
# / _ \ | | (_)
# | |_| | __ _ ___ _ __ | |_ _ ___
@@ -14,7 +14,7 @@
# \ /\ / (_) | | | | ( | | | | (_) \ V V /\__ \
# \/ \/ \___/|_| |_|\_\|_| |_|\___/ \_/\_/ |___/
#
-# This file was automatically generated by gh-aw (v0.71.5). DO NOT EDIT.
+# This file was automatically generated by gh-aw (v0.79.6). DO NOT EDIT.
#
# To update this file, edit the corresponding .md file and run:
# gh aw compile
@@ -24,25 +24,23 @@
#
#
# Secrets used:
-# - COPILOT_GITHUB_TOKEN
# - GH_AW_GITHUB_MCP_SERVER_TOKEN
# - GH_AW_GITHUB_TOKEN
# - GITHUB_TOKEN
# - OPENAI_API_KEY
#
# Custom actions used:
-# - actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+# - actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
# - actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
# - actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
# - actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
-# - github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5
+# - github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
#
# Container images used:
-# - ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959
-# - node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f
+# - ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c
name: "Issue 自动分类与回复"
-"on":
+on:
issues:
types:
- opened
@@ -63,13 +61,20 @@ jobs:
permissions:
actions: read
contents: read
+ env:
+ GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }}
outputs:
body: ${{ steps.sanitized.outputs.body }}
comment_id: ""
comment_repo: ""
+ daily_effective_workflow_exceeded: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_exceeded == 'true' }}
+ daily_effective_workflow_threshold: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_threshold || '' }}
+ daily_effective_workflow_total_effective_tokens: ${{ steps.daily-effective-workflow-guardrail.outputs.daily_effective_workflow_total_effective_tokens || '' }}
engine_id: ${{ steps.generate_aw_info.outputs.engine_id }}
lockdown_check_failed: ${{ steps.generate_aw_info.outputs.lockdown_check_failed == 'true' }}
model: ${{ steps.generate_aw_info.outputs.model }}
+ setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
+ setup-span-id: ${{ steps.setup.outputs.span-id }}
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
stale_lock_file_failed: ${{ steps.check-lock-file.outputs.stale_lock_file_failed == 'true' }}
text: ${{ steps.sanitized.outputs.text }}
@@ -77,24 +82,27 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5
+ uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.pre_activation.outputs.setup-trace-id }}
+ parent-span-id: ${{ needs.pre_activation.outputs.setup-parent-span-id || needs.pre_activation.outputs.setup-span-id }}
+ safe-output-artifact-client: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.40"
+ GH_AW_INFO_VERSION: "1.0.60"
+ GH_AW_INFO_ENGINE_ID: "copilot"
- name: Generate agentic run info
id: generate_aw_info
env:
GH_AW_INFO_ENGINE_ID: "copilot"
GH_AW_INFO_ENGINE_NAME: "GitHub Copilot CLI"
- GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || 'claude-sonnet-4.6' }}
- GH_AW_INFO_VERSION: "1.0.40"
- GH_AW_INFO_AGENT_VERSION: "1.0.40"
- GH_AW_INFO_CLI_VERSION: "v0.71.5"
+ GH_AW_INFO_MODEL: ${{ vars.GH_AW_MODEL_AGENT_COPILOT || vars.GH_AW_DEFAULT_MODEL_COPILOT || 'claude-sonnet-4.6' }}
+ GH_AW_INFO_VERSION: "1.0.60"
+ GH_AW_INFO_AGENT_VERSION: "1.0.60"
+ GH_AW_INFO_CLI_VERSION: "v0.79.6"
GH_AW_INFO_WORKFLOW_NAME: "Issue 自动分类与回复"
GH_AW_INFO_EXPERIMENTAL: "false"
GH_AW_INFO_SUPPORTS_TOOLS_ALLOWLIST: "true"
@@ -112,13 +120,32 @@ jobs:
setupGlobals(core, github, context, exec, io, getOctokit);
const { main } = require('${{ runner.temp }}/gh-aw/actions/generate_aw_info.cjs');
await main(core, context);
+ - name: Check daily workflow token guardrail
+ id: daily-effective-workflow-guardrail
+ if: ${{ env.GH_AW_MAX_DAILY_AI_CREDITS != '' }}
+ uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
+ env:
+ GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复"
+ GH_AW_WORKFLOW_ID: "issue-triage"
+ GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
+ GH_AW_WORKFLOW_DISPATCH_AW_CONTEXT: ${{ github.event.inputs.aw_context || '' }}
+ GH_AW_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GH_AW_MAX_DAILY_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_DAILY_AI_CREDITS || '5000' }}
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
+ setupGlobals(core, github, context, exec, io, getOctokit);
+ const { main } = require('${{ runner.temp }}/gh-aw/actions/check_daily_aic_workflow_guardrail.cjs');
+ await main();
- name: Checkout .github and .agents folders
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
sparse-checkout: |
.github
.agents
+ .antigravity
.claude
.codex
.crush
@@ -129,8 +156,8 @@ jobs:
fetch-depth: 1
- name: Save agent config folders for base branch restoration
env:
- GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi"
- GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc"
+ GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi"
+ GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc"
# poutine:ignore untrusted_checkout_exec
run: bash "${RUNNER_TEMP}/gh-aw/actions/save_base_github_folders.sh"
- name: Check workflow lock file
@@ -148,7 +175,7 @@ jobs:
- name: Check compile-agentic version
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
- GH_AW_COMPILED_VERSION: "v0.71.5"
+ GH_AW_COMPILED_VERSION: "v0.79.6"
with:
script: |
const { setupGlobals } = require('${{ runner.temp }}/gh-aw/actions/setup_globals.cjs');
@@ -170,11 +197,11 @@ jobs:
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl
+ GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
+ GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
+ GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
+ GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
- GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
- GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
- GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
- GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
@@ -182,54 +209,54 @@ jobs:
run: |
bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh"
{
- cat << 'GH_AW_PROMPT_1857816c8098cba9_EOF'
+ cat << 'GH_AW_PROMPT_72243dd344875363_EOF'
- GH_AW_PROMPT_1857816c8098cba9_EOF
+ GH_AW_PROMPT_72243dd344875363_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md"
cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md"
- cat << 'GH_AW_PROMPT_1857816c8098cba9_EOF'
+ cat << 'GH_AW_PROMPT_72243dd344875363_EOF'
Tools: add_comment, add_labels, missing_tool, missing_data, noop
- GH_AW_PROMPT_1857816c8098cba9_EOF
+ GH_AW_PROMPT_72243dd344875363_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md"
- cat << 'GH_AW_PROMPT_1857816c8098cba9_EOF'
+ cat << 'GH_AW_PROMPT_72243dd344875363_EOF'
The following GitHub context information is available for this workflow:
- {{#if __GH_AW_GITHUB_ACTOR__ }}
+ {{#if github.actor}}
- **actor**: __GH_AW_GITHUB_ACTOR__
{{/if}}
- {{#if __GH_AW_GITHUB_REPOSITORY__ }}
+ {{#if github.repository}}
- **repository**: __GH_AW_GITHUB_REPOSITORY__
{{/if}}
- {{#if __GH_AW_GITHUB_WORKSPACE__ }}
+ {{#if github.workspace}}
- **workspace**: __GH_AW_GITHUB_WORKSPACE__
{{/if}}
- {{#if __GH_AW_GITHUB_EVENT_ISSUE_NUMBER__ }}
- - **issue-number**: #__GH_AW_GITHUB_EVENT_ISSUE_NUMBER__
+ {{#if github.event.issue.number || (github.aw.context.item_type == 'issue' && github.aw.context.item_number)}}
+ - **issue-number**: #__GH_AW_EXPR_802A9F6A__
{{/if}}
- {{#if __GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__ }}
- - **discussion-number**: #__GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER__
+ {{#if github.event.discussion.number || (github.aw.context.item_type == 'discussion' && github.aw.context.item_number)}}
+ - **discussion-number**: #__GH_AW_EXPR_1A3A194A__
{{/if}}
- {{#if __GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__ }}
- - **pull-request-number**: #__GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER__
+ {{#if github.event.pull_request.number || (github.aw.context.item_type == 'pull_request' && github.aw.context.item_number)}}
+ - **pull-request-number**: #__GH_AW_EXPR_463A214A__
{{/if}}
- {{#if __GH_AW_GITHUB_EVENT_COMMENT_ID__ }}
- - **comment-id**: __GH_AW_GITHUB_EVENT_COMMENT_ID__
+ {{#if github.event.comment.id || github.aw.context.comment_id}}
+ - **comment-id**: __GH_AW_EXPR_FF1D34CE__
{{/if}}
- {{#if __GH_AW_GITHUB_RUN_ID__ }}
+ {{#if github.run_id}}
- **workflow-run-id**: __GH_AW_GITHUB_RUN_ID__
{{/if}}
- GH_AW_PROMPT_1857816c8098cba9_EOF
+ GH_AW_PROMPT_72243dd344875363_EOF
cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md"
- cat << 'GH_AW_PROMPT_1857816c8098cba9_EOF'
+ cat << 'GH_AW_PROMPT_72243dd344875363_EOF'
{{#runtime-import .github/workflows/issue-triage.md}}
- GH_AW_PROMPT_1857816c8098cba9_EOF
+ GH_AW_PROMPT_72243dd344875363_EOF
} > "$GH_AW_PROMPT"
- name: Interpolate variables and render templates
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
@@ -247,11 +274,11 @@ jobs:
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
+ GH_AW_EXPR_1A3A194A: ${{ github.event.discussion.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'discussion' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
+ GH_AW_EXPR_463A214A: ${{ github.event.pull_request.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'pull_request' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
+ GH_AW_EXPR_802A9F6A: ${{ github.event.issue.number || (fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_type == 'issue' && fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').item_number) }}
+ GH_AW_EXPR_FF1D34CE: ${{ github.event.comment.id || fromJSON(github.event.inputs.aw_context || github.event.client_payload.aw_context || '{}').comment_id }}
GH_AW_GITHUB_ACTOR: ${{ github.actor }}
- GH_AW_GITHUB_EVENT_COMMENT_ID: ${{ github.event.comment.id }}
- GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: ${{ github.event.discussion.number }}
- GH_AW_GITHUB_EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
- GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
GH_AW_GITHUB_REPOSITORY: ${{ github.repository }}
GH_AW_GITHUB_RUN_ID: ${{ github.run_id }}
GH_AW_GITHUB_WORKSPACE: ${{ github.workspace }}
@@ -268,11 +295,11 @@ jobs:
return await substitutePlaceholders({
file: process.env.GH_AW_PROMPT,
substitutions: {
+ GH_AW_EXPR_1A3A194A: process.env.GH_AW_EXPR_1A3A194A,
+ GH_AW_EXPR_463A214A: process.env.GH_AW_EXPR_463A214A,
+ GH_AW_EXPR_802A9F6A: process.env.GH_AW_EXPR_802A9F6A,
+ GH_AW_EXPR_FF1D34CE: process.env.GH_AW_EXPR_FF1D34CE,
GH_AW_GITHUB_ACTOR: process.env.GH_AW_GITHUB_ACTOR,
- GH_AW_GITHUB_EVENT_COMMENT_ID: process.env.GH_AW_GITHUB_EVENT_COMMENT_ID,
- GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER: process.env.GH_AW_GITHUB_EVENT_DISCUSSION_NUMBER,
- GH_AW_GITHUB_EVENT_ISSUE_NUMBER: process.env.GH_AW_GITHUB_EVENT_ISSUE_NUMBER,
- GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER: process.env.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER,
GH_AW_GITHUB_REPOSITORY: process.env.GH_AW_GITHUB_REPOSITORY,
GH_AW_GITHUB_RUN_ID: process.env.GH_AW_GITHUB_RUN_ID,
GH_AW_GITHUB_WORKSPACE: process.env.GH_AW_GITHUB_WORKSPACE,
@@ -298,17 +325,25 @@ jobs:
include-hidden-files: true
path: |
/tmp/gh-aw/aw_info.json
+ /tmp/gh-aw/model_multipliers.json
+ /tmp/gh-aw/models.json
/tmp/gh-aw/aw-prompts/prompt.txt
+ /tmp/gh-aw/aw-prompts/prompt-template.txt
+ /tmp/gh-aw/aw-prompts/prompt-import-tree.json
/tmp/gh-aw/github_rate_limits.jsonl
/tmp/gh-aw/base
+ /tmp/gh-aw/.github/agents
+ /tmp/gh-aw/.github/skills
if-no-files-found: ignore
retention-days: 1
agent:
needs: activation
+ if: needs.activation.outputs.daily_effective_workflow_exceeded != 'true'
runs-on: ubuntu-latest
permissions:
contents: read
+ copilot-requests: write
issues: read
pull-requests: read
env:
@@ -319,29 +354,37 @@ jobs:
GH_AW_MCP_LOG_DIR: /tmp/gh-aw/mcp-logs/safeoutputs
GH_AW_WORKFLOW_ID_SANITIZED: issuetriage
outputs:
- agentic_engine_timeout: ${{ steps.detect-copilot-errors.outputs.agentic_engine_timeout || 'false' }}
+ agentic_engine_timeout: ${{ steps.detect-agent-errors.outputs.agentic_engine_timeout || 'false' }}
+ ai_credits_rate_limit_error: ${{ steps.parse-mcp-gateway.outputs.ai_credits_rate_limit_error || 'false' }}
+ aic: ${{ steps.parse-mcp-gateway.outputs.aic }}
+ ambient_context: ${{ steps.parse-mcp-gateway.outputs.ambient_context }}
checkout_pr_success: ${{ steps.checkout-pr.outputs.checkout_pr_success || 'true' }}
effective_tokens: ${{ steps.parse-mcp-gateway.outputs.effective_tokens }}
has_patch: ${{ steps.collect_output.outputs.has_patch }}
- inference_access_error: ${{ steps.detect-copilot-errors.outputs.inference_access_error || 'false' }}
- mcp_policy_error: ${{ steps.detect-copilot-errors.outputs.mcp_policy_error || 'false' }}
+ inference_access_error: ${{ steps.detect-agent-errors.outputs.inference_access_error || 'false' }}
+ mcp_policy_error: ${{ steps.detect-agent-errors.outputs.mcp_policy_error || 'false' }}
model: ${{ needs.activation.outputs.model }}
- model_not_supported_error: ${{ steps.detect-copilot-errors.outputs.model_not_supported_error || 'false' }}
+ model_not_supported_error: ${{ steps.detect-agent-errors.outputs.model_not_supported_error || 'false' }}
output: ${{ steps.collect_output.outputs.output }}
output_types: ${{ steps.collect_output.outputs.output_types }}
+ setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
+ setup-span-id: ${{ steps.setup.outputs.span-id }}
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
+ unknown_model_ai_credits: ${{ steps.parse-mcp-gateway.outputs.unknown_model_ai_credits || 'false' }}
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5
+ uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.40"
+ GH_AW_INFO_VERSION: "1.0.60"
+ GH_AW_INFO_ENGINE_ID: "copilot"
- name: Set runtime paths
id: set-runtime-paths
run: |
@@ -351,7 +394,7 @@ jobs:
echo "GH_AW_SAFE_OUTPUTS_TOOLS_PATH=${RUNNER_TEMP}/gh-aw/safeoutputs/tools.json"
} >> "$GITHUB_OUTPUT"
- name: Checkout repository
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
- name: Create gh-aw temp directory
@@ -376,7 +419,7 @@ jobs:
- name: Checkout PR branch
id: checkout-pr
if: |
- github.event.pull_request || github.event.issue.pull_request
+ github.event.pull_request || github.event.issue.pull_request || github.event_name == 'workflow_dispatch' && fromJSON(github.event.inputs.aw_context || '{}').item_type == 'pull_request'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
@@ -388,7 +431,7 @@ jobs:
const { main } = require('${{ runner.temp }}/gh-aw/actions/checkout_pr_branch.cjs');
await main();
- name: Install GitHub Copilot CLI
- run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.40
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/install_copilot_cli.sh" 1.0.60
env:
GH_HOST: github.com
- name: Parse integrity filter lists
@@ -406,19 +449,28 @@ jobs:
- name: Restore agent config folders from base branch
if: steps.checkout-pr.outcome == 'success'
env:
- GH_AW_AGENT_FOLDERS: ".agents .claude .codex .crush .gemini .github .opencode .pi"
- GH_AW_AGENT_FILES: ".crush.json AGENTS.md CLAUDE.md GEMINI.md PI.md opencode.jsonc"
+ GH_AW_AGENT_FOLDERS: ".agents .antigravity .claude .codex .crush .gemini .github .opencode .pi"
+ GH_AW_AGENT_FILES: ".crush.json AGENTS.md ANTIGRAVITY.md CLAUDE.md GEMINI.md PI.md opencode.jsonc"
run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_base_github_folders.sh"
+ - name: Restore inline sub-agents from activation artifact
+ env:
+ GH_AW_SUB_AGENT_DIR: ".github/agents"
+ GH_AW_SUB_AGENT_EXT: ".agent.md"
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_sub_agents.sh"
+ - name: Restore inline skills from activation artifact
+ env:
+ GH_AW_SKILL_DIR: ".github/skills"
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/restore_inline_skills.sh"
- name: Download container images
- run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v1.0.3@sha256:2ac27ef03461ef2b877031b838a7d1fd7f12b12d4ace7796d8cad91446d55959 node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f
+ run: bash "${RUNNER_TEMP}/gh-aw/actions/download_docker_images.sh" ghcr.io/github/github-mcp-server:v1.1.2@sha256:30197479d8036c7811892bc07e06f9a05c9ef3cdd79bc59f256d50647f95788c
- name: Generate Safe Outputs Config
run: |
mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs"
mkdir -p /tmp/gh-aw/safeoutputs
mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs
- cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_18efef56cd5f6986_EOF'
+ cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_33a8e71ee9b45c67_EOF'
{"add_comment":{"max":1},"add_labels":{"allowed":["bug","feature","enhancement","documentation","question","duplicate","invalid"]},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{}}
- GH_AW_SAFE_OUTPUTS_CONFIG_18efef56cd5f6986_EOF
+ GH_AW_SAFE_OUTPUTS_CONFIG_33a8e71ee9b45c67_EOF
- name: Generate Safe Outputs Tools
env:
GH_AW_TOOLS_META_JSON: |
@@ -620,17 +672,22 @@ jobs:
export GH_AW_ENGINE="copilot"
MCP_GATEWAY_UID=$(id -u 2>/dev/null || echo '0')
MCP_GATEWAY_GID=$(id -g 2>/dev/null || echo '0')
- DOCKER_SOCK_GID=$(stat -c '%g' /var/run/docker.sock 2>/dev/null || echo '0')
- export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v /var/run/docker.sock:/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.6'
+ case "${DOCKER_HOST:-}" in
+ unix://* ) DOCKER_SOCK_PATH="${DOCKER_HOST#unix://}" ;;
+ /* ) DOCKER_SOCK_PATH="$DOCKER_HOST" ;;
+ * ) DOCKER_SOCK_PATH=/var/run/docker.sock ;;
+ esac
+ DOCKER_SOCK_GID=$(stat -c '%g' "$DOCKER_SOCK_PATH" 2>/dev/null || echo '0')
+ export MCP_GATEWAY_DOCKER_COMMAND='docker run -i --rm --network host --add-host host.docker.internal:127.0.0.1 --user '"${MCP_GATEWAY_UID}"':'"${MCP_GATEWAY_GID}"' --group-add '"${DOCKER_SOCK_GID}"' -v '"${DOCKER_SOCK_PATH}"':/var/run/docker.sock -e MCP_GATEWAY_PORT -e MCP_GATEWAY_DOMAIN -e MCP_GATEWAY_API_KEY -e MCP_GATEWAY_PAYLOAD_DIR -e MCP_GATEWAY_PAYLOAD_SIZE_THRESHOLD -e DOCKER_HOST=unix:///var/run/docker.sock -e DEBUG -e MCP_GATEWAY_LOG_DIR -e GH_AW_MCP_LOG_DIR -e GH_AW_SAFE_OUTPUTS -e GH_AW_SAFE_OUTPUTS_CONFIG_PATH -e GH_AW_SAFE_OUTPUTS_TOOLS_PATH -e GH_AW_ASSETS_BRANCH -e GH_AW_ASSETS_MAX_SIZE_KB -e GH_AW_ASSETS_ALLOWED_EXTS -e DEFAULT_BRANCH -e GITHUB_MCP_SERVER_TOKEN -e GITHUB_MCP_GUARD_MIN_INTEGRITY -e GITHUB_MCP_GUARD_REPOS -e GITHUB_REPOSITORY -e GITHUB_SERVER_URL -e GITHUB_SHA -e GITHUB_WORKSPACE -e GITHUB_TOKEN -e GITHUB_RUN_ID -e GITHUB_RUN_NUMBER -e GITHUB_RUN_ATTEMPT -e GITHUB_JOB -e GITHUB_ACTION -e GITHUB_EVENT_NAME -e GITHUB_EVENT_PATH -e GITHUB_ACTOR -e GITHUB_ACTOR_ID -e GITHUB_TRIGGERING_ACTOR -e GITHUB_WORKFLOW -e GITHUB_WORKFLOW_REF -e GITHUB_WORKFLOW_SHA -e GITHUB_REF -e GITHUB_REF_NAME -e GITHUB_REF_TYPE -e GITHUB_HEAD_REF -e GITHUB_BASE_REF -e GH_AW_SAFE_OUTPUTS_PORT -e GH_AW_SAFE_OUTPUTS_API_KEY -v /tmp/gh-aw/mcp-payloads:/tmp/gh-aw/mcp-payloads:rw -v /opt:/opt:ro -v /tmp:/tmp:rw -v '"${GITHUB_WORKSPACE}"':'"${GITHUB_WORKSPACE}"':rw ghcr.io/github/gh-aw-mcpg:v0.3.25'
mkdir -p /home/runner/.copilot
GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node)
- cat << GH_AW_MCP_CONFIG_0138aecd21cfde50_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
+ cat << GH_AW_MCP_CONFIG_f41962abaffbda74_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs"
{
"mcpServers": {
"github": {
"type": "stdio",
- "container": "ghcr.io/github/github-mcp-server:v1.0.3",
+ "container": "ghcr.io/github/github-mcp-server:v1.1.2",
"env": {
"GITHUB_HOST": "\${GITHUB_SERVER_URL}",
"GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}",
@@ -669,7 +726,7 @@ jobs:
"payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}"
}
}
- GH_AW_MCP_CONFIG_0138aecd21cfde50_EOF
+ GH_AW_MCP_CONFIG_f41962abaffbda74_EOF
- name: Mount MCP servers as CLIs
id: mount-mcp-clis
continue-on-error: true
@@ -699,26 +756,31 @@ jobs:
timeout-minutes: 20
run: |
set -o pipefail
+ printf '%s' "$(date +%s%3N)" > /tmp/gh-aw/agent_cli_start_ms.txt
touch /tmp/gh-aw/agent-step-summary.md
(umask 177 && touch /tmp/gh-aw/agent-stdio.log)
+ trap 'rm -f /home/runner/.copilot/settings.json' EXIT
+ mkdir -p /home/runner/.copilot
+ printf '%s' '{"builtInAgents":{"rubberDuck":false}}' > /home/runner/.copilot/settings.json
mkdir -p /tmp/
mkdir -p /tmp/gh-aw/
mkdir -p /tmp/gh-aw/agent/
mkdir -p /tmp/gh-aw/sandbox/agent/logs/
- GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || echo node)"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log
+ GH_AW_NODE_EXEC="${GH_AW_NODE_BIN:-}"; if [ -z "$GH_AW_NODE_EXEC" ] || [ ! -x "$GH_AW_NODE_EXEC" ]; then GH_AW_NODE_EXEC="$(command -v node 2>/dev/null || true)"; fi; if [ -z "$GH_AW_NODE_EXEC" ]; then echo "node runtime missing on this runner — check runtimes.node in workflow YAML" >&2; exit 127; fi; GH_AW_NPM_GLOBAL_ROOT="$(npm root -g 2>/dev/null || true)"; if [ -n "$GH_AW_NPM_GLOBAL_ROOT" ]; then export NODE_PATH="${GH_AW_NPM_GLOBAL_ROOT}${NODE_PATH:+:${NODE_PATH}}"; fi; "$GH_AW_NODE_EXEC" ${RUNNER_TEMP}/gh-aw/actions/copilot_harness.cjs copilot --add-dir /tmp/ --add-dir /tmp/gh-aw/ --add-dir /tmp/gh-aw/agent/ --log-level all --log-dir /tmp/gh-aw/sandbox/agent/logs/ --disable-builtin-mcps --no-ask-user --allow-tool github --allow-tool safeoutputs --prompt-file /tmp/gh-aw/aw-prompts/prompt.txt 2>&1 | tee /tmp/gh-aw/agent-stdio.log
env:
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
- COPILOT_API_KEY: dummy-byok-key-for-offline-mode
- COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
- COPILOT_MODEL: doubao-seed-2-0-code-preview-260215
- COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }}
+ COPILOT_MODEL: doubao-seed-evolving
COPILOT_PROVIDER_BASE_URL: https://ark.cn-beijing.volces.com/api/v3
+ COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }}
COPILOT_PROVIDER_TYPE: openai
+ COPILOT_PROVIDER_WIRE_API: responses
+ GH_AW_MAX_TURNS: ${{ vars.GH_AW_DEFAULT_MAX_TURNS || '' }}
GH_AW_MCP_CONFIG: /home/runner/.copilot/mcp-config.json
GH_AW_PHASE: agent
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
GH_AW_SAFE_OUTPUTS: ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }}
- GH_AW_VERSION: v0.71.5
+ GH_AW_TIMEOUT_MINUTES: 20
+ GH_AW_VERSION: v0.79.6
GITHUB_API_URL: ${{ github.api_url }}
GITHUB_AW: true
GITHUB_COPILOT_INTEGRATION_ID: agentic-workflows
@@ -728,12 +790,14 @@ jobs:
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_STEP_SUMMARY: /tmp/gh-aw/agent-step-summary.md
GITHUB_WORKSPACE: ${{ github.workspace }}
+ RUNNER_TEMP: ${{ runner.temp }}
+ S2STOKENS: true
XDG_CONFIG_HOME: /home/runner
- - name: Detect Copilot errors
- id: detect-copilot-errors
+ - name: Detect agent errors
if: always()
+ id: detect-agent-errors
continue-on-error: true
- run: node "${RUNNER_TEMP}/gh-aw/actions/detect_copilot_errors.cjs"
+ run: node "${RUNNER_TEMP}/gh-aw/actions/detect_agent_errors.cjs"
- name: Configure Git credentials
env:
REPO_NAME: ${{ github.repository }}
@@ -770,8 +834,7 @@ jobs:
const { main } = require('${{ runner.temp }}/gh-aw/actions/redact_secrets.cjs');
await main();
env:
- GH_AW_SECRET_NAMES: 'COPILOT_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY'
- SECRET_COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
+ GH_AW_SECRET_NAMES: 'GH_AW_GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GITHUB_TOKEN,OPENAI_API_KEY'
SECRET_GH_AW_GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN }}
SECRET_GH_AW_GITHUB_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN }}
SECRET_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -856,7 +919,7 @@ jobs:
- safe_outputs
if: >
always() && (needs.agent.result != 'skipped' || needs.activation.outputs.lockdown_check_failed == 'true' ||
- needs.activation.outputs.stale_lock_file_failed == 'true')
+ needs.activation.outputs.stale_lock_file_failed == 'true' || needs.activation.outputs.daily_effective_workflow_exceeded == 'true')
runs-on: ubuntu-slim
permissions:
contents: read
@@ -866,6 +929,7 @@ jobs:
concurrency:
group: "gh-aw-conclusion-issue-triage"
cancel-in-progress: false
+ queue: max
outputs:
incomplete_count: ${{ steps.report_incomplete.outputs.incomplete_count }}
noop_message: ${{ steps.noop.outputs.noop_message }}
@@ -874,15 +938,17 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5
+ uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.40"
+ GH_AW_INFO_VERSION: "1.0.60"
+ GH_AW_INFO_ENGINE_ID: "copilot"
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
@@ -897,6 +963,40 @@ jobs:
mkdir -p /tmp/gh-aw/
find "/tmp/gh-aw/" -type f -print
echo "GH_AW_AGENT_OUTPUT=/tmp/gh-aw/agent_output.json" >> "$GITHUB_OUTPUT"
+ - name: Collect usage artifact files
+ if: always()
+ continue-on-error: true
+ run: |
+ mkdir -p /tmp/gh-aw/usage/agent /tmp/gh-aw/usage/detection
+ echo "Usage artifact source file status:"
+ for file in /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl; do
+ [ -f "$file" ] && echo "FOUND: $file" || echo "MISSING: $file"
+ done
+ [ -f /tmp/gh-aw/aw-info.jsonl ] && cp /tmp/gh-aw/aw-info.jsonl /tmp/gh-aw/usage/aw-info.jsonl || true
+ [ -f /tmp/gh-aw/agent_usage.jsonl ] && cp /tmp/gh-aw/agent_usage.jsonl /tmp/gh-aw/usage/agent_usage.jsonl || true
+ [ -f /tmp/gh-aw/detection_usage.jsonl ] && cp /tmp/gh-aw/detection_usage.jsonl /tmp/gh-aw/usage/detection_usage.jsonl || true
+ [ -f /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true
+ [ -f /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true
+ [ -f /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/agent/token_usage.jsonl || true
+ [ -f /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall-audit-logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true
+ [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true
+ [ -f /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl ] && cp /tmp/gh-aw/threat-detection/sandbox/firewall/audit/api-proxy-logs/token-usage.jsonl /tmp/gh-aw/usage/detection/token_usage.jsonl || true
+ [ -f /tmp/gh-aw/usage/agent/token_usage.jsonl ] || : > /tmp/gh-aw/usage/agent/token_usage.jsonl
+ [ -f /tmp/gh-aw/usage/detection/token_usage.jsonl ] || : > /tmp/gh-aw/usage/detection/token_usage.jsonl
+ find /tmp/gh-aw/usage -type f -print | sort
+ - name: Upload usage artifact
+ if: always()
+ continue-on-error: true
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
+ with:
+ name: usage
+ path: |
+ /tmp/gh-aw/usage/aw-info.jsonl
+ /tmp/gh-aw/usage/agent_usage.jsonl
+ /tmp/gh-aw/usage/detection_usage.jsonl
+ /tmp/gh-aw/usage/agent/token_usage.jsonl
+ /tmp/gh-aw/usage/detection/token_usage.jsonl
+ if-no-files-found: ignore
- name: Process no-op messages
id: noop
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
@@ -904,9 +1004,13 @@ jobs:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_NOOP_MAX: "1"
GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复"
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_NOOP_REPORT_AS_ISSUE: "true"
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
+ GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
+ GH_AW_WORKFLOW_ID: "issue-triage"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
@@ -921,6 +1025,7 @@ jobs:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_MISSING_TOOL_CREATE_ISSUE: "true"
GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复"
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
@@ -935,6 +1040,7 @@ jobs:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_REPORT_INCOMPLETE_CREATE_ISSUE: "true"
GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复"
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
with:
github-token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
script: |
@@ -949,12 +1055,18 @@ jobs:
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复"
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
GH_AW_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
GH_AW_AGENT_CONCLUSION: ${{ needs.agent.result }}
GH_AW_WORKFLOW_ID: "issue-triage"
GH_AW_ACTION_FAILURE_ISSUE_EXPIRES_HOURS: "168"
GH_AW_ENGINE_ID: "copilot"
GH_AW_CHECKOUT_PR_SUCCESS: ${{ needs.agent.outputs.checkout_pr_success }}
+ GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens || '' }}
+ GH_AW_AI_CREDITS_RATE_LIMIT_ERROR: ${{ needs.agent.outputs.ai_credits_rate_limit_error || 'false' }}
+ GH_AW_UNKNOWN_MODEL_AI_CREDITS: ${{ needs.agent.outputs.unknown_model_ai_credits || 'false' }}
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
+ GH_AW_MAX_AI_CREDITS: ${{ vars.GH_AW_DEFAULT_MAX_AI_CREDITS || '1000' }}
GH_AW_INFERENCE_ACCESS_ERROR: ${{ needs.agent.outputs.inference_access_error }}
GH_AW_MCP_POLICY_ERROR: ${{ needs.agent.outputs.mcp_policy_error }}
GH_AW_AGENTIC_ENGINE_TIMEOUT: ${{ needs.agent.outputs.agentic_engine_timeout }}
@@ -962,6 +1074,9 @@ jobs:
GH_AW_ENGINE_API_HOSTS: "api.enterprise.githubcopilot.com,api.githubcopilot.com,api.business.githubcopilot.com,api.individual.githubcopilot.com"
GH_AW_LOCKDOWN_CHECK_FAILED: ${{ needs.activation.outputs.lockdown_check_failed }}
GH_AW_STALE_LOCK_FILE_FAILED: ${{ needs.activation.outputs.stale_lock_file_failed }}
+ GH_AW_DAILY_EFFECTIVE_WORKFLOW_EXCEEDED: ${{ needs.activation.outputs.daily_effective_workflow_exceeded }}
+ GH_AW_DAILY_EFFECTIVE_WORKFLOW_TOTAL_EFFECTIVE_TOKENS: ${{ needs.activation.outputs.daily_effective_workflow_total_effective_tokens }}
+ GH_AW_DAILY_EFFECTIVE_WORKFLOW_THRESHOLD: ${{ needs.activation.outputs.daily_effective_workflow_threshold }}
GH_AW_GROUP_REPORTS: "false"
GH_AW_FAILURE_REPORT_AS_ISSUE: "true"
GH_AW_MISSING_TOOL_REPORT_AS_FAILURE: "true"
@@ -980,18 +1095,21 @@ jobs:
outputs:
activated: ${{ steps.check_membership.outputs.is_team_member == 'true' }}
matched_command: ''
+ setup-parent-span-id: ${{ steps.setup.outputs.parent-span-id || steps.setup.outputs.span-id }}
+ setup-span-id: ${{ steps.setup.outputs.span-id }}
setup-trace-id: ${{ steps.setup.outputs.trace-id }}
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5
+ uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.40"
+ GH_AW_INFO_VERSION: "1.0.60"
+ GH_AW_INFO_ENGINE_ID: "copilot"
- name: Check team membership for workflow
id: check_membership
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
@@ -1016,15 +1134,19 @@ jobs:
discussions: write
issues: write
pull-requests: write
- timeout-minutes: 15
+ timeout-minutes: 45
env:
+ GH_AW_AGENT_AIC: ${{ needs.agent.outputs.aic }}
+ GH_AW_AIC: ${{ needs.agent.outputs.aic }}
+ GH_AW_AMBIENT_CONTEXT: ${{ needs.agent.outputs.ambient_context }}
GH_AW_CALLER_WORKFLOW_ID: "${{ github.repository }}/issue-triage"
GH_AW_EFFECTIVE_TOKENS: ${{ needs.agent.outputs.effective_tokens }}
GH_AW_ENGINE_ID: "copilot"
GH_AW_ENGINE_MODEL: ${{ needs.agent.outputs.model }}
- GH_AW_ENGINE_VERSION: "1.0.40"
+ GH_AW_ENGINE_VERSION: "1.0.60"
GH_AW_WORKFLOW_ID: "issue-triage"
GH_AW_WORKFLOW_NAME: "Issue 自动分类与回复"
+ GH_AW_WORKFLOW_SOURCE_URL: "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.ref_name }}/.github/workflows/issue-triage.md"
outputs:
code_push_failure_count: ${{ steps.process_safe_outputs.outputs.code_push_failure_count }}
code_push_failure_errors: ${{ steps.process_safe_outputs.outputs.code_push_failure_errors }}
@@ -1037,15 +1159,17 @@ jobs:
steps:
- name: Setup Scripts
id: setup
- uses: github/gh-aw-actions/setup@b8068426813005612b960b5ab0b8bd2c27142323 # v0.71.5
+ uses: github/gh-aw-actions/setup@5c2fe865bb4dc46e1450f6ee0d0541d759aea73a # v0.79.6
with:
destination: ${{ runner.temp }}/gh-aw/actions
job-name: ${{ github.job }}
trace-id: ${{ needs.activation.outputs.setup-trace-id }}
+ parent-span-id: ${{ needs.activation.outputs.setup-parent-span-id || needs.activation.outputs.setup-span-id }}
env:
GH_AW_SETUP_WORKFLOW_NAME: "Issue 自动分类与回复"
GH_AW_CURRENT_WORKFLOW_REF: ${{ github.repository }}/.github/workflows/issue-triage.lock.yml@${{ github.ref }}
- GH_AW_INFO_VERSION: "1.0.40"
+ GH_AW_INFO_VERSION: "1.0.60"
+ GH_AW_INFO_ENGINE_ID: "copilot"
- name: Download agent output artifact
id: download-agent-output
continue-on-error: true
@@ -1063,6 +1187,7 @@ jobs:
- name: Configure GH_HOST for enterprise compatibility
id: ghes-host-config
shell: bash
+ # zizmor: ignore[github-env] - GITHUB_SERVER_URL is set by GitHub Actions, not user input.
run: |
# Derive GH_HOST from GITHUB_SERVER_URL so the gh CLI targets the correct
# GitHub instance (GHES/GHEC). On github.com this is a harmless no-op.
@@ -1074,6 +1199,7 @@ jobs:
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
env:
GH_AW_AGENT_OUTPUT: ${{ steps.setup-agent-output-env.outputs.GH_AW_AGENT_OUTPUT }}
+ GH_AW_COMMENT_ID: ${{ needs.activation.outputs.comment_id }}
GH_AW_ALLOWED_DOMAINS: "api.business.githubcopilot.com,api.enterprise.githubcopilot.com,api.github.com,api.githubcopilot.com,api.individual.githubcopilot.com,api.snapcraft.io,archive.ubuntu.com,ark.cn-beijing.volces.com,azure.archive.ubuntu.com,crl.geotrust.com,crl.globalsign.com,crl.identrust.com,crl.sectigo.com,crl.thawte.com,crl.usertrust.com,crl.verisign.com,crl3.digicert.com,crl4.digicert.com,crls.ssl.com,github.com,host.docker.internal,json-schema.org,json.schemastore.org,keyserver.ubuntu.com,ocsp.digicert.com,ocsp.geotrust.com,ocsp.globalsign.com,ocsp.identrust.com,ocsp.sectigo.com,ocsp.ssl.com,ocsp.thawte.com,ocsp.usertrust.com,ocsp.verisign.com,packagecloud.io,packages.cloud.google.com,packages.microsoft.com,ppa.launchpad.net,raw.githubusercontent.com,registry.npmjs.org,s.symcb.com,s.symcd.com,security.ubuntu.com,telemetry.enterprise.githubcopilot.com,ts-crl.ws.symantec.com,ts-ocsp.ws.symantec.com,www.googleapis.com"
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_API_URL: ${{ github.api_url }}
diff --git a/.github/workflows/issue-triage.md b/.github/workflows/issue-triage.md
index f384730..ae11740 100644
--- a/.github/workflows/issue-triage.md
+++ b/.github/workflows/issue-triage.md
@@ -7,19 +7,22 @@ engine:
id: copilot
env:
COPILOT_PROVIDER_BASE_URL: "https://ark.cn-beijing.volces.com/api/v3"
- COPILOT_MODEL: doubao-seed-2-0-code-preview-260215
- COPILOT_PROVIDER_API_KEY: ${{ secrets.OPENAI_API_KEY }}
+ COPILOT_PROVIDER_BEARER_TOKEN: ${{ secrets.OPENAI_API_KEY }}
+ COPILOT_MODEL: doubao-seed-evolving
COPILOT_PROVIDER_TYPE: openai
+ COPILOT_PROVIDER_WIRE_API: responses
+
+features:
+ dangerously-disable-sandbox-agent: "controlled environment for issue triage automation"
+sandbox:
+ agent: false
+strict: false
network:
allowed:
- defaults
- ark.cn-beijing.volces.com
-sandbox:
- agent: false
-strict: false
-
tools:
github:
min-integrity: none
@@ -28,6 +31,7 @@ permissions:
issues: read
contents: read
pull-requests: read
+ copilot-requests: write
safe-outputs:
threat-detection: false
@@ -60,7 +64,7 @@ safe-outputs:
- `duplicate`:与已有 Issue 重复
- `invalid`:信息不完整或无效
-3. 根据用户的提问语言按照用户语言回复一条友好的评论,包含:
+3. 使用用户提问的语言回复一条友好的评论,包含:
- 感谢用户提交 Issue
- 说明你打的标签和原因
- 如果是 bug,请用户补充:复现步骤、环境信息、错误日志
From 9ba2a5cc7be5e69036ce36b1db8944a045ea091a Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Thu, 9 Jul 2026 17:09:33 +0800
Subject: [PATCH 16/25] ci:update codeql
---
.github/workflows/codeql-to-commit.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/codeql-to-commit.yml b/.github/workflows/codeql-to-commit.yml
index d297c94..98ab97f 100644
--- a/.github/workflows/codeql-to-commit.yml
+++ b/.github/workflows/codeql-to-commit.yml
@@ -27,7 +27,7 @@ jobs:
echo "Default branch: $DEFAULT_BRANCH"
ALERTS=$(gh api "/repos/$OWNER/$REPO/code-scanning/alerts?state=open&per_page=100" \
- --jq '[.[] | select(.rule.security_severity_level == "high" or .rule.security_severity_level == "medium" or .rule.severity == "warning") | {number: .number, level: (.rule.security_severity_level // .rule.severity)}]')
+ --jq '[.[] | select(.rule.security_severity_level == "critical" or .rule.security_severity_level == "high" or .rule.security_severity_level == "medium" or .rule.severity == "warning") | {number: .number, level: (.rule.security_severity_level // .rule.severity)}]')
COUNT=$(echo $ALERTS | jq 'length')
echo "Found $COUNT alerts with high / medium / warning"
From 8f1a1ab11c26936ca5b7987644a1f88de7eb9c6c Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sun, 19 Jul 2026 14:57:29 +0800
Subject: [PATCH 17/25] ci:cancel centos release
---
.github/workflows/Centos_build.yml | 2 +-
.github/workflows/release.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/Centos_build.yml b/.github/workflows/Centos_build.yml
index 0be115f..2aa6954 100644
--- a/.github/workflows/Centos_build.yml
+++ b/.github/workflows/Centos_build.yml
@@ -3,7 +3,7 @@ name: centos build workflows
on:
push:
branches:
- - 'develop'
+ - 'develop1'
paths:
- 'XEngine_Source/**'
- 'XEngine_Release/**'
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ff73ab2..aa2e11d 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -64,7 +64,7 @@ jobs:
- name: Download CentOS
uses: dawidd6/action-download-artifact@v21
with:
- workflow: Centos_build.yml
+ workflow: Centos_build1s.yml
workflow_conclusion: success
check_artifacts: false
skip_unpack: true
From 5b3ab34c9d9af72c01e85a84ea0d617b651a1b28 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sun, 19 Jul 2026 15:12:49 +0800
Subject: [PATCH 18/25] update:vs to 2026 version
---
.../MQCore_ConfigModule/MQCore_ConfigModule.vcxproj | 10 +++++-----
XEngine_Source/MQCore_DBModule/MQCore_DBModule.vcxproj | 10 +++++-----
.../MQCore_HelpModule/MQCore_HelpModule.vcxproj | 10 +++++-----
.../MQCore_MemoryCache/MQCore_MemoryCache.vcxproj | 10 +++++-----
.../MQCore_ProtocolModule.vcxproj | 10 +++++-----
.../MQCore_SessionModule/MQCore_SessionModule.vcxproj | 10 +++++-----
.../XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj | 10 +++++-----
7 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/XEngine_Source/MQCore_ConfigModule/MQCore_ConfigModule.vcxproj b/XEngine_Source/MQCore_ConfigModule/MQCore_ConfigModule.vcxproj
index c5d011a..c76069a 100644
--- a/XEngine_Source/MQCore_ConfigModule/MQCore_ConfigModule.vcxproj
+++ b/XEngine_Source/MQCore_ConfigModule/MQCore_ConfigModule.vcxproj
@@ -43,33 +43,33 @@
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
diff --git a/XEngine_Source/MQCore_DBModule/MQCore_DBModule.vcxproj b/XEngine_Source/MQCore_DBModule/MQCore_DBModule.vcxproj
index 291e008..7d8d2f8 100644
--- a/XEngine_Source/MQCore_DBModule/MQCore_DBModule.vcxproj
+++ b/XEngine_Source/MQCore_DBModule/MQCore_DBModule.vcxproj
@@ -43,33 +43,33 @@
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
diff --git a/XEngine_Source/MQCore_HelpModule/MQCore_HelpModule.vcxproj b/XEngine_Source/MQCore_HelpModule/MQCore_HelpModule.vcxproj
index 826fef1..7dd2a88 100644
--- a/XEngine_Source/MQCore_HelpModule/MQCore_HelpModule.vcxproj
+++ b/XEngine_Source/MQCore_HelpModule/MQCore_HelpModule.vcxproj
@@ -43,33 +43,33 @@
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
diff --git a/XEngine_Source/MQCore_MemoryCache/MQCore_MemoryCache.vcxproj b/XEngine_Source/MQCore_MemoryCache/MQCore_MemoryCache.vcxproj
index ec65175..00db5b0 100644
--- a/XEngine_Source/MQCore_MemoryCache/MQCore_MemoryCache.vcxproj
+++ b/XEngine_Source/MQCore_MemoryCache/MQCore_MemoryCache.vcxproj
@@ -43,33 +43,33 @@
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
diff --git a/XEngine_Source/MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj b/XEngine_Source/MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj
index 4d37441..3d6c19e 100644
--- a/XEngine_Source/MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj
+++ b/XEngine_Source/MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj
@@ -43,33 +43,33 @@
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
diff --git a/XEngine_Source/MQCore_SessionModule/MQCore_SessionModule.vcxproj b/XEngine_Source/MQCore_SessionModule/MQCore_SessionModule.vcxproj
index 18aadc9..19febc5 100644
--- a/XEngine_Source/MQCore_SessionModule/MQCore_SessionModule.vcxproj
+++ b/XEngine_Source/MQCore_SessionModule/MQCore_SessionModule.vcxproj
@@ -43,33 +43,33 @@
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
true
- v143
+ v145
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
DynamicLibrary
false
- v143
+ v145
true
Unicode
diff --git a/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj b/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj
index 7950519..50c4e97 100644
--- a/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj
+++ b/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj
@@ -43,33 +43,33 @@
Application
false
- v143
+ v145
true
Unicode
Application
true
- v143
+ v145
Unicode
Application
true
- v143
+ v145
Unicode
Application
false
- v143
+ v145
true
Unicode
Application
false
- v143
+ v145
true
Unicode
From 2dc2e64f914f74860f29bc3f8d753f8e4db427b3 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sun, 19 Jul 2026 15:26:45 +0800
Subject: [PATCH 19/25] modify:vs crt runtime unified
---
.../MQCore_ConfigModule/MQCore_ConfigModule.vcxproj | 4 ++--
.../MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj | 4 ++--
.../MQCore_SessionModule/MQCore_SessionModule.vcxproj | 4 ++--
.../XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/XEngine_Source/MQCore_ConfigModule/MQCore_ConfigModule.vcxproj b/XEngine_Source/MQCore_ConfigModule/MQCore_ConfigModule.vcxproj
index c76069a..7e571ff 100644
--- a/XEngine_Source/MQCore_ConfigModule/MQCore_ConfigModule.vcxproj
+++ b/XEngine_Source/MQCore_ConfigModule/MQCore_ConfigModule.vcxproj
@@ -152,7 +152,7 @@
true
Use
pch.h
- MultiThreaded
+ MultiThreadedDLL
4819
stdcpp20
stdc17
@@ -213,7 +213,7 @@
true
Use
pch.h
- MultiThreaded
+ MultiThreadedDLL
4819
stdcpp20
stdc17
diff --git a/XEngine_Source/MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj b/XEngine_Source/MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj
index 3d6c19e..a118431 100644
--- a/XEngine_Source/MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj
+++ b/XEngine_Source/MQCore_ProtocolModule/MQCore_ProtocolModule.vcxproj
@@ -156,7 +156,7 @@
true
Use
pch.h
- MultiThreaded
+ MultiThreadedDLL
4819
stdcpp20
stdc17
@@ -217,7 +217,7 @@
true
Use
pch.h
- MultiThreaded
+ MultiThreadedDLL
4819
stdcpp20
stdc17
diff --git a/XEngine_Source/MQCore_SessionModule/MQCore_SessionModule.vcxproj b/XEngine_Source/MQCore_SessionModule/MQCore_SessionModule.vcxproj
index 19febc5..1c60385 100644
--- a/XEngine_Source/MQCore_SessionModule/MQCore_SessionModule.vcxproj
+++ b/XEngine_Source/MQCore_SessionModule/MQCore_SessionModule.vcxproj
@@ -156,7 +156,7 @@
true
Use
pch.h
- MultiThreaded
+ MultiThreadedDLL
4819
stdcpp20
stdc17
@@ -217,7 +217,7 @@
true
Use
pch.h
- MultiThreaded
+ MultiThreadedDLL
4819
stdcpp20
stdc17
diff --git a/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj b/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj
index 50c4e97..4a7ebfb 100644
--- a/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj
+++ b/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.vcxproj
@@ -150,7 +150,7 @@
true
WIN32;NDEBUG;_CONSOLE;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
true
- MultiThreaded
+ MultiThreadedDLL
4819
stdcpp20
stdc17
@@ -199,7 +199,7 @@
true
WIN64;NDEBUG;_CONSOLE;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
true
- MultiThreaded
+ MultiThreadedDLL
4819
stdcpp20
stdc17
From f7dd3b33951ebd9a01c7358e8e69f75369c35500 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sat, 25 Jul 2026 14:23:40 +0800
Subject: [PATCH 20/25] added:reply with serial number for post message
---
XEngine_Source/XEngine_MQServiceApp/MQService_TCPTask.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/XEngine_Source/XEngine_MQServiceApp/MQService_TCPTask.cpp b/XEngine_Source/XEngine_MQServiceApp/MQService_TCPTask.cpp
index afbb92b..ba93698 100644
--- a/XEngine_Source/XEngine_MQServiceApp/MQService_TCPTask.cpp
+++ b/XEngine_Source/XEngine_MQServiceApp/MQService_TCPTask.cpp
@@ -314,6 +314,7 @@ bool MessageQueue_TCP_Handle(XENGINE_PROTOCOLHDR* pSt_ProtocolHdr, LPCXSTR lpszC
//可能为空表
st_DBQueue.nQueueSerial = 1;
}
+ st_MQProtocol.nSerial = st_DBQueue.nQueueSerial;
APIHelp_Counter_SerialSet(st_DBQueue.tszQueueName, st_DBQueue.nQueueSerial);
}
}
From 6991e11e7f3ae523bd08839f9ad682c01f4a2d67 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sat, 25 Jul 2026 14:46:45 +0800
Subject: [PATCH 21/25] modify:serial from 1 number to start
---
.../MQService_HTTPTask/MQService_HTTPPost.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/XEngine_Source/XEngine_MQServiceApp/MQService_HTTPTask/MQService_HTTPPost.cpp b/XEngine_Source/XEngine_MQServiceApp/MQService_HTTPTask/MQService_HTTPPost.cpp
index 53f1fca..2f1668c 100644
--- a/XEngine_Source/XEngine_MQServiceApp/MQService_HTTPTask/MQService_HTTPPost.cpp
+++ b/XEngine_Source/XEngine_MQServiceApp/MQService_HTTPTask/MQService_HTTPPost.cpp
@@ -99,6 +99,7 @@ bool MessageQueue_HttpTask_Post(LPCXSTR lpszClientAddr, LPCXSTR lpszFuncName, LP
XENGINE_DBUSERKEY st_Userkey;
memset(&st_Userkey, '\0', sizeof(XENGINE_DBUSERKEY));
+ st_Userkey.nKeySerial = 1;
_tcsxcpy(st_Userkey.tszUserName, st_UserInfo.tszUserName);
_tcsxcpy(st_Userkey.tszKeyName, st_ServiceCfg.tszTopic);
//创建
@@ -268,7 +269,7 @@ bool MessageQueue_HttpTask_Post(LPCXSTR lpszClientAddr, LPCXSTR lpszFuncName, LP
if (DBModule_MQUser_KeyQuery(&st_Userkey))
{
//有就更新
- st_Userkey.nKeySerial = st_MQProtocol.nSerial;
+ st_Userkey.nKeySerial = st_MQProtocol.nSerial == 0 ? 1 : st_MQProtocol.nSerial;
if (!DBModule_MQUser_KeyUPDate(&st_Userkey))
{
ProtocolModule_Packet_Http(tszSDBuffer, &nSDLen, ERROR_XENGINE_MESSAGE_HTTP_FAILURE, _X("update bind topic is failure"));
From d9cbdc141596ff57b7e8a87f299ab07017a9b5cf Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sat, 25 Jul 2026 15:32:02 +0800
Subject: [PATCH 22/25] update:vs to 2026 for example
---
XEngine_Apps/MQCore_HTTPApp/MQCore_HTTPApp.vcxproj | 8 ++++----
XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.cpp | 2 +-
XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.vcxproj | 8 ++++----
XEngine_Apps/MQCore_WSApp/MQCore_WSApp.vcxproj | 8 ++++----
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/XEngine_Apps/MQCore_HTTPApp/MQCore_HTTPApp.vcxproj b/XEngine_Apps/MQCore_HTTPApp/MQCore_HTTPApp.vcxproj
index 91905eb..e401992 100644
--- a/XEngine_Apps/MQCore_HTTPApp/MQCore_HTTPApp.vcxproj
+++ b/XEngine_Apps/MQCore_HTTPApp/MQCore_HTTPApp.vcxproj
@@ -29,26 +29,26 @@
Application
true
- v143
+ v145
MultiByte
Application
false
- v143
+ v145
true
Unicode
Application
true
- v143
+ v145
Unicode
Application
false
- v143
+ v145
true
Unicode
diff --git a/XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.cpp b/XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.cpp
index 099a40c..8d7c6de 100644
--- a/XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.cpp
+++ b/XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.cpp
@@ -289,7 +289,7 @@ void MQ_Get(int nType = 0)
else
{
_xtprintf("获取消息队列数据失败,错误码:%d\n", st_ProtocolHdr.wReserve);
- }
+ }
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
diff --git a/XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.vcxproj b/XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.vcxproj
index f3877e1..4bc95ab 100644
--- a/XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.vcxproj
+++ b/XEngine_Apps/MQCore_TCPApp/MQCore_TCPApp.vcxproj
@@ -29,26 +29,26 @@
Application
true
- v143
+ v145
MultiByte
Application
false
- v143
+ v145
true
Unicode
Application
true
- v143
+ v145
Unicode
Application
false
- v143
+ v145
true
Unicode
diff --git a/XEngine_Apps/MQCore_WSApp/MQCore_WSApp.vcxproj b/XEngine_Apps/MQCore_WSApp/MQCore_WSApp.vcxproj
index af1f394..7322106 100644
--- a/XEngine_Apps/MQCore_WSApp/MQCore_WSApp.vcxproj
+++ b/XEngine_Apps/MQCore_WSApp/MQCore_WSApp.vcxproj
@@ -29,26 +29,26 @@
Application
true
- v143
+ v145
MultiByte
Application
false
- v143
+ v145
true
Unicode
Application
true
- v143
+ v145
Unicode
Application
false
- v143
+ v145
true
Unicode
From 2eab04b1a6e7fc4872c2668cc14d4824877e90fd Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sun, 26 Jul 2026 12:00:37 +0800
Subject: [PATCH 23/25] added:heartbeat support
---
.../XEngine_Config/XEngine_Config.json | 11 ++-
.../MQCore_ConfigModule/Config_Define.h | 8 +++
.../Config_Json/Config_Json.cpp | 13 ++++
.../XEngine_MQServiceApp/MQService_Hdr.h | 5 ++
.../XEngine_MQServiceApp/MQService_Net.cpp | 24 +++++--
.../XEngine_MQServiceApp/MQService_Net.h | 4 ++
.../XEngine_MQServiceApp.cpp | 72 ++++++++++++++++++-
7 files changed, 130 insertions(+), 7 deletions(-)
diff --git a/XEngine_Release/XEngine_Config/XEngine_Config.json b/XEngine_Release/XEngine_Config/XEngine_Config.json
index 8e4a4f5..ba46c4c 100644
--- a/XEngine_Release/XEngine_Config/XEngine_Config.json
+++ b/XEngine_Release/XEngine_Config/XEngine_Config.json
@@ -14,6 +14,13 @@
"nHttpThread": 2,
"nWSThread": 2,
"nMQTTThread": 2
+ },
+ "XTime": {
+ "nHeartCheck": 3,
+ "nTCPTime": 5,
+ "nWSTime": 5,
+ "nHTTPTime": 5,
+ "nMQTTTime": 5
},
"XLog": {
"tszLOGFile": "./XEngine_Log/XEngine_MQServiceApp.Log",
@@ -26,7 +33,7 @@
"SQLAddr": "118.25.14.242",
"SQLPort": 3306,
"SQLUser": "root",
- "SQLPass": "123123Qyt!"
+ "SQLPass": "123"
},
"XPass": {
"nTimeout": 2,
@@ -53,7 +60,7 @@
"tszEMailSubject": "XEngine MessageQueue Notify",
"tszServiceAddr": "smtp://smtp.163.com",
"tszUser": "ggqytgodlove@163.com",
- "tszPass": "STZsBi3uuJvWsWL3"
+ "tszPass": "1"
},
"SMSNotify": {
"bEnable": false
diff --git a/XEngine_Source/MQCore_ConfigModule/Config_Define.h b/XEngine_Source/MQCore_ConfigModule/Config_Define.h
index 3e9c59a..749ddb6 100644
--- a/XEngine_Source/MQCore_ConfigModule/Config_Define.h
+++ b/XEngine_Source/MQCore_ConfigModule/Config_Define.h
@@ -33,6 +33,14 @@ typedef struct
int nMQTTThread;
}st_XMax;
struct
+ {
+ int nHeartCheck; //检测次数
+ int nTCPTime; //TCP检测时间
+ int nWSTime; //WEBSOCKET检测时间
+ int nMQTime; //MQTT检测时间
+ int nHTTPTime; //HTTP检测时间
+ }st_XTime;
+ struct
{
XCHAR tszLOGFile[XPATH_MAX];
int nMaxSize;
diff --git a/XEngine_Source/MQCore_ConfigModule/Config_Json/Config_Json.cpp b/XEngine_Source/MQCore_ConfigModule/Config_Json/Config_Json.cpp
index b5111bc..91d392a 100644
--- a/XEngine_Source/MQCore_ConfigModule/Config_Json/Config_Json.cpp
+++ b/XEngine_Source/MQCore_ConfigModule/Config_Json/Config_Json.cpp
@@ -76,6 +76,19 @@ bool CConfig_Json::Config_Json_File(LPCXSTR lpszConfigFile,XENGINE_SERVERCONFIG
pSt_ServerConfig->st_XMax.nHttpThread = st_JsonXMax["nHttpThread"].asInt();
pSt_ServerConfig->st_XMax.nWSThread = st_JsonXMax["nWSThread"].asInt();
pSt_ServerConfig->st_XMax.nMQTTThread = st_JsonXMax["nMQTTThread"].asInt();
+ //时间配置
+ if (st_JsonRoot["XTime"].empty() || (5 != st_JsonRoot["XTime"].size()))
+ {
+ Config_IsErrorOccur = true;
+ Config_dwErrorCode = ERROR_MQ_MODULE_CONFIG_JSON_XTIME;
+ return false;
+ }
+ Json::Value st_JsonXTime = st_JsonRoot["XTime"];
+ pSt_ServerConfig->st_XTime.nHeartCheck = st_JsonXTime["nHeartCheck"].asInt();
+ pSt_ServerConfig->st_XTime.nTCPTime = st_JsonXTime["nTCPTime"].asInt();
+ pSt_ServerConfig->st_XTime.nWSTime = st_JsonXTime["nWSTime"].asInt();
+ pSt_ServerConfig->st_XTime.nHTTPTime = st_JsonXTime["nHTTPTime"].asInt();
+ pSt_ServerConfig->st_XTime.nMQTime = st_JsonXTime["nMQTTTime"].asInt();
if (st_JsonRoot["XLog"].empty() || (5 != st_JsonRoot["XLog"].size()))
{
diff --git a/XEngine_Source/XEngine_MQServiceApp/MQService_Hdr.h b/XEngine_Source/XEngine_MQServiceApp/MQService_Hdr.h
index 7504b20..4e7f7b7 100644
--- a/XEngine_Source/XEngine_MQServiceApp/MQService_Hdr.h
+++ b/XEngine_Source/XEngine_MQServiceApp/MQService_Hdr.h
@@ -80,6 +80,11 @@ extern XHANDLE xhHTTPSocket;
extern XHANDLE xhWSSocket;
extern XHANDLE xhMQTTSocket;
+extern XHANDLE xhTCPHeart;
+extern XHANDLE xhHTTPHeart;
+extern XHANDLE xhWSHeart;
+extern XHANDLE xhMQTTHeart;
+
extern XHANDLE xhTCPPacket;
extern XHANDLE xhHTTPPacket;
extern XHANDLE xhWSPacket;
diff --git a/XEngine_Source/XEngine_MQServiceApp/MQService_Net.cpp b/XEngine_Source/XEngine_MQServiceApp/MQService_Net.cpp
index 312bbab..f836c4d 100644
--- a/XEngine_Source/XEngine_MQServiceApp/MQService_Net.cpp
+++ b/XEngine_Source/XEngine_MQServiceApp/MQService_Net.cpp
@@ -19,6 +19,10 @@ void XCALLBACK MessageQueue_Callback_TCPLeave(LPCXSTR lpszClientAddr, XSOCKET hS
{
XEngine_MQXService_Close(lpszClientAddr, XENGINE_MQAPP_NETTYPE_TCP, false);
}
+void XCALLBACK MessageQueue_Client_TCPHeart(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam)
+{
+ XEngine_MQXService_Close(lpszClientAddr, XENGINE_MQAPP_NETTYPE_TCP, true);
+}
//////////////////////////////////////////////////////////////////////////
bool XCALLBACK MessageQueue_Callback_MQTTLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam)
{
@@ -39,6 +43,10 @@ void XCALLBACK MessageQueue_Callback_MQTTLeave(LPCXSTR lpszClientAddr, XSOCKET h
{
XEngine_MQXService_Close(lpszClientAddr, XENGINE_MQAPP_NETTYPE_MQTT, false);
}
+void XCALLBACK MessageQueue_Client_MQTTHeart(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam)
+{
+ XEngine_MQXService_Close(lpszClientAddr, XENGINE_MQAPP_NETTYPE_MQTT, true);
+}
//////////////////////////////////////////////////////////////////////////
bool XCALLBACK MessageQueue_Callback_HttpLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam)
{
@@ -58,6 +66,10 @@ void XCALLBACK MessageQueue_Callback_HttpLeave(LPCXSTR lpszClientAddr, XSOCKET h
{
XEngine_MQXService_Close(lpszClientAddr, XENGINE_MQAPP_NETTYPE_HTTP, false);
}
+void XCALLBACK MessageQueue_Client_HttpHeart(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam)
+{
+ XEngine_MQXService_Close(lpszClientAddr, XENGINE_MQAPP_NETTYPE_HTTP, true);
+}
//////////////////////////////////////////////////////////////////////////
bool XCALLBACK MessageQueue_Callback_WSLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam)
{
@@ -93,6 +105,10 @@ void XCALLBACK MessageQueue_Callback_WSLeave(LPCXSTR lpszClientAddr, XSOCKET hSo
{
XEngine_MQXService_Close(lpszClientAddr, XENGINE_MQAPP_NETTYPE_WEBSOCKET, false);
}
+void XCALLBACK MessageQueue_Client_WSHeart(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam)
+{
+ XEngine_MQXService_Close(lpszClientAddr, XENGINE_MQAPP_NETTYPE_WEBSOCKET, true);
+}
//////////////////////////////////////////////////////////////////////////
void XEngine_MQXService_Close(LPCXSTR lpszClientAddr, int nIPProto, bool bHeart)
{
@@ -103,7 +119,7 @@ void XEngine_MQXService_Close(LPCXSTR lpszClientAddr, int nIPProto, bool bHeart)
{
NetCore_TCPXCore_CloseForClientEx(xhTCPSocket, lpszClientAddr);
}
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("TCP客户端离开,TCP客户端地址:%s"), lpszClientAddr);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("TCP客户端离开,TCP客户端地址:%s,心跳标记:%d"), lpszClientAddr, bHeart);
}
else if (XENGINE_MQAPP_NETTYPE_WEBSOCKET == nIPProto)
{
@@ -112,7 +128,7 @@ void XEngine_MQXService_Close(LPCXSTR lpszClientAddr, int nIPProto, bool bHeart)
{
NetCore_TCPXCore_CloseForClientEx(xhWSSocket, lpszClientAddr);
}
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Websocket客户端离开,Websocket客户端地址:%s"), lpszClientAddr);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("Websocket客户端离开,Websocket客户端地址:%s,心跳标记:%d"), lpszClientAddr, bHeart);
}
else if (XENGINE_MQAPP_NETTYPE_HTTP == nIPProto)
{
@@ -121,7 +137,7 @@ void XEngine_MQXService_Close(LPCXSTR lpszClientAddr, int nIPProto, bool bHeart)
{
NetCore_TCPXCore_CloseForClientEx(xhHTTPSocket, lpszClientAddr);
}
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端离开,HTTP客户端地址:%s"), lpszClientAddr);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端离开,HTTP客户端地址:%s,心跳标记:%d"), lpszClientAddr, bHeart);
}
else
{
@@ -130,7 +146,7 @@ void XEngine_MQXService_Close(LPCXSTR lpszClientAddr, int nIPProto, bool bHeart)
{
NetCore_TCPXCore_CloseForClientEx(xhMQTTSocket, lpszClientAddr);
}
- XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("MQTT客户端离开,MQTT客户端地址:%s"), lpszClientAddr);
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("MQTT客户端离开,MQTT客户端地址:%s,心跳标记:%d"), lpszClientAddr, bHeart);
}
XENGINE_PROTOCOL_USERINFO st_UserInfo;
memset(&st_UserInfo, '\0', sizeof(XENGINE_PROTOCOL_USERINFO));
diff --git a/XEngine_Source/XEngine_MQServiceApp/MQService_Net.h b/XEngine_Source/XEngine_MQServiceApp/MQService_Net.h
index 723b1dd..f16603d 100644
--- a/XEngine_Source/XEngine_MQServiceApp/MQService_Net.h
+++ b/XEngine_Source/XEngine_MQServiceApp/MQService_Net.h
@@ -3,18 +3,22 @@
bool XCALLBACK MessageQueue_Callback_TCPLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam); //用户连接
void XCALLBACK MessageQueue_Callback_TCPRecv(LPCXSTR lpszClientAddr, XSOCKET hSocket, LPCXSTR lpszRecvMsg,int nMsgLen,XPVOID lParam); //接受到数据
void XCALLBACK MessageQueue_Callback_TCPLeave(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam); //用户离开
+void XCALLBACK MessageQueue_Client_TCPHeart(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam);
bool XCALLBACK MessageQueue_Callback_MQTTLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
void XCALLBACK MessageQueue_Callback_MQTTRecv(LPCXSTR lpszClientAddr, XSOCKET hSocket, LPCXSTR lpszRecvMsg, int nMsgLen, XPVOID lParam);
void XCALLBACK MessageQueue_Callback_MQTTLeave(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
+void XCALLBACK MessageQueue_Client_MQTTHeart(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam);
bool XCALLBACK MessageQueue_Callback_HttpLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
void XCALLBACK MessageQueue_Callback_HttpRecv(LPCXSTR lpszClientAddr, XSOCKET hSocket, LPCXSTR lpszRecvMsg, int nMsgLen, XPVOID lParam);
void XCALLBACK MessageQueue_Callback_HttpLeave(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
+void XCALLBACK MessageQueue_Client_HttpHeart(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam);
bool XCALLBACK MessageQueue_Callback_WSLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
void XCALLBACK MessageQueue_Callback_WSRecv(LPCXSTR lpszClientAddr, XSOCKET hSocket, LPCXSTR lpszRecvMsg, int nMsgLen, XPVOID lParam);
void XCALLBACK MessageQueue_Callback_WSLeave(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
+void XCALLBACK MessageQueue_Client_WSHeart(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam);
void XEngine_MQXService_Close(LPCXSTR lpszClientAddr, int nIPProto, bool bHeart);
bool XEngine_MQXService_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen, int nIPProto, XENGINE_PROTOCOL_MSGATTR* pSt_MSGAttr = NULL, LPCXSTR lpszUserName = NULL);
\ No newline at end of file
diff --git a/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.cpp b/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.cpp
index 519d604..c4ac65c 100644
--- a/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.cpp
+++ b/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.cpp
@@ -8,6 +8,11 @@ XHANDLE xhHTTPSocket = NULL;
XHANDLE xhWSSocket = NULL;
XHANDLE xhMQTTSocket = NULL;
+XHANDLE xhTCPHeart = NULL;
+XHANDLE xhHTTPHeart = NULL;
+XHANDLE xhWSHeart = NULL;
+XHANDLE xhMQTTHeart = NULL;
+
XHANDLE xhTCPPacket = NULL;
XHANDLE xhHTTPPacket = NULL;
XHANDLE xhWSPacket = NULL;
@@ -32,12 +37,17 @@ void ServiceApp_Stop(int signo)
HttpProtocol_Server_DestroyEx(xhHTTPPacket);
RfcComponents_WSPacket_DestoryEx(xhWSPacket);
MQTTProtocol_Parse_Destory();
-
+
NetCore_TCPXCore_DestroyEx(xhTCPSocket);
NetCore_TCPXCore_DestroyEx(xhHTTPSocket);
NetCore_TCPXCore_DestroyEx(xhWSSocket);
NetCore_TCPXCore_DestroyEx(xhMQTTSocket);
+ SocketOpt_HeartBeat_DestoryEx(xhTCPHeart);
+ SocketOpt_HeartBeat_DestoryEx(xhWSHeart);
+ SocketOpt_HeartBeat_DestoryEx(xhHTTPHeart);
+ SocketOpt_HeartBeat_DestoryEx(xhMQTTHeart);
+
ManagePool_Thread_NQDestroy(xhTCPPool);
ManagePool_Thread_NQDestroy(xhHttpPool);
ManagePool_Thread_NQDestroy(xhWSPool);
@@ -253,6 +263,21 @@ int main(int argc, char** argv)
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,启动TCP网络服务器成功,TCP端口:%d,IO:%d"), st_ServiceCfg.nTCPPort, st_ServiceCfg.st_XMax.nIOThread);
NetCore_TCPXCore_RegisterCallBackEx(xhTCPSocket, MessageQueue_Callback_TCPLogin, MessageQueue_Callback_TCPRecv, MessageQueue_Callback_TCPLeave);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,注册TCP网络事件成功"));
+
+ if (st_ServiceCfg.st_XTime.nTCPTime > 0)
+ {
+ xhTCPHeart = SocketOpt_HeartBeat_InitEx(st_ServiceCfg.st_XTime.nHeartCheck, st_ServiceCfg.st_XTime.nTCPTime, MessageQueue_Client_TCPHeart);
+ if (NULL == xhTCPHeart)
+ {
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("启动服务中,初始化TCP验证心跳服务失败,错误:%lX"), NetCore_GetLastError());
+ goto XENGINE_APPEXIST;
+ }
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,初始化TCP验证心跳服务成功,检测次数:%d,检测时间:%d"), st_ServiceCfg.st_XTime.nHeartCheck, st_ServiceCfg.st_XTime.nTCPTime);
+ }
+ else
+ {
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _X("启动服务中,检测到TCP心跳服务没有启用"));
+ }
//任务池
BaseLib_Memory_Malloc((XPPPMEM)&ppSt_ListTCPParam, st_ServiceCfg.st_XMax.nTCPThread, sizeof(THREADPOOL_PARAMENT));
for (int i = 0; i < st_ServiceCfg.st_XMax.nTCPThread; i++)
@@ -296,6 +321,21 @@ int main(int argc, char** argv)
NetCore_TCPXCore_RegisterCallBackEx(xhHTTPSocket, MessageQueue_Callback_HttpLogin, MessageQueue_Callback_HttpRecv, MessageQueue_Callback_HttpLeave);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,注册HTTP网络事件成功"));
+ if (st_ServiceCfg.st_XTime.nHTTPTime > 0)
+ {
+ xhHTTPHeart = SocketOpt_HeartBeat_InitEx(st_ServiceCfg.st_XTime.nHeartCheck, st_ServiceCfg.st_XTime.nHTTPTime, MessageQueue_Client_HttpHeart);
+ if (NULL == xhHTTPHeart)
+ {
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("启动服务中,初始化HTTP心跳服务失败,错误:%lX"), NetCore_GetLastError());
+ goto XENGINE_APPEXIST;
+ }
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,初始化HTTP心跳服务成功,检测次数:%d,检测时间:%d"), st_ServiceCfg.st_XTime.nHeartCheck, st_ServiceCfg.st_XTime.nHTTPTime);
+ }
+ else
+ {
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _X("启动服务中,检测到HTTP心跳服务没有启用"));
+ }
+
BaseLib_Memory_Malloc((XPPPMEM)&ppSt_ListHTTPParam, st_ServiceCfg.st_XMax.nHttpThread, sizeof(THREADPOOL_PARAMENT));
for (int i = 0; i < st_ServiceCfg.st_XMax.nHttpThread; i++)
{
@@ -338,6 +378,21 @@ int main(int argc, char** argv)
NetCore_TCPXCore_RegisterCallBackEx(xhWSSocket, MessageQueue_Callback_WSLogin, MessageQueue_Callback_WSRecv, MessageQueue_Callback_WSLeave);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,注册Websocket网络事件成功"));
+ if (st_ServiceCfg.st_XTime.nWSTime > 0)
+ {
+ xhWSHeart = SocketOpt_HeartBeat_InitEx(st_ServiceCfg.st_XTime.nHeartCheck, st_ServiceCfg.st_XTime.nWSTime, MessageQueue_Client_WSHeart);
+ if (NULL == xhWSHeart)
+ {
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("启动服务中,初始化WEBSOCKET验证心跳服务失败,错误:%lX"), NetCore_GetLastError());
+ goto XENGINE_APPEXIST;
+ }
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,初始化WEBSOCKET验证心跳服务成功,检测次数:%d,检测时间:%d"), st_ServiceCfg.st_XTime.nHeartCheck, st_ServiceCfg.st_XTime.nWSTime);
+ }
+ else
+ {
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _X("启动服务中,检测到WEBSOCKET心跳服务没有启用"));
+ }
+
BaseLib_Memory_Malloc((XPPPMEM)&ppSt_ListWSParam, st_ServiceCfg.st_XMax.nWSThread, sizeof(THREADPOOL_PARAMENT));
for (int i = 0; i < st_ServiceCfg.st_XMax.nWSThread; i++)
{
@@ -379,6 +434,21 @@ int main(int argc, char** argv)
NetCore_TCPXCore_RegisterCallBackEx(xhMQTTSocket, MessageQueue_Callback_MQTTLogin, MessageQueue_Callback_MQTTRecv, MessageQueue_Callback_MQTTLeave);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,注册MQTT网络事件成功"));
+ if (st_ServiceCfg.st_XTime.nMQTime > 0)
+ {
+ xhMQTTHeart = SocketOpt_HeartBeat_InitEx(st_ServiceCfg.st_XTime.nHeartCheck, st_ServiceCfg.st_XTime.nMQTime, MessageQueue_Client_MQTTHeart);
+ if (NULL == xhMQTTHeart)
+ {
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("启动服务中,初始化MQTT心跳服务失败,错误:%lX"), NetCore_GetLastError());
+ goto XENGINE_APPEXIST;
+ }
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,初始化MQTT心跳服务成功,检测次数:%d,检测时间:%d"), st_ServiceCfg.st_XTime.nHeartCheck, st_ServiceCfg.st_XTime.nMQTime);
+ }
+ else
+ {
+ XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_WARN, _X("启动服务中,检测到MQTT心跳服务没有启用"));
+ }
+
BaseLib_Memory_Malloc((XPPPMEM)&ppSt_ListMQTTParam, st_ServiceCfg.st_XMax.nMQTTThread, sizeof(THREADPOOL_PARAMENT));
for (int i = 0; i < st_ServiceCfg.st_XMax.nMQTTThread; i++)
{
From 950a6d82c5b9c774cebcd95fa79426d5ca1f4591 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Sun, 26 Jul 2026 04:04:52 +0000
Subject: [PATCH 24/25] Potential fix for code scanning alert no. 44
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
---
.../XEngine_MQServiceApp/XEngine_MQServiceApp.cpp | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.cpp b/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.cpp
index c4ac65c..e3cdb87 100644
--- a/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.cpp
+++ b/XEngine_Source/XEngine_MQServiceApp/XEngine_MQServiceApp.cpp
@@ -122,14 +122,23 @@ LONG WINAPI Coredump_ExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers)
}
#endif
+// Application entry point.
+// Responsibilities:
+// 1) Perform platform-specific runtime initialization.
+// 2) Initialize service components (logging/network/protocol workers).
+// 3) Start and monitor the service lifecycle until shutdown.
+// 4) Release resources in reverse order on exit paths.
int main(int argc, char** argv)
{
#ifdef _WINDOWS
+ // Windows-only socket runtime initialization.
WSADATA st_WSAData;
WSAStartup(MAKEWORD(2, 2), &st_WSAData);
+ // Register crash handler to generate minidump for post-mortem analysis.
SetUnhandledExceptionFilter(Coredump_ExceptionFilter);
#ifndef _DEBUG
+ // Force UTF-8 locale in non-debug mode to keep runtime text handling consistent.
if (setlocale(LC_ALL, ".UTF8") == NULL)
{
fprintf(stderr, "Error setting locale.\n");
From 591abb63c74e4f1f9ac0ecc48e098e70ebf22fc9 Mon Sep 17 00:00:00 2001
From: qyt <486179@qq.com>
Date: Wed, 29 Jul 2026 09:10:01 +0800
Subject: [PATCH 25/25] update:CHANGELOG and document
---
CHANGELOG | 24 ++++++++++++++++++
XEngine_Docment/Docment_en.docx | Bin 130860 -> 133050 bytes
XEngine_Docment/Docment_zh.docx | Bin 134888 -> 136301 bytes
.../XEngine_Config/XEngine_VerConfig.json | 1 +
4 files changed, 25 insertions(+)
diff --git a/CHANGELOG b/CHANGELOG
index 019df1b..52d4ce1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,27 @@
+XEngine_MQService V3.20.0.1001
+
+ci:更新了CI版本库
+ci:删除了多余的扫描
+更新:依赖库
+更新:windows 编译器VS到2026版本
+增加:AI代理解决问题
+增加:发送消息会返回序列号了
+增加:心跳支持
+修改:现在绑定消息的序列号从1开始
+修改:VS编译器的运行时库统一
+修正:codeql 扫描出的问题
+
+ci:update last version
+ci:delete unused
+update:depend library
+update:vs to 2026
+added:agentic workflows for issue triage and auto fix
+added:reply with serial number for post message
+added:heartbeat support
+modify:serial from 1 number to start
+modify:vs crt runtime unified
+fixed:codeql scan problem
+======================================================================================
XEngine_MQService V3.19.0.1001
增加:权限控制开关
diff --git a/XEngine_Docment/Docment_en.docx b/XEngine_Docment/Docment_en.docx
index b3eb094be52f3f52a1524799ef934dd321e8780a..89bfdf06b99d6f2bc385d1b7ffd44bc68cb4e7ee 100644
GIT binary patch
delta 100635
zcmX_nWl)_<(=G1qEzr0KwheVWS~<@UXFL+}&MnPQ72<|2F%j{L+naKYG6PF4wp|mgB_uuzIh=)VM9Sdc{{sVuv<8rdpcS=d9e97I-Goy
zPu%{RzP1+h4y(${S5_Buxlzs0ju4>rz5L4cQ}feW#3~~PofSQZRyCu9i}}2&hl3;Z
z2V}`efxY``&apmDdhpdcZdLeV92meBSNo`{K`#YQ*Ti)M!}sYHK$6bk-xp+1%3))QvZW&3Y7zVh%%i_-O+(H~4PGhsVb9(}BnTXfma7Bp~ewvce&1wn|NvCShE@<+j
z89}5j5Af51e+Om*L$e&RI9Ece`D;&OvE7}U8Gg0#X733BKX{{z(VbuT(R+njpxc}z
zeJ#7^7D+?UNj}hone=>Y@l-!zUa4-4a4C+Etq1F=WwmN>^0(^ByY$f2>dM>n(Dmrb
z+aGc3YG2q8D2!!ms|sDJUs(sd+HH;G?>9Tk4t^3vXCHJ0GS^ahEn97dG0XEwZ=wS1
zXMe)Qw>gRX^F&Jz5XHx66*(LK-ab5jd0uDfRR+BYJO{p+U&fmloHy>c4p(o;3n>OmBZkDbq`aQd0bt<(B^m&ofYN169XUfD!6a
z&1*uh$VG8A`Q6J-Ah(G9NkR}ct>83_XR_I5zfg2@5H2`NNAK*n8f@{Smz%hh=mF-_
zZE0JIszBFrU8h-{@$C6iC9utax;>%SU4_gj73)(83@NCN%(?`}woIA`7JiIHIA@S|
z=LfA#ZmbW_2Hef8cpY_uSDq0M`ijMu2po6&8_}%BoN_<+U0VO5QHZEtH&!lQ>LW{~
zz$QwHqLX((ICzi#Fi&~1xPj`Qd!+m}v5@)3l_ig-XWUIauw%*HRW541gZ|>TH}d9h
zCed^Rh!vQe!ux;k*h=fI+I=6bu9w>o5TKz<<5B0-^uJ8OHF&&s{klH()>!^q$^33x
zsE0Duskiqw`t9*8R{Lgw-`|}mzPQ6Dv4wfn?Jn?2{gP>Th}o;@X{EaRhjy&Bq4caZ
z2~JKqZ8{ZY*$maZlhP|P_TTbY8>D0uOG9yApjz_J?03?6k&^pQS3fKW;zmxMePuHI
zNd0HIOLIGr%Pm@h^GmF7_Gq@a@aAIqL_6k>T}WmY=T34b$vw-9VLemr9*!;cFy*wZ
zT$A7~9WS=xJtS|yeHbO~SA41tm0(5;CMTSxnW)k~vtLr9f(ZR?qJHjNi}56Xvl(jO
z0Kh!DgC-1vh5dxa;z4=acP)LbasPwHE}KWfj>pyZ##SrY<2m
zbr-kC?9#rqr)^iPbwcB=f(;re?G#0;a3mJp$D)b&
z9WAMv?nZC4kHWxKmxU#2mx^a)^mSMbu#OfhjyYx?+L5`^eXPlJ#4wn|pC|hMMj7}v
zFFIR}x6<{p68~9|LPTS35O{=~zrU2fcNax09MM*nmFuzTk#mF56;*E*#QoW{8s^~2
z*_9lU6kU#t=^v-JCi%O2S+$)A0mGLu6Hgmey4r)o4RnmoK%Y?rO1c#D4RFwMC9Aa
z^-<6&)mSJS%w}Zs|3nX_jo*3(oQsvMzvs_5#3GvZkRwqPqVl5YR_osGEotR$!
zknCu~+G#px9Sj?~JhG9+haB2D2gJ}m`)WDX+O`rZS8me}`FE@93*ApvK7xhag>9uU
zqxbmy-57=%)ypxe;x(z7uK$)h_Z!vv4K9U9HGG%zg-*y8q7Q1b&C)RhZZo;A97x%Q
z;1d0Rm(B{yCqAa3ntfT_3GsQzp3hVmZs=wke_M>ewKYtv-i{mG+El~zx`iL7=`B!)
z-3`5}t(K=Napo~TB>kIrdjVq)Ga=hXhB6^<5|4(KTrNU&J!O)+y>ks`e}tkBfBcDF
zAb3G|z)sVowf_hqxD{0aKm~C>H{<~7nvig=k^U!La~}D_*60O>c5ZjvzsN0T$a?lL
zweWg;Q8mG)X7enk>0)TY@Uf#=xO&Hq#jQVRXE|tBn8>AyA9Z#l?1YHZ+_20K{rzo?K3S^wc(kv`3TzgTUma&-utPxs&ex_?AS04&)4`Iwa_
zEA!r)tQ~%+5i)SJ#Nv(WyfBQ1u8q$*MtT6~k9Pdf8W$LRwkU(eat;Pe*#ED&c%kXi_A
zdW7{PkUSN^@|s~lOoY&&yKperU?%J7XZkFO+&T#S82#FQ79MnxC&r7H#7YGkNMHa5
zo%wRh_rfhN4U%Y)sf+Ovj#}xKdQp?g%d8tBwbb2?VifS;*g!tFXmurmp?)OnL8JVf
z5X?nUV;M1<@CgPB7T*>tsEXLs%AUiBD%JKI(*$3s3qS+Q2Gq}-TUO-=OjMvDBR40NDYr-UdO+`a;VTT$iBLe#nD~`bCXD$Lqmjvod%lmW+1dH!%bzT
zOZGQF$janMMnlVk+zn2<`>JFL~%S^nQK!Ai8R;
zN;k=z`UALO}3M|6oa6)mY)~MEAlA`z0H%Qyiua37x?&IBl7x&G)eQfY_sk~*
zhf>cbI%o%&W#(irBANNBPrn~43!q%`pz4rdtnQ%TC*aM3WOdyovj%#Xrc_u=(>CK)Yxl+fpDzsBMr}#Rk
zE9Fqf2qv{3vG{qJ7Hg=KwKac8m6%Pq|A)d|w9e$XZCc5P@iS5v)bVntGlYJ0;pGy`
zk8~Sg%L1JQC?}DAh`??t3}4zB0!+Jq!iTv@mSzz+}s=F}~|bP*ipwBNp8^C;hFlR#h^!Jxk(dCS5(yj_WZn-UxyvPw1D
ztv=TkPlPB>!*?!#4}aJ|4FTc8-$ETUvA95p%VK9DR`&gz7K5di8#q?Xb)`CaG)0ag
znGgY*RFgX>S?htsYbtEoC%wcIC@WO@vi=ik!PL5~FB2vH*7BL?EMJQwZ|MDkmqF%U
z#~KPT%Sk484gu^~AciQ`(M)nlhna7`w8$rBEeMp^&*gBSr0KEnSAhU5kS8yFk%NLO
zyVazO7gQZQadW5(ItX)7?32NAKlegc4&EjANK*4qchGU}X4gMs5|cy7P`Js`pMQd~
zp*KSfZ@@PmX(GcJWHcTrR-_I!M&_*L4}MG%zM!_ncn0}mty_E2P<~0CsJkDcpDJL
z3;I!erc9^LbtSEy6-yMwcgPoO#NGE|$t5Fbc?xorFu|+eemV{$olrS#pKZ6r1n>D2
zXxx+^cA0++`7nmu{?9TDmgVyRzicSW5kWr$cZ1;1CGGGdQ>fts+>Rb*C;Mj;
zX$+0A1XyFZzppS(iZe8VNPoX|G^nMbr|n9n!#bgo)K#k$fuPPH!T#(wvhn0Fj4B}I
z3Ra{PnAU8dpsmbwk~`P!wJpYAarU!O;9ZTXKRcY9;ge5*v?L?O`!TTxYMBLMAqcU&
z9R|l0l$7j{F8|fT0ou?y4I3IFC~;4bnc`xCN9+U*c@1$I$U33&xZl{&THr+=;{3W0
z)U^Epcht;11=Hg^m}$xntU!$PrlwLb;V1-m
zhX7z1KcnVL110{2qS`Pm*Z6~uAIB&cN$D24ANRMmneqJvwEkT)-u#+0E?0J!shb`r
zHHV6Lcr(t(WjSvcHF99V6zR?ikz5*633^0_uQ6VpZ=6Q=5^d36Zo$Mka3Ewq
z<0m=(vIYdF7iN+%KJP?|AHUhjc?pD8&IL1
z(U0lm48e%*gm=3ZKLh*b;B_|cJV;6hewc&2hB^=Io=^qcZ+zv^dm)y295F=qpRaAUn|PqSIEAfeMME*IUj%U*&f}$W-M|N)C#=_g
z68IQcJ*Ub+jhW;C_|RZ=dn2*=0J$&&*;M>gN5z>|hda7ZifF=&ysVE@KF8fkF&kMP
z1iy>;@i!oX7X&3r&})kQ`k_R+GalLl`n*&jyaa?bm(b^6xm>(%&%+FHvVY2%ujT<4
zc8~EB9;7bjQ#^-@n`PBD)P}a1uxA^?u;na*wZ;o-ULpBdNBWyKLo=xy*ngOKe**Qr
zM801F!1MI`mGQg2e-)b$ytXp6O)mKjUWM@W=I%!hsJ5!AQU&ygJo;6NkyZM4uP(vX<6=O8zWN4l!gM|d
z|BW#5{KtE(t&rqXpHeaabY!O8+7vGw{8y0Xo~m7bx>~;{!T~{T0Megpti}G
z<%4FC)m1528oSF~!;Eq9t1~)4Ncz}7%@T^hTR-W3-i8Q>hxfRL>w-_z5c4j+5tyY^
zm$q-mwH0t1n$^!K0C`eW{!CD0>0ect=U3Rz_@Jr&FYAgq4}3VK^4mTu=Hpg?m58LD
z&tTR^lW4|E+@@xm7SNm*h`pJ9zwFESU);RX_8^;$Wh+N=OQp7yAOF;J@x%|QV=|D!
z)h^@*vbOrKf?;PuNZiO1g5R2_W?PiBHRUq%$q8w2xL^M%ss?@sq#|ZG9bH*lUXyz!
zST-_=M*UVd@}c&V=Ie6Y?|=uXeoy5My#}@a@<2IrS3D#-(oLa_#zO
zyFC|H=;)(h$vyg<7!SYNe=^Yxuc{H`T?}{#1TAr&s*$6%S%e%WZIioAlXUAd#IW^~
zvNh4d^gqLIgs?C{bt4DCF3btn%sse#)-|(7__M5g2-EKk@1p6H%hCnqLTmWzjk_~u
zOU|o{F!WO8Pue}gcyt>Q<2gkdGbGYY3fx%!Da!2Gm_Rf
zh@hg^2}L*-Vc_QdH)|weTSqT;auq1KFKCgQtoJ2^mEh5{HxlRN(6gryD6{_1+`_oK
z=#O6|n=Frp5jZKaD!x=4u*;jJjfd_pDX4E}6v5UKWU!L34HimCw&K@AK48kuU>!2-
zA}}L9X!5QKE4J;|>{j!=$LLXJA9+mtn`@BJ$6(w^bIJ0vW*}`~=Rp4K(H6wx)m2CXXIEHaj)H_uBxMrfsM5+G^>4d&GRQI
zw1w#6OPOf&cwOZ`SqAa`@Bz!NJwF&W)JRkrv9KNMVxQ{G{^58AE&*+)Qn5&d{!+PK
zVU(@op_n+ysY=T7$KuH8zbqLefPG5qO^c1a>{btzQ2^UCW{rTT;=RH0%49nmeA9P1
zq<5xsi8rUopf_r;<(}+^RVobW@;6VDq2Tw=*{^&?vJ@V9Plw$pTgknT!25H)_SzEG
zEc1=oEKdXg3dx+^1!73maVPQK1nwC2F}rdTH`aOdu~=EFcv*xNm8hok?$71fwY}yi
z2}p)AD0ElO{#^4ZofwyT($DmlAuqftQMDucT?21Un(}-~2<>B{sKerqEzJroH{Z$f
zn%^_TNi17oc9G<$E(ae{vsGtjl14wX0a8V#Lz&(76E}T-fk{Wy_0hqY;tb5UGm?OP
zs&6OCOsIIg;y3Dc6{E}4v2;8o)Y!<91ZFH>@CtJUe<8OV%@1BVjTPoX%(;rit;R&1
z%A^0Q3f+GBal}yD#ZQr`PiEqx^o9{BzAW6vX~ICFH2UK7X#@YdShT6^Ad=Eh&Sc{V
zB`jO(T9?Kb==;iyEH&@`2{Q5Z3)Ro5r~)wv*h0**+x;k_^^N;O)Io{yY&5+-(U`v%
z2|Cpr3T>)UQ-%X02pjq;lhszvq<@zoV8Cj7=|jK_3ldB0cV%aCkqB_5I(=A=J(95CQPpN#96(`8Kf
zS&0>x-it^J+hjwN^`!9Cy{l~2GP&+V
zFG!Atr`>2(_VvxD&wVB1ZS-rE)~!VNQh(VRpw&s2!n(>m&dujE$=qc5S@v4be$B%}
z-nQD;X0^+f8FcC)I@euzTxaE``$LnP-Q0$zJpe-2zK4CeLC@=kINIa8VLHv#(sq*<
z_F8t9=1ji@?mns_@c@4?bW*Q2ofJFyU8fbc-N~f3+a?ChPte3uTPt7^BphGExN_73
zR4vyzxYm@g^3-P~)cPsuYsIomN()AiCW>Y4GBMq)s419KH8D*%^3->txTM`x-8b$*
zRrA<|9vw*vH1If=W@R~TwA~mDFJ1fw!(dlH8Q!VrXTtK}91!X0??CCga~Ev1iHXC<
zoPGF{wU!N)Mc`0e<*xv?&Z9zf{%$e?!w9j^ja2tYE^e1T+xuE7&VBm*>F`CjK
z7Vm$KzSBulq*rFB-uV72oKGL7#0Sum?HUAEiXv-aAbs(bdj~Ujjf@v4o6lXFcGguM
z;OTC%cBS2Sjmw*%nzchvR?LiVuqzuOE1s2{yne8ivv9(t?V=yEq!z(a#mg8#L`)AU
z9&2=jK1m^ya3kmLg~e21)k}b&s^EYlM}k$$mV)08gt1iQs8Y2n^diLcQlj1X*H?SG
z@SiBPzkT`9B|Y8bW1&Jp47WIr1Q^htCtwBm3bxBKZq|nsGi8fy_^nqsXloxgxs$g{
zPRa*lzlLs3a+5uo+v3p<^5--H_5!r|ae^hfVkp)-wOc|tnqD%k{CGiQD1;{jwXQSx
z2DQw-(dMv*oT;=V5jP&u#WviOqUhHw_eQL=IA`-&mk@*JuB0z_4$|MBv6NuPt1U_U
zFjKZl4G8&yC4o}-mg_K^Id!7>=O$Cp9NZ5eTS&g{HV6ybJlh{7F=NV>#!WHe_
zkrsz7nbB}y0K1{orAXN}pBy*&lod!h63xPpk9BR$^tcpvl`7DsP%Ptnz_P}zZ5w6R
znM*tvYI9%o{&~AQGT3+Y>Ru(HC@*Eq)BDejRls9_2Gap0qv&u|;+D$>CRA63t
zP^2$MCOffsHjrp?lmOwcxhCjbm+ni
zwZq>pH+5{bBCgHBXDgr&cw%yOpt6mrZMrusOo__K%{0~lLR}E45k}p34
zQY1zm((}?94ZxCX{(Tjetbf(s;NPN}kb5!=iAi6wm9wQ+YLOFub!hJpONyawjaGT!U|aMt)#;G`;Ruk5TxxX8qQ;KsGkZ9h%J3YV
zeqI&pJK%{?))SeK(^SUikR|j8v>tT9rGNA$k!jy#9IcB9kR_a3Ab8eLFbd$;d>-)?
zOE=T7Wq3=oc_N|qgT498+g3Q|gl)m@`Q6a9v99_N&>=ZEy07yLG<&c0zbyIL!~;PH
zFV!THw7fs7TDibjr{qs6j+d7JzAlP(7E{?5`fmx_;@^iq4-SbvVLj3uuIJ^G^`#Nu
zc3jYp1xSYuguS?Rj-KNta#jhrSxw#;$apVYL03Cwt_`wieH1WRSUAp_y0ajWeQsnm
z;OL(NX1xiOv!Qe<*1I;iWlcy|K$>YSa4V(3yD>_GXaXnS`Dt=~52KY;&Z)Y6m-L8)
zqhWV{E#4%3P2ox^U5)GPd3Z}P`br~uYuu#F{#G*Ce2}QXG+D#WeNU%)Td4eL%9Kel
z)Ff?&>M&(kO8pA0%^F{BHs@EQ_xys1E%w)5z``hkmlCo0QutfCs8W#tiL)+7m|%L~
z)y%_D5&Unjw1-1jBF5*a#&!6eRjrK-)s~+XZq}<*)-gfVj2NK6(tLT^#BfFA<|0Ri
z((o|wK2;`mq&sOh?NUST^Xg(cs%Eu(k=C3=UI`uzPS=Ry+Z~-3Mparws)@?T2@gC8
z5Ywd}O@Z0Wt_h(cX7YXNzS>^c#Tv3LMW-i6(-=cm6D=XtDPPFw)7EjMaMS9(mR*L^
zO1AApIhV2-GdV0gLB{U=Z5G9F`Y?7QvFZW+6%(
z9^^KnaH+`oI|x11>7BuW(3}J!_r?nS@jV5JpVqD)W}x(-d6e1+n`*+%MpASS;A|Zi
z`ZTaY8$^^a^2Z&I*Ixn*r~A;6)8#YM^J4#)a>A4~Pe%5rM9v->RQzR{sWuK@ThoDA
z(8h$?(oo9IE8J3dy!t$ct*0gR=)0F6>VmzI4kALAMP4tU#~QocRBdPKs0|MVjvm%T
zq$yQ1sXpfj7Dp$cq6u-I`xBP|2q)ClA9h9A>^L4+Gt=ewFYTLjskDSsq+r&Hxs)|(
z=pN2ReT%HL`;sAZ?=i4FJ)g~p0gQXN$r9AVHA(=#ahzsZqQ*#f4p~TLB;S*g=Q4Ar_qb|gEllBdou`fW?G2M;>!pY|JlFmx>d_?AqUfP7sH
zR`R0h@p`kbgs@fSv=+VOX!h8Ym_qyEvSUAQn7Z?D4L+!IAnQU+6V(1NOoSepTuD<>l
zJ78=3a{dXv%(H~{X=?EuVAst|W2X5o!EHItOExWo=}%T1#KvM)#6HCQi)D+0%4LW<
z>c9qztCo2!U)t8^d;N84#vBA)cmm8okDn|uBXs@6(e@~)a!-Q6ZZt)WUbCVNM5AUA
zPYJu_h87QY+7L(%n*x0%e0SS6xMwdiE6nlDmZFIkSeVm7x#IM`R9ce=;a9ZwKbX!_B
z8{gv}ol7o0a1tmxoJuM1>o$EYOGlhjfbb}+MTU}F)sH05H@o^Y9Jw9c?JdW6;TcTT
z+dgfyft^IOf)gx&Nbfy&{6>Q4oXM!~%y#nu_VZ&MGY_+}A~ynKgfGlSbLVIo9w@
zL*wPxT5ZYJ0yNC^a{X@bc)uyPeA_mF%#H!OjA{niM)DH?I-XRnv5_-fZ4Bz8Uazs<
zY?(_F`eW%Jm;H=i+6!u}Uq`SncxX{V!VEzW|E5s|qmG0pe}*p?PG5a*s9<`Oj9Pku^y@fh}mANYd#j
z=vkiSaElFrCC;43!^xnUt_i>Oc*xJc&H(~XXF|*ieAdn4TzOWmTId#wP+|mOuMm?m
zvX6G$Ema|mlP4nXzV0Mkr>?tKl}A(6ueunQ7cALX{!yok4y-y;jB$wSMJl=6Ikf0j
zh#DENm1B%lV!TD)-L6?!3^Yju%y~Fqb;_!&yw}bE*iQt-W(>(+I~V_XmJMIlfaws=
zs@&G0n)I&~(Cs8|c;sy_s4*30yWl5Fqw#Wq1Mt8^^ihb<78FxQdl?b*X&DI
zt4VpftTS#5qG76y*7{S5Q{`-vhaU7nxo@Tp%VDMo=EpAf+{Iy%hBBg2HM0E;%ajHU
z&fp+G%cX@$)Tn2omb*SP(t_uC^YwCs^6Ry3V}bcD;rDZ)CfK^Fs-o2j4K64Hh^5RA
zcGMM#rRIYy7vI?Wo2`@^?RC>*(KvkAtO?w?fI{u%cp1El?h5sM$uW|A?^zPZi69cM
zCZjUvt#K8%`F-DC@Yxia-UU**9&XB8RdQE=Tcf^`GIbGgIWlXLQyS&!-|u{j7QRA#
ze{nq8$g{Y!jS~iUBFm~mmi
zZb3qCTZNiQNzMY!WUZpr^AGaK`Ns@Lv`Rm_U{-yKwpG>wBZpX_qNh?nBu$ybA=m|n
z>8+_agsqoHOu*O+D<@6CuWv&;4_rGD;rnPbB$&vlG*+Z3apWY^bQRR7CI#E?rb?xD
zdwC*~c01-^fMzU=SpiNry{?KCK!gV@1Pq1!WxW+gpu4S|L2;q`jpyv>j`n}PH4Vjo
z@)-Z}Q=;_t=tfXJhAcvB-k{E3k5^m%YhQDvL&V%iU9t*)tGkL^SPe`E*)DQi=5
zzr_2f3?DarUKe50v4(N-CbEe9v^
zTxG24hLOB~gmND=%JuOmavuc}0r~?eOoS5>7gd5glT!71CRmgTssb}<9w8fXRHpB-
z$qPF)w=5^Tkuf$6zTuo^3ufg2x3H!ll#Iie+T)b@evX8UH|tsXbxY&y%iae;@^pdf
zB8~SEUk=QsZh}?YvfD=8p1vJXSLgmUa$>3mB
z5q0i*w5Zg+{Oet+DG?C(yv6>$3%otvzh7MEzeTsH#TDILap(pHPp*Egu}P7!1PyxE
ziy~fb8LhmO?v!tZ#|=mrH`)?v8G(@Norfp*cGe(awhb)Pk5bPU7Y1|kHyMtVd>vNLUp^oPXoe%&%m1Sn?*hu`8T0J=WN1r
zo
z{`FDM-|PM9RmO7ql+byhvMko_SILm>P
z^xVMBQ}#g5BOvf;^8iGGP`{jjZ2A3OK#3@T5-pDcTv@p|8x(UPrY6U&8;>yoDDkDjk-_1ekQP3
z3zdO?G!TDDbEL?P6h%fN#9Av4XDolsm)5sk?VchpeSgV=B$f*)PIQrXZ|E2t1w5qH3m`!;X&h;RJ
zxhX&Ly~>=3h)VuG2ZLDJzH`&s4uLT6fo0*HId-i#J^lwn>=E1VdrCVfLJf=gR;(>F
zgHtfN{_H`o(gKHv;YcI(d3O1V2)4Po-G!X62w+_<=KUp`(yzz-OS7LH555^3#OR>b
z+$i%z+7cfv3)RT~~{dez=MpGdK2Jc`Jl
zi4(3|-!JvpU7+X~!Cdy`$F!5I(vZ(m%ISrCrOE7As#ZcbCu-z=^-l4hr4!2h2?Q0p
zaDmZ32pN&qOdZITm66hh!#oZp-RS7%$x1gA$%Aj{ttDygr
z6tuYeb_7gMK_~TM3N|-ieyR-}*zFr@QP__9{|7ZAh(
zuiG~EoRuLFC3ykKV^~M8$SP#=OT1&_@0t~6YTW>l3%~^M`V-_mZgwk;A@e3XRg;{r
zpqV~B-&luSwCP!$h=&QqR#nZ|iu?FeVALd-j#j}yfmOWGB(T;VvVy6)EnznWDg*>N
zGfdqmECD3vs`BiamJV_eosXULK=|X%dXZTN?*KYUOx0+&_G-NCzs8t$xGH61z%)yL
z5Prg9I%GI*Gxf_ikpO-v?Vyj$-Lb<~`o=Ue9~JQl2Y0pUuA2zPNrQHMS)aB=3}8q6
z{_Zq7uOX}&NVc1NshLLe@{DrKzAweE{xldF4NX}`#$?T1JyK@dR>lN=1M0o(Ir*^z-eDWWRG#rlV`7K`J``y{d79?oj@
zW6KNmv!aDv$&*bikpMVCq`(K{zkVrj%n}V;0$uvcmz5QR<4^+W*u1?F4`K~mc?`@F
zp);x9|b_3)59&is1yo`2hUrMT$n*Cd4W|b!hOVC9AMQ$&t3%Q|tD~2KJ
zM_J;Kv;k8mZyq#syRPCYyMKrzas7vgrN#e81o#gUSz?to{AqF4Ya$E})Z{7>t{}IG
z`_3r+D2)EDelDo0$=9fMUFO!;TW4LWZ-_DW0k!Qcj7at|)gFurIF=yI2vB{&SG;pd
zykbnv?nI&a`2wnYB)o#I4>9+h|Bfl-7VE&MN>Dnp%*>Hlrn!S@!mBvMOY9Z73n|krGj|ge5Nja3`_WdL
zrzfQ;tPlHdl-cpX@m7O1tutMH*%Nlxb1IJ1i?&q4$(We3=;d6JHI
ziaKN>Nh}sT6p$@V&VS-zK_Wt0?HYLoe;?jhV#x{!*z+kX&i*}4dr_{IDf{U?knFLT
zjqzF&PxlFY!hFrGVkyy|#u=7Rcl-VP1fRX3ug>-yuer~md%B{rL#HfsCJ)Mpy%
zy?T+HOblj&T4)X|s+}dhXd(cWJoHx%i6ZqS6;Y8UR%cBYI68e&%iy?#uZ?{_24eqA5>P*7dA{4bOMPpKJ}|43q!UWJxq
zn;GJH8=zn?!;;T4Ij1@n`mC`=g_f87PvKpfcD8!%
zt4aDXxQPXp@ICFPk(c1-)%yL|3ClxlKW3&I=4G!L=g_`>=dN6Wtxh1GrR&NLR7P}k)WI_e=w&?@weyeTwbY142G
zHVd5~dEdpM{I@j1bhN(}ed&4C2p+X@1#P$lupaQh`!#To#$r^=D2oH8}+h*WZ85uBfk;7}0wx;e+
zrz5p#ZB|J}*KVuuI*Y9omv}-clg7wFx0oSOhh3cAq*sVf+#wvxDd$t|?seB4m{mb-
ztW&N&TJFC(!GT6(l;zQIn%7f_%o?kt*k$Y_Yz}y4=>{|2Sn-W6p#K(DX#<=}tHT+BKc5`GmAL=wbH<_$d48ht
zA0$#dOg&kGFe34&&pVl3AAUhC%zHqv@PCD1(I9aebk7a&v9nEyfHw!Jf`o9*8u#!6
zGL3wi1^nGs-mTB=14-qYUf#Y-k~{QQ)Fqrp{V|y!HU7LRc)MV@a0X2fi$GWU705}J
zMVIq*j&JNI^Tv$$b}-=B#OscA$%ezSkAvAyv~Ri$mOulyg#{Fx8m|j%dKe6^BQfoh7``A!QNR;;jip`o
zJ;IPS!~8`y3-rFNP>v$4enC#diJ=gml3BeP#qeos+Z{9!5MD_aNpWjoot|oQAR9hy
zgSQL!@QUNb{M8l)`Yg|(()T#r`;2$CCB*KZns~FoK{+Y%&GuP9_u2aGb9HNdU+?Xt
zf>1JN)o)|&`MZj743+Q1&%k-_?452ESL!>r&_rU@No94@HPyb3WdxCFy1RNdm*9@X
zReS8*14FZ~ku$+#pTe8s)!tyJH&h^YqqSHJo_YUy!h-N1SBT1yw;B(u&vnjG2>9Px7TpY40@7CQEFA(BHoq`t-C
zw+oJ7yz}2(!l>hAb-_B_;J}Zu=<4NfzuX2KFk1JqMcYFC!KWJy1X%Y~YF9p6iKiO^
zroS5whf-02f+KR<#!-tg<=*zFm$lo<57i5B6;vBU-^iS{uH*BCl+e
zx%;UvFM}KIb@Y!L?VGB-F{E^&I=7cS`#R!R6Rpe7ALj!)pA^rq?HijaoPdg+FGrMD
z^NHrp>#3j=;3#__qxy2An*o2Y??-|RJHz9N7Z+3cH+?3eGw4{W?aK+l&vz+usgFdL
z7HRwYW0q%8!jp*27Q9M<+53E<)tkynng)9`ef!eex^ACcD048aLU&HwIG%F)VpJ@!
zpczf|yyfoBighMY{R~Q!a^_LCY7|Z6$v2Es;$*aqfhwC&6c3=O@9pMjKOtI_G%jUc
zs57@~QlLjTH%~F*tbTF(y5iet16-P==RJh=MB>}$OnzmQaJ>@ic45T%9Xp|?zlgj3
zycF?Q&C4!Adh2Adz@!nN-uE>yigjD1GEF&klktb)-q;^s^|9$t_B`YKn@A$MEVJ>N
zDv+=(;Q#jf<%6^v=kNNd{To4=`H-!wT!=?$6=9%$m*nv#eng|eDEF_5#`bD-XYaK}@Ll{OqNFeVD>+et0FCPzqc-G9^+xdvQ&*J#Uj
z@w9$({L(zWYoxaQmihchj(j3O8J6U{czl09XBHLE^bmwuVywmT+csMM3<_;J~MlbsdP>1kKDS~s9Az9g%(-Fq2kIlVQj?heqM_{t#v&^Tt=M4c5;vX9n;oZ{wA87z}(J)?iue7^87Q#@AXX6Jx@{{e&A%1l^$pv`QWC
zW<2(%djdu^>t6uZpNl>Dr+BI{=ySJ#Ls+mpSWqy3)y)WQ9~x7VRW2345l?@<{w_L>OGTA@ILjw$
z3L1|~YslwfBKpDRl4@mexxl9ZC~0zwoyMkmf*$xgF?0L|v1x8K2f&@hOs7>S0Xd4m
z``xPXuIJy|Wx9qBpYbWKrr&RXw{_r|9e7fHH+`4siJJW^*&(WQDD+Hz_1bdDEhj9v
zWBm4p2|VS$-@d=?zrV2q_kDMO9(H;4MU?34$ou8LJ^Jo}DbV?PHxRwj%s+%;x-37!
zaKXlKEpmhcK%+W)p8X0vN1a
z7wESZ_)?lPNuQ91sh#qj!He4OW`1RSzo`dF#
z8rWF>(^XAi>U-Kq1e=OwI@KRzVKPRyl>DKmry!H>cX*+>>cGvWo6z_=#3+AnYCV$w
zB^qW@F@}G*=Z}T^crT}X6XOj~RAHt;64DhrNzu8ul4FfnnM87{ld5rd0#zpx~(Dz%6Z8X#PcRc}2(Ev?JP$
zAN*3^nTY(42mw{38mN+y^fA}xc;&+;MxQJd%jT!5ge(=)1gcM&=zCp1R0xXOkS3wN
zn?4x7|Ivyw2nrTU#b^Z|XIiS+i_z;q)D@h*64pMVcbD3*-e6Qp_OR
z*d!fT8mM$x#8VGsV!h%ihzFBT6k`0GRUrP3cgN?z2C8PdXqgm(shLr+cV{X{{7U>?y||B1_FPvvT|P>W0$a!AgJ3pobY(v
zx{WAYXjh=h-}l-?Nog#Erb7KUe#$Fdg~0$etd@SOgx5Yt!rK^Fsfv|pCN}q%Ug)Qrv9$WSJ+QVL
z=pp!Zo|*-z7R9M3cpyJZZMHAzWL~Y9^s(V}y=DUgx09NIZtnhmJUL+1L)|{uz79+Z
zYHTX_Vcl=Jy-Xb32<%oc$feEY!QPr1s;AA}-nv(`C^vh!L1)8mUp_zI79
zXa6}j?i-ym>ENlG2uW7W>~^#4W^F1=o+`v@LV%-A4FMR+>c=eLsP*
zRcFytiUNf*D`Ll{k#KDt%Qjy8#*O~z?XgG9)Pczq@z_e}WOpR%dQro@;I`*OuHwt-
zv75U+D+tY)pL^Swsev9mZMuQw=-`F_H+F-YgeUIdj&nd#+*Y4_;kG031
zmrM0mQ&8@QHy6IwOBp4lmNiM@)w-U>eu!aY7^D!n$9joqGl?0Eu{lMj1$
zb{igwXvGy!DRx@-Cbjg$o+4BG<`Wqx+uI|2(Ui`CpL6J&H$DF>*;vQ@nC(6r1NoEu
zjO5wrTO(T4UhHHdnnN5GSaXyX)ek%f{QNkPc)rdm-3>YIuyFC(q+w5+Zj+m@iU04PHBf8@#ow4RDv)ClLAM2nPq>9E`v7
zarEW2*k43H$~9Bw0V|(yJwWGiQy{Sxbv1^;)6-X4-R|@yo~QeyQ5&em;`2WZ-;NX)
zu=hIKFThMW9vF3ewLd@YBHT|!y+3KVf0Y#|7y79z;K=#j`AFsY4wk!`cfooi$B}h
z*mTBV^8`n(dtoQ}yfdP!v_Q%Ee>T3M+^nWBus@Mvh
z#oRONSgLOWg(t}`?RvESfU(00araOE>H7Y=HzEY<6?<_16&bSHS%bo=^nP*Mpnk
zzrDB}o%wzGXCYMoSA*-DUwG;N*|PUt_{96Gi%%kW17#+-k}-}z$Gn;E@Y(HTe$_#ckWu5QnBuL!4~lYfh0e&sZu)5HUJM7^8jer@Ip=9UM^AB$vkd!0{)XY=Ry
z)8jo`|5JBP{?r}#^Or%7y7RjVDJ+iJA|6=2emIL!oR~42sbY^}z#v4Lt=qqc{ft)F
zEwARTXrOfJ!rv3~ndhdd++H^M9WCi-(-YXe5gL
zAcQE5gc!?KOwS6t*1rktT6|O+yUO`kQS;-`?hvF9Ebk-fWH>-V&qSQL)KIW++8S*LK~0
zD;GnAw%3LTgg-FEbUR_3A#C(U+tEzQ42NrT)d;J63cA3Y7oKBLPp#7K6p)Y=BD>cg
z-hV76kM@AEA2{N|Xq*+BFj4|ik_9-YZ!)YPBi|Z0pB6$E_kT<7`ID>R=(ouvoZ-ng
z=Ye47ySXszi}PjYGF#(8N{zbrtL9ptD40UJCg8QRIamVgam)4odO5MTzQi5j#AByn
zkL9hd;Is4Gi&>tpS7iF2GIs7C5~9$W1}OuTK=lgVJ`Eu?K8qu=^}74wUadVgZb2x3!QZ^`bC0>2nJQ0v@7
zZ0a2uwPRgD9_#Z*md^kX`2UV7ucRDd%Ujz)_bV^VgkkC8Pt>ZV!JN{1Z-_^&+K0Pk
zrVSB8BxIp*u7j0+EHOn0Swfh=_11F6taLX0y`JQ5q4REo&gdZg6%b!Rm_U4j*$E|a
z17;w#2!GjnFGWWZur^*rFv!zC|K0DxY?Zj{^~^bjS*vPox$-wYt+Ac+{KR?tQCmkC
zDm1INj5c!pew$YtG|9P9qJ71;b<9wVCK1l>qqfxrM|pLUAc1Qh0r|+f{yOT4GEo>?
zTJMFi#~dR)z8%e+9g8~difK-GYsdY?Sr{%5Q-70#r7|i*H5=Br=s;7YaD5j&Dg)^u
zhp`Eyv&z`oe1^yzE}yp-kHgFFLYXc5n}V#)kz);pQa)7>kCzk5DKoNQN{HkPD(FA0
zM%Yus%NGb?`DcIl_`Y$x96_pdTAX!`Ve0&g&}XZJ3>V+blYtTdQV%xNg;ivrVR?*U?v|Q^#>J8E
zbVV>;=Q5O*QmOBZMtLr$0!UILF8){%MSoOrNlIY`MQxZ&qi$Y2Vvf0VdbYkqK#B8-
zsUjkcs_}Xfh&hwMNDEsfH{xyX;(v&B
zQ30_es3Ig=&7f%0U+`R1^cm{mq7g=YIfjDzQm@hVL23P=5I42!%ESg{~h2!+}|^8;*PG
zIB4Qsi{CvtjzDEd7ULx|fF-;yYh2mu>)*^PMdu&YvHdHsyad3Bq^69inDC`j21Ej!
z2ta~$jQ`OsHHTgJo52*>B1}b%at}eis^LK{&oddNSdR>oz}C5uq8wRHv47C@P0nuA
zL5s&WiNegLuZ_b{#pH9^GqsH|pa
zF3#9MOH-u^B7=%(=}hX{tA8B>srKr75
z>w#Yh%-Y0WM8ycA^fUr*6iKmv(iVJXSu?lFUz~AF=b7wsme}N1`7EDT(CvP8z@fHp
z1^`kFFf1Gqga82|UB6XT>t@*78F@q)ui&HYthD5Un+i;i$E6UmDSs9l^~nSgXQN}e
zssWzV28*;ziFMqP;J
zGR;^TH50S3WzVt1sPTgoq}poGJeT9}#SC&6C!_V%IE9T63cVqBC@uvcr#{B6mHAO%oonJ%18ETB$#XnY;RRm(9EPYN|UbTANLp^YpKqQfi|
z8>1wilUR>n;1LWg_xuLIz}roWSi2q|CMBAqVh}?(r+@PdP>dc(DI_7U(1;$WaE!ag
z0%;~wLZj+;_H;#BDHK#jN=XkHvpEDT5LiuRs$$wg^_I=0ut4f>ZiCQAc^Wg?`7+1JolJUDr}MG~Ri2AB8r)F8KT?E$EVGG$T|u;oJn^`M{{O3lg=5$`XeW4rl>O&8AGBw=F$pYFr$DHnW1@UOkI+!H+HPl
zxr^_B^D+Zcjl!avf%9CLL4d(cDu0f}ilWRT&?-ZwNn^iL?^c2H{KV)iYAQ;-%ID#e
zR^CdlD+)qzx)^dcdwq4Y|G1LmkAL`w;!ZEWt=H_rw#Ut0|M3t1xc_^iq|Q?Btygd|
z7L9=g2V!eu#d^2G7RGN~$o!{6gUbdvdjca^%Q#7)+$cDgfI%(
zMD@Mk0;`STFo?@kr)a(O;^9}Xe-i|__-I9d<05LMs&fI)ccOn|fHg#~Q^!vn(qz-C4&WuWMr6J?zODNdNEb4N7@
zhKn6wct)6%Sq1sWgW+5|ZGV7^caH$3#&R9YRpnywF#6*$u0Am^e1*W0n!A-Aml!aj
ziy#`a)Ic2uS3FO#?f}E9%QWJt%a7^@!*{=+W-xsB3u^+ycfV*qFnsItGmEsGUmcje
zz8$&v^V|h9O`lkRQ!5oN!rn?rNkUxN{fVt`;38n}nhxD|u5#!9B7Yk-i+oR~p_L2h
znp={E8$11`=D=ZZqSF-OsL>I9WplY^l-N*!zXJ3tgcHXIz<*Diy^M3tvCuk9(mG%U
z?&a_8?{Vt!^>t;3H%3Yf0S+LD$%pq?O5cCzWQ!B1GM)zX{g9dG9=F#XFXM8vRAx%D
zmE&gGcMBx+71m02oiNCkGb;N@+wsFqYv
zaG-UQFw@TU7JsUAB3A9`&%pz90@xV4F03@LH72h;*8ilbj4cIsG%8K?U*
zwsP%3C>q?XJqW+LAhJv>R;gMpeY~F?CrVej`nu>}AD!zD^%f6EP%0u=C{tXOpb#3c
zl_9FNOR&LUJncT$Ph<*+Pi?Jn6+xS(IE)&J;p#EhUw`7!t>pTlHj>(6%{Da1Xdv&4
zl%JbekGcM1u7BtADMKcm4-Q$jux}&R4;XjHvjCR?U=%fJ7@pnviLG$py3X|@34zXV
z|I;pUeRiE$hDIKA61wzxowKLSTt9JVNFvxIoY=2iKf_EJMw`rn9CQ8M=K8S$zQ19U
z*_b|ycz?8C8Ykvrh41X<)U#*Lp>jBGvL|9G50mwJZc*bpwFzexidW!a$_UEB9p~Dp
zX%STDIKz*S;#|@KPix&FixoxHM`B}uC0%9#N+G}iaiLYW5PNw9m}N*)A)72ED{-nJ
zrjTk`)KMBr$Wbi%QQ=g_fW2V=!Y0@o6vFbj)_$lgZ
z`Q&Bz#i9F&+nby5#0mO0x7RoRN8N(mPv7Kc?j`wo@%Q}K)3AdVFLl2XaR!MSEY>On8)dbUQP9fhJh60))XhbN@u2mSe)>
znD98Xgvah*C(t>1^F}wb*WSz6wZ7el4Jl$+m~Opt*j&U6uvlrk(dA*Qa8|m`Revy>
zvWz{Idx;nb>|TAyaM&T_Dv;68@X)^GVA)(MSK-IF0T4zE94f)bT*c!eh8#L)4%+7|
z;#%${MkR(2;R2~c*3&&t3~|k@vxdFj&Xva0M$L+mBvlmk-$q4&%S
z&Zm{4-n|_;sru#zwsdrU>rO3iZYf4nLNzKR!hz+0xG3f@Ed}fz!3SIdq<^zQ6(rRe
zmsG9~gLs&&M+CpbquZIW&8)Pt2r3duq+sTV;MXqGh^H<;IwJUOBlzXzd0Slc?p4*F
z7=Q*73etj0$1oRGl76%pt#AZ8Z&;|D!yuo`B?bz(u?K(#9Cl)WrxtRFo2V;UW%QW79$#M6)J)S}s-;H|7v?Xu_`P4C^g}O(V$wA*@p@y*xHeBr>TeHXCU|
z=25ql5ayW^eBoFFLutx7ZeA0fxQR`(s({BM*z^uPASmSXv062}(0>nWf9!40a+y_`
z0>1#3lXsyYyzq)G_;LXGw{Ht>6k}<(JWuDB&v%%G}B7S^vcZcES&fG&0PJ4JEuS1!A@v6cD
zkK9CZVkx`7(y?;KB7YATISOAT7vo8wetLJ&Vsmuzb~!T*aRxVPn>92LW({6vYSOBs
z?(+zgAc$?TA0?z#r0SSQctkdLBpWqk@vGX{^AcKL?OL
zj-p06HKcff8tfzCl-oL~X)_q^7~%$o`9ViLfw+OB)~L|*vNOoItoDkE*gPt=>%r@I
z)cm)8eEaQIxPLHO8Ath11WKg>oZJ=H_pw)_Fc+XIgK$*(8Kl@s-t|PI${fnP2HtNY
zMGaj5H02a$UC%11%%?Ylec2SXonXp!CP0_79uC<-+-qJ@gm{=F6l&sKimt>HHKR~a
zWl~)s{9OP$8HcF4J%A~w^Pd}X`T;^mQ75I^3I
z4MJh7Bs|`Z&xaRZl204Sq^;@1keA&qCO?MGW}!jd>P||9QJAd*=Nh;@6FS+g?4-hn
zYw5(*Zx-pq@X;C@)*kZ+H(N_5-Y=x4bmA_`T1h8jo*9W$!P$pED@62x775`VG!_#y
z1v0e1S$|lgX459!y!!apV}diwI$aLWi8*IgD#a
zFoVv19x|Itr46x=24i^0dD25hg<{i&{~rJV|9}7NUCnOeN_Kt~!kYkr;jSW!f0}6n
z{Jq^6yW8DT&lm`T1|`uJZ&Rc$N!iyu7+|s(AV82+f-EwNtg_4`t1JS{+svK8yhW;t
zlq^w{RHREbrIs5|+Y&|AIp;fHRh_Cj=k-ZC@x#!Gh9|Gie}3Od$V+y9^7B{ZKk}N;
z*MA9leL*tVZ_x){(e?z<5MOW;Bx!aLM7}lhlJxb72mtxs{O#8#NCZR*(%k%uxirF$
z+NqEK4IHLx-9q@|0%M
z%^pG@UvuY$xXl$UPKw{%ILcCd;V6jk?R_uJj5P3yFBBK8F`{%PowfV6`?
zEAqxzpPzg20CN}+^A4u+a$@_%%YP+B1e&aB3w=^O&;9B5zb`WaC&no=%}gGLl6N6|
z(`H+7bQ9c86JN0XbdUs-EQq7+52Sip<6M?xNrp_AeRqhUrrm-Fz1qZjV_l&$D0Hz+
zf`Kp0^|oDC^nq&}*VYwiASNPW(G@SqnO+(U9%U>eaFWFFjgycrFMF8aZ-3q<-k9pX
zv2NWU^gGv1bc@FuEKge=KGu8I=UlL}@6!_0*8o~nO(4oleQjevOWOgh&{5d}pdl0s
z$FIDcj2~C=uhEfQQ~YBO=u>PAnDMU^53KlP&g-j6R}fS*Q(_te*HC&i9Ty|t@GhL`
zzGxu+>@8{962TN-c(lw48h`0*=4s&X+rBqmq21~yJpuUDzTOewR{!Q8$aNHx|LE-*yle-i%hIpCcoGacg>3b(
z`b;*aEfn5iR%bA;0&K;yRHk^z!J9YgSyxwal6A7dq?M+f;KnU8RDZQqMN@H9Q6iJL
zqgA6fSvH|&9pPVEYgZO7Rz(0UofzhPemlvS(Xx{4%BF1ao#f9n5pCu_EfBnj3Db)nBbj=xDkm8@!`*&o#f!
z&as-UFz}LgS2XnK3d*{-P{ogWh7vPd5lmi98ue#jK
z-||`a5(d~IASsR}YQ{0xP2obO;W=PhJP~hbX&@=Ks6*ay@A@-y(t?G#HdNJodb{Rw
zx-VySYF^Bh8-G}tOwA?XBEGFNH7^AZ7Cw<@B3G!~wrow)_yt3DF*V1EsE2cINUk$A
z7lCW)u3Os8bwFJep1XB}uVo}QFleW?L7$1ZZUW2`X<5cPk;`j?Hx8dv`oMoJMVMPf(IPh7C#;{&G%Zbt8}XeAO(>bp
zF>pWg2`^2ta!P#iB!5_gSye`+r1PHP)E`4vpVrh+V=a%{oKT4M!i5
zs+uw|_{}+XF%%{8)&oxcr*MdZE5L@PA|7fKyq?jbUNH9KY1YZ||F_xii9OxZ3X&8KI
z=a{kuIttPTyMUU2_0=mVs%HTIgB@7`;8k7Wn*d-E>|C%{ckorh=!jcKVn}k4h~S|f
zA(@llr+1jUI56NeVpaW-1CJbdfX?YHM42RimHAK+_QeoANj-EXO|B?NU?DtIU
zS1;sPO@Feg$*L{A{9;0NUO3qF-o
z7~^ixyCwfq5B!0sfF+Rq0H
zvLs8^F(V|=RF;12`n0M7No(A}`V8&{?d&}W12dRcu`JAlXb(>Y?#8^v)!R==*unp`
z(yBF1XK0dykWw$6y8aMhO}U50rD4_|57ai+
zzA{AQ8U~f69#DRX9sed6cz>hUIvtGkq*Er
z?X`83GP~tfvT(Ot-ol#&TUOr46(k>pKIl22_HaqwI;RE)<(DgE~}1mDZGGB7Xx{#vOJo^7j0B
z7tPjv&)EL)3zcOW=Tk9Wefu&|nYIEPvmmNs0KUod7SvD=R-H|ERWw!Ao7{C5Qw1Ik
z+Zv}N3)Xd^E!n_w46U@10ii6ZI-O-K(C-p}zfEWxqHMc)7nGexzwAAf@_o!+>cM!e
z&7KN7ZWzP&J}nA(oqvkLFu3(g0pDtLsgmMK1}vX9cNAMj^rZ3;U5n@f2uau#b5xMo
z&omoV9J*@)u}w@Viz2d{jH`BrTOO_3#Q>W1ASaVfPstoche?nQYc#A%;ihmVZVgaR!AhTFN)9SX3
zk_hQ5QG)tt`t$$(H4f!Z;a
zSOkeP_JXhyD1Qwswp=HD;laho45&7JY`wesq=`G@{ie-Y7tLQ)Wi@C;fberciRzK)
zLfdpm)%zo8*MfFUZK+&LyU@?zI2CKj5(`W+&*~#ZH?YqBkd8A%Cq8%DzB5!!t4-fbQ~g(zp(r@7I^VY3EDP|Q!Os=l0Yh0NXmS$fZGBn
zvUj+xTuA2c_29Wvs$<+KV!MunKxtkoJGSUJ`r`uBw@YyKaZsE>-3`b{Z0J5tI4%@d
z;{rG&w|_W|Oz_-6v#b}x}hwrilAk=2Df~;
z^`)vNfw^>BW3^95JG&0pHQAMTAIMwAI7_s&
zRHdoFxL(j;GmM`>fpnI0sBZ`OjA1JeB_Ul`xqlb0T-Mb5`Gu$r#hwXH4ipGI#;Gb$
zkzzsPP|s%8Q)B;X+P6aAOF9Gc%CD>8=j_5PBeQTn@}vAXMdIVu;&%q|coO=VKV;zm
z1XR}*xgWu-&jF>WT*#(+;?jO_%`{D8Vh>a%~S!A103$vRinbWO8b
zU4Q89@&ggIp5t(HjXH-skSIgZcJ?(Xcy=Dy<|WqEazU0xHtX2t3mL3S3OO-7d$+t#
zdd$;dZr4_levk^|6=PQeTXJO+K#t`gpBvbHD;|%#(>@1aH!>+VqxH!|9rwv&A&V!$
zAn&m0UWdxGeAVU@p{$s$yW0UM?L8kYRe#y>(r2x9yv-}5{^|ez^~ok)qj_U^=S2gb
zXg}`}s&-gabiNyE9YGB^t^#&j)QTl6P@RxpZ(5})JD2gi;j&2DaFxVaJc!Hd$Q7#E
zkc%He0Bnht)a9wF?*}tAh5pTqGD?zq=^zMRpZxjX{^zGZ{L`QQ_%GznGr3D|kAI9P
zEnm8-sQV7qMog$8C%n8>^n>*4+K+n-^*R9`d0s=yj
zm`7P$wXND;PZVvDs;P0(ESa*ck?y%|s+mSnO+(dCX`TJZG@5y!-A
zM~lCl#l3#<_j5Kr;LE_*)*IvFH-FJN?q*{C9BR=T5>l3az5MVCpU2+dHuLV^ZIf?%
zOyha{)BxlRb2A|?jqA@>M(@o*y6WHmOsMh0(9MdjZ5uB4tZT<^_9ZZL>}HSMZ0oz(
zPifsPWP4`)V>f&3W>?}DieWk$I?iT~-7JsBi>3~Zh8^tZ&-m^N`tjJuzJI9LP5aQO
z>nDL%^Zego7`GNF3v9e>x(2jt-g~2tynN*4BQJkjynHq7lifu}V&3q>z{sjB0mX87
zmm)th^0zr0GpVQ2|?~{v#Q;kBooe`;#LZ*ZE}`r>M3G_n8YI{z6%
z&!L*SY|1jX%|Dxv(i@RVpLd%wr{IRn;#W&3cM_l7|t9D#8#2JGjBy0yuw_m;nUUl7WouaFW
z^wn69X$phcQKUu&tY-r0v(8!Z1GK>?(j
zyotjwzNZ4-$8!NOQYLC#4YPQ+7;FR@D${~)guz}y+Mlo9&HK;g}+9calp5_{9Dn!!!
z&Es@}Gm`V^M1R*0Z;tbcwRn#P;dJN=5Aiffv8K)#a4%U>a`emQB6j3h9NY4QFk<@W3L8}rSn}cB;?zQV`x8WrZX>L{yt(A8g#qCs3
z5pH5STyDCG1&q>$F;S6q6*>FnJKKH37-YfS?iZBSW`EsZ>S(L(TQGLlzm0w2)7xdj
zUSaFS%LeJf->Xy&EfKS1{=pYNiAok&;%eB)57!Hc2k2Dqf;aeK8l(YTBg7*c>^}m&
zU6urc%paa&+zv*9m(oPa@iaT77o>hfgUhoXfu%!0NOxsa+HNDtiey#qW*gx~BQU=`G0(UY~f=EGB>61R?&^r9a#e-W!p;utlWI3)2`Q8-qO|
zYXMPFh=&$_DoPBW3iqP`!##Hc{C2+3g
zlz%fQyy^9>ge%rO#M&Gv6?)Qu1Wfydb}iJCygT1{GRm?EErd>%_NfxEgD;bQwYakC
z7zjzclZiaNYi*#8i}*HR;UXC#71$#0P3|uxGoFAj2rb%{tBSCF8U7mx{gFKrJ}_j>
zF#&Jddl9ieMKwwQKs;i0#d5sl$%5DKaDNH4RPcQ<8f>5jZ!+
zxmp6R;xV(ZeAU)-pgX3{uiP3hHIg$|iGSlKel&QFnu27X`!m%PJpWAUt-Ki~XMZf!
zWgtQTDLdvO7H2C}4HH#3I}%ZO`I@p}#i|i^Zxb23t@%7GTpW
zO6O6Q+;Qoe#P)}7sI;RX-Lw$D`hOR^eDa{XOET6;&qhKVg%85T+jpO?8JrU-mZDe|
z?}Xa*owIzD3(iKIRafhkAvOgRv0h$qnfoAO@WIAi_W5)&^fF%vg8?3iqPq#
z?{=EeKMM(PuSC>c7!rvE!4KoXcS%5Wm
zHt7Q>LKr6KFp@C#+jj-#kl<#3lnWsw_S3J`YNfmT6U&?-smI>rhTal=8#Y
z{qyoT+qjN4m`6AhoNnDS)$aZ7`?tFyjD;{<7^)p$a2*zsY~92d86u=fLK)UKEG0^4
z5t|z#7!q-u5{e3;A{2jkzE{?y5`=0E1OCMPh_!pck<&0*q;LVo7Pvqp!OGB6%kW1-
zmgp93`k-I}2xb`gebjt3YK5$-9%wNM1gd(Zd{>$81<4uZrt}(8Gy^{hu9H+Y
z*?~=^L1$7!j-NT;$g=vsLiz)@+P_lUzFLMBI7I$s?O0YR|D5Q116I=_8jB$k-j7);
zVGzOXz>{3lajt(qF!|Jgpa)nHnvP-wl{aBNVEK+S@X)EXY+6o}B`hZ$xIJr5t0!$2
z$RC(XKZ@x9qI{fR=Cuy{vgRF@j!cw{!_{kztSvS;!MfRe6)_%|P-^0$L#zTd6Qs$D
zmPyAsZP@_Nth0vl@U;#9ONm^zv~l6tqdm2$zp%Hk5v+ep;^-zb{WUSq36^joFcLl;
zxKQ{t14WPq9N5WDxdOI?K(?>4N>63Gjh{;;&TJ*h9h+L+UFSCG6rnjwAZjYH!bT_;
zn(Tg>`Q?uiEEl2edxFNf7d&i!cyLR#t#DQw+q%9y))cO`(eJJ6c@MYi#lmlz_B6(M
zW;#8Vu52*T42^bosBD8$mSrvTs$?R#NqJtLR?i>hdso!2_N(Q7zkK|!>aVK!Y$lx#
zz55H75$FLF3bcVbAp=z
zQeOyp#eVv=TCKRfJJZZM5vfwn_O^TD*cM?Sk5YEr+kbvPEw;9$G-eUbI3s)eLX>@X
z`2Ov-2ndT9*F;%>U@9m?xVICnMSzeB6GE}Np=l_&;<3I7IYm5<(~zKo%Lpxh9oH#)
zLh_I(1@k>%cEZZ8ap8F!Et0qZX9M(6m|&^NxnsDKAuF^)+aYK<0|YBvx#z5ykQ?7YhIj
ztkc&tOZ5eq&bqBd)%iCyLX$itixrpu@yNiv8dXDUfWTOH_J8Vn{4uH0~VZQtK0$8LL!?-
z*(K-FZt|z@#F^AD0YF6rmRNIXgUKAHg=N|t`AX`Xb-%Fi4H1W`kA#VLde7!;n-Yq8f$4}YA<8SkxWw>
z6LgR|L8BlH@;9YrOpJk{zF@J(#xHU4u^TPX_yEohI6-lSwI#=f5%z{m(E`oepwR#j
z%y1O8QRCjI8FH#xpvfQ*sA`d>!$_}8ZZ?cGYLl*pk;Z>*(tH@HwVZf+flEaMG^SE>
zY~iQgB98U*PF(<4VM{lZQF{VrFsm?_isu1}z^f+kanhS`g}6)z8z&V-F8!SrQR#nC
z`#b4T;a@7l?)3&SlCIa+3H<*U2Iu5e$=c*lvbdDM_54B{w-$*8KU10PC*#;k(u
z-wVK=v#NjJL4_T++FPYlc@CrNcd(`x(n5Hp%+os$3)Ii!IKusW)FiOgn!Tl!`bxBNhvl$+)hIj!F6jZCV3Q
z{49rR`>_rGRm+`fX#JLFi}uiz{)7Ae>cJ`t$9XX`9~1MKVFf1wkE4gJkQ#3oD1tKJ
z!A|z_47fWiWcSEl$uYOP^;5p2%)KN#&y`kx1>cbh43kJ#ToQxD|EBZDqdhT@7ws{uJ3RG~v;K)I
z%SOWC05;TkXerY>t)YiKDVV5Hgt12p-vxzp-b)vq^}Q6KDydWt6Qh`S~6G+N}Npml5az6n|dAi;-6k002BE000mG004Jya%3-NZ*O#EaxpG=
zZEWmW*^cA9a=s6ccQAZ_T*RkGi?vw(PtSq8$g6D2yPX6FlteAIHfy#0GC^{e2gqd}
zCkXNuAt~G4Gd=VF-Tfm$fJ7HES*-e4ELIhZ@}K^E_Pt6D#Mbk>-3X%?zW)T_BRVPiOCPgKN1AUNu
z@m(Vhlh8`P7@<#vmgO3dD#F;LSel_pD~dw{CJCCV4T2mb)f=2~ejl0{g8~U-K#npT
z5U23`g28+kgr_8`@fL{v1b+}(ASaD(F~
zG(u7j1ix;67(t}`(1c#yyrYEA)hrI0H~FWBJXXC~%HMt-63~0!w0~$iiGt_UOVYb+
z{2tqt;+@dQd>Ev}YE%q8WXCW_95;Go2miBZXwbQXC-lM{|bKW)akq5s_{3+ACGA{GZwnUC!Fgl}jN`sDJnuL!`nWF}#Jn??ey_|c05kiTUFvr|@DCP$
zg_W48>3j_CzSk6%1u1Yq@(8{X(Ryb>xg&C~5KBk(LgSGaF(&+&(f9}8#ecPjk^TDu
zz88mC^n&&=_k4pkcuD;QuD?EjbxRztlUefnlvy|+LMMW6G=B$n5XM0FkVYsCR8S;W
z$PVB)a%B8Nn($2M*ne&f%fk&btKigH{fg?y2obnu1Y$5ivBU9QniW~5N~q`vPBB%y
zJ&4*wwW>LPuF|w9^Rm!>kUG!;nU~^`@+r}0G5J}f7Z0h|%mMN{P_I&$>IO*Frsc*-
zI(7rtMu$E!5r11pvajh#D~6-72=xFgUu8Q8XK@%>1kwn-Fuu>jx1?5w$5<&cH*DiE
zG`nG-Ly5WJ5e#Hf*-K#@fD~~BDHlu!$33ul&-Nf}H56;4b@Rp}-4leu9wH;(emS+TBVg;^R(V>G(
zg^p9gh~o~LWfNS&EFA=G=%MAJO#_}67E^SglN)?5e{o6Bf2ga(Au0(XV8c=vc&;6M
z#TJG!vhSThnh)u3u-3l|YfU(jpCYabzPgBYffMUUZ3F2o@ob~P+_i_61&y>@@_J-#
z*k6(Dk+}syL@oW^DkX{-L=$xLDtl&V%;E|@VmO|yRs!H7-~5k%{Fi_Kw|}l+O37tR
z@*Wa%e_TU}5yvb>WYDxr(!GxSL>WR3|5s2Ql-Da+{5vyTnN+aiC_^Pt*+5HJL_~4i
zOGwOt=GlsU{EHC3^9+DD;8(3ry@*FBta~u@E4cAojnS5nWr2L0q$TT}1(SnNaXpVr
z;sq5{JTZJj#GVS8N$9yI9wi;Tdf4{j3Wk<9+NRavH7$B(;X-ArvKlScS3+12*8ud*uf4}Zyd!huLxK}ub-cQplKDmu_}SRl+`o
z!Cw<^{X5RLus_YbB|>=;eUE#ieha)VlX7Vva;`p3Na}Hpk|R|?N0bhX<4aN0&XP3r
zu>l^LtSE{vXyl6#yuC^?b!@*Ep|Z?y4Wv@u#L0vt=)atC!2Km*(3PWF2~i~ff0&w<
zu7F(_t^anWG=Yv1LYBf`JZPm&I!b?W$f}znPk*VSZh?*46
zMExJkU#{{81EoL&W2{dTdBkh>f7fIb6(}v?^2EYsjYCqZq&PrOP+@ODd6N-n`j6y|
zH^H{f_=@seU3HUAOAcl749qEaESs;ME`II%!|Rx7jpagH;eK0g_m|mFR%Ygvo@kiV
z|C>LYZtNX5$Qw2X*h%Wf6&(H5lAN!
zx}~p;Uhf=ly)3!cvuVa?a+q^3n1hBSerYxhyD(vkx#bmMw*lBN+_3{C`q+8Rm
zgWKi=lWlKnqpmy~;EkC+HiunZbb6leEtEW-e7&$FUw*#xE
z=9JPPfNE_zzKG0b-!>b^30RqZ`x17wo$jX5#NA5LtS?-5mqmBzNB(%&^Jeo_tAFC*
ztbRiE<5ks1ll6XEf3(`NPXMnd55tGLwly{W*j44hGa|D^E^>=UtN0h7;+u+l=}`xOTe>Uzx{|tWZ8{E*LH!
z)#E{XI3KPyz6u%xIq*%!AD#=i)2~c%fZK*5MT2;zrbCrIf0j0sTFU9X7#ubiin7zu
z0!4Y!U)4Bfwb?FuyY5CS`d88Ab>3c1=cd*-i-Q3BRACKf*)^T*mF=RjnRney7ZAXq
zMMv53`eB9ln!Z-?ifP41`vs%
zyK8`<^Uv?SuJ`l#bne(|?|rYm)_;H_xsazQ6ZvM|u*G^Ug_8SP_X6K4Nht(m$+e(k
zsKP2$TFbc=5#_3qvajjJ2GTo;$`OEBr2eM8)LZ7lHc=bD==_PUQQaP$b$%=QbGL)}
zoEy@f{2l%VMLGkT)ZT5-GTsdu_b)y2e9d$0z_>-B8BLZ%OBo!z{eCgw)oVZ+%TMJ_x<~OI70T>qCh?H+izbzIM|s
z23>y|6PHc3KD(08Q($5wpjl<^^ehhge3!PNS$=w_l%=nO2^u33YPfTBz&Cup`;2_Mpmu
zu=QglT6_LmL6Yl1#`;WS@!3P430C_#f6J}?XP)o1CLzQQ1Z{PvSq0}4Hx7IC@=rf(
z@4phvC#WU&jyA@Pd~yRhjr#5Kx~yu)qE@vvb*R*VfYkcD;;S82Q=gZOVG~dKV
zou0OMnKv6-r7}K+pUV8Uug5{T{D68(lt^mr2kkPL2p?Ig0=2TpR{Gdm)087oEO#ir
zU5QZtNUwA>KC4j~1x2Y95N&R!&JrwDOU)$%eM$!lk&~M0)?L&;)dU2{NK)4~sG!lG
z7;U<{8_3T5DD1gl+z#*FM=&{ywS@(98lq?p^bU^w_%O)E4^_u!veo?a)X0~z+oBh|
zyDOc_iV*R^v1>dvr(`jwlS$P6ccvMkM-pW}*!dfT>yd8__l-#b56Pj=Uf*ac)7>>M
z$Hix_9nF`kFi*>dvxX-UisId)cb|MHdL=~anp1wDKRB5cvA)eN6*V`bo*Ge*YUBBP
zJG&N@8wj?esCE6!Lt{Gpj6}@v_i8AyQ15tjEP}OC|Kt9o
zL~Zkf-ZQ2NIt=-DnEdaGd1s_Fa8h|q8=J8++o#h^W%B$2)s_usd=Ar{hFuGh0c~|Ho}Q)O?nu9uo0fl+#`7+>s;r=iPDN)mkhq@n@N#`we(c2C~M4TRzv5x6@EN*tK+-s-l)rG^tGrlw^LKMs36I1*OgZ7r4fG=p
zU{!msw9I{D{Nil!aa!YZCEFD>Zb|1LqsD_P#|FWzrY465CEUSDh+EZ>Ez?Jp*&
zK^t2D;Oy|`;O^Ym=W4cma%7+&v)QYu5%9$vFW;SotF^VjG24sx^Y?eg!1d6klVfJa
z$;g6Fw)R}x<;_GjkJRne_V(#!Cj7yQ2323~xNtMnxjPH<3L(VSKZ9be7k1_~m|M7lCq;YTcgz&K(}N-Ce{%
z@3f&S(d9R810)mCpx-J;JnLNp!xRCZf~%4z0<;HKcki#(LadmHXqR&VC&r?
z{MzYcp8$F^UwqOaguXkujqS}mdwiZl@gPYFT-l)6Knq9788>&ZgN*x{^IY_T>v>{m
z?RJ|;61rvSayIh>XA>G_evk6KfuX%IH`|ve=)M~WwN-t)H#9bc5^-vc?>l$$IXW(A
z;qyU9qMz-pcUD7v?$hg`4#2+^51yN|3FFDbq3Gae8n<*;>+@(jC%VPm2m*%No$1ZC
zi`(1I)giQzttj!n8dG{^Gxhx4z24fbG5TRU3p{|f&9hFBQS%(|cld)TT@@8%W*M_(fQsUo~+OI_6FCVkK8Yx$pIcf0IIWd3`+-gwA`Jj
zCZhIgWYfuLvDN2NwM7c%1#r3Q~t&DraGO(WkMGu?@_b81qf>qo;DviMj1Fg%A84BxF5R?27F=nd)xaE!*jLz
z=<_Ri^fzl`U{PX0VvHUtF%3G%qyriG`m|4uMr(inM?Or`~ID>m{NM
zesME&7fxXAi|GeJ+iv6Y(Px+Q@yOm?#Adl;%|v=ATJD~zWhHgQ_;bgBkoEn|#qE9G
z=-&RV!1diM^kO#}eLXU=umHUuy}xLO-C-7eeSjgr`>-W)2Jp_gY&0Z@Zo6H-o@n**
za=qU>Q&O28oZX#erTSjq2D>i+5U{(G)9Yt5RfmJKsn7)@k&(N@jl46nS(X#pi?em@
zXb}&z*50jg^EC>iR&M#Z?dIyBd#r6vs-Lsj-!bF9cUDBLtr^jF8$A0!RJlC~zb>x>
zezgH3sk1_W7iPb6w&0xO%CXP5RRnqEa4u5rxX82S(Q~FvFyd5?Y=Jjl@75pqF8P0G
z$&|YL>mL&E^!RN4zc!z%vpkmlyX`>)bg}Mw^S;p7xj>|qBKQ98#a;2Exdk-Oy3ozz92Q{3wNI}zyp{(Sg7rkeuPdeedq{SSJ7Kyc6CaC{`tGqsm8
zh-S6P0p31nVT#c&7-KQzk!TDpJ4|kLhh)|Y5W~MjhzNxr;hX%OY
z5?I_`9-b_vz89+Q@jy{M{LsUPHxh`B=03E&Cgm)5|8izFjmuK_fE0LT{yDflPZZyLuR`FIgmlB0SMvJWMuW
zVG6=-M}^gm_^vT3(5Eu6gNiCD9u^&j36jW;uuSnU6?j*af+W+Y{
z4@o$6qdIL9bqI)!T|zmrCeoO4ZR@-ieixm6n@Z710Z9DVy(SrYtbUjTSiy%&k><|
zQwSF!i%>ZW8iElfr!V8~1drsom{bfvc5uDI*pkS=>7bYacU3Kf;JCu%JE~W5|IB)r
z!zXm*gtq?Fjb5d30jxS6l=>msOFwb9%`!gA;3KmG*ZLH`Ztyy(lg6P0Sw_fZ6jTe@
zODJ)w0m0NczvWp{+-g;@`Jq4+5Y(GsxZNxzUp{07<(?}L4qpbf#zXX3z}3eCWNkXy
z4oq}0q)C|m*8u~JpUb!s{5Q(mm)V8n!Cr2VA;
zC?iy$Y9sZM2{ITo++-^Ti@6}nw|tl&SWoIy#X01e4^0VadOtH{#0GW@HvD2g%+z>;
zWx=cOF
z*GV((_tDu*O{8VG=g~3!h|xU3sd&OF?jN#=^^D$cb^?jfxhuE;D`EgKYKfk9M9`Rt
z(L2-n+DJ`nYVWm=xO7`v*_1ssR!6@`wjVO+Kcz<<3sH~glVR4qinno^XM_rRcE^-C
zI3ZP58Jnez;k8M2qt&-W{8!7#xxi3hpXI~tOr)ei?+@}s{b!5B&^u|nl$Zu~b$T@I
z$D(SKdXEbcb&}Dg!Trj8+Z@5_gU=y!?YyNJ0Y)R5%jr9cUg5bu$HP74ThL%?Oc!I4
z72VnP$@~!wQt)wk2R|4SQASH^(UspdW2v}8uy}+u(pTzJdA=OUE|Fsd(9OSTVPtYi
z8_~aXxQVE3UwZAi`_k3YY3!|gb9KgayvOl{vx=o4mr_V#vY5o`e%eihR2Opix}>cyfEJ6Q2Y`E6@hl_h+q6$Ifp6p4lUc0~E2u1eN;6#}i)m6LeK%(lovDfyhpy!v4yIBNcr9
z=q8&~8bWJ`Ee<%H@mp&s;&4h&;iu5M@JIpM);xdtZT+%%>yzWa#-ujs8dfI0*+Xr6
ztlUB2qpOn-1RV7bfkHB3_glzGWdy$1p#-Xvh5^@iuaA=P*ir|;4{F1A;R<*A>m%Sf
zY;;A1>&nzt=;fN)JTc_EhBHi(WK){JpL2G<8_cs>4jJS&!%GIrDs;WZB(aGPIVX
z@!>_%1kf#IaK`8l0x9pl;de&+dlrMCZc$Z_0Ux@udlGYuo)u#CD6W)AI@q=+0c5M#)#K9O5}*}IqB|B8lT
zl6-?y`qhYj&9a`vW9nH6`b#q{lJrWNU^3#VYeIf8?NYeg-=opI@Y}epp$1QTm%VA8
zP${`Gl9?C1hvqLRl$vAO8y`2;B$zKq<6nZn{s6PO!KxWIc@CuO_7pdokC^!Nr1zg$0;;DtM$Ad3^y!u46CX^eps<2
z0brcc{Jr#noL1>a{~Xt*8#N^NG`$MadI?>~=xR%7X63*?b2us?u$Wysifdix20bq<
z0ulT+`8#2hWOrpfHiPE#5bLig2cFg{m%%sbRQqoqx>rf1tmfqU`8DRsqF83AgkssT
z$uKsof2OfH*T<65?Vl7TVGB@c@dy3}AhXu@J!W{~tBd7h`Kka}E4Kb*7wJ8-Mpf1O
zWg?oE^R=}vInCHd@z%Y0e-?faUOo%)Too&C+~pJvr(Y99Eews#-dLy^IId>Zv0Wyq
z=0ru7>JnF5l#4&xMJ-bmsnfaj1qx||!DRSX7_@O&iO`+gim4FZxR=-8*sW2Xz_=KQ
zpN86$gE7}RK&x*p&F*z&^@1X^^<<7T3(B~_R$}+!!*BAo
z1*|##y^NYJjrkM7G2|(#!eqf0t}38A?3tfT>#76}exFp6!_n-YDEJIo4cM=^KC|h+
zUizfdPUG2!<8MxFV>z;?rLfviWiZs^COsX{mBNFTkzos+ZW`E}sltm~{iKVGYN@mD
z_QZEm$}p#vehpjE<;<|-J&r;gddy|e%iVNKIkzr){qur}ZqpUCKNdlvZuPVx*};BLD%XJ17nxyL!6243uzH-*v|J7$EI$
zl$3T16cd!_(qJQ}q(Y?Y660y_aqu_YT`^@Cnwlwmj(RGJ8DcO%(Oc{?m`>H2FYx6|
zLt*tr6KDTY#G6(#SBdYAx7bIcmCbIMV!IrTArL}ytltW#%awHXmN&*35&dKY>r!Q+G42p
zUFIRHdR1oNm6!+x=#v?TyFYtoO&B3M&SwF&(2no0Mn|&tFiLu>ZzRuQq2`%MjXg-24-#BLaJ?STZRqHTLNoZ1dv@
zI8ZXwHhpzo$HBmW^E`)BPQIMp2Wu$ny
z!3AP5=fl%suhOl{OM5;~=alfJcG568>4sxBiq@&epRwQ5@lkA$x?zcU-dnUKF;1kh
zpyB~k8nxY&9@1}FJ6379^~Ls_Ly@C+pR1v}`D3|%;ODwZ!|C!L49y61`_|}asZGfZ
z?RfXLCti_gUtzPS1r`etY;a3&nBvcHkC?B0#AdW`wki}}oO(P-P7LF$T}LLDc~9?F
zRF^G@)>X!KMi^xsv3r9tCKP2~3;78(2+n{SY9Qu(vty)Q#oVmEDXk2)Y8;Qgg{TMD^t}nl5KJ8`0GjkC3oUb89Z9}u5XY&`dy?M
z$X$4eZX}PiF5_JLaLKXuMXu?c$6p_59C?cXgFQ%nk|atLmz_qJ(B<&AK7aZMkKi_A
zR35h2-hP7N=GbelL6S``lG&x5d=^!poz+4AD1Mc@G@!GnN=svPL8a89^O6%x0lSfA
z(T)-nqw>+n`DC0FF67mY6>y
zDTzv|wL4$7?(#TGPSN?VH)Dp36-8dVJI-2sx<#-%_HNNr1=fULEnpA%oVW}y^a=;i
zOqG(4f5~l)^f|he1N#?W%_^VrVpR>(JaecT-czh0+j;Aq=*t#u!W^%@P&R+}UnWtU
zr+b--1i{Efhx;=B=$8|vzO45rGj6NF)*4pjDt%@SUi-=<(K9JBa(c79&YUJ9=q1t2
zm=0F&+I3?2_uSUkrsLeToiq)AA$@en9x;mCP)hh<>-E|nd7ez1**K1=eu=vohddqp
z?}NzVGD21USO2=FTkSwe?Je|76}>L+M3V9h^}$*0L{$ym8#8zxE)#pchKRkOqOnAr
z39nb~-#k>Aq~e+2W{vlAPt+7Py~8-{#*SXNLm+o~)3n}BMq(CGRfb|fW9L+u-JXEq
z|B4uG>|lHWZADClS~0X#8ZXG)K>O#Pqv78(krEIgRA*VDT^CuVc6Ag&8dvNq9&y!$
z!6~z9XM~c%=Ih_Z-CbTP;Ga}$6aTUZdfbx7@LTOyn=x+dGUutq)FZmx#j}5`y~++=
zqUww!KU%qKt0g#8#JB)c%#s9AX-4KELgMu6yiVp=qg2zIkyN3>$Atw#2I_2UF_{Rf
z5Sob=E0?*&`;=*r`ytZ5II7H&y4RzOj6buZNz0Z7w?V7yxsb-9q#;2F#A53DAm3j+
z7afJ);3CbSz5SJhB6Dh+MI}nr9dXSjz~J`H?zLYu=h6K1A0oiI@j5u_$Gjzc_ZyRx
z{z41nD|%~zVz|d0q~=P9G!5xzPlSHAogRD}Ba
zH>V|8MpDCR0fQa3AieDC-?HEIUUp5;IobxiO`n50U~-k7%Ek@#S^4E5AZo{K;o=m}
zJ<)q40uEK{K50d~;f;Ijssl!ul6lu*MUG>#di79xuD}K&dR&x_Va>uapT;r6e_O%>
zxjjY@C3#BqYr4@
zR&}SHKtIoNy%^xbB0GuI*)7xRtN^M!!4bP)mU$inXGsp1!Ma|aH`9mSNOk)u@M4im
zb`)_tJZ)4Cw*I&5n@{9o=?=+Ou^*LxnLJV$Nl74?ERPd->KD^~ddHaOb|J|Qi&BkJ
z`RG;a+AK=W>mv2B1xIWynlH@R08cQ?jpi){ph3W|SEEKS@^pXviAzJY4Pb8V8l70+DB-c;~~#+2M-Sku)#T#g-hb@sM(rt
zjI{W5WKNz8ddN8$SrFP&*@+=sTvj-2SWztF*%wO~ZQa$TtPFm2G78^#pETOJ6jlfZ
zM1pf3($jg|;5h=TF7u?0(PlolMVW+^=-NyVGP3wdZ``xB`34`$GeIr!6SlM-^0Kb9
z*~wLpe8mI-L(RPumPPAvgA{n{4|_`y&}ikX~O78_U~{|{9v6$VTo8V}h@
zPtLZc<@cZ#kgJ*8a~h!`m&db?3YPjNfUe$&*b63PXL#I1p<;o5LptlDp32`?}{WjV3E8#Cd>*Om`zwy0Z~70qt4b
zA}q0nt_+PJ
z+F@C`JQKo9jfB`uf9<>Cwq`|X@ObqhWddGKwhRV#r}!|YG5>6U)D0^^gYBXNWy?6p
z;u^HWV>%mm);qKCT`uP+-rwL%Vj|n@D4?JW=iuKJ%#ofkF@zMG0HCE1iW_hx?w%mA0Orf%h&X67C
z$V?d5C~UTGMUU0RdJxXIw$d;-u>2PcC)*U|XnQa9)k}ZE2x+Q4zYnD%qF7Z&NlZ_c
z!+rg%YZ`ayTU5q@OjJSOaEaW(z;Zgv;{6*IkzkM1ScZ=%7`%YIe`A%<;xl4$=QV
zFmJfDcSDOkX3OPOBGDk=K$)-4D1w8jBed0m7Yd6v!v$pQ_MQ-7t$k>02*NcmM94MZ
zUt0$Z^C5)HmLI@xz^FE+^Rh%pV`&SO!ty13Cq>v*4scKbP0JWPNQ@yF*Oqu*g!)L?
z4gC<+sjkA6{z=^tTGtZSD1^MO
zh(^ans++*^?XcEk{=e}R+5ge5CQSAsZ}&>t&Tiau3|2Z%tiBO&Sa5ga#
z5%Ar^W#+@V15QXEtas-P^+P`2DvZ;4vn?my0|?unu;j?iz`tCc)I^TDC%hKZO=jjZ
z;$E4~g&$!$`l40dQWINSFCxQ;s8Ubh$nEKI^VLrZ0v}Jh9Q53e@fT=k$+tbhv54kr
z8fm#yW+v(g@2L_hOR6C;$RwmO=#OiR2+%3SCG65OmY_oL#U2rlC+Fr6ixs5YmtcDV
zEL6___+{oZp0FXx=rHIeYRFdogLTq(`szS4g2|s2YX6g-!N2AeKk8tx$193_y6NRZ
zVn%~voVM!hIC!EJAAfjK