Repository navigation
release: v1.16.0 — Responses 协议接入与 Skill 系统落地 - #270
Merged
Merged
Conversation
- created_at microsecond ties in tight enqueue loops left recent-list and claim order undefined; break with rowid (insertion order) in both directions - add regression test freezing _utc_now so all rows share one timestamp; refs #246
- state that group-level merge applies only to numeric group_id; empty or non-numeric scopes return the global index; refs #246
- Replace silent except-pass on persona interest_topics with debug log (fail-soft kept) - Add missing second blank line after class definition (E305) - Drop dead user_id params from record_message/check_interest/check_fallback/check_relevance/check_qa; sync orchestrator, adapter and test callers
- Drive resolve_group by fields(ResolvedAwakeningSettings): single merge loop replaces two 10-line per-field enumerations - Converge both from_dict filters into _filter_config_fields helper - Derive routes _OVERRIDE_FIELDS from AwakeningSettingsBody.model_fields; document interest_topics Web-contract decision - Fold over-length lines in routes/awakening.py
- Define structural Protocols for the LLM surface awakening depends on (judge channel, persona topics, group status, rule switch, rate limiter, stats, generate callable); svc/Any annotations converge to narrow types - Replace _judge_target getattr probing with explicit JudgeTarget/JudgeSettings resolved via typed config view - Add LLMService.persona_interest_topics as the narrow persona-extras read owned by the persona domain - Promote _is_group_llm_enabled to public is_group_llm_enabled; scheduler and tests follow - Type BoredomSendPlan.reply_result via ReplyResult TypedDict (new llm/reply_types.py) with delivered_text extension - Add optional config injection param to check_awakening_triggers/iter_boredom_send_plans as the official test seam
- chat/awakening.py -> chat/awakening/ package: config/state/text_signals/judge/triggers/boredom with one-way deps (config <- state <- text_signals <- judge <- triggers <- boredom) and a facade re-exporting only the public contract - Facade attribute-assignment test seams migrated with the split: orchestrator tests use the config injection param; boredom tests patch owning submodule singletons (state._state) and pass config through - random patch point moves to quickquip.chat.awakening.triggers.random.random; group-messages harness patches owning config/state singletons - routes/awakening.py imports CONFIG_AWAKENING_TOML from common.paths directly; facade drops the pass-through re-export - All package files satisfy the <=100 col baseline
- Move collect_mention_profiles / collect_known_participants (plus AT_QQ_PATTERN and MENTION_PROFILE_LIMIT) into the llm identity domain as pure projections over IdentityIndex - LLMService keeps thin delegates resolving the scope identities, preserving the test seam and call sites - service.py sheds ~130 lines of envelope identity knowledge; identity.py grows from a re-export shim into the envelope orchestration owner
- New llm/reply_chain.py: TurnRequestAssembler (explicit assembly object replacing the 74-line _assemble_request closure with 6 nonlocals), normalize_turn_input, finalize_reply_text, reply_result factory, build_raw_turn_text (dedup of the twin raw_turn assembly in _begin_agent_recorder / _persist_turn_and_build_reply), image_caption_blob, LLM_RULE_NAME / MAX_QUOTED_MESSAGE_CHARS constants (re-exported by service for plugins/llm_runtime) - New ChatTurnRequest input struct (llm/reply_types.py) collapses the three-layer 24-param threading through generate_reply / generate_private_reply / _generate_reply_for_scope - _generate_reply_for_scope drops from 524 to ~395 lines of phase-annotated orchestration; per-path error dicts converge on the factory with key sets preserved exactly - Module patch points stay in service.py: moved code receives the resolved sensitive filter and bound callables as explicit parameters (single_shot pattern)
- llm-module.md: service.py entry notes the reply-chain extraction; new reply_chain.py entry; identity.py entry covers envelope orchestration; awakening module path updated to the package layout
- Drop dead TurnRequestAssembler.session_preset field (effect already baked into system_prompt) - Promote cross-submodule contract names in the awakening package to public (judge/text_signals/triggers exports consumed by sibling modules), leaving module-internal helpers private - Normalize judge target diagnostics: empty string instead of str(None) when default_provider is unset - Fix _filter_config_fields docstring to match actual passthrough behavior - Restore private names for identity.py pattern constants (no external consumers) - Remove AwakeningExtendSession from the facade (zero external consumers); docstring states the real export surface
- _parse_judge_text: fail-closed on non-numeric score values (string/null/nested) instead of raising through the judge chain; regression tests added - deep-cr-trigger.sh: map the awakening package paths (src/quickquip/chat/awakening*) to message-policy so the Deep-CR gate keeps covering the split modules - check_awakening_triggers: svc typed as AwakeningServiceView (judge channel + persona topics composite protocol) aligning orchestrator and per-rule narrow interfaces - ChatTurnRequest.delivery_sink typed via the existing DeliverySink Protocol instead of Any
refactor: long-file audit full split (awakening package + LLM reply chain)
- Move defectify/turmfluch/card_le_nearest entries plus their CommandSingleShotSpec bundles into service_parts/single_shot.py (SingleShotEntriesMixin); patch-point callables (build_provider_client/_get_sensitive_filter) are fetched from the service module namespace inside the methods, keeping quickquip.llm.service.* patch semantics - Move the per-turn image preprocessing phase (_preprocess_images_for_model + outcome dataclass) into service_parts/images.py (ImagesMixin); stays a method so the instance-level patch seam in test_scene_patch_budget keeps working - service.py 1685 -> 1416 lines
- Consolidate the three function-level backward imports into a single _patch_point_callables helper (lazy fetch keeps quickquip.llm.service.* patch semantics; no import-time cycle) - Promote ImagePreprocessingOutcome to a public name (it is the cross-module return contract of the phase) - Docs enumeration nit already covered by a444ef7
refactor(llm): sink single-shot entries and image preprocessing phase
Whitespace/paren reflow and implicit string-literal concatenation only; SQL triple-quotes converted to adjacent literals with whitespace-only diffs; prompt/template strings byte-verified identical
Same mechanical discipline: whitespace/paren reflow, implicit concatenation for long CJK literals; instruction strings in the awakening triggers and defectify prompt byte-verified identical
Assertion/call reflow and implicit string concatenation; identity placeholder template byte-verified identical
Whitespace/paren reflow plus one hoisted payload local; covered by tests/unit/scripts/test_deploy_v4.py
style.md already declares the line-length 100 baseline; pyproject was the lagging side. Repo-wide zero E501 verified by the preceding fold commits
…iptions Independent CR caught four implicit-concat folds leaving a trailing comma, turning description strings into 1-element tuples and emitting JSON arrays to providers when the opt-in tool is enabled. File is now AST-identical to origin/dev. Adds a schema-type guard test over all registered tools
style: enforce the 100-column baseline repo-wide (E501)
Near-term candidates per the 1.16.0 theme decision: both items deliver in full at 1.16.0, phased via dev batches; the two are decoupled and independently orderable
- New provider/openai_responses/ package (profiles/request/response/stream/client) ported from prism-vesicle HTTP path: store:false full-replay input items, encrypted reasoning include, fail-closed call_id declared/answered accounting, per-profile capability bits (openai-public + codex-http-relay) - Six-tier reasoning_effort config field (low/medium/high/xhigh/max/ultra) mapped to per-profile wire efforts in one table; thinking_budget numeric scope stays claude/gemini only - In-loop native replay contract: validated Responses output items (reasoning ciphertext + function_calls) carried to the next round via native_content; oversized tool batches rejected whole (Gemini-style fail-closed); encrypted_content reserved flat in token estimates - Wiring: factory branch, config allowlist + validation, owner /responses endpoint, re-exports, llm.toml.example section; inclusive input-token semantics verified for usage/pricing/usage_store - Tests: 51 unit tests + 3 integration tests (second-payload native replay, batch rejection, mid-loop budget guard); no behavior change for existing protocols
- Guard non-dict error/incomplete_details/response payloads in body parse and stream failure events: malformed shapes now end as LLMProviderError instead of AttributeError bypassing fail-closed into the non-stream fallback (lens 1+2) - Accept 'completed' as a normal finish reason (NORMAL_FINISH_REASONS) so summarize/briefing features using the Responses provider are not misclassified as discarded_finish (lens 1) - Retry classification: transport=True for stream 'error' events and streams ending before response.completed; response.failed without an error object is terminal (400), matching the ported source (lens 2) - owner profile fingerprint conditionally includes responses_profile/reasoning_effort for openai_responses only (existing protocol fingerprints unchanged) (lens 2+3) - Single-source vocabulary: RESPONSES_PROFILE_IDS/REASONING_EFFORT_CHOICES module constants in config.py, reverse-imported by profiles.py; effort map columns derived from PROFILES registry (lens 1+4+5) - Tests: two-consecutive-tool-round integration case (third payload native accumulation + pairing), cross-round call_id reuse fail-closed, non-dict payload shapes, retry classification, reasoning/relay mismatch, SSE wire-format end-to-end, usage/pricing inclusive assertions, trace annotation; drop dev/ path reference from public test docstring - Nit fixes: trace combine annotates failed streams truthfully, shared TOOL_IMAGE_FLUSH_NOTICE constant, module-level flat-field table, bool/int defenses on sequence/index, base.py native_blocks comment, responses_profile case normalization, admin doc protocol table, toml temperature hint
- Incomplete responses are normal truncation, not hard errors: fold response.incomplete into the terminal, normalize max_output_tokens to the sibling-protocol 'length' finish reason (quick_judge length classification + summary cascade semantics), allow empty visible output, pass other reasons through; failed/cancelled still raise - Sequence continuity relaxes to monotonic non-decreasing once an event lacks sequence_number (relay-stripped positions no longer false-report jumps); backward jumps stay fail-closed - Stream error events with fatal codes share the response.failed fatal table (400 terminal); other codes stay transport-retryable - Nits: count_wire_items single-counts native_content messages (mirrors estimate_request_tokens, no tool_calls/thinking double count), INCLUDE_ENCRYPTED_REASONING as tuple, responses profile default single-sourced via config.DEFAULT_RESPONSES_PROFILE_ID, reconcile fail callback annotated - Tests: incomplete normalization (parse + stream fold + pass-through), sequence gap/backward jump, fatal error event, wire item single-count; bot blocking (finish_reason vocabulary) was already fixed in 3738895
feat(provider): OpenAI Responses protocol backend (1.16.0 PR-A)
- branching.md 新增「Bot Review 机制与双轨交叉核对」节:机制事实(opened 自动评审一次/head 移动中断/时长线性/评论管线区分/沉默非 approval)、等待编排轮询脚本、双轨交叉核对纪律(防锚定/证据裁决/thread 回复) - 规范源自 PRTS-MCP docs/dev/WORKFLOW.md 与 CLAUDE.md 双轨 CR 章节,按 QuickQuip 六级分级改写;机制事实经 PR #263 实测验证 - reviewer 契约补防锚定句;docs 索引钩子更新;self-docs 引用副本再生(47 项同步通过)
- 中文散文直引号改弯引号(两处);交叉引用书名号统一为弯引号 - 轮询脚本补超时判空提示,与「沉默不代表 approval」呼应 - docs/index.md 索引口径与 docs/dev/README.md 对齐 - self-docs 引用副本再生(47 项同步通过)
docs(dev): 引入 KHPilot Bot Review 机制与双轨交叉核对规范
- Web Admin 新增「纪元」页:锯齿时间轴(保留条数/窗口 tokens/输入构成三模式)、推进事件标注与逐事件回放、窗口/信封构成条、冷场倒计时 KPI - 锚点推进事件旁路落库 epoch_events;用量计量新增 epoch_history_rows 列(保留条数曲线数据源) - 信封六段分解进程内缓存,经动作队列由 bot 进程快照回传实时态 - llm.db 连接切换 WAL + busy_timeout 重试(对齐 usage/trace 既有模式),修复 bot 写/web 读并发锁竞争 - 窗口/信封构成条只读取消息元数据(id/role/token),不触碰正文
- onMounted 改快照优先 + ensureDefaultGroup 守卫补选:修复 activeKeyId 永空导致的 KPI/构成条默认态失效 - epoch_events 超限截断方向取反(ASC+LIMIT 丢最新 → 保最新):路由 _list_epoch_events_sync 与 store list_epoch_events 双侧对齐 - 会话选择器与回退过滤归档会话(路由拒绝 archive: 键,选中即 422 错误条) - pollRuntimeAction 单次请求 AbortController 时限:长挂 GET 不再让轮询永久挂起 - epoch_snapshot 移出 bot 事件循环(asyncio.to_thread)+ 导出键数上限 50 - conversation_range_stats 复用 row_budget 单一口径,不再平行维护估算公式 - epoch_events 90 天保留清理(record 路径按日节流,对齐看板最大 range) - 信封六段元数据抽为单一来源 ENVELOPE_SEGMENTS(构成条与图例共用)
epoch_snapshot 移入 worker 线程后,EpochManager.snapshot() 与 EnvelopeBreakdownCache.export() 的推导式迭代可能与事件循环线程的增删并发;list() 先行原子快照 items(C 层循环不释放 GIL),消掉理论 RuntimeError。
feat(admin): 纪元与信封可视化看板
Deep-CR L1-1/L2-1(生产已于 2026-09-26 实际发生):病态正则静态检查漏掉 无分组相邻量化链(.*.*.*.*z 等),且匹配同步跑在事件循环上不可中断, 模型可被诱导触发全机冻结(CPU 单核钉死,仅 SIGKILL 可恢复)。 - 静态检查新增两条规则:相邻可空量化原子链(含全能原子两连即拒、 四连无条件拒)与量化符总数上限(>20 拒) - 匹配引擎由 stdlib re 换 regex 模块,search 调用级 timeout=1s 真正 中断回溯(sre 在 C 层持 GIL 不可中断,to_thread 无效;regex 引擎 对部分经典形态免疫但不免疫全部,实测 (a|aa)+c 仍 >8s) - 新增 4s 调用级墙钟预算,超时返回已扫描部分并标注 - 回归测试含生产实证形态、超时中断路径与防误杀清单
Deep-CR L1-2:runtime.tool_calling_enabled=false(默认)且 skills 目录 非空时,catalog 块仍注入系统提示并指引模型用不存在的 activate_skill 激活。现与工具广告面同条件门控。
Deep-CR L2-3:scripts/ 哈希路径全量读盘无上限,误放大文件会让每轮 LLM 请求的目录扫描同步读盘数百 MB。超限脚本不编入清单(不可执行), 记 script-oversize 诊断,与既有 cap 族对齐。
Deep-CR L5-1:§2 与 §6.3 把激活状态错归 context 且漏列 state.py; self-docs 副本随同步管线重生成。
Bot Review 与独立 CR 交叉确认的 should-fix:模块 docstring 仍宣称 "标准库 re 实现"(与引擎替换直接矛盾)、TOOL_DESCRIPTION 未反映相邻 链规则与超时兜底、docs/admin/skills.md 安全模型条目未含三层防御与 256KiB 脚本上限;门控注释措辞按"注册/广告面"两概念修正,mixin docstring 补第三条短路条件。self-docs 副本随同步管线重生成。 留痕跳过的 nit:script-oversize 逐文件诊断的日志膨胀风险、超时路径 缺"真实命中+超时"组合覆盖。
fix(llm): skill 工具执行面防护收口——检索 ReDoS 三层防御与扫描面上限
历史 73 个版本段中纯中文 31 个、emoji 双语 22 个(+3 混用),且 1.15.0 起连续 5 个版本段为纯中文——少数服从多数并沿用当前形态。emoji 只存在于小节头 行(正文零命中),extract_release_notes.py 按版本段整段提取对头形态无感, 42 行机械替换,空行结构保留。CLAUDE.md 规范行同步;self-docs 副本(CHANGELOG 与 CLAUDE.md 均在副本源清单)重生成。
Deep-CR L2-2/L4-1:format_skill_list 此前裸扫描目录,被 AI 面判 block 的 description 会经命令回复原文直发群聊;现复用 _drop_blocked_skill_descriptions, 两个可见面对同一数据给出一致判定。
Deep-CR L2-NV1:_drain_after_kill 此前全量 decode 排空残余,短暂超出 script_max_output_bytes(约 2 倍上限);现与 _collect_output 同用 _decode_capped 截断,超时路径与正常路径口径一致。
Bot Review NIT:超时分支此前硬编码 output_truncated=False,drain 改为 有界截断后残余超限时未置标记;现由 _drain_after_kill 返回截断标志。
Deep-CR L4-2:docs/admin/skills.md 明文"照 personas.example 先例"从 skills.example/ 复制部署,但 Windows 发布产物不带该目录(对照 Docker 路径 Dockerfile:35 已 COPY)。现打包清单加入 skills.example、模板清单钉住两只 预置 Skill 的 SKILL.md,start.bat 首启按 personas 同款 copy 守卫复制到 skills/(未部署 Skill 时实例行为零扰动,工具面默认关闭)。
Bot Review should-fix×2:skills.md/deployment.md 说明懒人包首启自动复制 (与手动复制先例并存);start.bat 的 personas/skills 两段同构目录复制抽为 :copy_dir_if_missing 子例程。nit(模板清单仅钉 SKILL.md)留痕跳过。 self-docs 副本随同步管线重生成。
fix(llm): skill 可见面合规统一与脚本排空上限收口
fix(release): Windows 懒人包携带 skills.example 并首启复制
Deep-CR L1-3/L3-1:a9a1eed 确立"去重表不得活得比可见历史长"不变量,纪元 推进路径清登记,但 /llm context_limit 行数兜底与词表归档路径不清——激活 正文随窗口收缩出窗后,重新激活被去重短路,只拿到"正文不再重复注入"的 假陈述且无重取指引。 - SkillActivationState 登记值扩为 (hash, 激活时会话尾部行 id),新增 drop_outdated 巡检:登记尾部早于生效锚点即清(未知尾部不参与,维持 旧行为;误差方向安全——偏早清除只会多注入一次正文,不会缺注入) - 新增 store.latest_conversation_row_id 窄查询;激活 handler 记录尾部 - _load_scrubbed_history_and_participants 在生效锚点定稿后对 scope 巡检, 一处守卫覆盖纪元推进外的全部窗口收缩路径 - 去重短路不刷新尾部:登记尾部 = 正文实际注入轮,与可见性语义自洽
Bot Review blocking×2:集成测试此前手工调 drop_outdated,删掉 service.py 守卫行仍绿——现改走 _load_scrubbed_history_and_participants 真实链路 (history_limit 行数兜底使锚点越过激活尾部),负向验证:移除守卫行该测试 必红。守卫注释与 state docstring 诚实化:覆盖锚点推进类收缩(行数兜底+ 纪元整体清除);词表归档与投影降级类(行不动、可见面变)不在守卫内, 自救=read_skill_resource,残留面留档。
fix(llm): Skill 激活登记随窗口收缩失效
冻结 pyproject 1.16.0;CHANGELOG 汇总本周期 20+ 份本地草稿与合并历史 (v1.15.4 后 19 个入库单元),新增/变更/修复三段共 23 条,含升级说明 (skills 卷迁移基线、风格家族改名、Windows 包首启复制)与比较链接。
Blocking:[Unreleased] 比较链接未随 freeze 推进(对照 v1.15.3/.4 先例), 打 tag 后会错误包含整个 1.16.0;Should-fix:ROADMAP 稳定版本声明同步。 self-docs 副本重生成。
Owner
Author
|
收口 CR 处置记录: Blocking(Unreleased 比较链接未推进):已修(1baff99)——基点 Should-fix(ROADMAP 稳定版本声明):已修—— Not verified 项回应:zhipu_family 改名映射面向维护者私有部署 llm.toml(不入库),升级说明保留该句作为改名提示,无害。 验证:extract_release_notes v1.16.0 正常提取 2726 字符;全量 2420 passed + ruff;sync --check 47 副本一致。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
发布说明
v1.15.4 → v1.16.0(Minor,双主题)。范围:v1.15.4(392e811)后 130+ commits,含 19 个入库单元(17 个 PR + 2 个封号期本地合并,评审补偿见 #252)与本 freeze commit(仅动 CHANGELOG.md / pyproject.toml / self-docs 副本)。
两大主题
protocol = "openai_responses"接入官方 /v1/responses 或 Codex 形态中转;provider 级 reasoning_effort 六档;跨轮原生回放(含 reasoning 密文),维度切换自动降级通用投影。A/B 双端点(官方 PayGo + CPA/AGW)全形态验收 + 12 天生产 dogfood,期间产出 feat(llm): deliver model-generated images via outbound pipeline #253/fix(llm): tolerate relay keepalive events in Responses stream folding #254/fix(llm): SSE 捕获改扫描偏移防事件循环卡死 #257/fix(llm): 同 scope 轮次串行闸门杜绝 LoopNotWritable 记账丢失 #258 四个生产实况修复。其余要点
模型生图直送群聊(#253)、全局管理员身份(#260,admins.toml)、纪元与信封可视化看板(#265,llm.db 切 WAL)、唤醒/回复链/服务三批结构整改(#247/#248)、风格家族谱系化重命名、长生成期间稳定性修复(SSE O(n²) 卡死 #257、scope 串行闸门 #258、判定链路失败分类 #262)。
升级说明(必读)
deploy-v4.sh --migrate:skills/ 已纳入迁移基线捕获,无需手动预建验证
CHANGELOG 全文
见 diff 中 CHANGELOG.md(### 新增 7 条 / ### 变更 6 条 / ### 修复 10 条 / 无移除;小节头为 2026-09 统一后的纯中文形态)。
Refs #252