ResourcePort 实现——host声明目录+TTS合成(issue #108 Q2) #152

Closed
opened 2026-08-18 02:53:06 +00:00 by KumaAgent · 0 comments
Member

Parent

#108 Q2(issue #108 grill,2026-08-18 拍板:真建资源 port);ADR 更新见 PR #150

What to build

新增 ResourcePort(host 声明的静态资源目录 + TTS 合成契约),ArisePorts.resource: ResourcePort | None
可选字段,新增模型工具 list_resources(kind)

原文(docs/adr/0001-standalone-core-and-ports.md「更新(2026-08-18,issue #108 grill Q2)」节):

class ResourcePort(Protocol):
    async def list_resources(
        self, kind: Literal["sticker", "emote", "reaction", "voice"]
    ) -> dict[str, str]:
        """resource_id → 含义(人类可读,供模型检索/选择)。目录化无硬编码——
        host 在加载时声明,core 不内置任何具体资源。"""
        ...

    async def synthesize(self, text: str, voice_id: str) -> tuple[str, int | None]:
        """契约见 ADR-0011 §6,voice_id 从 list_resources("voice") 目录里选。"""
        ...

可选,靠"port 存在与否"当完整信号,不新开 CapabilitySet 布尔位——capabilities.sticker/
voice 管的是平台能不能发这类消息,resource port 管的是有没有策划目录可查,两者正交。

Acceptance criteria

  • ResourcePort Protocol 按上述原文实现,ArisePorts 新增 resource: ResourcePort | None = None
  • 新增模型工具 list_resources(kind),透传到 ports.resource.list_resources(kind)resource
    None 时该工具不注册进可见工具集(同 delegate 池熔断时深挖工具消失的既有先例,is_delegate_enabled
    一类的可见性判断逻辑)
  • tools.pycontent_type=sticker/voice 的字段描述更新,引导模型先查 list_resources
    引用查到的 resource_id
  • 不新开 CapabilitySet 布尔位——这是 AC 明确排除的做法,resource port 是否为 None
    就是完整信号
  • synthesize 契约实现,EgressPort.send_voice 接上 audio_ref
  • 补测试:resource=Nonelist_resources/语音相关工具不出现在可见工具集;resource 存在
    list_resources 正确透传 host 声明的目录

Not in scope

  • search_stickers(习得贴纸)不受影响,两者并存不合并(ADR-0024 既有边界)
  • char_count 喂经济 hook 的接线属于 #157(ArisePorts.economic_hook),本票只管
    synthesize 产出 char_count,不管它被谁消费——若 #157 晚于本票落地,char_count 暂时产出但
    未被消费是可接受的中间状态,不要在本票里顺手把经济 hook 也建了
## Parent #108 Q2(issue #108 grill,2026-08-18 拍板:真建资源 port);ADR 更新见 PR #150 ## What to build 新增 `ResourcePort`(host 声明的静态资源目录 + TTS 合成契约),`ArisePorts.resource: ResourcePort | None` 可选字段,新增模型工具 `list_resources(kind)`。 原文(`docs/adr/0001-standalone-core-and-ports.md`「更新(2026-08-18,issue #108 grill Q2)」节): > ```python > class ResourcePort(Protocol): > async def list_resources( > self, kind: Literal["sticker", "emote", "reaction", "voice"] > ) -> dict[str, str]: > """resource_id → 含义(人类可读,供模型检索/选择)。目录化无硬编码—— > host 在加载时声明,core 不内置任何具体资源。""" > ... > > async def synthesize(self, text: str, voice_id: str) -> tuple[str, int | None]: > """契约见 ADR-0011 §6,voice_id 从 list_resources("voice") 目录里选。""" > ... > ``` > **可选,靠"port 存在与否"当完整信号,不新开 `CapabilitySet` 布尔位**——`capabilities.sticker`/ > `voice` 管的是平台能不能发这类消息,`resource` port 管的是有没有策划目录可查,两者正交。 ## Acceptance criteria - [ ] `ResourcePort` Protocol 按上述原文实现,`ArisePorts` 新增 `resource: ResourcePort | None = None` - [ ] 新增模型工具 `list_resources(kind)`,透传到 `ports.resource.list_resources(kind)`;`resource` 为 `None` 时该工具不注册进可见工具集(同 `delegate` 池熔断时深挖工具消失的既有先例,`is_delegate_enabled` 一类的可见性判断逻辑) - [ ] `tools.py` 里 `content_type=sticker/voice` 的字段描述更新,引导模型先查 `list_resources` 再 引用查到的 `resource_id` - [ ] **不新开 `CapabilitySet` 布尔位**——这是 AC 明确排除的做法,`resource` port 是否为 `None` 就是完整信号 - [ ] `synthesize` 契约实现,`EgressPort.send_voice` 接上 `audio_ref` - [ ] 补测试:`resource=None` 时 `list_resources`/语音相关工具不出现在可见工具集;`resource` 存在 时 `list_resources` 正确透传 host 声明的目录 ## Not in scope - `search_stickers`(习得贴纸)不受影响,两者并存不合并(ADR-0024 既有边界) - `char_count` 喂经济 hook 的接线属于 #157(`ArisePorts.economic_hook`),本票只管 `synthesize` 产出 `char_count`,不管它被谁消费——若 #157 晚于本票落地,`char_count` 暂时产出但 未被消费是可接受的中间状态,不要在本票里顺手把经济 hook 也建了
Yushu closed this issue 2026-08-18 07:32:30 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ProjectKuma/arise#152
No description provided.