@pencil-agent/nano-pencil 1.11.16 → 1.11.17
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/dist/core/config/settings-manager.d.ts +14 -0
- package/dist/core/config/settings-manager.js +4 -0
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.js +3 -0
- package/dist/core/extensions/types.d.ts +3 -0
- package/dist/core/runtime/agent-session.js +1 -0
- package/dist/core/session/session-manager.d.ts +9 -0
- package/dist/core/session/session-manager.js +45 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/extensions/defaults/interview/index.js +189 -101
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.js +15 -0
- package/dist/packages/mem-core/consolidation.d.ts +3 -1
- package/dist/packages/mem-core/consolidation.js +13 -3
- package/dist/packages/mem-core/dream-lock.d.ts +5 -0
- package/dist/packages/mem-core/dream-lock.js +78 -0
- package/dist/packages/mem-core/engine.d.ts +11 -0
- package/dist/packages/mem-core/engine.js +38 -5
- package/dist/packages/mem-core/extension.js +224 -8
- package/dist/packages/mem-core/i18n.js +6 -2
- package/dist/packages/mem-core/types.d.ts +3 -0
- package/docs/Dream.md +665 -0
- package/docs/Interview.md +203 -0
- package/docs/InterviewRegression.md +122 -0
- package/package.json +1 -1
|
@@ -78,6 +78,18 @@ export interface Settings {
|
|
|
78
78
|
autocompleteMaxVisible?: number;
|
|
79
79
|
showHardwareCursor?: boolean;
|
|
80
80
|
markdown?: MarkdownSettings;
|
|
81
|
+
/** NanoMem / Dream settings */
|
|
82
|
+
nanomem?: {
|
|
83
|
+
autoDream?: {
|
|
84
|
+
enabled?: boolean;
|
|
85
|
+
minHours?: number;
|
|
86
|
+
minSessions?: number;
|
|
87
|
+
scanIntervalMinutes?: number;
|
|
88
|
+
};
|
|
89
|
+
dream?: {
|
|
90
|
+
lockStaleMinutes?: number;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
81
93
|
}
|
|
82
94
|
export type SettingsScope = "global" | "project";
|
|
83
95
|
export interface SettingsStorage {
|
|
@@ -124,6 +136,8 @@ export declare class SettingsManager {
|
|
|
124
136
|
private static migrateSettings;
|
|
125
137
|
getGlobalSettings(): Settings;
|
|
126
138
|
getProjectSettings(): Settings;
|
|
139
|
+
/** Get merged effective settings (project overrides global). */
|
|
140
|
+
getSettings(): Settings;
|
|
127
141
|
reload(): void;
|
|
128
142
|
/** Apply additional overrides on top of current settings */
|
|
129
143
|
applyOverrides(overrides: Partial<Settings>): void;
|
|
@@ -181,6 +181,10 @@ export class SettingsManager {
|
|
|
181
181
|
getProjectSettings() {
|
|
182
182
|
return structuredClone(this.projectSettings);
|
|
183
183
|
}
|
|
184
|
+
/** Get merged effective settings (project overrides global). */
|
|
185
|
+
getSettings() {
|
|
186
|
+
return structuredClone(this.settings);
|
|
187
|
+
}
|
|
184
188
|
reload() {
|
|
185
189
|
const globalLoad = SettingsManager.tryLoadFromStorage(this.storage, "global");
|
|
186
190
|
if (!globalLoad.error) {
|
|
@@ -96,6 +96,7 @@ export class ExtensionRunner {
|
|
|
96
96
|
getContextUsageFn = () => undefined;
|
|
97
97
|
compactFn = () => { };
|
|
98
98
|
getSystemPromptFn = () => "";
|
|
99
|
+
getSettingsFn = () => ({});
|
|
99
100
|
newSessionHandler = async () => ({ cancelled: false });
|
|
100
101
|
forkHandler = async () => ({ cancelled: false });
|
|
101
102
|
navigateTreeHandler = async () => ({ cancelled: false });
|
|
@@ -165,6 +166,7 @@ export class ExtensionRunner {
|
|
|
165
166
|
this.getContextUsageFn = contextActions.getContextUsage;
|
|
166
167
|
this.compactFn = contextActions.compact;
|
|
167
168
|
this.getSystemPromptFn = contextActions.getSystemPrompt;
|
|
169
|
+
this.getSettingsFn = contextActions.getSettings;
|
|
168
170
|
// Process provider registrations queued during extension loading
|
|
169
171
|
for (const { name, config } of this.runtime.pendingProviderRegistrations) {
|
|
170
172
|
this.modelRegistry.registerProvider(name, config);
|
|
@@ -382,6 +384,7 @@ export class ExtensionRunner {
|
|
|
382
384
|
getContextUsage: () => this.getContextUsageFn(),
|
|
383
385
|
compact: (options) => this.compactFn(options),
|
|
384
386
|
getSystemPrompt: () => this.getSystemPromptFn(),
|
|
387
|
+
getSettings: () => this.getSettingsFn(),
|
|
385
388
|
};
|
|
386
389
|
}
|
|
387
390
|
createCommandContext() {
|
|
@@ -205,6 +205,8 @@ export interface ExtensionContext {
|
|
|
205
205
|
compact(options?: CompactOptions): void;
|
|
206
206
|
/** Get the current effective system prompt. */
|
|
207
207
|
getSystemPrompt(): string;
|
|
208
|
+
/** Get current merged settings (project overrides global). */
|
|
209
|
+
getSettings(): import("../config/settings-manager.js").Settings;
|
|
208
210
|
}
|
|
209
211
|
/**
|
|
210
212
|
* Extended context for command handlers.
|
|
@@ -931,6 +933,7 @@ export interface ExtensionContextActions {
|
|
|
931
933
|
getContextUsage: () => ContextUsage | undefined;
|
|
932
934
|
compact: (options?: CompactOptions) => void;
|
|
933
935
|
getSystemPrompt: () => string;
|
|
936
|
+
getSettings: () => import("../config/settings-manager.js").Settings;
|
|
934
937
|
}
|
|
935
938
|
/**
|
|
936
939
|
* Actions for ExtensionCommandContext (ctx.* in command handlers).
|
|
@@ -1815,6 +1815,7 @@ export class AgentSession {
|
|
|
1815
1815
|
return undefined;
|
|
1816
1816
|
}
|
|
1817
1817
|
},
|
|
1818
|
+
getSettings: () => this.settingsManager.getSettings(),
|
|
1818
1819
|
isIdle: () => !this.isStreaming,
|
|
1819
1820
|
abort: () => this.abort(),
|
|
1820
1821
|
hasPendingMessages: () => this.pendingMessageCount > 0,
|
|
@@ -319,5 +319,14 @@ export declare class SessionManager {
|
|
|
319
319
|
* @param onProgress Optional callback for progress updates (loaded, total)
|
|
320
320
|
*/
|
|
321
321
|
static listAll(onProgress?: SessionListProgress): Promise<SessionInfo[]>;
|
|
322
|
+
/**
|
|
323
|
+
* Lightweight scan: count session files with mtime > sinceMs without reading file contents.
|
|
324
|
+
* Designed for gate checks (e.g., auto-dream) where approximate counts are OK.
|
|
325
|
+
*/
|
|
326
|
+
static countTouchedSince(cwd: string, sinceMs: number, options?: {
|
|
327
|
+
sessionDir?: string;
|
|
328
|
+
excludeBasename?: string;
|
|
329
|
+
concurrency?: number;
|
|
330
|
+
}): Promise<number>;
|
|
322
331
|
}
|
|
323
332
|
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
2
|
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync, readFileSync, readSync, statSync, writeFileSync, } from "fs";
|
|
3
3
|
import { readdir, readFile, stat } from "fs/promises";
|
|
4
|
-
import { join, resolve } from "path";
|
|
4
|
+
import { basename, join, resolve } from "path";
|
|
5
5
|
import { getAgentDir as getDefaultAgentDir, getSessionsDir } from "../../config.js";
|
|
6
6
|
import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage, } from "../messages.js";
|
|
7
7
|
export const CURRENT_SESSION_VERSION = 3;
|
|
@@ -413,6 +413,21 @@ async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progress
|
|
|
413
413
|
}
|
|
414
414
|
return sessions;
|
|
415
415
|
}
|
|
416
|
+
async function runWithConcurrency(items, concurrency, fn) {
|
|
417
|
+
const results = new Array(items.length);
|
|
418
|
+
let nextIndex = 0;
|
|
419
|
+
const worker = async () => {
|
|
420
|
+
while (true) {
|
|
421
|
+
const i = nextIndex++;
|
|
422
|
+
if (i >= items.length)
|
|
423
|
+
return;
|
|
424
|
+
results[i] = await fn(items[i]);
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
const poolSize = Math.max(1, Math.min(concurrency, items.length || 1));
|
|
428
|
+
await Promise.all(Array.from({ length: poolSize }, () => worker()));
|
|
429
|
+
return results;
|
|
430
|
+
}
|
|
416
431
|
/**
|
|
417
432
|
* Manages conversation sessions as append-only trees stored in JSONL files.
|
|
418
433
|
*
|
|
@@ -1087,5 +1102,34 @@ export class SessionManager {
|
|
|
1087
1102
|
return [];
|
|
1088
1103
|
}
|
|
1089
1104
|
}
|
|
1105
|
+
/**
|
|
1106
|
+
* Lightweight scan: count session files with mtime > sinceMs without reading file contents.
|
|
1107
|
+
* Designed for gate checks (e.g., auto-dream) where approximate counts are OK.
|
|
1108
|
+
*/
|
|
1109
|
+
static async countTouchedSince(cwd, sinceMs, options) {
|
|
1110
|
+
const dir = options?.sessionDir ?? getDefaultSessionDir(cwd);
|
|
1111
|
+
const concurrency = options?.concurrency ?? 64;
|
|
1112
|
+
try {
|
|
1113
|
+
if (!existsSync(dir))
|
|
1114
|
+
return 0;
|
|
1115
|
+
const files = (await readdir(dir))
|
|
1116
|
+
.filter((f) => f.endsWith(".jsonl"))
|
|
1117
|
+
.filter((f) => (options?.excludeBasename ? basename(f, ".jsonl") !== options.excludeBasename : true))
|
|
1118
|
+
.map((f) => join(dir, f));
|
|
1119
|
+
const mtimes = await runWithConcurrency(files, concurrency, async (file) => {
|
|
1120
|
+
try {
|
|
1121
|
+
const s = await stat(file);
|
|
1122
|
+
return s.mtimeMs;
|
|
1123
|
+
}
|
|
1124
|
+
catch {
|
|
1125
|
+
return 0;
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
return mtimes.filter((m) => m > sinceMs).length;
|
|
1129
|
+
}
|
|
1130
|
+
catch {
|
|
1131
|
+
return 0;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1090
1134
|
}
|
|
1091
1135
|
//# sourceMappingURL=session-manager.js.map
|
|
@@ -13,6 +13,7 @@ export const BUILTIN_SLASH_COMMANDS = [
|
|
|
13
13
|
name: "memory",
|
|
14
14
|
description: "Show project memory and knowledge (NanoMem)",
|
|
15
15
|
},
|
|
16
|
+
{ name: "dream", description: "Consolidate project memory (NanoMem)" },
|
|
16
17
|
{ name: "export", description: "Export session to HTML file" },
|
|
17
18
|
{ name: "share", description: "Share session as a secret GitHub gist" },
|
|
18
19
|
{ name: "copy", description: "Copy last agent message to clipboard" },
|