@pencil-agent/nano-pencil 1.11.8 → 1.11.10
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/builtin-extensions.js +11 -0
- package/dist/cli/args.d.ts +1 -0
- package/dist/cli/args.js +13 -8
- package/dist/core/extensions/loader.js +1 -0
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/footer-data-provider.d.ts +2 -1
- package/dist/core/footer-data-provider.js +7 -5
- package/dist/core/runtime/agent-session.d.ts +1 -0
- package/dist/core/runtime/agent-session.js +4 -1
- package/dist/core/runtime/sdk.js +2 -0
- package/dist/extensions/defaults/interview/index.js +25 -0
- package/dist/extensions/defaults/mcp/index.js +1 -0
- package/dist/extensions/defaults/team/index.d.ts +3 -0
- package/dist/extensions/defaults/team/index.js +985 -0
- package/dist/extensions/defaults/team/team-controller.d.ts +18 -0
- package/dist/extensions/defaults/team/team-controller.js +92 -0
- package/dist/extensions/defaults/team/team-parser.d.ts +16 -0
- package/dist/extensions/defaults/team/team-parser.js +45 -0
- package/dist/extensions/defaults/team/team-types.d.ts +55 -0
- package/dist/extensions/defaults/team/team-types.js +2 -0
- package/dist/main.js +12 -6
- package/dist/modes/interactive/components/footer.js +1 -1
- package/dist/modes/interactive/interactive-mode.js +6 -6
- package/dist/nanopencil-defaults.d.ts +5 -3
- package/dist/nanopencil-defaults.js +16 -15
- package/dist/packages/mem-core/config.d.ts +7 -0
- package/dist/packages/mem-core/config.js +10 -3
- package/dist/packages/mem-core/consolidation.js +48 -1
- package/dist/packages/mem-core/engine.d.ts +20 -1
- package/dist/packages/mem-core/engine.js +324 -55
- package/dist/packages/mem-core/eviction.js +7 -1
- package/dist/packages/mem-core/extension.js +191 -1
- package/dist/packages/mem-core/extraction.js +35 -1
- package/dist/packages/mem-core/i18n.d.ts +3 -0
- package/dist/packages/mem-core/i18n.js +8 -3
- package/dist/packages/mem-core/index.d.ts +2 -2
- package/dist/packages/mem-core/index.js +1 -1
- package/dist/packages/mem-core/linking.d.ts +11 -1
- package/dist/packages/mem-core/linking.js +151 -0
- package/dist/packages/mem-core/scoring.js +15 -1
- package/dist/packages/mem-core/types.d.ts +51 -2
- package/dist/packages/mem-core/update.js +82 -0
- package/package.json +2 -2
|
@@ -28,6 +28,7 @@ const BUNDLED_SECURITY_AUDIT_EXTENSION = join(__dirname, "extensions", "defaults
|
|
|
28
28
|
const BUNDLED_SOUL_EXTENSION = join(__dirname, "extensions", "defaults", "soul", "index.js");
|
|
29
29
|
const BUNDLED_INTERVIEW_EXTENSION = join(__dirname, "extensions", "defaults", "interview", "index.js");
|
|
30
30
|
const BUNDLED_LOOP_EXTENSION = join(__dirname, "extensions", "defaults", "loop", "index.js");
|
|
31
|
+
const BUNDLED_TEAM_EXTENSION = join(__dirname, "extensions", "defaults", "team", "index.js");
|
|
31
32
|
const BUNDLED_MCP_EXTENSION = join(__dirname, "extensions", "defaults", "mcp", "index.js");
|
|
32
33
|
const BUNDLED_EXPORT_HTML_EXTENSION = join(__dirname, "extensions", "optional", "export-html", "index.js");
|
|
33
34
|
/** 从当前模块位置向上查找包根(含 package.json 且 name 为 nano-pencil 相关) */
|
|
@@ -148,6 +149,16 @@ export function getBuiltinExtensionPaths() {
|
|
|
148
149
|
paths.push(loopTs);
|
|
149
150
|
}
|
|
150
151
|
// === MCP 扩展(MCP 工具协议适配) ===
|
|
152
|
+
// Built-in team extension
|
|
153
|
+
if (existsSync(BUNDLED_TEAM_EXTENSION)) {
|
|
154
|
+
paths.push(BUNDLED_TEAM_EXTENSION);
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const teamTs = join(__dirname, "extensions", "defaults", "team", "index.ts");
|
|
158
|
+
if (existsSync(teamTs))
|
|
159
|
+
paths.push(teamTs);
|
|
160
|
+
}
|
|
161
|
+
// Built-in MCP extension
|
|
151
162
|
if (existsSync(BUNDLED_MCP_EXTENSION)) {
|
|
152
163
|
paths.push(BUNDLED_MCP_EXTENSION);
|
|
153
164
|
}
|
package/dist/cli/args.d.ts
CHANGED
package/dist/cli/args.js
CHANGED
|
@@ -37,6 +37,9 @@ export function parseArgs(args, extensionFlags) {
|
|
|
37
37
|
else if (arg === "--provider" && i + 1 < args.length) {
|
|
38
38
|
result.provider = args[++i];
|
|
39
39
|
}
|
|
40
|
+
else if (arg === "--cwd" && i + 1 < args.length) {
|
|
41
|
+
result.cwd = args[++i];
|
|
42
|
+
}
|
|
40
43
|
else if (arg === "--model" && i + 1 < args.length) {
|
|
41
44
|
result.model = args[++i];
|
|
42
45
|
}
|
|
@@ -182,8 +185,9 @@ ${chalk.bold("Commands:")}
|
|
|
182
185
|
${APP_NAME} <command> --help Show help for install/remove/update/list
|
|
183
186
|
|
|
184
187
|
${chalk.bold("Options:")}
|
|
185
|
-
--provider <name> Provider name (default: google)
|
|
186
|
-
--
|
|
188
|
+
--provider <name> Provider name (default: google)
|
|
189
|
+
--cwd <dir> Working directory to use for project-local discovery
|
|
190
|
+
--model <pattern> Model pattern or ID (supports "provider/id" and optional ":<thinking>")
|
|
187
191
|
--api-key <key> API key (defaults to env vars)
|
|
188
192
|
--system-prompt <text> System prompt (default: coding assistant prompt)
|
|
189
193
|
--append-system-prompt <text> Append text or file contents to the system prompt
|
|
@@ -287,12 +291,13 @@ ${chalk.bold("Environment Variables:")}
|
|
|
287
291
|
MINIMAX_API_KEY - MiniMax API key
|
|
288
292
|
KIMI_API_KEY - Kimi For Coding API key
|
|
289
293
|
AWS_PROFILE - AWS profile for Amazon Bedrock
|
|
290
|
-
AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock
|
|
291
|
-
AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock
|
|
292
|
-
AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)
|
|
293
|
-
AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)
|
|
294
|
-
${
|
|
295
|
-
|
|
294
|
+
AWS_ACCESS_KEY_ID - AWS access key for Amazon Bedrock
|
|
295
|
+
AWS_SECRET_ACCESS_KEY - AWS secret key for Amazon Bedrock
|
|
296
|
+
AWS_BEARER_TOKEN_BEDROCK - Bedrock API key (bearer token)
|
|
297
|
+
AWS_REGION - AWS region for Amazon Bedrock (e.g., us-east-1)
|
|
298
|
+
${`${APP_NAME.toUpperCase()}_CWD`.padEnd(32)} - Working directory override for project-local discovery
|
|
299
|
+
${ENV_AGENT_DIR.padEnd(32)} - Session storage directory (default: ~/${CONFIG_DIR_NAME}/agent)
|
|
300
|
+
PI_PACKAGE_DIR - Override package directory (for Nix/Guix store paths)
|
|
296
301
|
PI_OFFLINE - Disable startup network operations when set to 1/true/yes
|
|
297
302
|
PI_TOOLS_DOWNLOAD_TIMEOUT_MS - Timeout in ms for downloading fd/ripgrep (default: 60000)
|
|
298
303
|
PI_SHARE_VIEWER_URL - Base URL for /share command (default: https://pi.dev/session/)
|
|
@@ -107,6 +107,7 @@ export function createExtensionRuntime() {
|
|
|
107
107
|
*/
|
|
108
108
|
function createExtensionAPI(extension, runtime, cwd, eventBus) {
|
|
109
109
|
const api = {
|
|
110
|
+
cwd,
|
|
110
111
|
// Registration methods - write to extension
|
|
111
112
|
on(event, handler) {
|
|
112
113
|
const list = extension.handlers.get(event) ?? [];
|
|
@@ -649,6 +649,8 @@ export type ExtensionHandler<E, R = undefined> = (event: E, ctx: ExtensionContex
|
|
|
649
649
|
* ExtensionAPI passed to extension factory functions.
|
|
650
650
|
*/
|
|
651
651
|
export interface ExtensionAPI {
|
|
652
|
+
/** Working directory resolved for this extension load */
|
|
653
|
+
cwd: string;
|
|
652
654
|
on(event: "resources_discover", handler: ExtensionHandler<ResourcesDiscoverEvent, ResourcesDiscoverResult>): void;
|
|
653
655
|
on(event: "session_start", handler: ExtensionHandler<SessionStartEvent>): void;
|
|
654
656
|
on(event: "session_before_switch", handler: ExtensionHandler<SessionBeforeSwitchEvent, SessionBeforeSwitchResult>): void;
|
|
@@ -8,7 +8,8 @@ export declare class FooterDataProvider {
|
|
|
8
8
|
private gitWatcher;
|
|
9
9
|
private branchChangeCallbacks;
|
|
10
10
|
private availableProviderCount;
|
|
11
|
-
|
|
11
|
+
private cwd;
|
|
12
|
+
constructor(cwd: string);
|
|
12
13
|
/** Current git branch, null if not in repo, "detached" if detached HEAD */
|
|
13
14
|
getGitBranch(): string | null;
|
|
14
15
|
/** Extension status texts set via ctx.ui.setStatus() */
|
|
@@ -4,8 +4,8 @@ import { dirname, join, resolve } from "path";
|
|
|
4
4
|
* Find the git HEAD path by walking up from cwd.
|
|
5
5
|
* Handles both regular git repos (.git is a directory) and worktrees (.git is a file).
|
|
6
6
|
*/
|
|
7
|
-
function findGitHeadPath() {
|
|
8
|
-
let dir =
|
|
7
|
+
function findGitHeadPath(cwd) {
|
|
8
|
+
let dir = cwd;
|
|
9
9
|
while (true) {
|
|
10
10
|
const gitPath = join(dir, ".git");
|
|
11
11
|
if (existsSync(gitPath)) {
|
|
@@ -46,7 +46,9 @@ export class FooterDataProvider {
|
|
|
46
46
|
gitWatcher = null;
|
|
47
47
|
branchChangeCallbacks = new Set();
|
|
48
48
|
availableProviderCount = 0;
|
|
49
|
-
|
|
49
|
+
cwd;
|
|
50
|
+
constructor(cwd) {
|
|
51
|
+
this.cwd = cwd;
|
|
50
52
|
this.setupGitWatcher();
|
|
51
53
|
}
|
|
52
54
|
/** Current git branch, null if not in repo, "detached" if detached HEAD */
|
|
@@ -54,7 +56,7 @@ export class FooterDataProvider {
|
|
|
54
56
|
if (this.cachedBranch !== undefined)
|
|
55
57
|
return this.cachedBranch;
|
|
56
58
|
try {
|
|
57
|
-
const gitHeadPath = findGitHeadPath();
|
|
59
|
+
const gitHeadPath = findGitHeadPath(this.cwd);
|
|
58
60
|
if (!gitHeadPath) {
|
|
59
61
|
this.cachedBranch = null;
|
|
60
62
|
return null;
|
|
@@ -110,7 +112,7 @@ export class FooterDataProvider {
|
|
|
110
112
|
this.gitWatcher.close();
|
|
111
113
|
this.gitWatcher = null;
|
|
112
114
|
}
|
|
113
|
-
const gitHeadPath = findGitHeadPath();
|
|
115
|
+
const gitHeadPath = findGitHeadPath(this.cwd);
|
|
114
116
|
if (!gitHeadPath)
|
|
115
117
|
return;
|
|
116
118
|
// Watch the directory containing HEAD, not HEAD itself.
|
|
@@ -210,6 +210,7 @@ export declare class AgentSession {
|
|
|
210
210
|
get compactionCoordinator(): CompactionCoordinator | undefined;
|
|
211
211
|
/** Model registry for API key resolution and model discovery */
|
|
212
212
|
get modelRegistry(): ModelRegistry;
|
|
213
|
+
get cwd(): string;
|
|
213
214
|
/** Emit an event to all listeners */
|
|
214
215
|
private _emit;
|
|
215
216
|
private _lastAssistantMessage;
|
|
@@ -216,6 +216,9 @@ export class AgentSession {
|
|
|
216
216
|
get modelRegistry() {
|
|
217
217
|
return this._modelRegistry;
|
|
218
218
|
}
|
|
219
|
+
get cwd() {
|
|
220
|
+
return this._cwd;
|
|
221
|
+
}
|
|
219
222
|
// =========================================================================
|
|
220
223
|
// Event Subscription
|
|
221
224
|
// =========================================================================
|
|
@@ -2048,7 +2051,7 @@ export class AgentSession {
|
|
|
2048
2051
|
const resolvedCommand = prefix ? `${prefix}\n${command}` : command;
|
|
2049
2052
|
try {
|
|
2050
2053
|
const result = options?.operations
|
|
2051
|
-
? await executeBashWithOperations(resolvedCommand,
|
|
2054
|
+
? await executeBashWithOperations(resolvedCommand, this._cwd, options.operations, {
|
|
2052
2055
|
onChunk,
|
|
2053
2056
|
signal: this._bashAbortController.signal,
|
|
2054
2057
|
})
|
package/dist/core/runtime/sdk.js
CHANGED
|
@@ -240,6 +240,7 @@ export async function createAgentSession(options = {}) {
|
|
|
240
240
|
if (options.enableMCP) {
|
|
241
241
|
try {
|
|
242
242
|
currentMcpManager = new MCPManager();
|
|
243
|
+
currentMcpManager.setWorkingDir(cwd);
|
|
243
244
|
await currentMcpManager.initialize();
|
|
244
245
|
initialMcpTools = [...currentMcpManager.getTools()];
|
|
245
246
|
time("mcp.initialize");
|
|
@@ -282,6 +283,7 @@ export async function createAgentSession(options = {}) {
|
|
|
282
283
|
// ignore
|
|
283
284
|
}
|
|
284
285
|
currentMcpManager = new MCPManager();
|
|
286
|
+
currentMcpManager.setWorkingDir(cwd);
|
|
285
287
|
await currentMcpManager.initialize();
|
|
286
288
|
time("mcp.initialize");
|
|
287
289
|
return currentMcpManager.getTools();
|
|
@@ -61,6 +61,15 @@ function truncateForPrompt(str, maxChars) {
|
|
|
61
61
|
return str;
|
|
62
62
|
return str.slice(0, maxChars);
|
|
63
63
|
}
|
|
64
|
+
const LOOP_PROMPT_PREFIX = "[LOOP:";
|
|
65
|
+
function isLoopManagedPrompt(prompt) {
|
|
66
|
+
const trimmed = prompt.trim();
|
|
67
|
+
if (!trimmed)
|
|
68
|
+
return false;
|
|
69
|
+
return (trimmed.startsWith(LOOP_PROMPT_PREFIX) ||
|
|
70
|
+
trimmed.includes("Autonomous loop goal:") ||
|
|
71
|
+
trimmed.includes("You are inside a managed loop."));
|
|
72
|
+
}
|
|
64
73
|
/**
|
|
65
74
|
* Check if interview should be triggered based on prompt content and context.
|
|
66
75
|
* Only triggers for:
|
|
@@ -121,6 +130,10 @@ function shouldRunInterview(prompt) {
|
|
|
121
130
|
if (process.env.PI_JUST_SWITCHED_PERSONA === "true") {
|
|
122
131
|
return false;
|
|
123
132
|
}
|
|
133
|
+
// Loop-generated follow-up turns should stay autonomous and never re-open interview.
|
|
134
|
+
if (isLoopManagedPrompt(prompt)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
124
137
|
// Avoid triggering interview for greetings/small-talk/memory questions.
|
|
125
138
|
if (isNonTaskPrompt(prompt))
|
|
126
139
|
return false;
|
|
@@ -335,6 +348,18 @@ export default async function interviewExtension(pi) {
|
|
|
335
348
|
// Start from provided answers (if any) then allow extra clarifications.
|
|
336
349
|
const referenceSystemPrompt = ctx.getSystemPrompt();
|
|
337
350
|
let answers = { ...answersFromModel };
|
|
351
|
+
if (isLoopManagedPrompt(query)) {
|
|
352
|
+
return {
|
|
353
|
+
content: [{ type: "text", text: query }],
|
|
354
|
+
details: {
|
|
355
|
+
original_intent: query,
|
|
356
|
+
refined_intent: query,
|
|
357
|
+
completion_score: 1,
|
|
358
|
+
answers,
|
|
359
|
+
missing_slots: [],
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
}
|
|
338
363
|
// UI mode guard: prevent the model from triggering interactive interview for non-task prompts.
|
|
339
364
|
if (ctx.hasUI && !isTaskLikePrompt(query)) {
|
|
340
365
|
return {
|
|
@@ -19,6 +19,7 @@ export default async function mcpExtension(pi) {
|
|
|
19
19
|
console.log("[mcp] Initializing MCP...");
|
|
20
20
|
try {
|
|
21
21
|
mcpManager = new MCPManager();
|
|
22
|
+
mcpManager.setWorkingDir(pi.cwd);
|
|
22
23
|
await mcpManager.initialize();
|
|
23
24
|
const mcpTools = mcpManager.getTools();
|
|
24
25
|
// Register MCP tools
|