@pencil-agent/nano-pencil 1.11.15 → 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.d.ts +5 -0
- package/dist/core/runtime/agent-session.js +8 -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/extensions/defaults/loop/index.js +27 -22
- package/dist/extensions/defaults/team/index.js +68 -6
- package/dist/modes/acp/acp-mode.js +64 -1
- 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).
|
|
@@ -222,6 +222,11 @@ export declare class AgentSession {
|
|
|
222
222
|
* Includes built-in commands, extension commands, prompt templates, and skills.
|
|
223
223
|
*/
|
|
224
224
|
getSlashCommands(): SessionSlashCommandDescriptor[];
|
|
225
|
+
/**
|
|
226
|
+
* Try to execute an extension slash command directly.
|
|
227
|
+
* Returns true when a matching extension command was found, even if it failed internally.
|
|
228
|
+
*/
|
|
229
|
+
tryExecuteExtensionCommand(text: string): Promise<boolean>;
|
|
225
230
|
/** Emit an event to all listeners */
|
|
226
231
|
private _emit;
|
|
227
232
|
private _lastAssistantMessage;
|
|
@@ -257,6 +257,13 @@ export class AgentSession {
|
|
|
257
257
|
...skillCommands,
|
|
258
258
|
];
|
|
259
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* Try to execute an extension slash command directly.
|
|
262
|
+
* Returns true when a matching extension command was found, even if it failed internally.
|
|
263
|
+
*/
|
|
264
|
+
async tryExecuteExtensionCommand(text) {
|
|
265
|
+
return this._tryExecuteExtensionCommand(text);
|
|
266
|
+
}
|
|
260
267
|
// =========================================================================
|
|
261
268
|
// Event Subscription
|
|
262
269
|
// =========================================================================
|
|
@@ -1808,6 +1815,7 @@ export class AgentSession {
|
|
|
1808
1815
|
return undefined;
|
|
1809
1816
|
}
|
|
1810
1817
|
},
|
|
1818
|
+
getSettings: () => this.settingsManager.getSettings(),
|
|
1811
1819
|
isIdle: () => !this.isStreaming,
|
|
1812
1820
|
abort: () => this.abort(),
|
|
1813
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" },
|