@rol1n/pi-kit 0.1.1 → 0.1.2
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/LICENSE +21 -0
- package/README.md +95 -33
- package/README_zh.md +136 -0
- package/memory-log/README.md +80 -13
- package/memory-log/config.ts +1 -1
- package/memory-log/hooks/compaction-hook.ts +58 -15
- package/memory-log/hooks/compaction-trigger.ts +24 -97
- package/memory-log/hooks/observer-trigger.ts +2 -1
- package/memory-log/index.ts +4 -0
- package/memory-log/ledger/index.ts +1 -0
- package/memory-log/ledger/recall.ts +111 -0
- package/memory-log/ledger/render.ts +3 -1
- package/memory-log/ledger/serialize.ts +2 -4
- package/memory-log/ledger/types.ts +4 -1
- package/memory-log/runtime.ts +0 -5
- package/memory-log/tools/recall.ts +60 -0
- package/package.json +4 -3
- package/web-reach/README.md +1 -1
- package/web-reach/html.ts +0 -83
- package/web-reach/index.ts +0 -82
- package/web-reach/page.ts +0 -214
- package/web-reach/rsc.ts +0 -161
- package/web-reach/search.ts +0 -85
- package/web-reach/transport.ts +0 -35
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 RoL1n_SrP
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,45 +1,78 @@
|
|
|
1
1
|
# pi-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Modular extensions and prompt templates for the [Pi Coding Agent](https://pi.dev), published as the **`@rol1n/pi-kit`** bundle and as standalone **`@rol1n/<extension>`** packages.
|
|
4
|
+
|
|
5
|
+
<p align="left">
|
|
6
|
+
<b>English</b> •
|
|
7
|
+
<a href="README_zh.md"><b>中文说明</b></a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
[](https://www.npmjs.com/package/@rol1n/pi-kit)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
|
|
13
|
+
---
|
|
4
14
|
|
|
5
15
|
## Install
|
|
6
16
|
|
|
17
|
+
Install the default bundle:
|
|
18
|
+
|
|
7
19
|
```sh
|
|
8
20
|
pi install npm:@rol1n/pi-kit
|
|
9
21
|
```
|
|
10
22
|
|
|
11
|
-
|
|
23
|
+
Or install any standalone extension individually:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
pi install npm:@rol1n/memory-log
|
|
27
|
+
pi install npm:@rol1n/subagent
|
|
28
|
+
pi install npm:@rol1n/multi-harness
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Install from GitHub or a local checkout during development:
|
|
12
32
|
|
|
13
33
|
```sh
|
|
14
34
|
pi install https://github.com/RolinShmily/pi-kit
|
|
15
35
|
pi install /absolute/path/to/pi-kit
|
|
16
36
|
```
|
|
17
37
|
|
|
18
|
-
Update
|
|
38
|
+
Update installed packages:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pi update npm:@rol1n/pi-kit
|
|
42
|
+
pi update --extensions
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
19
46
|
|
|
20
47
|
## Extensions
|
|
21
48
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
|
25
|
-
|
|
|
49
|
+
Each top-level directory is a self-contained extension (`<name>/index.ts` + `README.md`). Detailed commands, parameters, and settings are documented in each extension's README:
|
|
50
|
+
|
|
51
|
+
| Extension | Description | In `@rol1n/pi-kit` | Standalone Package |
|
|
52
|
+
| :--- | :--- | :---: | :--- |
|
|
53
|
+
| [ask-u-questions](ask-u-questions/README.md) | Interactive single-choice, multi-choice, and text dialogs | Yes | `@rol1n/ask-u-questions` |
|
|
54
|
+
| [continue-signal](continue-signal/README.md) | Resume an idle agent via `/continue` or `Alt+C` | Yes | `@rol1n/continue-signal` |
|
|
26
55
|
| [custom-providers](custom-providers/README.md) | Additional model providers and gateway registration | Yes | `@rol1n/custom-providers` |
|
|
27
|
-
| [image-generate](image-generate/README.md) | Image generation tool and `/image-generate` selector | Yes | `@rol1n/image-generate` |
|
|
28
|
-
| [memory-log](memory-log/README.md) |
|
|
29
|
-
| [model-vision](model-vision/README.md) | Image understanding and OCR tool | No | `@rol1n/model-vision` |
|
|
30
|
-
| [multi-harness](multi-harness/README.md) | Delegate
|
|
31
|
-
| [oai-subquota](oai-subquota/README.md) | OpenAI Codex subscription quota monitor | Yes | `@rol1n/oai-subquota` |
|
|
32
|
-
| [prompt-snipaste](prompt-snipaste/README.md) |
|
|
33
|
-
| [screenshot](screenshot/README.md) | Insert the latest Windows/WSL screenshot path | No | `@rol1n/screenshot` |
|
|
34
|
-
| [srp-theme](srp-theme/README.md) |
|
|
35
|
-
| [subagent](subagent/README.md) | Delegate to
|
|
36
|
-
| [tui-asr](tui-asr/README.md) | Streaming voice dictation via DashScope ASR | Yes | `@rol1n/tui-asr` |
|
|
37
|
-
| [web-reach](web-reach/README.md) | Keyless Exa web search and multi-tier page extraction |
|
|
38
|
-
| [windows-wheel-fix](windows-wheel-fix/README.md) | Windows ConPTY/Zellij mouse-wheel reporting fix | Yes (Windows
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
56
|
+
| [image-generate](image-generate/README.md) | Image generation tool and `/image-generate` model selector | Yes | `@rol1n/image-generate` |
|
|
57
|
+
| [memory-log](memory-log/README.md) | Tiered asynchronous observational memory and instant compaction | Yes | `@rol1n/memory-log` |
|
|
58
|
+
| [model-vision](model-vision/README.md) | Image understanding and OCR tool (`model_vision`) | No | `@rol1n/model-vision` |
|
|
59
|
+
| [multi-harness](multi-harness/README.md) | Delegate tasks across `pi`, `codex`, `claude`, and `opencode` | Yes | `@rol1n/multi-harness` |
|
|
60
|
+
| [oai-subquota](oai-subquota/README.md) | OpenAI Codex subscription quota monitor and statusline | Yes | `@rol1n/oai-subquota` |
|
|
61
|
+
| [prompt-snipaste](prompt-snipaste/README.md) | Prompt snippet selector (`/snipaste`, `Alt+S`) with 7 built-in prompts | Yes | `@rol1n/prompt-snipaste` |
|
|
62
|
+
| [screenshot](screenshot/README.md) | Insert the latest Windows/WSL screenshot path (`/screenshot`) | No | `@rol1n/screenshot` |
|
|
63
|
+
| [srp-theme](srp-theme/README.md) | Last-prompt preview widget and real-time streaming TPS meter | Yes | `@rol1n/srp-theme` |
|
|
64
|
+
| [subagent](subagent/README.md) | Delegate tasks to parallel Pi workers in tmux/Zellij or background processes | Yes | `@rol1n/subagent` |
|
|
65
|
+
| [tui-asr](tui-asr/README.md) | Streaming voice dictation via Aliyun DashScope ASR (`/asr`, `Alt+M`) | Yes | `@rol1n/tui-asr` |
|
|
66
|
+
| [web-reach](web-reach/README.md) | Keyless Exa MCP web search and multi-tier page extraction | No | `@rol1n/web-reach` |
|
|
67
|
+
| [windows-wheel-fix](windows-wheel-fix/README.md) | Windows ConPTY / Zellij mouse-wheel reporting fix | Yes (Windows) | `@rol1n/windows-wheel-fix` |
|
|
68
|
+
|
|
69
|
+
> Standalone packages with cross-extension dependencies (`tui-asr` / `image-generate` -> `@rol1n/custom-providers`, `multi-harness` -> `@rol1n/subagent`) declare standard npm `dependencies` and resolve them automatically on install.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Resource Selection
|
|
74
|
+
|
|
75
|
+
`@rol1n/pi-kit` exposes 12 extension entrypoints and the 7 prompt templates bundled in [prompt-snipaste/prompts](prompt-snipaste/prompts/). Use `pi config` or filter loaded resources in `settings.json`:
|
|
43
76
|
|
|
44
77
|
```json
|
|
45
78
|
{
|
|
@@ -53,22 +86,51 @@ The kit exposes 13 extension entrypoints and the 7 prompt templates bundled in [
|
|
|
53
86
|
}
|
|
54
87
|
```
|
|
55
88
|
|
|
56
|
-
|
|
89
|
+
---
|
|
57
90
|
|
|
58
|
-
|
|
91
|
+
## Development & Publishing
|
|
92
|
+
|
|
93
|
+
[kit.config.json](kit.config.json) controls bundle selection (`bundle`), inter-extension dependencies (`deps`), and release versions. The top-level `version` belongs to `@rol1n/pi-kit`; each extension can set its own `version`, otherwise it inherits the top-level version. Set explicit extension versions to release the kit and standalone packages independently.
|
|
94
|
+
|
|
95
|
+
### Automated releases
|
|
96
|
+
|
|
97
|
+
1. Update the code and bump the relevant version(s) in `kit.config.json`.
|
|
98
|
+
2. Push to `main` with changes to `kit.config.json` or `package.json`, or manually run **Publish to npm** in GitHub Actions. Changes to the packaging script or workflow also trigger a release run.
|
|
99
|
+
3. CI runs the same pipeline for both triggers:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
npm run manifest
|
|
103
|
+
npm run check
|
|
104
|
+
npm run publish:ci -- all
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The workflow in [`.github/workflows/publish.yml`](.github/workflows/publish.yml) generates `package.json`, validates the layout, then publishes all standalone extensions in dependency order, followed by the kit. Already-published versions are skipped; versions are never bumped automatically. `bundle: false` excludes an extension from the kit, not from standalone publishing. Publishing runs do not overlap, and a new run does not cancel an active release. Code-only pushes do not trigger publishing.
|
|
108
|
+
|
|
109
|
+
You do not need to run `manifest` or publish locally for an npm release. CI generates the manifest only in its checkout and does not commit it back. For local or Git installs, run `npm run manifest` and commit the generated `package.json` when changing bundle selection or versions so the repository manifest stays in sync.
|
|
110
|
+
|
|
111
|
+
### Local development and manual publishing
|
|
59
112
|
|
|
60
113
|
```sh
|
|
61
|
-
# Sync
|
|
114
|
+
# Sync the local manifest and validate all extensions
|
|
62
115
|
npm run manifest
|
|
63
116
|
npm run check
|
|
64
117
|
|
|
65
|
-
# Stage
|
|
66
|
-
npm run prepare:extension --
|
|
118
|
+
# Stage a standalone package into dist/<id>
|
|
119
|
+
npm run prepare:extension -- memory-log
|
|
67
120
|
|
|
68
|
-
#
|
|
69
|
-
npm run publish:ci --
|
|
70
|
-
npm run publish:ci -- kit
|
|
71
|
-
npm run publish:ci -- tui-asr
|
|
121
|
+
# Optional local release; also accepts extensions, kit, or a single extension ID
|
|
122
|
+
npm run publish:ci -- all
|
|
72
123
|
```
|
|
73
124
|
|
|
74
|
-
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Acknowledgements
|
|
128
|
+
|
|
129
|
+
- [elpapi42/pi-observational-memory](https://github.com/elpapi42/pi-observational-memory) — Observational memory architecture and inspiration for [`memory-log`](memory-log/README.md).
|
|
130
|
+
- [earendil-works/pi](https://github.com/earendil-works/pi) — The Pi coding agent harness and SDK.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
[MIT](LICENSE) © RoL1n_SrP
|
package/README_zh.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# pi-kit
|
|
2
|
+
|
|
3
|
+
> 面向 [Pi Coding Agent](https://pi.dev) 的模块化扩展与提示词模板套件,支持作为 **`@rol1n/pi-kit`** 聚合包或 **`@rol1n/<extension>`** 独立包安装。
|
|
4
|
+
|
|
5
|
+
<p align="left">
|
|
6
|
+
<a href="README.md"><b>English</b></a> •
|
|
7
|
+
<b>中文说明</b>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
[](https://www.npmjs.com/package/@rol1n/pi-kit)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 安装
|
|
16
|
+
|
|
17
|
+
安装默认聚合包:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
pi install npm:@rol1n/pi-kit
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
或按需安装任意独立扩展包:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
pi install npm:@rol1n/memory-log
|
|
27
|
+
pi install npm:@rol1n/subagent
|
|
28
|
+
pi install npm:@rol1n/multi-harness
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
开发期间也可直接从 GitHub 或本地目录安装:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
pi install https://github.com/RolinShmily/pi-kit
|
|
35
|
+
pi install /absolute/path/to/pi-kit
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
更新已安装的包:
|
|
39
|
+
|
|
40
|
+
```sh
|
|
41
|
+
pi update npm:@rol1n/pi-kit
|
|
42
|
+
pi update --extensions
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## 扩展列表
|
|
48
|
+
|
|
49
|
+
仓库根目录下每个文件夹均为自包含扩展(`<name>/index.ts` + `README.md`)。各扩展的详细命令、参数与配置说明请参阅对应目录的 README:
|
|
50
|
+
|
|
51
|
+
| 扩展目录 | 功能简介 | 默认纳入 `pi-kit` | 独立 npm 包名 |
|
|
52
|
+
| :--- | :--- | :---: | :--- |
|
|
53
|
+
| [ask-u-questions](ask-u-questions/README.md) | 交互式单选、多选与自由文本提问弹窗(共享 UI 锁) | Yes | `@rol1n/ask-u-questions` |
|
|
54
|
+
| [continue-signal](continue-signal/README.md) | 通过 `/continue` 或 `Alt+C` 唤醒空闲智能体继续未完成任务 | Yes | `@rol1n/continue-signal` |
|
|
55
|
+
| [custom-providers](custom-providers/README.md) | 自定义模型服务商与网关(Magpie、智谱、阿里百炼等)注册 | Yes | `@rol1n/custom-providers` |
|
|
56
|
+
| [image-generate](image-generate/README.md) | OpenRouter / 百炼文生图与参考图生图工具及 `/image-generate` 模型选择器 | Yes | `@rol1n/image-generate` |
|
|
57
|
+
| [memory-log](memory-log/README.md) | 分层异步观察记忆系统与零模型阻塞的确定性秒级压缩 | Yes | `@rol1n/memory-log` |
|
|
58
|
+
| [model-vision](model-vision/README.md) | 本地与远程图片视觉理解、OCR 与 UI 诊断工具(`model_vision`) | No | `@rol1n/model-vision` |
|
|
59
|
+
| [multi-harness](multi-harness/README.md) | 跨 `pi`、`codex`、`claude`、`opencode` 的多 CLI 协同委派运行时 | Yes | `@rol1n/multi-harness` |
|
|
60
|
+
| [oai-subquota](oai-subquota/README.md) | OpenAI Codex 订阅额度(5h / 7d 窗口与重置时间)状态栏监控 | Yes | `@rol1n/oai-subquota` |
|
|
61
|
+
| [prompt-snipaste](prompt-snipaste/README.md) | 提示词片段选择器(`/snipaste`、`Alt+S`),内置 7 个常用提示词模板 | Yes | `@rol1n/prompt-snipaste` |
|
|
62
|
+
| [screenshot](screenshot/README.md) | 一键将最新 Windows / WSL 系统截图路径插入编辑器(`/screenshot`) | No | `@rol1n/screenshot` |
|
|
63
|
+
| [srp-theme](srp-theme/README.md) | 编辑器下方最近提问预览组件与实时流式 TPS 速率仪表 | Yes | `@rol1n/srp-theme` |
|
|
64
|
+
| [subagent](subagent/README.md) | 基于 tmux / Zellij 分屏或后台进程的并发 Pi 子智能体工具 | Yes | `@rol1n/subagent` |
|
|
65
|
+
| [tui-asr](tui-asr/README.md) | 基于阿里百炼 Paraformer 的终端实时流式语音听写(`/asr`、`Alt+M`) | Yes | `@rol1n/tui-asr` |
|
|
66
|
+
| [web-reach](web-reach/README.md) | 免 Key Exa MCP 网页搜索与多级网页正文提取(RSC / HTML / PDF / Jina) | No | `@rol1n/web-reach` |
|
|
67
|
+
| [windows-wheel-fix](windows-wheel-fix/README.md) | 修复 Windows ConPTY / Zellij 下鼠标滚轮被误转为上下方向键的问题 | Yes (仅 Windows) | `@rol1n/windows-wheel-fix` |
|
|
68
|
+
|
|
69
|
+
> 带有跨扩展依赖的独立包(`tui-asr` / `image-generate` 依赖 `@rol1n/custom-providers`,`multi-harness` 依赖 `@rol1n/subagent`)已声明标准 npm `dependencies`,单独安装时会自动拉取补全并激活所需依赖。
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 资源按需筛选
|
|
74
|
+
|
|
75
|
+
`@rol1n/pi-kit` 默认导出 12 个扩展入口与 [prompt-snipaste/prompts](prompt-snipaste/prompts/) 下的 7 个提示词模板。可通过 `pi config` 或在 `settings.json` 中按需过滤:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"packages": [
|
|
80
|
+
{
|
|
81
|
+
"source": "npm:@rol1n/pi-kit",
|
|
82
|
+
"extensions": ["**/*.ts", "!tui-asr/**"],
|
|
83
|
+
"prompts": ["prompt-snipaste/prompts/diagnose-report.md"]
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## 构建与发布
|
|
92
|
+
|
|
93
|
+
[kit.config.json](kit.config.json) 统一管理聚合包选择(`bundle`)、扩展间的依赖关系(`deps`)与发布版本。顶层 `version` 属于 `@rol1n/pi-kit`;各扩展可以单独设置 `version`,未设置时继承顶层版本。为每个扩展显式设置版本即可让聚合包与独立包分别升级。
|
|
94
|
+
|
|
95
|
+
### 自动发布
|
|
96
|
+
|
|
97
|
+
1. 修改代码,并在 `kit.config.json` 中提升需要发布的包的版本。
|
|
98
|
+
2. 将包含 `kit.config.json` 或 `package.json` 变更的提交推送到 `main`,或在 GitHub Actions 手动运行 **Publish to npm**。修改打包脚本或工作流本身也会触发发布流程。
|
|
99
|
+
3. 自动和手动触发均执行同一条流水线:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
npm run manifest
|
|
103
|
+
npm run check
|
|
104
|
+
npm run publish:ci -- all
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
[`.github/workflows/publish.yml`](.github/workflows/publish.yml) 会生成 `package.json`、校验扩展布局,再按依赖顺序发布所有独立扩展,最后发布聚合包。已存在的版本自动跳过,不会自动提升版本号。`bundle: false` 只表示不纳入聚合包,不影响独立发布。发布流程不会并行执行,新触发的流程也不会取消正在进行的发布。仅修改扩展代码不会触发发布。
|
|
108
|
+
|
|
109
|
+
发布 npm 包无需本地运行 `manifest` 或 `publish`。CI 只在运行目录中生成清单,不会自动提交回仓库。若使用本地或 Git 安装,调整聚合包选择或版本后仍应运行 `npm run manifest` 并提交生成的 `package.json`,保持仓库清单同步。
|
|
110
|
+
|
|
111
|
+
### 本地开发与手动发布
|
|
112
|
+
|
|
113
|
+
```sh
|
|
114
|
+
# 同步本地清单并校验所有扩展
|
|
115
|
+
npm run manifest
|
|
116
|
+
npm run check
|
|
117
|
+
|
|
118
|
+
# 将单个扩展构建到 dist/<id>
|
|
119
|
+
npm run prepare:extension -- memory-log
|
|
120
|
+
|
|
121
|
+
# 可选的本地发布,也支持 extensions、kit 或单个扩展 ID
|
|
122
|
+
npm run publish:ci -- all
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## 致谢
|
|
128
|
+
|
|
129
|
+
- [elpapi42/pi-observational-memory](https://github.com/elpapi42/pi-observational-memory) — [`memory-log`](memory-log/README.md) 的观察记忆架构灵感与上游基础。
|
|
130
|
+
- [earendil-works/pi](https://github.com/earendil-works/pi) — Pi Coding Agent 运行时与 SDK。
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 许可证
|
|
135
|
+
|
|
136
|
+
[MIT](LICENSE) © RoL1n_SrP
|
package/memory-log/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# memory-log
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Tiered asynchronous observational memory for long-running Pi sessions.
|
|
4
|
+
|
|
5
|
+
`memory-log` keeps multi-day coding sessions coherent across compactions without blocking your workflow. Based on the observational memory paradigm from [elpapi42/pi-observational-memory](https://github.com/elpapi42/pi-observational-memory), it moves memory distillation into background subprocesses while you work, making compaction a model-free rendering step when sufficient observations are available. If a safe cutoff or usable memory summary is unavailable, Pi's native summarizer takes over instead.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
@@ -8,20 +10,60 @@ Observational memory for long Pi sessions: background observers distill conversa
|
|
|
8
10
|
pi install npm:@rol1n/memory-log
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
Also included in `@rol1n/pi-kit`. The extension loads with new-session memory disabled by default.
|
|
13
|
+
Also included in `@rol1n/pi-kit`. The extension loads with new-session memory disabled by default (`/mem-log on` to enable for the current session, or `"defaultEnabled": true` in settings).
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Why it exists
|
|
18
|
+
|
|
19
|
+
Long AI coding sessions typically hit two walls:
|
|
20
|
+
|
|
21
|
+
1. **The Compression Wall (Summary of a Summary)**: Traditional compaction summarizes the conversation when the context window fills up. Over multiple cycles, the agent carries a compressed summary of a previous summary, gradually losing concrete architectural rationale, rejected approaches, and subtle constraints.
|
|
22
|
+
2. **Compaction Stalls**: Waiting for a model to rewrite a massive transcript right when the context window overflows interrupts flow.
|
|
23
|
+
|
|
24
|
+
`memory-log` solves both by doing the heavy lifting **asynchronously in the background** as the session progresses:
|
|
25
|
+
|
|
26
|
+
- **Background Observers**: Whenever raw conversation history accumulates a full chunk (`chunkTokens`), a background Pi worker distills that chunk into timestamped, priority-tagged (`🔴` / `🟡` / `🟢`) atomic observations stored in the session branch ledger.
|
|
27
|
+
- **Consolidator & Durable Topic Files**: When the active observation pool reaches `consolidateAtPoolTokens`, a background consolidator archives older observations into durable Markdown topic files under `.memory/<sessionId>/` (`INDEX.md`, `<topic>.md`) and appends project milestones to `.memory/<sessionId>/JOURNEY.md`, draining the active pool back toward `poolTargetTokens`.
|
|
28
|
+
- **Safe Deterministic Compaction**: After `agent_settled` (all retries and queued continuations have finished), context pressure can trigger compaction. The cutoff snaps to a completed observation boundary near `tailTokens`, never crossing an unobserved gap in newly recorded chunks or splitting a tool call from its results. The entire unobserved tail stays verbatim, even if larger than the target. The summary is rendered from `JOURNEY.md` + the **Memory Map** + active observations, without an LLM call. Missing boundaries or empty memory delegate to Pi's native summarizer, which may make an LLM call.
|
|
29
|
+
- **Source Recall**: `memory_recall` retrieves the original conversation chunk behind an observation by timestamp, including history hidden by compaction and observations archived to topic files.
|
|
30
|
+
- **TUI Observability**: Displays live footer gauges (`Next` chunk progress, `Pool` capacity, `Ctx` window usage), active worker spinners, and session memory cost.
|
|
31
|
+
|
|
32
|
+
---
|
|
12
33
|
|
|
13
34
|
## Commands
|
|
14
35
|
|
|
15
36
|
| Command | Action |
|
|
16
37
|
|---|---|
|
|
17
|
-
| `/mem-log
|
|
18
|
-
| `/mem-log
|
|
19
|
-
| `/mem-log
|
|
20
|
-
| `/mem-log
|
|
38
|
+
| `/mem-log` | Enable memory log (if off) or display status & timeline (if on) |
|
|
39
|
+
| `/mem-log on` / `/mem-log off` | Enable or disable observational memory for the current session |
|
|
40
|
+
| `/mem-log status` or `/mem-log:status` | View gauges, worker states, cost summary, and observation timeline |
|
|
41
|
+
| `/mem-log compact` or `/mem-log:compact` | Request immediate compaction (native summarization if no safe memory cutoff exists) |
|
|
42
|
+
| `/mem-log consolidate` or `/mem-log:consolidate` | Consolidate the active observation pool into durable topic files immediately |
|
|
43
|
+
|
|
44
|
+
---
|
|
21
45
|
|
|
22
|
-
##
|
|
46
|
+
## Source recall
|
|
23
47
|
|
|
24
|
-
|
|
48
|
+
The agent can call `memory_recall` with an observation's full timestamp-id (including a `.NN` suffix, if present), or an unambiguous prefix:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{ "timestamp": "2026-10-23T14:30:00" }
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
- New observations persist exact `sourceEntryIds`; provenance covers the **whole chunk**, not a per-fact citation.
|
|
55
|
+
- Older records remain readable: ranges are inferred from coverage anchors in source order, not worker completion order. Inferred ranges are explicitly labeled and may include extra conversation; old records cannot prove gaps caused by failed workers. Legacy compaction coverage retains its existing watermark interpretation.
|
|
56
|
+
- Recall searches only the **current branch**. Missing sources are reported as unavailable or partial, never borrowed from another branch. Archived observations remain traceable in the ledger.
|
|
57
|
+
- Output is paged at 12,000 source characters. Use the returned `nextOffset` as `offset` to continue; `limit` can request a smaller page. Images/non-text blocks use placeholders.
|
|
58
|
+
- Recall is read-only and remains available when background memory processing is disabled.
|
|
59
|
+
|
|
60
|
+
Automatic compaction requires a Pi version that exposes `agent_settled`. Aborted runs do not trigger it; there is no retry-error guessing or idle polling. Pi's own compaction mechanism remains independent.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Configuration
|
|
65
|
+
|
|
66
|
+
Add a `memoryLog` section to `~/.pi/agent/settings.json` (global) or `.pi/settings.json` (project-level override):
|
|
25
67
|
|
|
26
68
|
```json
|
|
27
69
|
{
|
|
@@ -34,7 +76,6 @@ Add `memoryLog` to personal or project Pi settings. Project values override pers
|
|
|
34
76
|
"tailTokens": 20000,
|
|
35
77
|
"journeyTargetTokens": 1000,
|
|
36
78
|
"observerConcurrency": 4,
|
|
37
|
-
"resumeAfterMidRunCompaction": true,
|
|
38
79
|
"passive": false,
|
|
39
80
|
"debugLog": false,
|
|
40
81
|
"models": {
|
|
@@ -45,10 +86,36 @@ Add `memoryLog` to personal or project Pi settings. Project values override pers
|
|
|
45
86
|
}
|
|
46
87
|
```
|
|
47
88
|
|
|
48
|
-
|
|
89
|
+
`resumeAfterMidRunCompaction` is retained for configuration compatibility but has no effect: this extension's automatic trigger now runs only after settlement and never starts a synthetic continuation.
|
|
90
|
+
|
|
91
|
+
### Model resolution
|
|
92
|
+
|
|
93
|
+
`models.observer` and `models.consolidator` accept `{ "provider": "...", "id": "...", "thinking": "off|minimal|low|medium|high|xhigh" }`.
|
|
94
|
+
Resolution priority: **explicit `memoryLog.models` -> current session model -> Pi default model (`defaultProvider` / `defaultModel`)**.
|
|
95
|
+
|
|
96
|
+
### Environment overrides
|
|
97
|
+
|
|
98
|
+
| Variable | Purpose |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `PI_OM_PASSIVE=1` | Disable automatic observer/consolidator/compaction triggers while keeping manual commands |
|
|
101
|
+
| `PI_OM_OBSERVER_PROVIDER` / `PI_OM_OBSERVER_MODEL` / `PI_OM_OBSERVER_THINKING` | Override observer worker model |
|
|
102
|
+
| `PI_OM_CONSOLIDATOR_PROVIDER` / `PI_OM_CONSOLIDATOR_MODEL` / `PI_OM_CONSOLIDATOR_THINKING` | Override consolidator worker model |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Storage layout
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
<project-root>/.memory/<session-id>/
|
|
110
|
+
├── INDEX.md # Orchestrator-rendered index of durable topics (injected as the Memory Map)
|
|
111
|
+
├── JOURNEY.md # Chronological project history maintained by the consolidator
|
|
112
|
+
└── <topic-slug>.md # Durable topic notes read on demand by the agent
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Short-term observations and enable/disable gates are stored directly in the Pi session JSONL ledger so they branch and fork naturally with your session tree.
|
|
49
116
|
|
|
50
|
-
|
|
117
|
+
---
|
|
51
118
|
|
|
52
|
-
##
|
|
119
|
+
## Credits
|
|
53
120
|
|
|
54
|
-
|
|
121
|
+
Adapted from and inspired by [elpapi42/pi-observational-memory](https://github.com/elpapi42/pi-observational-memory) (MIT License), extended with file-backed durable topic consolidation (`.memory/<sessionId>/`), `JOURNEY.md` tracking, and TUI progress gauges.
|
package/memory-log/config.ts
CHANGED
|
@@ -42,7 +42,7 @@ export interface Config {
|
|
|
42
42
|
* used as the last-resort fallback when no session model is available.
|
|
43
43
|
*/
|
|
44
44
|
settingsDefaultModel?: { provider?: string; id?: string };
|
|
45
|
-
/**
|
|
45
|
+
/** @deprecated Compatibility only; automatic compaction now runs after agent_settled. */
|
|
46
46
|
resumeAfterMidRunCompaction: boolean;
|
|
47
47
|
/** Power-user setting: disable all triggers (distinct from the on/off gate). */
|
|
48
48
|
passive: boolean;
|
|
@@ -14,16 +14,50 @@ import {
|
|
|
14
14
|
type Entry,
|
|
15
15
|
} from "../ledger/index.ts";
|
|
16
16
|
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Completed boundaries behind the contiguous observation frontier. A later worker
|
|
19
|
+
* finishing first must not authorize discarding an earlier failed/in-flight chunk.
|
|
20
|
+
* Legacy records only have a cumulative watermark; retain that older contract.
|
|
21
|
+
*/
|
|
18
22
|
function chunkBoundaryIndices(branch: Entry[]): number[] {
|
|
19
23
|
const indexes = entryIndexById(branch);
|
|
20
|
-
const
|
|
21
|
-
|
|
24
|
+
const boundaries = new Set<number>();
|
|
25
|
+
const coveredAt = new Map<string, number>();
|
|
26
|
+
let legacyFrontier = -1;
|
|
27
|
+
for (let i = 0; i < branch.length; i++) {
|
|
28
|
+
const entry = branch[i];
|
|
22
29
|
if (!isObservationsRecordedEntry(entry)) continue;
|
|
23
30
|
const idx = indexes.get(entry.data.coversUpToId);
|
|
24
|
-
if (idx
|
|
31
|
+
if (idx === undefined || idx >= i || !isSourceEntry(branch[idx])) continue;
|
|
32
|
+
if (entry.data.sourceEntryIds === undefined) {
|
|
33
|
+
legacyFrontier = Math.max(legacyFrontier, idx);
|
|
34
|
+
} else {
|
|
35
|
+
const ids = entry.data.sourceEntryIds;
|
|
36
|
+
// Reject unresolved, out-of-order, or non-source anchors.
|
|
37
|
+
let previous = -1;
|
|
38
|
+
const valid = ids.length > 0 && ids.at(-1) === entry.data.coversUpToId && ids.every((id) => {
|
|
39
|
+
const index = indexes.get(id);
|
|
40
|
+
if (index === undefined || index <= previous || index > idx || !isSourceEntry(branch[index])) return false;
|
|
41
|
+
previous = index;
|
|
42
|
+
return true;
|
|
43
|
+
});
|
|
44
|
+
if (!valid) continue;
|
|
45
|
+
for (const id of ids) coveredAt.set(id, Math.min(coveredAt.get(id) ?? Infinity, idx));
|
|
46
|
+
}
|
|
47
|
+
boundaries.add(idx);
|
|
48
|
+
}
|
|
49
|
+
const safeBoundaries: number[] = [];
|
|
50
|
+
let requiredCoverageEnd = -1;
|
|
51
|
+
for (let i = 0; i < branch.length; i++) {
|
|
52
|
+
if (isSourceEntry(branch[i])) {
|
|
53
|
+
const coveredEnd = i <= legacyFrontier ? i : (coveredAt.get(branch[i].id) ?? Infinity);
|
|
54
|
+
requiredCoverageEnd = Math.max(requiredCoverageEnd, coveredEnd);
|
|
55
|
+
}
|
|
56
|
+
// The projection must include the records that authorize this cut, not just
|
|
57
|
+
// records for overlapping chunks whose watermarks lie beyond it.
|
|
58
|
+
if (boundaries.has(i) && requiredCoverageEnd <= i) safeBoundaries.push(i);
|
|
25
59
|
}
|
|
26
|
-
return
|
|
60
|
+
return safeBoundaries;
|
|
27
61
|
}
|
|
28
62
|
|
|
29
63
|
/** First source entry after `boundaryIndex` that is a valid cut point, or undefined. */
|
|
@@ -37,9 +71,9 @@ function firstKeptAfterBoundary(branch: Entry[], boundaryIndex: number): Entry |
|
|
|
37
71
|
|
|
38
72
|
export function snapCutoff(
|
|
39
73
|
branch: Entry[],
|
|
40
|
-
|
|
74
|
+
_proposedFirstKeptId: string,
|
|
41
75
|
tailTokens: number,
|
|
42
|
-
): { firstKeptId: string; tail: number | undefined } {
|
|
76
|
+
): { firstKeptId: string | undefined; tail: number | undefined } {
|
|
43
77
|
const indexes = entryIndexById(branch);
|
|
44
78
|
const lastCompactionIdx = findLastCompactionIndex(branch);
|
|
45
79
|
const boundaries = chunkBoundaryIndices(branch);
|
|
@@ -80,26 +114,21 @@ export function snapCutoff(
|
|
|
80
114
|
}
|
|
81
115
|
}
|
|
82
116
|
|
|
83
|
-
if (!finalFirstKeptId) {
|
|
84
|
-
finalFirstKeptId = proposedFirstKeptId;
|
|
85
|
-
finalTail = undefined;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
117
|
return { firstKeptId: finalFirstKeptId, tail: finalTail };
|
|
89
118
|
}
|
|
90
119
|
|
|
91
|
-
export function snapFirstKeptEntryId(branch: Entry[], proposedFirstKeptId: string, tailTokens: number): string {
|
|
120
|
+
export function snapFirstKeptEntryId(branch: Entry[], proposedFirstKeptId: string, tailTokens: number): string | undefined {
|
|
92
121
|
return snapCutoff(branch, proposedFirstKeptId, tailTokens).firstKeptId;
|
|
93
122
|
}
|
|
94
123
|
|
|
95
124
|
export function canSkipObserverWait(
|
|
96
125
|
branch: Entry[],
|
|
97
|
-
snappedFirstKeptId: string,
|
|
126
|
+
snappedFirstKeptId: string | undefined,
|
|
98
127
|
snappedTail: number | undefined,
|
|
99
128
|
tailTokens: number,
|
|
100
129
|
observersInFlight: Iterable<{ coversUpToId: string }>,
|
|
101
130
|
): boolean {
|
|
102
|
-
if (snappedTail === undefined || snappedTail > tailTokens) return false;
|
|
131
|
+
if (!snappedFirstKeptId || snappedTail === undefined || snappedTail > tailTokens) return false;
|
|
103
132
|
|
|
104
133
|
const indexes = entryIndexById(branch);
|
|
105
134
|
const cutoffIndex = indexes.get(snappedFirstKeptId);
|
|
@@ -115,6 +144,7 @@ export function canSkipObserverWait(
|
|
|
115
144
|
export function registerCompactionHook(pi: ExtensionAPI, runtime: Runtime): void {
|
|
116
145
|
pi.on("session_before_compact", async (event: any, ctx: any) => {
|
|
117
146
|
if (!runtime.enabled || runtime.config.passive) return undefined;
|
|
147
|
+
if (event.signal?.aborted) return { cancel: true };
|
|
118
148
|
|
|
119
149
|
const hasUI = ctx.hasUI;
|
|
120
150
|
if (runtime.compactHookInFlight) {
|
|
@@ -140,11 +170,24 @@ export function registerCompactionHook(pi: ExtensionAPI, runtime: Runtime): void
|
|
|
140
170
|
snap = snapCutoff(branch, firstKeptEntryId, tailTokens);
|
|
141
171
|
}
|
|
142
172
|
|
|
173
|
+
if (event.signal?.aborted) return { cancel: true };
|
|
174
|
+
if (!runtime.enabled) return undefined;
|
|
175
|
+
|
|
176
|
+
// No proven observed cut: let Pi summarize the raw history, never stamp an
|
|
177
|
+
// empty deterministic summary over unobserved messages (including old tails).
|
|
143
178
|
const snapped = snap.firstKeptId;
|
|
179
|
+
if (!snapped || snap.tail === undefined) {
|
|
180
|
+
if (hasUI) ctx.ui.notify("memory-log: no safe observed cutoff — using Pi's native summarizer", "info");
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
144
183
|
const projection = buildCompactionProjection(branch, snapped);
|
|
145
184
|
const journey = readJourney(runtime.memoryRoot);
|
|
146
185
|
const map = renderMemoryMap(listTopics(runtime.memoryRoot));
|
|
147
186
|
const summary = renderSummary(journey, map, projection.observations);
|
|
187
|
+
if (!summary.trim()) {
|
|
188
|
+
if (hasUI) ctx.ui.notify("memory-log: memory summary is empty — using Pi's native summarizer", "info");
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
148
191
|
|
|
149
192
|
return {
|
|
150
193
|
compaction: {
|