pasm-skills 0.4.1__tar.gz

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.
@@ -0,0 +1,212 @@
1
+ Metadata-Version: 2.4
2
+ Name: pasm-skills
3
+ Version: 0.4.1
4
+ Summary: PASM 智能体基座 —— 写/跑基于 PASM 引擎的智能体:SDK(BaseAgent)+ 智能体框架 + 场景仿真 + 技能包打包工具
5
+ Author: arronzheng
6
+ License: MIT
7
+ Project-URL: Homepage, https://gitee.com/arronzheng/pasm-skills
8
+ Project-URL: Repository, https://github.com/arronJack/pasm-skills
9
+ Project-URL: Source, https://gitee.com/arronzheng/pasm-skills
10
+ Project-URL: Issues, https://gitee.com/arronzheng/pasm-skills/issues
11
+ Keywords: pasm,agent,agent-framework,agent-sdk,cognition,memory,emotion,long-run,verification,skill-package
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
22
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ Provides-Extra: torch
26
+ Requires-Dist: torch; extra == "torch"
27
+
28
+ # PASM Skills · 智能体基座
29
+
30
+ > **本仓是基座:只提供"写智能体"的能力,不提供成品智能体。**
31
+ > 想直接拿现成的智能体用(游戏 NPC / 老人陪伴 / 学习陪伴 / 长期验证),
32
+ > 装独立公开仓 **pasm-agents**。
33
+ >
34
+ > ```bash
35
+ > pip install pasm-skills # 基座:SDK + 框架 + 打包工具(零依赖)
36
+ > pip install pasm-agents # 成品智能体集(依赖本基座)
37
+ > ```
38
+
39
+ 基座给你三样东西:
40
+
41
+ | | 是什么 | 入口 |
42
+ |---|---|---|
43
+ | **📖 使用教程** | 从"这是干什么的"到"写出并发布一个智能体",走一遍 | **[`docs/TUTORIAL.md`](docs/TUTORIAL.md)** |
44
+ | **SDK** | `BaseAgent` —— 记忆 / 情绪 / 动作 / 反馈 / 持久化开箱可用 | `from pasm_skills.sdk import BaseAgent` |
45
+ | **框架** | 智能体基类与注册表、仓隔离探测、场景仿真底座、核心契约检查工具箱 | `from pasm_skills.agent import Agent, register` |
46
+ | **打包** | 把智能体打成平台可直接上传的技能包(两种归档形态) | `from pasm_skills.build import SkillSpec, run_cli` |
47
+
48
+ ---
49
+
50
+ ## 一、30 秒写一个智能体
51
+
52
+ ```python
53
+ from pasm_skills.sdk import BaseAgent
54
+
55
+ class TeaHouseOwner(BaseAgent):
56
+ def action_pool(self): # 能做什么
57
+ return ["greet", "brew", "gossip", "rest"]
58
+
59
+ def _render_reply(self, text, facts, mood): # 怎么回
60
+ tone = "蔫" if mood < -0.2 else "乐"
61
+ return f"({tone}){self.persona.get('name')}:来了您呐"
62
+
63
+ a = TeaHouseOwner(agent_id="owner", persona={"name": "王掌柜", "temper": 0.6, "energy": 0.3})
64
+ a.observe("客人夸今年的龙井好", salience=3, tags=["茶"]) # 写记忆(重要度参与淘汰)
65
+ print(a.act()) # 'brew' / 'greet' / ...
66
+ print(a.chat("生意怎么样")) # 走 _render_reply
67
+ print(a.mood) # 情绪(属性,不加括号)
68
+ a.feedback("praise", action="brew") # 显式夸"brew"这个动作 → 它会更常出现
69
+ a.save() # ~/.pasm-agents/owner/
70
+ ```
71
+
72
+ 跑一个完整走查(8 个环节 + 反馈塑形的实测对比):
73
+
74
+ ```bash
75
+ git clone https://gitee.com/arronzheng/pasm-skills
76
+ cd pasm-skills
77
+ python examples/build_your_agent.py
78
+ python templates/agent_template.py # 骨架自带的冒烟
79
+ ```
80
+
81
+ **手把手教程**:[`docs/BUILD-AGENT.md`](docs/BUILD-AGENT.md)
82
+
83
+ ---
84
+
85
+ ## 二、基座负责什么 / 不负责什么
86
+
87
+ | 基座负责 | 基座不负责 |
88
+ |---|---|
89
+ | ✅ 记忆写入 / 重要度淘汰 / 检索 | ❌ 具体某个智能体的人格与话术 |
90
+ | ✅ 情绪状态与渲染(有 torch 时接真人格模块) | ❌ 具体业务逻辑(用药提醒、选题策略…) |
91
+ | ✅ 动作选择(性格基线 + 反馈塑形) | ❌ 调用哪个大模型(**基座零 LLM 依赖**) |
92
+ | ✅ 状态落盘与跨进程恢复 | ❌ 具体智能体的测试与验收标准 |
93
+ | ✅ 档位检测与如实降级标注 | ❌ 替你把降级藏起来 |
94
+ | ✅ 技能包打包(两种归档形态) | ❌ 替你上传到平台 |
95
+
96
+ **基座不内置任何智能体**,这是刻意的:`python -m pasm_skills list` 在干净环境下
97
+ 会显示 0 个智能体,并提示你装一个。
98
+
99
+ ---
100
+
101
+ ## 三、档位透明(永不隐藏降级)
102
+
103
+ | tier | 依赖 | 得到什么 |
104
+ |---|---|---|
105
+ | `light` | 无 | 纯内置:重要度淘汰 + 字面检索 + 性格/反馈加权 |
106
+ | `core` | 能 `import pasm.cognitive`(**不需要 torch**) | 真 `memory_layers`(分层记忆)+ `learning.LearningEngine` |
107
+ | `bionic` | 上面 + torch | 再加真情绪 / 人格模块 |
108
+
109
+ **三个档位下接口完全一致** —— 调用方不写分支,但 `agent.tier` 一定会如实告诉你现在在哪一档。
110
+
111
+ ---
112
+
113
+ ## 四、目录
114
+
115
+ ```
116
+ pasm-skills/
117
+ ├── pasm_skills/ ★ 基座本体
118
+ │ ├── sdk/ ★ SDK:BaseAgent(写智能体从这里开始)
119
+ │ │ └── base.py 记忆 / 情绪 / 动作 / 反馈 / 持久化 + 两个适配层
120
+ │ ├── agent.py 框架:Agent 基类 / AgentResult / Finding / 注册表
121
+ │ ├── discovery.py 智能体发现(entry points / PASM_SKILLS_PATH)
122
+ │ ├── context.py 仓隔离探测(RepoContext)
123
+ │ ├── scenarios.py 场景仿真底座(解释器择优 / PRELUDE / 阈值判定)
124
+ │ ├── checks.py 核心契约检查工具箱
125
+ │ ├── build.py ★ 技能包打包库(两种归档形态)
126
+ │ └── cli.py pasm-skills 命令行
127
+ │
128
+ ├── templates/ ★ 脚手架:复制就能改
129
+ │ ├── agent_template.py 智能体骨架(自带冒烟)
130
+ │ └── SKILL.template.body.md 技能正文模板
131
+ │
132
+ ├── examples/ 可跑示例(不依赖任何成品智能体)
133
+ │ └── build_your_agent.py 从零到落盘的完整走查
134
+ │
135
+ ├── skill/ ★ 基座自己的技能正文
136
+ │ └── SKILL.authoring.body.md 「怎么写 PASM 智能体 + 打技能包」
137
+ │
138
+ ├── tools/
139
+ │ └── build_skill.py 声明本仓技能 → 调用 pasm_skills.build
140
+ │
141
+ └── docs/
142
+ ├── TUTORIAL.md ★ 使用教程(先读这个)
143
+ ├── BUILD-AGENT.md ★ 手把手:从零做一个智能体
144
+ ├── SKILL-FORMAT.md ★ 技能包格式与两种归档形态
145
+ ├── ARCHITECTURE.md 框架分层与设计取舍
146
+ └── SERVER-NEEDS.md 服务器需求评估(结论:不需要)
147
+ ```
148
+
149
+ ---
150
+
151
+ ## 五、命令行
152
+
153
+ ```bash
154
+ python -m pasm_skills selftest # 自检:SDK / 框架 / 发现机制(零依赖)
155
+ python -m pasm_skills list # 已发现的智能体 + 三仓定位
156
+ python -m pasm_skills agents # 只报告智能体从哪加载进来(排障)
157
+ python -m pasm_skills repos # 只打印仓库定位
158
+ python -m pasm_skills run <name> # 跑一个智能体
159
+ python -m pasm_skills run --all # 跑全部已发现的
160
+ ```
161
+
162
+ 退出码:`0` 全部通过 / `1` 有 FAIL / `2` 用法错误 —— 可直接用于 CI。
163
+
164
+ ---
165
+
166
+ ## 六、让自己的智能体被基座发现
167
+
168
+ | 方式 | 适用 | 用法 |
169
+ |---|---|---|
170
+ | `PASM_SKILLS_PATH` | 本地开发最快 | 指向一个 `.py` 文件或目录 |
171
+ | `PASM_SKILLS_AGENT_MODULES` | 显式钉死模块 | 逗号分隔的模块名 |
172
+ | **entry points**(推荐) | 装成包后自动发现 | `[project.entry-points."pasm_skills.agents"]` |
173
+
174
+ ```toml
175
+ [project.entry-points."pasm_skills.agents"]
176
+ my-agents = "my_pkg.agents"
177
+ ```
178
+
179
+ 三种都失败也不会报错 —— 基座照样能 `selftest` / `list`,只是智能体数为 0。
180
+ **基座不依赖任何智能体。**
181
+
182
+ ---
183
+
184
+ ## 七、安装
185
+
186
+ ```bash
187
+ pip install pasm-skills # 基座(零依赖,stdlib only)
188
+ pip install -e . # 开发模式
189
+ pip install pasm-agents # 想要现成智能体(依赖本基座)
190
+ ```
191
+
192
+ ## 八、本机配置(可选)
193
+
194
+ 本机"带 torch 的那个解释器"往往在仓库外,所以配置也放**仓库外**。
195
+ 在 `~/.pasm-skills/local.json` 写:
196
+
197
+ ```json
198
+ { "python": ["/path/to/python-with-torch", "%%HOME%%/venv/bin/python"] }
199
+ ```
200
+
201
+ (`%%HOME%%` 是占位符;也支持 `PASM_LOCAL_CONF` 指定别的路径。)
202
+
203
+ - 找得到 → 场景跑 `bionic` / `core` 档;找不到 → 自动降级 `light` 并**在每条结论里标注**
204
+ - 建议指向**自带 site-packages 的 venv**:若环境改写了 `APPDATA`,Python 的 user site
205
+ packages 会指向别处,装在 user site 的 torch 就会"时有时无"
206
+
207
+ 优先级:`PASM_TORCH_PYTHON` → `PASM_PYTHON` → 本机配置 → 当前解释器 → 仓库内 venv → `PATH`。
208
+
209
+ ## 九、许可证
210
+
211
+ MIT。技能包在部分平台需按平台要求标 `MIT-0`(比 MIT 更宽松,允许无署名使用)——
212
+ 本仓的 `tools/build_skill.py` 里对两种形态分别处理,详见 `docs/SKILL-FORMAT.md`。
@@ -0,0 +1,185 @@
1
+ # PASM Skills · 智能体基座
2
+
3
+ > **本仓是基座:只提供"写智能体"的能力,不提供成品智能体。**
4
+ > 想直接拿现成的智能体用(游戏 NPC / 老人陪伴 / 学习陪伴 / 长期验证),
5
+ > 装独立公开仓 **pasm-agents**。
6
+ >
7
+ > ```bash
8
+ > pip install pasm-skills # 基座:SDK + 框架 + 打包工具(零依赖)
9
+ > pip install pasm-agents # 成品智能体集(依赖本基座)
10
+ > ```
11
+
12
+ 基座给你三样东西:
13
+
14
+ | | 是什么 | 入口 |
15
+ |---|---|---|
16
+ | **📖 使用教程** | 从"这是干什么的"到"写出并发布一个智能体",走一遍 | **[`docs/TUTORIAL.md`](docs/TUTORIAL.md)** |
17
+ | **SDK** | `BaseAgent` —— 记忆 / 情绪 / 动作 / 反馈 / 持久化开箱可用 | `from pasm_skills.sdk import BaseAgent` |
18
+ | **框架** | 智能体基类与注册表、仓隔离探测、场景仿真底座、核心契约检查工具箱 | `from pasm_skills.agent import Agent, register` |
19
+ | **打包** | 把智能体打成平台可直接上传的技能包(两种归档形态) | `from pasm_skills.build import SkillSpec, run_cli` |
20
+
21
+ ---
22
+
23
+ ## 一、30 秒写一个智能体
24
+
25
+ ```python
26
+ from pasm_skills.sdk import BaseAgent
27
+
28
+ class TeaHouseOwner(BaseAgent):
29
+ def action_pool(self): # 能做什么
30
+ return ["greet", "brew", "gossip", "rest"]
31
+
32
+ def _render_reply(self, text, facts, mood): # 怎么回
33
+ tone = "蔫" if mood < -0.2 else "乐"
34
+ return f"({tone}){self.persona.get('name')}:来了您呐"
35
+
36
+ a = TeaHouseOwner(agent_id="owner", persona={"name": "王掌柜", "temper": 0.6, "energy": 0.3})
37
+ a.observe("客人夸今年的龙井好", salience=3, tags=["茶"]) # 写记忆(重要度参与淘汰)
38
+ print(a.act()) # 'brew' / 'greet' / ...
39
+ print(a.chat("生意怎么样")) # 走 _render_reply
40
+ print(a.mood) # 情绪(属性,不加括号)
41
+ a.feedback("praise", action="brew") # 显式夸"brew"这个动作 → 它会更常出现
42
+ a.save() # ~/.pasm-agents/owner/
43
+ ```
44
+
45
+ 跑一个完整走查(8 个环节 + 反馈塑形的实测对比):
46
+
47
+ ```bash
48
+ git clone https://gitee.com/arronzheng/pasm-skills
49
+ cd pasm-skills
50
+ python examples/build_your_agent.py
51
+ python templates/agent_template.py # 骨架自带的冒烟
52
+ ```
53
+
54
+ **手把手教程**:[`docs/BUILD-AGENT.md`](docs/BUILD-AGENT.md)
55
+
56
+ ---
57
+
58
+ ## 二、基座负责什么 / 不负责什么
59
+
60
+ | 基座负责 | 基座不负责 |
61
+ |---|---|
62
+ | ✅ 记忆写入 / 重要度淘汰 / 检索 | ❌ 具体某个智能体的人格与话术 |
63
+ | ✅ 情绪状态与渲染(有 torch 时接真人格模块) | ❌ 具体业务逻辑(用药提醒、选题策略…) |
64
+ | ✅ 动作选择(性格基线 + 反馈塑形) | ❌ 调用哪个大模型(**基座零 LLM 依赖**) |
65
+ | ✅ 状态落盘与跨进程恢复 | ❌ 具体智能体的测试与验收标准 |
66
+ | ✅ 档位检测与如实降级标注 | ❌ 替你把降级藏起来 |
67
+ | ✅ 技能包打包(两种归档形态) | ❌ 替你上传到平台 |
68
+
69
+ **基座不内置任何智能体**,这是刻意的:`python -m pasm_skills list` 在干净环境下
70
+ 会显示 0 个智能体,并提示你装一个。
71
+
72
+ ---
73
+
74
+ ## 三、档位透明(永不隐藏降级)
75
+
76
+ | tier | 依赖 | 得到什么 |
77
+ |---|---|---|
78
+ | `light` | 无 | 纯内置:重要度淘汰 + 字面检索 + 性格/反馈加权 |
79
+ | `core` | 能 `import pasm.cognitive`(**不需要 torch**) | 真 `memory_layers`(分层记忆)+ `learning.LearningEngine` |
80
+ | `bionic` | 上面 + torch | 再加真情绪 / 人格模块 |
81
+
82
+ **三个档位下接口完全一致** —— 调用方不写分支,但 `agent.tier` 一定会如实告诉你现在在哪一档。
83
+
84
+ ---
85
+
86
+ ## 四、目录
87
+
88
+ ```
89
+ pasm-skills/
90
+ ├── pasm_skills/ ★ 基座本体
91
+ │ ├── sdk/ ★ SDK:BaseAgent(写智能体从这里开始)
92
+ │ │ └── base.py 记忆 / 情绪 / 动作 / 反馈 / 持久化 + 两个适配层
93
+ │ ├── agent.py 框架:Agent 基类 / AgentResult / Finding / 注册表
94
+ │ ├── discovery.py 智能体发现(entry points / PASM_SKILLS_PATH)
95
+ │ ├── context.py 仓隔离探测(RepoContext)
96
+ │ ├── scenarios.py 场景仿真底座(解释器择优 / PRELUDE / 阈值判定)
97
+ │ ├── checks.py 核心契约检查工具箱
98
+ │ ├── build.py ★ 技能包打包库(两种归档形态)
99
+ │ └── cli.py pasm-skills 命令行
100
+ │
101
+ ├── templates/ ★ 脚手架:复制就能改
102
+ │ ├── agent_template.py 智能体骨架(自带冒烟)
103
+ │ └── SKILL.template.body.md 技能正文模板
104
+ │
105
+ ├── examples/ 可跑示例(不依赖任何成品智能体)
106
+ │ └── build_your_agent.py 从零到落盘的完整走查
107
+ │
108
+ ├── skill/ ★ 基座自己的技能正文
109
+ │ └── SKILL.authoring.body.md 「怎么写 PASM 智能体 + 打技能包」
110
+ │
111
+ ├── tools/
112
+ │ └── build_skill.py 声明本仓技能 → 调用 pasm_skills.build
113
+ │
114
+ └── docs/
115
+ ├── TUTORIAL.md ★ 使用教程(先读这个)
116
+ ├── BUILD-AGENT.md ★ 手把手:从零做一个智能体
117
+ ├── SKILL-FORMAT.md ★ 技能包格式与两种归档形态
118
+ ├── ARCHITECTURE.md 框架分层与设计取舍
119
+ └── SERVER-NEEDS.md 服务器需求评估(结论:不需要)
120
+ ```
121
+
122
+ ---
123
+
124
+ ## 五、命令行
125
+
126
+ ```bash
127
+ python -m pasm_skills selftest # 自检:SDK / 框架 / 发现机制(零依赖)
128
+ python -m pasm_skills list # 已发现的智能体 + 三仓定位
129
+ python -m pasm_skills agents # 只报告智能体从哪加载进来(排障)
130
+ python -m pasm_skills repos # 只打印仓库定位
131
+ python -m pasm_skills run <name> # 跑一个智能体
132
+ python -m pasm_skills run --all # 跑全部已发现的
133
+ ```
134
+
135
+ 退出码:`0` 全部通过 / `1` 有 FAIL / `2` 用法错误 —— 可直接用于 CI。
136
+
137
+ ---
138
+
139
+ ## 六、让自己的智能体被基座发现
140
+
141
+ | 方式 | 适用 | 用法 |
142
+ |---|---|---|
143
+ | `PASM_SKILLS_PATH` | 本地开发最快 | 指向一个 `.py` 文件或目录 |
144
+ | `PASM_SKILLS_AGENT_MODULES` | 显式钉死模块 | 逗号分隔的模块名 |
145
+ | **entry points**(推荐) | 装成包后自动发现 | `[project.entry-points."pasm_skills.agents"]` |
146
+
147
+ ```toml
148
+ [project.entry-points."pasm_skills.agents"]
149
+ my-agents = "my_pkg.agents"
150
+ ```
151
+
152
+ 三种都失败也不会报错 —— 基座照样能 `selftest` / `list`,只是智能体数为 0。
153
+ **基座不依赖任何智能体。**
154
+
155
+ ---
156
+
157
+ ## 七、安装
158
+
159
+ ```bash
160
+ pip install pasm-skills # 基座(零依赖,stdlib only)
161
+ pip install -e . # 开发模式
162
+ pip install pasm-agents # 想要现成智能体(依赖本基座)
163
+ ```
164
+
165
+ ## 八、本机配置(可选)
166
+
167
+ 本机"带 torch 的那个解释器"往往在仓库外,所以配置也放**仓库外**。
168
+ 在 `~/.pasm-skills/local.json` 写:
169
+
170
+ ```json
171
+ { "python": ["/path/to/python-with-torch", "%%HOME%%/venv/bin/python"] }
172
+ ```
173
+
174
+ (`%%HOME%%` 是占位符;也支持 `PASM_LOCAL_CONF` 指定别的路径。)
175
+
176
+ - 找得到 → 场景跑 `bionic` / `core` 档;找不到 → 自动降级 `light` 并**在每条结论里标注**
177
+ - 建议指向**自带 site-packages 的 venv**:若环境改写了 `APPDATA`,Python 的 user site
178
+ packages 会指向别处,装在 user site 的 torch 就会"时有时无"
179
+
180
+ 优先级:`PASM_TORCH_PYTHON` → `PASM_PYTHON` → 本机配置 → 当前解释器 → 仓库内 venv → `PATH`。
181
+
182
+ ## 九、许可证
183
+
184
+ MIT。技能包在部分平台需按平台要求标 `MIT-0`(比 MIT 更宽松,允许无署名使用)——
185
+ 本仓的 `tools/build_skill.py` 里对两种形态分别处理,详见 `docs/SKILL-FORMAT.md`。
@@ -0,0 +1,128 @@
1
+ """pasm-skills —— PASM 智能体基座。
2
+
3
+ **基座只提供能力,不提供具体智能体。** 它给你三样东西:
4
+
5
+ 1. **SDK**(`pasm_skills.sdk`)—— `BaseAgent`:观测 / 记忆 / 情绪 / 动作 / 反馈 / 持久化开箱可用,
6
+ 写智能体的人只需要关心 persona、动作池、回复模板;
7
+ 2. **框架**(`pasm_skills.agent` / `context` / `scenarios` / `checks`)——
8
+ 智能体基类 + 注册表、仓库隔离探测、场景仿真底座、核心契约检查工具箱;
9
+ 3. **打包**(`pasm_skills.build`)—— 把智能体打成平台可直接上传的技能包(两种归档形态)。
10
+
11
+ 三分钟上手:
12
+
13
+ python -m pasm_skills selftest # 自检(零依赖,随时可跑)
14
+ python -m pasm_skills list # 看已发现的智能体 + 三仓定位
15
+
16
+ 具体智能体由外部包提供(本基座**不内置**),发现方式见 `pasm_skills.discovery`:
17
+ entry points 组 `pasm_skills.agents`,或 `PASM_SKILLS_PATH` / `PASM_SKILLS_AGENT_MODULES`。
18
+ 官方智能体集在独立公开仓 **pasm-agents**(NPC / 老人陪伴 / 学习陪伴 / 长期验证)。
19
+
20
+ 零依赖:只用标准库,不需要 torch / 不需要 API key / 不需要服务器。
21
+ """
22
+ from __future__ import annotations
23
+
24
+ __version__ = "0.4.1"
25
+
26
+ from .agent import ( # noqa: F401
27
+ AGENTS, FAIL, HOOKS, OK, SKIP, WARN,
28
+ Agent, AgentResult, Finding,
29
+ agent, catalog, names, register, run_agent,
30
+ )
31
+ from . import discovery # noqa: F401 智能体发现(entry points / 环境变量)
32
+ from . import scenarios # noqa: F401 领域场景仿真底座(PRELUDE / 解释器择优 / 指标判定)
33
+ from . import sdk # noqa: F401 产品智能体 SDK(BaseAgent)
34
+ from .context import REPO_SPEC, RepoContext # noqa: F401
35
+
36
+ __all__ = [
37
+ "__version__", "selftest",
38
+ "Agent", "AgentResult", "Finding", "AGENTS", "HOOKS",
39
+ "OK", "WARN", "FAIL", "SKIP",
40
+ "agent", "catalog", "names", "register", "run_agent",
41
+ "RepoContext", "REPO_SPEC", "scenarios", "sdk", "discovery",
42
+ ]
43
+
44
+
45
+ def selftest() -> bool:
46
+ """框架自检:不依赖任何 PASM 仓、也不依赖任何具体智能体,纯本地可跑。"""
47
+ ok = True
48
+
49
+ def check(cond: bool, msg: str) -> None:
50
+ nonlocal ok
51
+ if not cond:
52
+ ok = False
53
+ print(" x %s" % msg)
54
+ else:
55
+ print(" v %s" % msg)
56
+
57
+ print("pasm-skills selftest v%s(基座)" % __version__)
58
+
59
+ # 结论对象
60
+ check(Finding(OK, "t").line().startswith("[OK]"), "Finding.line 带等级标签")
61
+ r = AgentResult(agent="a", ok=True,
62
+ findings=[Finding(OK, "1"), Finding(FAIL, "2")])
63
+ check(r.counts()[FAIL] == 1 and r.worst() == FAIL, "AgentResult 统计与最差等级正确")
64
+ check(r.to_dict()["worst"] == FAIL, "AgentResult.to_dict 可序列化")
65
+
66
+ # 智能体与注册表(基座不再内置智能体,这里现造一个)
67
+ class _T(Agent):
68
+ name = "_selftest_agent"
69
+ goal = "自检用"
70
+
71
+ def run(self):
72
+ self.ok("收集一条结论")
73
+
74
+ register(_T)
75
+ check("_selftest_agent" in names(), "注册表能登记自定义智能体")
76
+ check(agent("_selftest_agent") is _T, "按名字取回正确类")
77
+
78
+ class _Boom(Agent):
79
+ name = "_selftest_boom"
80
+ goal = "抛异常也要被兜住"
81
+
82
+ def run(self):
83
+ raise RuntimeError("boom")
84
+
85
+ register(_Boom)
86
+ res = _Boom().execute()
87
+ check(res.worst() == FAIL and "boom" in res.error, "run() 异常被兜住并计为 FAIL")
88
+
89
+ # 智能体发现:没有任何外部智能体时也必须安静地成功
90
+ try:
91
+ loaded, _warns = discovery.load_agents()
92
+ check(isinstance(loaded, list), "智能体发现机制可用(无外部智能体也不报错)")
93
+ except Exception as ex: # noqa: BLE001
94
+ check(False, "智能体发现机制可用(异常:%s)" % ex)
95
+
96
+ # SDK:不依赖 PASM 核心也能建、能记、能选动作、能落盘
97
+ import tempfile
98
+ try:
99
+ from .sdk import BaseAgent
100
+ with tempfile.TemporaryDirectory() as td:
101
+ class _A(BaseAgent):
102
+ def action_pool(self):
103
+ return ["a1", "a2"]
104
+
105
+ def _render_reply(self, text, facts, mood):
106
+ return "ok:%s" % text
107
+
108
+ a = _A(agent_id="_selftest_sdk", persona={"name": "自检"}, persist_dir=td)
109
+ a.observe("第一条记忆", salience=3)
110
+ check(a.act() in ("a1", "a2"), "SDK:act() 从动作池里选")
111
+ check(a.chat("hi").startswith("ok:"), "SDK:chat() 走 _render_reply")
112
+ check(a.mood.__class__ is float, "SDK:mood 是 float 属性(不是方法)")
113
+ check(isinstance(a.feedback("praise", action="a1"), dict), "SDK:feedback 返回权重字典")
114
+ check(a.tier in ("light", "core", "bionic"), "SDK:tier 标注当前档位")
115
+ a.save()
116
+ check((a.persist_dir / "agent_state.json").exists(), "SDK:save() 落盘")
117
+ except Exception as ex: # noqa: BLE001
118
+ check(False, "SDK:建/记/选/存全链路可跑(异常:%s)" % ex)
119
+
120
+ # 上下文
121
+ ctx = RepoContext(roots=[])
122
+ check(isinstance(ctx.describe(), dict), "RepoContext 可描述三仓定位")
123
+ check(ctx.has() is True, "空 needs 视为满足")
124
+
125
+ AGENTS.pop("_selftest_agent", None)
126
+ AGENTS.pop("_selftest_boom", None)
127
+ print("pasm-skills selftest:", "通过" if ok else "失败")
128
+ return ok
@@ -0,0 +1,5 @@
1
+ """`python -m pasm_skills` 入口。"""
2
+ from .cli import main
3
+
4
+ if __name__ == "__main__":
5
+ raise SystemExit(main())