metame-cli 1.6.1 → 1.6.3
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.
- package/index.js +88 -12
- package/package.json +1 -1
- package/scripts/agent-intent-shared.js +11 -2
- package/scripts/core/session-source-db.js +125 -0
- package/scripts/daemon-agent-intent.js +51 -15
- package/scripts/daemon-agent-tools.js +52 -3
- package/scripts/daemon-agent-workflow.js +98 -0
- package/scripts/daemon-bridges.js +18 -8
- package/scripts/daemon-command-router.js +1 -1
- package/scripts/daemon-engine-runtime.js +16 -6
- package/scripts/daemon-user-acl.js +19 -1
- package/scripts/daemon-weixin-bridge.js +6 -2
- package/scripts/daemon.js +46 -3
- package/scripts/docs/hermes-memory-upgrade-converged.md +461 -0
- package/scripts/docs/hermes-memory-upgrade-plan.md +506 -0
- package/scripts/feishu-adapter.js +269 -39
- package/scripts/memory-extract.js +72 -4
- package/scripts/memory-wiki-schema.js +31 -0
- package/scripts/memory.js +8 -2
- package/scripts/providers.js +37 -6
- package/skills/send-to-user/SKILL.md +76 -0
package/scripts/providers.js
CHANGED
|
@@ -159,23 +159,53 @@ function saveProviders(config) {
|
|
|
159
159
|
// PROVIDER ENV BUILDER (Core mechanism)
|
|
160
160
|
// ---------------------------------------------------------
|
|
161
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Read the env mapping defined in ~/.claude/settings.json.
|
|
164
|
+
* Returns a plain string→string object (only string values are kept).
|
|
165
|
+
* Returns {} on any error or if the file/env block is missing.
|
|
166
|
+
*/
|
|
167
|
+
function readClaudeSettingsEnv() {
|
|
168
|
+
const home = process.env.HOME || os.homedir();
|
|
169
|
+
const settingsPath = path.join(home, '.claude', 'settings.json');
|
|
170
|
+
try {
|
|
171
|
+
if (!fs.existsSync(settingsPath)) return {};
|
|
172
|
+
const data = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
173
|
+
if (!data || typeof data.env !== 'object' || data.env === null) return {};
|
|
174
|
+
const out = {};
|
|
175
|
+
for (const [k, v] of Object.entries(data.env)) {
|
|
176
|
+
if (typeof v === 'string') out[k] = v;
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
} catch {
|
|
180
|
+
return {};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
162
184
|
/**
|
|
163
185
|
* Build env var overrides for a named provider.
|
|
164
|
-
*
|
|
165
|
-
*
|
|
186
|
+
*
|
|
187
|
+
* Always inherits the env mapping from ~/.claude/settings.json (slot mappings
|
|
188
|
+
* like ANTHROPIC_DEFAULT_*_MODEL stay in place across providers).
|
|
189
|
+
* For 'anthropic' (official): returns the inherited Claude settings env unchanged.
|
|
190
|
+
* For custom providers: overrides ANTHROPIC_BASE_URL plus both
|
|
191
|
+
* ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN with the provider's credentials.
|
|
166
192
|
*/
|
|
167
193
|
function buildEnv(providerName) {
|
|
168
194
|
const config = loadProviders();
|
|
169
195
|
const name = providerName || config.active;
|
|
170
196
|
|
|
171
|
-
|
|
197
|
+
const env = readClaudeSettingsEnv();
|
|
198
|
+
|
|
199
|
+
if (name === 'anthropic') return env;
|
|
172
200
|
|
|
173
201
|
const provider = config.providers[name];
|
|
174
|
-
if (!provider) return
|
|
202
|
+
if (!provider) return env;
|
|
175
203
|
|
|
176
|
-
const env = {};
|
|
177
204
|
if (provider.base_url) env.ANTHROPIC_BASE_URL = provider.base_url;
|
|
178
|
-
if (provider.api_key)
|
|
205
|
+
if (provider.api_key) {
|
|
206
|
+
env.ANTHROPIC_API_KEY = provider.api_key;
|
|
207
|
+
env.ANTHROPIC_AUTH_TOKEN = provider.api_key;
|
|
208
|
+
}
|
|
179
209
|
return env;
|
|
180
210
|
}
|
|
181
211
|
|
|
@@ -390,6 +420,7 @@ function getEngine() { return _currentEngine; }
|
|
|
390
420
|
const api = {
|
|
391
421
|
loadProviders,
|
|
392
422
|
saveProviders,
|
|
423
|
+
readClaudeSettingsEnv,
|
|
393
424
|
buildEnv,
|
|
394
425
|
buildSpawnEnv,
|
|
395
426
|
buildActiveEnv,
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: send-to-user
|
|
3
|
+
description: |
|
|
4
|
+
把本地文件直接发到用户手机(飞书 / Telegram / iMessage),而不是只在群里报路径。
|
|
5
|
+
触发:用户说「把 X 文件发我 / 给我下载 / 发到手机 / 发文件」、要 PDF/CSV/PNG/log
|
|
6
|
+
下载、要查看文件内容(超过聊天可读长度)。
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Send-to-User — 把文件交付到用户手机
|
|
10
|
+
|
|
11
|
+
## 它解决什么问题
|
|
12
|
+
|
|
13
|
+
聊天里贴长文本/大块代码体验很糟。当用户要的是一个**文件**(截图、报表、日志、
|
|
14
|
+
压缩包、构件),最佳交付方式是直接把文件推到他们手机上的对话里——飞书会显示成
|
|
15
|
+
附件卡片、可下载、可分享。MetaMe 已经把上传、`file_key` 转换、消息发送全部封装
|
|
16
|
+
好,你只需要在回复里贴一个 marker。
|
|
17
|
+
|
|
18
|
+
## 怎么用——一行 marker 协议
|
|
19
|
+
|
|
20
|
+
完成你正常的回答后,**在回复末尾**为每个要交付的文件追加一行:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
[[FILE:/absolute/path/to/file]]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
约束:
|
|
27
|
+
|
|
28
|
+
1. **绝对路径**。不写 `~`、不写相对路径——daemon 不会做 shell 展开。
|
|
29
|
+
2. **一行一个文件**。多个文件就多行。每行只放一个 marker,前后不要再加文字。
|
|
30
|
+
3. **文件必须已经存在**。daemon 在发送前会校验存在性,不存在的会被静默丢弃。
|
|
31
|
+
4. **marker 独占行**。不要把 marker 写在 markdown 列表项里、不要包在反引号里。
|
|
32
|
+
5. 用户**看不到**这一行 marker——daemon 解析后会从输出里剥掉再回显文本,所以
|
|
33
|
+
你的正文该写什么写什么,marker 是给 daemon 看的「附录」。
|
|
34
|
+
6. **路径含空格/中文是 OK 的**,不要做 shell 转义、不要加引号——daemon 直接当
|
|
35
|
+
字面字符串送给 `fs.statSync` 与上传 API。例:`[[FILE:/Users/王总/桌面/今日报表.xlsx]]`。
|
|
36
|
+
|
|
37
|
+
## 完整示例
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
我已经把今天的访问日志整理好了,9–11 点有一波 502 集中在 nginx-edge-3,
|
|
41
|
+
原因是上游 keepalive 池被打满,详情见附件。
|
|
42
|
+
|
|
43
|
+
[[FILE:/var/log/metame/edge-2026-04-28.csv]]
|
|
44
|
+
[[FILE:/Users/yaron/Desktop/edge-error-summary.png]]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
daemon 会:
|
|
48
|
+
- 文本部分作为飞书消息正常发送("我已经把...")
|
|
49
|
+
- CSV 与 PNG 各上传一次,作为飞书附件出现在用户对话里
|
|
50
|
+
- 上传失败时回退为文本告知文件路径,你不需要自己处理失败
|
|
51
|
+
|
|
52
|
+
## 何时**不**用
|
|
53
|
+
|
|
54
|
+
- 用户问的是文件**内容**,且文件 < ~200 行 → 直接把内容贴进消息更直接
|
|
55
|
+
- 用户在做代码 review,不需要文件本体只想看代码 → 用代码块更方便
|
|
56
|
+
- 你刚刚生成的临时文件还没写到磁盘 → 先 `Write` 工具落盘,再贴 marker
|
|
57
|
+
|
|
58
|
+
## 调试
|
|
59
|
+
|
|
60
|
+
如果用户说「没收到附件」:
|
|
61
|
+
|
|
62
|
+
1. 你的 marker 是否独占一行?多检查反引号、列表项、空格。
|
|
63
|
+
2. 文件是否真的存在?在 marker 之前先 `ls -la /the/path` 确认。
|
|
64
|
+
3. 是否大于飞书附件大小限制(单文件 30MB)?大文件请压缩或分片。
|
|
65
|
+
4. 飞书应用是否拥有 `im:resource` 权限?这是首装环节的事,你这边没办法补救,
|
|
66
|
+
告诉用户去 https://open.feishu.cn 应用后台核对。
|
|
67
|
+
|
|
68
|
+
## 技术细节(供你判断使用)
|
|
69
|
+
|
|
70
|
+
- 解析器: `scripts/daemon-claude-engine.js` 里 `parseFileMarkers()`
|
|
71
|
+
- 发送器: `scripts/daemon-file-browser.js` 里 `sendFileButtons()`,优先调用
|
|
72
|
+
`bot.sendFile`(飞书走 `client.im.file.create` 上传 → file_key → 消息)
|
|
73
|
+
- 飞书适配器: `scripts/feishu-adapter.js` 的 `sendFile(chatId, filePath, caption)`
|
|
74
|
+
- 失败兜底: 文本文件会被截断到 3000 字以纯文本回显;二进制文件抛错给用户。
|
|
75
|
+
|
|
76
|
+
不需要自己调以上 API——你只负责贴 marker,剩下的 daemon 都做了。
|