niahere 0.2.83 → 0.2.84
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 +13 -2
- package/package.json +1 -1
- package/src/commands/validate.ts +23 -0
- package/src/core/finalizer.ts +35 -9
- package/src/types/config.ts +7 -0
- package/src/utils/config.ts +14 -0
package/README.md
CHANGED
|
@@ -43,8 +43,8 @@ nia start # starts daemon + registers OS service
|
|
|
43
43
|
- **Skills** — loads skills from multiple directories, invokable as slash commands
|
|
44
44
|
- **Cross-platform service** — launchd (macOS), systemd (Linux), service-aware restart
|
|
45
45
|
- **MCP tools** — 20 tools for job management, messaging, memory, rules, and channel control
|
|
46
|
-
- **Background memory consolidation** —
|
|
47
|
-
- **Session summaries** — handoff notes between sessions for continuity
|
|
46
|
+
- **Background memory consolidation** — stages memory candidates from conversations automatically
|
|
47
|
+
- **Session summaries** — optional handoff notes between sessions for continuity
|
|
48
48
|
- **Backups** — `nia backup` with auto-backup before updates
|
|
49
49
|
- **Optional integrations** — add Gmail, Discord, and more via skills
|
|
50
50
|
|
|
@@ -119,6 +119,17 @@ All config and data lives in `~/.niahere/`:
|
|
|
119
119
|
nia.pid, daemon.log, cron-state.json, cron-audit.jsonl
|
|
120
120
|
```
|
|
121
121
|
|
|
122
|
+
Post-session background LLM work can be disabled in `config.yaml`:
|
|
123
|
+
|
|
124
|
+
```yaml
|
|
125
|
+
session_finalization:
|
|
126
|
+
enabled: true
|
|
127
|
+
memory_consolidation: true
|
|
128
|
+
summaries: true
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Use `nia config set session_finalization.memory_consolidation false` to stop memory staging, `nia config set session_finalization.summaries false` to stop session summaries, or `nia config set session_finalization.enabled false` to disable both.
|
|
132
|
+
|
|
122
133
|
## Contributing
|
|
123
134
|
|
|
124
135
|
**Don't add features. Add skills.**
|
package/package.json
CHANGED
package/src/commands/validate.ts
CHANGED
|
@@ -85,6 +85,29 @@ export function validateConfig(): Result {
|
|
|
85
85
|
messages.push(`${PASS} runner: ${runner}`);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// Session finalization
|
|
89
|
+
const sf = raw.session_finalization as Record<string, unknown> | undefined;
|
|
90
|
+
if (sf) {
|
|
91
|
+
let sessionFinalizationOk = true;
|
|
92
|
+
for (const key of ["enabled", "memory_consolidation", "summaries"]) {
|
|
93
|
+
const val = sf[key];
|
|
94
|
+
if (val !== undefined && typeof val !== "boolean") {
|
|
95
|
+
messages.push(`${FAIL} session_finalization.${key} must be true or false`);
|
|
96
|
+
ok = false;
|
|
97
|
+
sessionFinalizationOk = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (sessionFinalizationOk) {
|
|
101
|
+
const enabled = sf.enabled !== false;
|
|
102
|
+
const memoryConsolidation = sf.memory_consolidation !== false;
|
|
103
|
+
const summaries = sf.summaries !== false;
|
|
104
|
+
messages.push(
|
|
105
|
+
`${PASS} session_finalization: ${enabled ? "enabled" : "disabled"} ` +
|
|
106
|
+
`(memory_consolidation=${memoryConsolidation}, summaries=${summaries})`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
88
111
|
// Channels
|
|
89
112
|
const ch = raw.channels as Record<string, unknown> | undefined;
|
|
90
113
|
if (ch) {
|
package/src/core/finalizer.ts
CHANGED
|
@@ -10,10 +10,25 @@
|
|
|
10
10
|
import { getSql } from "../db/connection";
|
|
11
11
|
import { consolidateSession } from "./consolidator";
|
|
12
12
|
import { summarizeSession } from "./summarizer";
|
|
13
|
+
import { loadConfig } from "../utils/config";
|
|
13
14
|
import { log } from "../utils/log";
|
|
14
15
|
|
|
16
|
+
type FinalizationTask = "consolidate" | "summarize";
|
|
17
|
+
|
|
18
|
+
function getEnabledTasks(): FinalizationTask[] {
|
|
19
|
+
const { sessionFinalization } = loadConfig();
|
|
20
|
+
if (!sessionFinalization.enabled) return [];
|
|
21
|
+
|
|
22
|
+
const tasks: FinalizationTask[] = [];
|
|
23
|
+
if (sessionFinalization.memoryConsolidation) tasks.push("consolidate");
|
|
24
|
+
if (sessionFinalization.summaries) tasks.push("summarize");
|
|
25
|
+
return tasks;
|
|
26
|
+
}
|
|
27
|
+
|
|
15
28
|
/** Enqueue a session for finalization. Always returns immediately. */
|
|
16
29
|
export async function finalizeSession(sessionId: string, room: string): Promise<void> {
|
|
30
|
+
if (getEnabledTasks().length === 0) return;
|
|
31
|
+
|
|
17
32
|
const sql = getSql();
|
|
18
33
|
|
|
19
34
|
// Get current message count for idempotency
|
|
@@ -77,19 +92,30 @@ async function processOne(sessionId: string, room: string, messageCount: number)
|
|
|
77
92
|
if (claimed.length === 0) return; // Already claimed or cancelled
|
|
78
93
|
|
|
79
94
|
const requestId = claimed[0].id;
|
|
95
|
+
const tasks = getEnabledTasks();
|
|
96
|
+
if (tasks.length === 0) {
|
|
97
|
+
await sql`
|
|
98
|
+
UPDATE finalization_requests
|
|
99
|
+
SET status = 'done', updated_at = NOW()
|
|
100
|
+
WHERE id = ${requestId}
|
|
101
|
+
`;
|
|
102
|
+
log.info({ sessionId, room, messageCount }, "finalizer: skipped because all tasks are disabled");
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
80
105
|
|
|
81
106
|
try {
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
107
|
+
const results = await Promise.allSettled(
|
|
108
|
+
tasks.map((task) =>
|
|
109
|
+
task === "consolidate" ? consolidateSession(sessionId, room) : summarizeSession(sessionId, room),
|
|
110
|
+
),
|
|
111
|
+
);
|
|
86
112
|
|
|
87
113
|
const errors: string[] = [];
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
114
|
+
for (let i = 0; i < results.length; i++) {
|
|
115
|
+
const result = results[i];
|
|
116
|
+
if (result.status === "rejected") {
|
|
117
|
+
errors.push(`${tasks[i]}: ${formatRejection(result.reason)}`);
|
|
118
|
+
}
|
|
93
119
|
}
|
|
94
120
|
|
|
95
121
|
const finalStatus = errors.length === 0 ? "done" : "failed";
|
package/src/types/config.ts
CHANGED
|
@@ -35,6 +35,12 @@ export interface ChannelsConfig {
|
|
|
35
35
|
slack: SlackConfig;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
export interface SessionFinalizationConfig {
|
|
39
|
+
enabled: boolean;
|
|
40
|
+
memoryConsolidation: boolean;
|
|
41
|
+
summaries: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
38
44
|
export interface Config {
|
|
39
45
|
model: string;
|
|
40
46
|
runner: "claude" | "codex";
|
|
@@ -43,5 +49,6 @@ export interface Config {
|
|
|
43
49
|
database_url: string;
|
|
44
50
|
log_level: string;
|
|
45
51
|
gemini_api_key: string | null;
|
|
52
|
+
sessionFinalization: SessionFinalizationConfig;
|
|
46
53
|
channels: ChannelsConfig;
|
|
47
54
|
}
|
package/src/utils/config.ts
CHANGED
|
@@ -16,6 +16,11 @@ const DEFAULTS: Config = {
|
|
|
16
16
|
database_url: DEFAULT_DATABASE_URL,
|
|
17
17
|
log_level: "info",
|
|
18
18
|
gemini_api_key: null,
|
|
19
|
+
sessionFinalization: {
|
|
20
|
+
enabled: true,
|
|
21
|
+
memoryConsolidation: true,
|
|
22
|
+
summaries: true,
|
|
23
|
+
},
|
|
19
24
|
channels: {
|
|
20
25
|
enabled: true,
|
|
21
26
|
default: "telegram",
|
|
@@ -100,6 +105,14 @@ export function loadConfig(): Config {
|
|
|
100
105
|
const gemini_api_key =
|
|
101
106
|
process.env.GEMINI_API_KEY || (typeof raw.gemini_api_key === "string" ? raw.gemini_api_key : null);
|
|
102
107
|
|
|
108
|
+
// Session finalization — controls post-session background LLM work.
|
|
109
|
+
const sf = (raw.session_finalization || {}) as Record<string, unknown>;
|
|
110
|
+
const sessionFinalization = {
|
|
111
|
+
enabled: sf.enabled !== false,
|
|
112
|
+
memoryConsolidation: sf.memory_consolidation !== false,
|
|
113
|
+
summaries: sf.summaries !== false,
|
|
114
|
+
};
|
|
115
|
+
|
|
103
116
|
// --- Channels (nested under `channels:` in yaml) ---
|
|
104
117
|
const ch = (raw.channels || {}) as Record<string, unknown>;
|
|
105
118
|
const chTg = (ch.telegram || {}) as Record<string, unknown>;
|
|
@@ -159,6 +172,7 @@ export function loadConfig(): Config {
|
|
|
159
172
|
database_url,
|
|
160
173
|
log_level,
|
|
161
174
|
gemini_api_key,
|
|
175
|
+
sessionFinalization,
|
|
162
176
|
channels: {
|
|
163
177
|
enabled: channelsEnabled,
|
|
164
178
|
default: defaultChannel,
|