capability-runtime 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- capability_runtime/__init__.py +90 -0
- capability_runtime/adapters/__init__.py +13 -0
- capability_runtime/adapters/agent_adapter.py +439 -0
- capability_runtime/adapters/agently_backend.py +423 -0
- capability_runtime/adapters/triggerflow_workflow_engine.py +865 -0
- capability_runtime/adapters/workflow_engine.py +43 -0
- capability_runtime/config.py +172 -0
- capability_runtime/errors.py +20 -0
- capability_runtime/guards.py +150 -0
- capability_runtime/host_protocol.py +400 -0
- capability_runtime/host_toolkit/__init__.py +55 -0
- capability_runtime/host_toolkit/approvals_profiles.py +94 -0
- capability_runtime/host_toolkit/evidence_hooks.py +65 -0
- capability_runtime/host_toolkit/history.py +74 -0
- capability_runtime/host_toolkit/invoke_capability.py +409 -0
- capability_runtime/host_toolkit/resume.py +317 -0
- capability_runtime/host_toolkit/system_prompt.py +132 -0
- capability_runtime/host_toolkit/turn_delta.py +128 -0
- capability_runtime/logging_utils.py +94 -0
- capability_runtime/manifest.py +173 -0
- capability_runtime/output_validator.py +139 -0
- capability_runtime/protocol/__init__.py +43 -0
- capability_runtime/protocol/agent.py +62 -0
- capability_runtime/protocol/capability.py +98 -0
- capability_runtime/protocol/chat_backend.py +38 -0
- capability_runtime/protocol/context.py +244 -0
- capability_runtime/protocol/workflow.py +119 -0
- capability_runtime/registry.py +287 -0
- capability_runtime/reporting/__init__.py +2 -0
- capability_runtime/reporting/node_report.py +497 -0
- capability_runtime/runtime.py +930 -0
- capability_runtime/runtime_ui_events_mixin.py +310 -0
- capability_runtime/sdk_lifecycle.py +982 -0
- capability_runtime/service_facade.py +418 -0
- capability_runtime/services.py +181 -0
- capability_runtime/structured_output.py +208 -0
- capability_runtime/structured_stream.py +38 -0
- capability_runtime/types.py +103 -0
- capability_runtime/ui_events/__init__.py +19 -0
- capability_runtime/ui_events/projector.py +617 -0
- capability_runtime/ui_events/session.py +292 -0
- capability_runtime/ui_events/store.py +127 -0
- capability_runtime/ui_events/transport.py +33 -0
- capability_runtime/ui_events/v1.py +76 -0
- capability_runtime/upstream_compat.py +182 -0
- capability_runtime/utils/__init__.py +1 -0
- capability_runtime/utils/usage.py +65 -0
- capability_runtime/workflow_runtime.py +218 -0
- capability_runtime-0.1.0.dist-info/METADATA +232 -0
- capability_runtime-0.1.0.dist-info/RECORD +52 -0
- capability_runtime-0.1.0.dist-info/WHEEL +5 -0
- capability_runtime-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Runtime canonical capability manifest / descriptor helpers."""
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from enum import Enum
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from .protocol.agent import AgentSpec
|
|
10
|
+
from .protocol.capability import CapabilityKind, CapabilityRef, CapabilitySpec
|
|
11
|
+
from .protocol.workflow import ConditionalStep, LoopStep, ParallelStep, Step, WorkflowSpec, WorkflowStep
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CapabilityVisibility(str, Enum):
|
|
15
|
+
"""能力可见性。"""
|
|
16
|
+
|
|
17
|
+
PUBLIC = "public"
|
|
18
|
+
INTERNAL = "internal"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class CapabilityManifestEntry:
|
|
23
|
+
"""
|
|
24
|
+
manifest entry:描述一个 capability 的宿主可消费元数据。
|
|
25
|
+
|
|
26
|
+
参数:
|
|
27
|
+
- capability_id:能力唯一 ID,必须与 spec.base.id 对齐
|
|
28
|
+
- kind:能力类型
|
|
29
|
+
- version:能力版本
|
|
30
|
+
- name/description:宿主展示用摘要
|
|
31
|
+
- tags:能力标签
|
|
32
|
+
- visibility:可见性(public/internal)
|
|
33
|
+
- expose:是否默认出现在对外发现列表
|
|
34
|
+
- source:注册来源
|
|
35
|
+
- metadata:扩展字段
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
capability_id: str
|
|
39
|
+
kind: CapabilityKind
|
|
40
|
+
version: str
|
|
41
|
+
name: str | None = None
|
|
42
|
+
description: str | None = None
|
|
43
|
+
tags: list[str] = field(default_factory=list)
|
|
44
|
+
visibility: CapabilityVisibility = CapabilityVisibility.PUBLIC
|
|
45
|
+
expose: bool = True
|
|
46
|
+
source: str = "runtime.register"
|
|
47
|
+
metadata: dict[str, Any] = field(default_factory=dict)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class CapabilityDescriptor:
|
|
52
|
+
"""
|
|
53
|
+
descriptor:manifest entry + spec + 依赖的统一描述结构。
|
|
54
|
+
|
|
55
|
+
参数:
|
|
56
|
+
- entry:manifest 元数据
|
|
57
|
+
- spec:原始 AgentSpec / WorkflowSpec;仅注册 manifest entry 时允许为空
|
|
58
|
+
- dependencies:收敛后的 capability refs
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
entry: CapabilityManifestEntry
|
|
62
|
+
spec: AgentSpec | WorkflowSpec | None = None
|
|
63
|
+
dependencies: list[CapabilityRef] = field(default_factory=list)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def build_manifest_entry_from_spec(
|
|
67
|
+
spec: AgentSpec | WorkflowSpec,
|
|
68
|
+
*,
|
|
69
|
+
source: str = "runtime.register",
|
|
70
|
+
) -> CapabilityManifestEntry:
|
|
71
|
+
"""
|
|
72
|
+
基于 spec.base 构造默认 manifest entry。
|
|
73
|
+
|
|
74
|
+
参数:
|
|
75
|
+
- spec:AgentSpec 或 WorkflowSpec
|
|
76
|
+
- source:注册来源
|
|
77
|
+
|
|
78
|
+
返回:
|
|
79
|
+
- 衍生出的默认 CapabilityManifestEntry
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
base = spec.base
|
|
83
|
+
return CapabilityManifestEntry(
|
|
84
|
+
capability_id=base.id,
|
|
85
|
+
kind=base.kind,
|
|
86
|
+
version=base.version,
|
|
87
|
+
name=base.name,
|
|
88
|
+
description=base.description,
|
|
89
|
+
tags=list(base.tags),
|
|
90
|
+
source=source,
|
|
91
|
+
metadata=dict(base.metadata),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def collect_capability_dependencies(spec: AgentSpec | WorkflowSpec | None) -> list[CapabilityRef]:
|
|
96
|
+
"""
|
|
97
|
+
从 spec 收敛 capability 依赖引用。
|
|
98
|
+
|
|
99
|
+
参数:
|
|
100
|
+
- spec:AgentSpec 或 WorkflowSpec;为空时返回空列表
|
|
101
|
+
|
|
102
|
+
返回:
|
|
103
|
+
- 去重且保持首次出现顺序的 CapabilityRef 列表
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
if spec is None:
|
|
107
|
+
return []
|
|
108
|
+
|
|
109
|
+
collected: list[CapabilityRef] = []
|
|
110
|
+
seen: set[tuple[str, CapabilityKind | None]] = set()
|
|
111
|
+
|
|
112
|
+
def add_ref(ref: CapabilityRef) -> None:
|
|
113
|
+
key = (ref.id, ref.kind)
|
|
114
|
+
if key in seen:
|
|
115
|
+
return
|
|
116
|
+
seen.add(key)
|
|
117
|
+
collected.append(ref)
|
|
118
|
+
|
|
119
|
+
if isinstance(spec, AgentSpec):
|
|
120
|
+
for ref in spec.collaborators:
|
|
121
|
+
add_ref(ref)
|
|
122
|
+
for ref in spec.callable_workflows:
|
|
123
|
+
add_ref(ref)
|
|
124
|
+
return collected
|
|
125
|
+
|
|
126
|
+
def walk_workflow_step(step: WorkflowStep) -> None:
|
|
127
|
+
if isinstance(step, (Step, LoopStep)):
|
|
128
|
+
add_ref(step.capability)
|
|
129
|
+
return
|
|
130
|
+
if isinstance(step, ParallelStep):
|
|
131
|
+
for branch in step.branches:
|
|
132
|
+
walk_workflow_step(branch)
|
|
133
|
+
return
|
|
134
|
+
if isinstance(step, ConditionalStep):
|
|
135
|
+
for branch in step.branches.values():
|
|
136
|
+
walk_workflow_step(branch)
|
|
137
|
+
if step.default is not None:
|
|
138
|
+
walk_workflow_step(step.default)
|
|
139
|
+
|
|
140
|
+
for workflow_step in spec.steps:
|
|
141
|
+
walk_workflow_step(workflow_step)
|
|
142
|
+
return collected
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def validate_manifest_entry_matches_spec(entry: CapabilityManifestEntry, spec: AgentSpec | WorkflowSpec) -> None:
|
|
146
|
+
"""
|
|
147
|
+
校验显式 manifest entry 与 spec.base 的关键字段一致。
|
|
148
|
+
|
|
149
|
+
参数:
|
|
150
|
+
- entry:宿主声明的 manifest entry
|
|
151
|
+
- spec:要注册的能力声明
|
|
152
|
+
|
|
153
|
+
异常:
|
|
154
|
+
- ValueError:entry 与 spec.base 不一致
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
base: CapabilitySpec = spec.base
|
|
158
|
+
if entry.capability_id != base.id:
|
|
159
|
+
raise ValueError(
|
|
160
|
+
f"Manifest entry capability_id mismatch: {entry.capability_id!r} != {base.id!r}"
|
|
161
|
+
)
|
|
162
|
+
if entry.kind != base.kind:
|
|
163
|
+
raise ValueError(f"Manifest entry kind mismatch: {entry.kind!r} != {base.kind!r}")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
__all__ = [
|
|
167
|
+
"CapabilityVisibility",
|
|
168
|
+
"CapabilityManifestEntry",
|
|
169
|
+
"CapabilityDescriptor",
|
|
170
|
+
"build_manifest_entry_from_spec",
|
|
171
|
+
"collect_capability_dependencies",
|
|
172
|
+
"validate_manifest_entry_matches_spec",
|
|
173
|
+
]
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Output 校验组件:包装 output_validator 并写入 NodeReport.meta。"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import inspect
|
|
7
|
+
import json
|
|
8
|
+
from typing import Any, Callable, Dict, Optional
|
|
9
|
+
|
|
10
|
+
from .config import OutputValidationMode
|
|
11
|
+
from .structured_output import apply_structured_output_summary, validate_structured_output
|
|
12
|
+
from .types import NodeReport
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class OutputValidator:
|
|
16
|
+
"""输出校验器(mode + validator callback 的组合封装)。"""
|
|
17
|
+
|
|
18
|
+
def __init__(self, *, mode: OutputValidationMode, validator: Optional[Callable[..., Any]]) -> None:
|
|
19
|
+
"""
|
|
20
|
+
构造输出校验器。
|
|
21
|
+
|
|
22
|
+
参数:
|
|
23
|
+
- mode:`off/warn/error`
|
|
24
|
+
- validator:可选校验回调(推荐 keyword-only 签名)
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
self._mode = mode
|
|
28
|
+
self._validator = validator
|
|
29
|
+
|
|
30
|
+
def _invoke_validator(self, *, final_output: Any, report: NodeReport, context: Dict[str, Any]) -> Any:
|
|
31
|
+
"""
|
|
32
|
+
调用 validator,并只在“签名确实不匹配”时回退到 positional。
|
|
33
|
+
|
|
34
|
+
说明:
|
|
35
|
+
- 不用 `except TypeError` 直接判定签名不匹配,避免把 validator 内部 bug 误吞;
|
|
36
|
+
- 优先走推荐的 keyword-only 契约:`(*, final_output, node_report, context)`。
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
validator = self._validator
|
|
40
|
+
assert validator is not None
|
|
41
|
+
|
|
42
|
+
keyword_args = {"final_output": final_output, "node_report": report, "context": context}
|
|
43
|
+
try:
|
|
44
|
+
signature = inspect.signature(validator)
|
|
45
|
+
except (TypeError, ValueError):
|
|
46
|
+
return validator(final_output, report, context)
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
signature.bind_partial(**keyword_args)
|
|
50
|
+
except TypeError as keyword_bind_error:
|
|
51
|
+
try:
|
|
52
|
+
signature.bind_partial(final_output, report, context)
|
|
53
|
+
except TypeError:
|
|
54
|
+
raise keyword_bind_error
|
|
55
|
+
return validator(final_output, report, context)
|
|
56
|
+
return validator(**keyword_args)
|
|
57
|
+
|
|
58
|
+
def validate(
|
|
59
|
+
self,
|
|
60
|
+
*,
|
|
61
|
+
final_output: Any,
|
|
62
|
+
report: NodeReport,
|
|
63
|
+
context: Dict[str, Any],
|
|
64
|
+
output_schema: Optional[Any] = None,
|
|
65
|
+
) -> None:
|
|
66
|
+
"""
|
|
67
|
+
调用 output_validator 并把“最小披露”摘要写入 NodeReport.meta。
|
|
68
|
+
|
|
69
|
+
行为:
|
|
70
|
+
- mode=off:不调用
|
|
71
|
+
- mode=warn:记录摘要但不覆盖状态
|
|
72
|
+
- mode=error:validator 返回 ok=False 时覆盖为 failed(可回归护栏)
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
capability_id = str(context.get("capability_id") or "")
|
|
76
|
+
if output_schema is not None and getattr(output_schema, "fields", None):
|
|
77
|
+
validation = validate_structured_output(
|
|
78
|
+
final_output=final_output,
|
|
79
|
+
output_schema=output_schema,
|
|
80
|
+
capability_id=capability_id,
|
|
81
|
+
mode=self._mode,
|
|
82
|
+
)
|
|
83
|
+
apply_structured_output_summary(
|
|
84
|
+
report=report,
|
|
85
|
+
validation=validation,
|
|
86
|
+
fail_on_error=self._mode == "error",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
if self._mode == "off" or self._validator is None:
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
raw = self._invoke_validator(final_output=final_output, report=report, context=context)
|
|
94
|
+
except Exception as exc:
|
|
95
|
+
# validator 自身异常:作为可观测信息记录;不强行失败(避免“验证器把系统打挂”)。
|
|
96
|
+
report.meta["output_validation"] = {
|
|
97
|
+
"mode": self._mode,
|
|
98
|
+
"ok": False,
|
|
99
|
+
"error": f"validator_exception:{type(exc).__name__}",
|
|
100
|
+
}
|
|
101
|
+
if self._mode == "error":
|
|
102
|
+
report.status = "failed"
|
|
103
|
+
report.reason = "output_validation_error"
|
|
104
|
+
report.meta["output_validation_overrode_status"] = True
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
if not isinstance(raw, dict):
|
|
108
|
+
report.meta["output_validation"] = {
|
|
109
|
+
"mode": self._mode,
|
|
110
|
+
"ok": True,
|
|
111
|
+
"note": "validator_return_not_dict",
|
|
112
|
+
}
|
|
113
|
+
return
|
|
114
|
+
|
|
115
|
+
ok = bool(raw.get("ok", True))
|
|
116
|
+
schema_id = raw.get("schema_id") if isinstance(raw.get("schema_id"), str) else None
|
|
117
|
+
errors = raw.get("errors") if isinstance(raw.get("errors"), list) else []
|
|
118
|
+
|
|
119
|
+
summary: Dict[str, Any] = {"mode": self._mode, "ok": ok}
|
|
120
|
+
if schema_id:
|
|
121
|
+
summary["schema_id"] = schema_id
|
|
122
|
+
if errors:
|
|
123
|
+
# errors 期望是可披露的摘要条目(path/kind/message)
|
|
124
|
+
summary["errors"] = errors
|
|
125
|
+
|
|
126
|
+
normalized_payload = raw.get("normalized_payload")
|
|
127
|
+
if isinstance(normalized_payload, dict):
|
|
128
|
+
payload_text = json.dumps(normalized_payload, ensure_ascii=False, separators=(",", ":"))
|
|
129
|
+
digest = hashlib.sha256(payload_text.encode("utf-8")).hexdigest()
|
|
130
|
+
summary["normalized_payload_sha256"] = digest
|
|
131
|
+
summary["normalized_payload_bytes"] = len(payload_text.encode("utf-8"))
|
|
132
|
+
summary["normalized_payload_top_keys"] = sorted(list(normalized_payload.keys()))[:20]
|
|
133
|
+
|
|
134
|
+
report.meta["output_validation"] = summary
|
|
135
|
+
|
|
136
|
+
if (not ok) and self._mode == "error":
|
|
137
|
+
report.status = "failed"
|
|
138
|
+
report.reason = "output_validation_error"
|
|
139
|
+
report.meta["output_validation_overrode_status"] = True
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Protocol 层:纯能力类型定义,不依赖任何上游模块。"""
|
|
4
|
+
|
|
5
|
+
from .agent import AgentIOSchema, AgentSpec
|
|
6
|
+
from .capability import (
|
|
7
|
+
CapabilityKind,
|
|
8
|
+
CapabilityRef,
|
|
9
|
+
CapabilityResult,
|
|
10
|
+
CapabilitySpec,
|
|
11
|
+
CapabilityStatus,
|
|
12
|
+
)
|
|
13
|
+
from .chat_backend import ChatBackendProtocol
|
|
14
|
+
from .context import ExecutionContext, RecursionLimitError
|
|
15
|
+
from .workflow import (
|
|
16
|
+
ConditionalStep,
|
|
17
|
+
InputMapping,
|
|
18
|
+
LoopStep,
|
|
19
|
+
ParallelStep,
|
|
20
|
+
Step,
|
|
21
|
+
WorkflowSpec,
|
|
22
|
+
WorkflowStep,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"CapabilityKind",
|
|
27
|
+
"CapabilityRef",
|
|
28
|
+
"CapabilitySpec",
|
|
29
|
+
"CapabilityStatus",
|
|
30
|
+
"CapabilityResult",
|
|
31
|
+
"AgentSpec",
|
|
32
|
+
"AgentIOSchema",
|
|
33
|
+
"ChatBackendProtocol",
|
|
34
|
+
"WorkflowSpec",
|
|
35
|
+
"Step",
|
|
36
|
+
"LoopStep",
|
|
37
|
+
"ParallelStep",
|
|
38
|
+
"ConditionalStep",
|
|
39
|
+
"InputMapping",
|
|
40
|
+
"WorkflowStep",
|
|
41
|
+
"ExecutionContext",
|
|
42
|
+
"RecursionLimitError",
|
|
43
|
+
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""Agent 元能力声明。"""
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
from .capability import CapabilityRef, CapabilitySpec
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class AgentIOSchema:
|
|
13
|
+
"""
|
|
14
|
+
轻量 IO schema——描述 Agent 的输入/输出字段。
|
|
15
|
+
|
|
16
|
+
参数:
|
|
17
|
+
- fields: 字段名 → 类型描述(如 {"synopsis": "str", "score": "int"})
|
|
18
|
+
- required: 必填字段列表
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
fields: Dict[str, str] = field(default_factory=dict)
|
|
22
|
+
required: List[str] = field(default_factory=list)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class AgentSpec:
|
|
27
|
+
"""
|
|
28
|
+
Agent 声明。
|
|
29
|
+
|
|
30
|
+
参数:
|
|
31
|
+
- base: 公共能力字段
|
|
32
|
+
- tools: 注册的 Tool 名称列表
|
|
33
|
+
- collaborators: 可协作的其他 Agent 引用
|
|
34
|
+
- callable_workflows: 可调用的 Workflow 引用
|
|
35
|
+
- input_schema: 输入 schema(可选)
|
|
36
|
+
- output_schema: 输出 schema(可选)
|
|
37
|
+
- loop_compatible: 是否可被 LoopStep 循环调用
|
|
38
|
+
- llm_config: LLM 覆盖配置
|
|
39
|
+
- prompt_template: 可选的 prompt 模板(支持 {field} 占位符)
|
|
40
|
+
- system_prompt: 可选的“Agent 级 system message”(用于该 Agent 的提示词组织)
|
|
41
|
+
|
|
42
|
+
注意:
|
|
43
|
+
- 这不是 Host 的 system/developer 级策略提示词注入通道;
|
|
44
|
+
- Host 级策略提示词应通过上游 `skills_runtime` 的 prompt/config overlays 注入(避免 `initial_history` 漂移)。
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
base: CapabilitySpec
|
|
48
|
+
tools: List[str] = field(default_factory=list)
|
|
49
|
+
# skills:仅声明“希望使用的 skill 名称”,注入与执行由上游 skills_runtime 完成。
|
|
50
|
+
skills: List[str] = field(default_factory=list)
|
|
51
|
+
# skills_mention_map:把 skill_name 映射为 SDK 可识别的严格 mention。
|
|
52
|
+
# - legacy(≤0.1.4.post2):"$[account:domain].skill_name"
|
|
53
|
+
# - v0.1.5+:"$[namespace].skill_name"(namespace 可为 "a:b:c" 多段)
|
|
54
|
+
skills_mention_map: Dict[str, str] = field(default_factory=dict)
|
|
55
|
+
collaborators: List[CapabilityRef] = field(default_factory=list)
|
|
56
|
+
callable_workflows: List[CapabilityRef] = field(default_factory=list)
|
|
57
|
+
input_schema: Optional[AgentIOSchema] = None
|
|
58
|
+
output_schema: Optional[AgentIOSchema] = None
|
|
59
|
+
loop_compatible: bool = False
|
|
60
|
+
llm_config: Optional[Dict[str, Any]] = None
|
|
61
|
+
prompt_template: Optional[str] = None
|
|
62
|
+
system_prompt: Optional[str] = None
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
两种能力原语(Agent / Workflow)共享的统一接口。
|
|
5
|
+
|
|
6
|
+
说明:
|
|
7
|
+
- 本仓对外承诺的能力原语仅包含 `agent` 与 `workflow`(见 `CapabilityKind`)。
|
|
8
|
+
- skills 的发现/治理/执行引擎属于上游 `skills_runtime`;本仓不把 `skill` 做成公共协议原语。
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from enum import Enum
|
|
13
|
+
from typing import Any, Dict, List, Optional
|
|
14
|
+
|
|
15
|
+
from ..types import NodeReport
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CapabilityKind(str, Enum):
|
|
19
|
+
"""能力种类。"""
|
|
20
|
+
|
|
21
|
+
AGENT = "agent"
|
|
22
|
+
WORKFLOW = "workflow"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class CapabilityRef:
|
|
27
|
+
"""
|
|
28
|
+
能力引用——在组合中引用另一个能力。
|
|
29
|
+
|
|
30
|
+
参数:
|
|
31
|
+
- id: 被引用能力的唯一 ID
|
|
32
|
+
- kind: 可选的类型提示(用于校验,不设则运行时从 Registry 推断)
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
id: str
|
|
36
|
+
kind: Optional[CapabilityKind] = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass(frozen=True)
|
|
40
|
+
class CapabilitySpec:
|
|
41
|
+
"""
|
|
42
|
+
能力声明的公共字段。
|
|
43
|
+
|
|
44
|
+
参数:
|
|
45
|
+
- id: 全局唯一 ID(如 "MA-013"、"WF-001D")
|
|
46
|
+
- kind: 能力种类(agent/workflow)
|
|
47
|
+
- name: 人类可读名称(如 "单角色设计师")
|
|
48
|
+
- description: 描述(可为空)
|
|
49
|
+
- version: 语义化版本(默认 "0.1.0")
|
|
50
|
+
- tags: 标签列表(用于分类和搜索)
|
|
51
|
+
- metadata: 自由扩展字段(框架不解读,业务可用于存储额外信息)
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
id: str
|
|
55
|
+
kind: CapabilityKind
|
|
56
|
+
name: str
|
|
57
|
+
description: str = ""
|
|
58
|
+
version: str = "0.1.0"
|
|
59
|
+
tags: List[str] = field(default_factory=list)
|
|
60
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class CapabilityStatus(str, Enum):
|
|
64
|
+
"""能力执行状态。"""
|
|
65
|
+
|
|
66
|
+
PENDING = "pending"
|
|
67
|
+
RUNNING = "running"
|
|
68
|
+
SUCCESS = "success"
|
|
69
|
+
FAILED = "failed"
|
|
70
|
+
CANCELLED = "cancelled"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass
|
|
74
|
+
class CapabilityResult:
|
|
75
|
+
"""
|
|
76
|
+
所有能力执行后返回此结构。
|
|
77
|
+
|
|
78
|
+
参数:
|
|
79
|
+
- status: 执行状态
|
|
80
|
+
- output: 执行输出(类型由具体能力决定,通常是 dict 或 str)
|
|
81
|
+
- error: 错误信息(仅 FAILED 时非 None)
|
|
82
|
+
- error_code: 机器可处理的错误码(SCREAMING_SNAKE_CASE,可选)
|
|
83
|
+
- report: 执行报告(可选;历史字段,建议优先使用 node_report)
|
|
84
|
+
- node_report: 控制面强结构报告(桥接模式下产出;Workflow/Host 编排优先读取)
|
|
85
|
+
- artifacts: 产出的文件路径列表
|
|
86
|
+
- duration_ms: 执行耗时(毫秒,可选)
|
|
87
|
+
- metadata: 扩展信息
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
status: CapabilityStatus
|
|
91
|
+
output: Any = None
|
|
92
|
+
error: Optional[str] = None
|
|
93
|
+
error_code: Optional[str] = None
|
|
94
|
+
report: Optional[Any] = None
|
|
95
|
+
node_report: Optional[NodeReport] = None
|
|
96
|
+
artifacts: List[str] = field(default_factory=list)
|
|
97
|
+
duration_ms: Optional[float] = None
|
|
98
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ChatBackend 协议定义。
|
|
3
|
+
|
|
4
|
+
提供类型安全的 ChatBackend 接口,用于 backend wrapper 的静态类型检查。
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import AsyncGenerator, Protocol, runtime_checkable
|
|
10
|
+
|
|
11
|
+
from skills_runtime.llm.chat_sse import ChatStreamEvent
|
|
12
|
+
from skills_runtime.llm.protocol import ChatRequest
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@runtime_checkable
|
|
16
|
+
class ChatBackendProtocol(Protocol):
|
|
17
|
+
"""
|
|
18
|
+
ChatBackend 协议:定义流式聊天后端的接口。
|
|
19
|
+
|
|
20
|
+
说明:
|
|
21
|
+
- 与 `skills_runtime.llm.protocol.ChatBackend` 对齐
|
|
22
|
+
- 用于 backend wrapper 的类型注解,减少 `Any` 使用
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def stream_chat(self, request: ChatRequest) -> AsyncGenerator[ChatStreamEvent, None]:
|
|
26
|
+
"""
|
|
27
|
+
发起流式聊天请求。
|
|
28
|
+
|
|
29
|
+
参数:
|
|
30
|
+
- request:ChatRequest 或兼容对象
|
|
31
|
+
|
|
32
|
+
返回:
|
|
33
|
+
- ChatStreamEvent 异步生成器
|
|
34
|
+
"""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
__all__ = ["ChatBackendProtocol"]
|