@mortiseai/stem 0.0.1 → 0.0.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/README.md CHANGED
@@ -66,6 +66,7 @@ stem --model BaiLian:glm-5.2 # 会话默认模型(platform:model 完
66
66
  stem --model glm-5.2 # 裸模型 id(目录唯一命中,否则落默认平台)
67
67
  stem --lang ja --model BaiLian:glm-5.2 # 组合使用
68
68
  stem --resume <sessionId> # 恢复历史会话(续写同一份会话日志)
69
+ stem --tenant acme # 租户模式:全部落盘状态按 tenants/acme 隔离
69
70
  echo "一句话问答" | stem --bare # SIMPLE 模式:stdin → 单次回答(non-TTY)
70
71
  ```
71
72
 
@@ -204,6 +205,46 @@ Stem 的三种核心业务模式:
204
205
 
205
206
  `--resume <id>` / `-r <id>` / `--resume=<id>`:恢复指定会话(退出提示里有 `--resume <id>` 可直接复制),复用原会话日志文件续写。
206
207
 
208
+ ### 多租户隔离 · `--tenant`
209
+
210
+ `--tenant <code>`(或 `--tenant=<code>`)以租户模式启动:**全部落盘状态**按租户
211
+ 完全隔离,近似独立实例;不带 flag 时行为与以往完全一致。
212
+
213
+ - **flag-only**:租户码只认启动参数。shell `export STEM_TENANT` / `.env` /
214
+ settings `env` 段里的 `STEM_TENANT` 一律被入口清除,不作为输入
215
+ (`STEM_TENANT` 是内部传播通道,不要手工设置)。自拉起 stem 子进程时须显式
216
+ 转发 `--tenant`。
217
+ - **经 npm/bun 脚本启动**:`bun run dev --tenant acme` 直接可用;npm 会吞
218
+ flag,需用 **`npm run dev --tenant=acme`**(等号形式,经 npm_config_tenant
219
+ 中继)或 `npm run dev -- --tenant acme`。npm 下的空格形式
220
+ `npm run dev --tenant acme` 值会被 npm 吞成布尔 — CLI 检测到后直接报错
221
+ 退出(绝不静默落个人模式)。
222
+ - **租户码**:1–64 字符,小写字母/数字开头,允许 `.` `_` `-`(拒绝大写与路径
223
+ 分隔符);非法直接报错退出。
224
+
225
+ 目录布局(H = 租户段 `tenants/<code>`):
226
+
227
+ | 数据 | 无租户 | 租户模式 |
228
+ |---|---|---|
229
+ | 存储(session/causal/distill/evolve) | `<cwd>/mstem-storage/<kind>/` | `<cwd>/mstem-storage/H/<kind>/` |
230
+ | 家目录状态(projects/history/plans/keybindings/memory/plugins/skills/mcp/hooks/llms/workflows/agents) | `~/.mstem/...` | `~/.mstem/H/...` |
231
+ | 用户 settings | `~/.mstem.json` | `~/.mstem/H/settings.json` |
232
+ | 项目配置(settings/skills/plugins/agents/workflows/hooks/mcp/llms/memory) | `<cwd>/.mstem/...` | `<cwd>/.mstem/H/...` |
233
+ | debug 日志 | `<cwd>/logs/` | `<cwd>/logs/H/` |
234
+
235
+ - **env 覆盖 × 租户**:目录形 env(`STEM_STORAGE_DIR` / `STEM_SESSION_DIR` 等)
236
+ 即使显式设置,租户段照插(如 `STEM_STORAGE_DIR=/data` + `--tenant acme` →
237
+ `/data/tenants/acme/...`)— 隔离是边界,不随根重定向失效。文件形显式指针
238
+ env(`STEM_SETTINGS_PATH` / `STEM_CMD_LOG` / `STEM_LLMS_PATH` /
239
+ `STEM_HOOKS_PATH` / `STEM_MCP_CONFIG_PATH` / `STEM_PLUGINS_DIR`)按字面生效。
240
+ - **首启为空 + 自动建空间**:租户首次以正常路径启动(TUI / daemon run /
241
+ mcp serve;`--help` 等 fast-echo 不算)时自动创建其目录骨架
242
+ (`.mstem/tenants/<code>/`、存储四目录、`logs/tenants/<code>/`、
243
+ `~/.mstem/tenants/<code>/projects/`),但**不播种任何配置** — 新租户的
244
+ settings/llms/mcp/skills 全部独立,需逐租户放入(llms.json 凭据不跨租户
245
+ 共享是特性,不是缺陷;想共享凭据可用字面生效的 `STEM_LLMS_PATH`)。
246
+ - 租户会话与个人历史互不可见:`/resume` 在租户模式下只枚举该租户自己的会话。
247
+
207
248
  ### 图片粘贴 · 图文混合理解(macOS)
208
249
 
209
250
  对齐 Claude Code:剪贴板里有图片(如 Cmd+Shift+Ctrl+4 截图)时按 **Ctrl+V**,输入框插入 `[Image #N]` 占位;提交后文本与图片按占位位置交错组成混合消息发给模型。模型也可以直接 `Read` 图片文件(png/jpg/gif/webp)"看到"内容。
@@ -268,6 +309,14 @@ CLI 的全部运行时开关统一放 settings 级联的 **`env` 段**(不再使
268
309
  | `STEM_WEBSEARCH_ENABLED` / `STEM_WEBSEARCH_PROVIDER` | web_search 总开关 / provider(`auto\|duckduckgo\|brave-web`) |
269
310
  | `STEM_TELEMETRY` | `1` = 无头模式开启 telemetry 观测帧(`--sdk-telemetry` 的 env 形式) |
270
311
  | `STEM_TELEMETRY_WS` | telemetry WS tap 地址 |
312
+ | `STEM_STORAGE_DIR` | 统一存储根(缺省 `<cwd>/mstem-storage`;优先于 settings `storage.dir`;租户模式下自动追加 `tenants/<code>` 段) |
313
+ | `STEM_SESSION_DIR` | 会话聊天 JSONL 目录(缺省 `<存储根>/session`;租户段同上) |
314
+ | `STEM_CAUSAL_DIR` / `STEM_DISTILL_DIR` / `STEM_EVOLVE_DIR` | 各洞察模式数据目录(缺省 `<存储根>/<mode>`;租户段同上) |
315
+ | `STEM_TENANT` | **内部通道,勿手工设置** — 只由 `--tenant` flag 写入,env 段里的值会被入口忽略 |
316
+
317
+ 存储目录 env 的取值支持三种形态:`~/...`(home 展开)、绝对路径、相对路径
318
+ (相对 cwd 解析)。会话聊天文件默认落 `<cwd>/mstem-storage/session/<sessionId>.jsonl`;
319
+ 升级前写在 `~/.mstem/projects/<项目>/` 的历史会话仍可被 `/resume` 找到并续写原文件。
271
320
 
272
321
  ---
273
322
 
package/bin/stem.mjs CHANGED
@@ -22,7 +22,23 @@ if (!skipDotenv && existsSync(envFile)) {
22
22
 
23
23
  const distEntry = join(rootDir, 'dist', 'cli.mjs')
24
24
  if (process.env.STEM_DEV !== '1' && existsSync(distEntry)) {
25
- await import(pathToFileURL(distEntry).href)
25
+ // 长会话内存水位高(UI 历史 + 渲染缓冲),Node 默认老生代上限 ~4GB 在大并发
26
+ // 子任务场景会 OOM。V8 堆参数只能在进程启动时生效,所以未显式配置时 re-exec
27
+ // 一次,把 --max-old-space-size=8192 带给真正的 CLI 进程;用户自己的
28
+ // NODE_OPTIONS / execArgv 配置优先,不覆盖。
29
+ const heapConfigured =
30
+ process.execArgv.some(a => a.includes('--max-old-space-size')) ||
31
+ (process.env.NODE_OPTIONS ?? '').includes('--max-old-space-size')
32
+ if (heapConfigured) {
33
+ await import(pathToFileURL(distEntry).href)
34
+ } else {
35
+ const result = spawnSync(
36
+ process.execPath,
37
+ ['--max-old-space-size=8192', distEntry, ...process.argv.slice(2)],
38
+ { stdio: 'inherit' },
39
+ )
40
+ process.exit(result.status ?? 1)
41
+ }
26
42
  } else {
27
43
  // dev 模式:bun 直跑源码。bun 会自动加载 cwd 下的 .env,跳过时显式指向空设备。
28
44
  const envFlag = skipDotenv