@aipper/aiws-spec 0.0.51 → 0.0.52
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.
|
@@ -14,13 +14,13 @@
|
|
|
14
14
|
],
|
|
15
15
|
"recommended_a": [
|
|
16
16
|
{
|
|
17
|
-
"id": "pi-extension-settings",
|
|
18
|
-
"package": "pi-extension-settings",
|
|
17
|
+
"id": "@juanibiapina/pi-extension-settings",
|
|
18
|
+
"package": "@juanibiapina/pi-extension-settings",
|
|
19
19
|
"tier": "recommended_a"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
|
-
"id": "pi-powerbar",
|
|
23
|
-
"package": "pi-powerbar",
|
|
22
|
+
"id": "@juanibiapina/pi-powerbar",
|
|
23
|
+
"package": "@juanibiapina/pi-powerbar",
|
|
24
24
|
"tier": "recommended_a"
|
|
25
25
|
},
|
|
26
26
|
{
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"tier": "recommended_a"
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
|
-
"id": "rpiv-ask-user-question",
|
|
43
|
-
"package": "rpiv-ask-user-question",
|
|
42
|
+
"id": "@juicesharp/rpiv-ask-user-question",
|
|
43
|
+
"package": "@juicesharp/rpiv-ask-user-question",
|
|
44
44
|
"tier": "recommended_a"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
@@ -63,7 +63,8 @@
|
|
|
63
63
|
{
|
|
64
64
|
"id": "pi-mcp-adapter",
|
|
65
65
|
"package": "pi-mcp-adapter",
|
|
66
|
-
"tier": "recommended_b"
|
|
66
|
+
"tier": "recommended_b",
|
|
67
|
+
"reason": "MCP adapter; heavy deps \u2014 sequential install with timeout; may need manual retry"
|
|
67
68
|
},
|
|
68
69
|
{
|
|
69
70
|
"id": "pi-fff",
|
|
@@ -76,8 +77,8 @@
|
|
|
76
77
|
"tier": "recommended_b"
|
|
77
78
|
},
|
|
78
79
|
{
|
|
79
|
-
"id": "plan-mode",
|
|
80
|
-
"package": "plan-mode",
|
|
80
|
+
"id": "pi-plan-mode",
|
|
81
|
+
"package": "pi-plan-mode",
|
|
81
82
|
"tier": "recommended_b"
|
|
82
83
|
},
|
|
83
84
|
{
|
|
@@ -54,12 +54,12 @@ Low conflict with AIWS governance; useful quality-of-life.
|
|
|
54
54
|
|
|
55
55
|
| package | notes |
|
|
56
56
|
|---------|--------|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
57
|
+
| `@juanibiapina/pi-extension-settings` | settings UX |
|
|
58
|
+
| `@juanibiapina/pi-powerbar` | status bar |
|
|
59
59
|
| `pi-lsp` | LSP |
|
|
60
60
|
| `pi-hashline-edit-pro` | edit helper (watch tool names vs force deny) |
|
|
61
61
|
| `rpiv-todo` | todos |
|
|
62
|
-
|
|
|
62
|
+
| `@juicesharp/rpiv-ask-user-question` | structured questions |
|
|
63
63
|
| `pi-btw` | asides |
|
|
64
64
|
| `pi-caffeinate` | keep awake |
|
|
65
65
|
| `pi-workspace-history` | history |
|
|
@@ -68,10 +68,10 @@ Low conflict with AIWS governance; useful quality-of-life.
|
|
|
68
68
|
|
|
69
69
|
| package | notes |
|
|
70
70
|
|---------|--------|
|
|
71
|
-
| `pi-mcp-adapter` | MCP |
|
|
71
|
+
| `pi-mcp-adapter` | MCP (heavy deps; install may hang — retry alone or skip) |
|
|
72
72
|
| `pi-fff` | file finder |
|
|
73
73
|
| `pi-slopchop` | slop cleanup |
|
|
74
|
-
| `plan-mode` | plan UX (AIWS keeps plan truth) |
|
|
74
|
+
| `pi-plan-mode` | plan UX (AIWS keeps plan truth) |
|
|
75
75
|
| `pi-cache-optimizer` | cache (truncation caution) |
|
|
76
76
|
| `pi-rtk-optimizer` | RTK |
|
|
77
77
|
| `pi-agent-browser-native` | browser |
|
|
@@ -102,7 +102,7 @@ Low conflict with AIWS governance; useful quality-of-life.
|
|
|
102
102
|
- Missing **required** → exit code ≠ 0
|
|
103
103
|
- Conflicts / forbidden installed → warn (exit ≠ 0 if any required missing or any conflict)
|
|
104
104
|
- `init --pi` / `update` (when `.pi/` exists or `--pi`): print same report as **warn**; do not fail init/update by default
|
|
105
|
-
- Optional `--install-pi-plugins`: install **
|
|
105
|
+
- Optional `--install-pi-plugins`: install **all declared installable** plugins (required + recommended A/B, user scope); never forbidden; default without flag remains detect+prompt only
|
|
106
106
|
|
|
107
107
|
## Related
|
|
108
108
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Autoload Plugin
|
|
3
|
+
*
|
|
4
|
+
* Injects AIWS memory context at session start so each session
|
|
5
|
+
* has continuity without needing the nocturne_memory MCP server.
|
|
6
|
+
*
|
|
7
|
+
* What it does:
|
|
8
|
+
* 1. On the first user message of a new session, reads:
|
|
9
|
+
* - Active goal(s) from .aiws/goals/*.state.json
|
|
10
|
+
* - Recent decisions from .aiws/memory-bank/decision/ (last 3)
|
|
11
|
+
* - Project overview from .aiws/memory-bank/project/
|
|
12
|
+
* 2. Injects a <memory-context> block into the assistant's first response.
|
|
13
|
+
* 3. Deduplicates per session — injects once only.
|
|
14
|
+
*
|
|
15
|
+
* Disable: export MEMORY_AUTOLOAD_DISABLE=1
|
|
16
|
+
*
|
|
17
|
+
* @module memory-autoload
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { readFileSync, existsSync, readdirSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
|
|
23
|
+
const MEMORY_BANK = ".aiws/memory-bank";
|
|
24
|
+
const GOALS_DIR = ".aiws/goals";
|
|
25
|
+
|
|
26
|
+
export const MemoryAutoloadPlugin = async ({ project, client, directory }) => {
|
|
27
|
+
const processed = new Set();
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
"chat.message": async (input, output) => {
|
|
31
|
+
const sid = input?.sessionID;
|
|
32
|
+
if (!sid || processed.has(sid)) return;
|
|
33
|
+
if (process.env.MEMORY_AUTOLOAD_DISABLE === "1") {
|
|
34
|
+
processed.add(sid);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const root = directory || process.cwd();
|
|
39
|
+
const bankDir = join(root, MEMORY_BANK);
|
|
40
|
+
if (!existsSync(bankDir)) {
|
|
41
|
+
processed.add(sid);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const blocks = [];
|
|
46
|
+
|
|
47
|
+
// ── 1. Active/paused goals (ADVISORY ONLY — not FSM authority) ─
|
|
48
|
+
// TOOLING-003D: authoritative goal-context + next_action come from
|
|
49
|
+
// session-start → buildSessionContext → getActiveGoal(s).
|
|
50
|
+
// memory-autoload must NOT become authority over goal state.
|
|
51
|
+
try {
|
|
52
|
+
const goalsDir = join(root, GOALS_DIR);
|
|
53
|
+
if (existsSync(goalsDir)) {
|
|
54
|
+
const files = readdirSync(goalsDir).filter((f) =>
|
|
55
|
+
f.endsWith(".state.json"),
|
|
56
|
+
);
|
|
57
|
+
const advisory = [];
|
|
58
|
+
for (const file of files.sort()) {
|
|
59
|
+
try {
|
|
60
|
+
const state = JSON.parse(
|
|
61
|
+
readFileSync(join(goalsDir, file), "utf-8"),
|
|
62
|
+
);
|
|
63
|
+
const st = state.status;
|
|
64
|
+
if (st === "active" || st === "paused") {
|
|
65
|
+
const phase = state.current_phase ?? "?";
|
|
66
|
+
const iter = state.iteration ?? "?";
|
|
67
|
+
advisory.push(
|
|
68
|
+
`- [${st}] ${state.goal_id || file} — phase=${phase}, iteration=${iter}`,
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
/* skip malformed state file */
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (advisory.length) {
|
|
76
|
+
blocks.push(
|
|
77
|
+
"[Goals — advisory memory only; use session <goal-context> for next_action]",
|
|
78
|
+
);
|
|
79
|
+
blocks.push(...advisory);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
/* goals dir missing */
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ── 2. Recent decisions (last 3, sorted by filename) ──────────
|
|
87
|
+
try {
|
|
88
|
+
const decDir = join(bankDir, "decision");
|
|
89
|
+
if (existsSync(decDir)) {
|
|
90
|
+
const files = readdirSync(decDir)
|
|
91
|
+
.filter((f) => f.endsWith(".md") && f !== "handoff-evidence.md")
|
|
92
|
+
.sort()
|
|
93
|
+
.reverse()
|
|
94
|
+
.slice(0, 3);
|
|
95
|
+
for (const file of files) {
|
|
96
|
+
try {
|
|
97
|
+
const content = readFileSync(join(decDir, file), "utf-8");
|
|
98
|
+
const title =
|
|
99
|
+
content
|
|
100
|
+
.split("\n")
|
|
101
|
+
.find((l) => l.startsWith("#"))
|
|
102
|
+
?.replace(/^#+\s*/, "") || file.replace(".md", "");
|
|
103
|
+
const summary = content
|
|
104
|
+
.split("\n")
|
|
105
|
+
.slice(1, 8)
|
|
106
|
+
.filter((l) => l.trim())
|
|
107
|
+
.join("\n")
|
|
108
|
+
.trim();
|
|
109
|
+
blocks.push(`\n[Decision] ${title}\n${summary}`);
|
|
110
|
+
} catch {
|
|
111
|
+
/* skip unreadable file */
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} catch {
|
|
116
|
+
/* decision dir missing */
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── 3. Project overview ────────────────────────────────────────
|
|
120
|
+
try {
|
|
121
|
+
const projDir = join(bankDir, "project");
|
|
122
|
+
if (existsSync(projDir)) {
|
|
123
|
+
const files = readdirSync(projDir).filter((f) => f.endsWith(".md"));
|
|
124
|
+
for (const file of files.slice(0, 2)) {
|
|
125
|
+
try {
|
|
126
|
+
const content = readFileSync(join(projDir, file), "utf-8");
|
|
127
|
+
const title =
|
|
128
|
+
content
|
|
129
|
+
.split("\n")
|
|
130
|
+
.find((l) => l.startsWith("#"))
|
|
131
|
+
?.replace(/^#+\s*/, "") || file.replace(".md", "");
|
|
132
|
+
const excerpt = content
|
|
133
|
+
.split("\n")
|
|
134
|
+
.slice(1, 12)
|
|
135
|
+
.filter((l) => l.trim())
|
|
136
|
+
.join("\n")
|
|
137
|
+
.trim();
|
|
138
|
+
blocks.push(`\n[Project: ${title}]\n${excerpt}`);
|
|
139
|
+
} catch {
|
|
140
|
+
/* skip */
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} catch {
|
|
145
|
+
/* project dir missing */
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ── 4. If aiws memory boot produces anything, append it ────────
|
|
149
|
+
// (skipped — avoids shell dependency; use --disclosure boot on
|
|
150
|
+
// `aiws memory write` and the injected goal/decision blocks
|
|
151
|
+
// above already provide sufficient context)
|
|
152
|
+
|
|
153
|
+
if (blocks.length === 0) {
|
|
154
|
+
processed.add(sid);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const context = `<memory-context>\n${blocks.join("\n")}\n</memory-context>`;
|
|
159
|
+
|
|
160
|
+
const parts = output?.parts || [];
|
|
161
|
+
const textIdx = parts.findIndex(
|
|
162
|
+
(p) => p.type === "text" && p.text !== undefined,
|
|
163
|
+
);
|
|
164
|
+
if (textIdx !== -1) {
|
|
165
|
+
parts[textIdx].text = `${context}\n\n${parts[textIdx].text}`;
|
|
166
|
+
} else {
|
|
167
|
+
parts.unshift({ type: "text", text: context });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
try {
|
|
171
|
+
await client.app.log({
|
|
172
|
+
body: {
|
|
173
|
+
service: "memory-autoload",
|
|
174
|
+
level: "info",
|
|
175
|
+
message: `Injected ${blocks.length} memory blocks for session ${sid.slice(0, 12)}`,
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
} catch {
|
|
179
|
+
/* logging optional */
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
processed.add(sid);
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
};
|
|
@@ -32,3 +32,16 @@ Red Flags(这些想法都是错的):
|
|
|
32
32
|
<!-- AIWS_MANAGED_END:agents -->
|
|
33
33
|
|
|
34
34
|
你可以在本段下方追加项目自定义说明;`aiws update` 不会改动托管块以外内容。
|
|
35
|
+
|
|
36
|
+
## Memory Protocol
|
|
37
|
+
|
|
38
|
+
本仓库使用 `aiws memory` 系统持久化跨会话知识。automation 协议:
|
|
39
|
+
|
|
40
|
+
1. **自动注入(插件)** — `.opencode/plugins/memory-autoload.js` 在会话首次消息时读取活跃目标、近期决策、项目概览并注入 `<memory-context>`。需依赖:`MEMORY_AUTOLOAD_DISABLE=1` 可关闭
|
|
41
|
+
2. **会话启动时** — 自动读取 `.aiws/memory-bank/.index.yaml` 获取记忆索引,了解已记录的知识领域
|
|
42
|
+
3. **回答前** — 若问题涉及已记忆的领域,先用 `aiws memory search <keywords>` 检索相关记录
|
|
43
|
+
4. **获取新知识后** — 对重要决策、根因分析、架构约定等跨会话有价值的信息,使用 `aiws memory write <domain>://<path>` 写入永久记忆(写入会自动更新索引)。标记 `--disclosure boot` 可让记忆出现在下次插件注入中
|
|
44
|
+
5. **记忆关联** — 对相关记忆使用 `aiws memory link add` 建立关系
|
|
45
|
+
6. **nocturne_memory MCP** — 仓库预配了远程 MCP 服务器(nocturne_memory),作为全局知识层自动可用,两者互补而非替代。当前未集成到 OpenCode 配置中
|
|
46
|
+
|
|
47
|
+
目标:把关键认知固化到 git-tracked 文件,实现跨机器/跨会话的知识连续性。
|
|
@@ -64,6 +64,7 @@
|
|
|
64
64
|
".opencode/plugins/aiws-inject-context.js",
|
|
65
65
|
".opencode/plugins/aiws-session-start.js",
|
|
66
66
|
".opencode/plugins/aiws-workflow-state.js",
|
|
67
|
+
".opencode/plugins/memory-autoload.js",
|
|
67
68
|
".opencode/lib/aiws-context.js",
|
|
68
69
|
".opencode/commands/**",
|
|
69
70
|
".opencode/skills/**",
|
|
@@ -257,6 +258,7 @@
|
|
|
257
258
|
".opencode/plugins/aiws-inject-context.js",
|
|
258
259
|
".opencode/plugins/aiws-session-start.js",
|
|
259
260
|
".opencode/plugins/aiws-workflow-state.js",
|
|
261
|
+
".opencode/plugins/memory-autoload.js",
|
|
260
262
|
".opencode/lib/aiws-context.js",
|
|
261
263
|
".opencode/command/p-aiws-change-archive.md",
|
|
262
264
|
".opencode/command/p-aiws-change-finish.md",
|