@pencil-agent/nano-pencil 1.3.0 โ 1.3.1
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/core/slash-commands.ts +5 -0
- package/modes/interactive/components/index.ts +1 -0
- package/modes/interactive/components/memory-stats.ts +139 -0
- package/modes/interactive/components/pencil-loader.ts +85 -0
- package/modes/interactive/components/soul-stats.ts +193 -0
- package/modes/interactive/interactive-mode.ts +94 -38
- package/modes/interactive/theme/warm.json +81 -81
- package/package.json +1 -1
package/core/slash-commands.ts
CHANGED
|
@@ -24,6 +24,11 @@ export const BUILTIN_SLASH_COMMANDS: ReadonlyArray<BuiltinSlashCommand> = [
|
|
|
24
24
|
},
|
|
25
25
|
{ name: "apikey", description: "Update API key for current provider" },
|
|
26
26
|
{ name: "mcp", description: "Manage MCP servers (list, enable, disable)" },
|
|
27
|
+
{ name: "soul", description: "Show AI personality and stats (Soul)" },
|
|
28
|
+
{
|
|
29
|
+
name: "memory",
|
|
30
|
+
description: "Show project memory and knowledge (NanoMem)",
|
|
31
|
+
},
|
|
27
32
|
{ name: "export", description: "Export session to HTML file" },
|
|
28
33
|
{ name: "share", description: "Share session as a secret GitHub gist" },
|
|
29
34
|
{ name: "copy", description: "Copy last agent message to clipboard" },
|
|
@@ -25,6 +25,7 @@ export {
|
|
|
25
25
|
export { LoginDialogComponent } from "./login-dialog.js";
|
|
26
26
|
export { ModelSelectorComponent } from "./model-selector.js";
|
|
27
27
|
export { OAuthSelectorComponent } from "./oauth-selector.js";
|
|
28
|
+
export { PencilLoader } from "./pencil-loader.js";
|
|
28
29
|
export { ProviderSelectorComponent } from "./provider-selector.js";
|
|
29
30
|
export {
|
|
30
31
|
type ModelsCallbacks,
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [INPUT]: NanoMem engine
|
|
3
|
+
* [OUTPUT]: Formatted display of memory stats
|
|
4
|
+
* [POS]: Interactive mode component for /memory command
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Use any type for NanoMemEngine since it's a local package
|
|
8
|
+
interface NanoMemEngine {
|
|
9
|
+
getStats(): {
|
|
10
|
+
knowledge: number;
|
|
11
|
+
lessons: number;
|
|
12
|
+
preferences: number;
|
|
13
|
+
facets: number;
|
|
14
|
+
work: number;
|
|
15
|
+
episodes: number;
|
|
16
|
+
totalSessions: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface DisplayOptions {
|
|
21
|
+
compact?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Format NanoMem stats for display
|
|
26
|
+
*/
|
|
27
|
+
export function formatMemoryStats(
|
|
28
|
+
memory: any,
|
|
29
|
+
options: DisplayOptions = {},
|
|
30
|
+
): string {
|
|
31
|
+
if (options.compact) {
|
|
32
|
+
return formatCompactMemory(memory);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return formatFullMemory(memory);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Format compact memory stats (single line)
|
|
40
|
+
*/
|
|
41
|
+
function formatCompactMemory(memory: NanoMemEngine): string {
|
|
42
|
+
const stats = memory.getStats();
|
|
43
|
+
|
|
44
|
+
const totalMemories =
|
|
45
|
+
stats.knowledge +
|
|
46
|
+
stats.lessons +
|
|
47
|
+
stats.preferences +
|
|
48
|
+
stats.facets +
|
|
49
|
+
stats.episodes;
|
|
50
|
+
|
|
51
|
+
return `๐ Memory: ${totalMemories} ้กน | Knowledge: ${stats.knowledge} | Lessons: ${stats.lessons} | Episodes: ${stats.episodes}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Format full memory stats (detailed view)
|
|
56
|
+
*/
|
|
57
|
+
function formatFullMemory(memory: NanoMemEngine): string {
|
|
58
|
+
const lines: string[] = [];
|
|
59
|
+
|
|
60
|
+
lines.push("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
61
|
+
lines.push("โ ๐ Project Memory - NanoMem โ");
|
|
62
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ");
|
|
63
|
+
lines.push("โ");
|
|
64
|
+
|
|
65
|
+
const stats = memory.getStats();
|
|
66
|
+
|
|
67
|
+
// Memory Types
|
|
68
|
+
const memoryTypes = [
|
|
69
|
+
{ type: "knowledge", name: "็ฅ่ฏ", emoji: "๐", count: stats.knowledge },
|
|
70
|
+
{ type: "lessons", name: "็ป้ชๆ่ฎญ", emoji: "๐ก", count: stats.lessons },
|
|
71
|
+
{
|
|
72
|
+
type: "preferences",
|
|
73
|
+
name: "็จๆทๅๅฅฝ",
|
|
74
|
+
emoji: "โค๏ธ",
|
|
75
|
+
count: stats.preferences,
|
|
76
|
+
},
|
|
77
|
+
{ type: "facets", name: "ๆจกๅผ/ๅฐๅข", emoji: "๐งฉ", count: stats.facets },
|
|
78
|
+
{ type: "work", name: "ๅทฅไฝๆ่ฆ", emoji: "๐", count: stats.work },
|
|
79
|
+
{ type: "episodes", name: "ไผ่ฏ่ฎฐๅฝ", emoji: "๐", count: stats.episodes },
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
lines.push("โ ๐ Memory Types");
|
|
83
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
84
|
+
|
|
85
|
+
for (const mem of memoryTypes) {
|
|
86
|
+
const bar = createBar(Math.min(mem.count / 100, 1), 15);
|
|
87
|
+
lines.push(
|
|
88
|
+
`โ ${mem.emoji} ${mem.name.padEnd(12)} ${bar} ${mem.count.toString().padStart(5)} ้กน`,
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
lines.push("โ");
|
|
93
|
+
lines.push("โ ๐ Recent Knowledge (Top 5)");
|
|
94
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
95
|
+
|
|
96
|
+
// Note: This would require loading actual entries
|
|
97
|
+
// For now, show stats only
|
|
98
|
+
lines.push(`โ (ๅ
ฑ ${stats.knowledge} ๆก้กน็ฎ็ฅ่ฏ)`);
|
|
99
|
+
lines.push(`โ ๆ่ฟๆดๆฐ: ${stats.totalSessions > 0 ? "ๆฌๆฌกไผ่ฏ" : "ๆ "}`);
|
|
100
|
+
|
|
101
|
+
lines.push("โ");
|
|
102
|
+
lines.push("โ ๐ก Lessons Learned");
|
|
103
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
104
|
+
lines.push(`โ (ๅ
ฑ ${stats.lessons} ๆก็ป้ชๆ่ฎญ)`);
|
|
105
|
+
lines.push(` โ ๏ธ ไป้่ฏฏไธญๅญฆไน ๏ผ้ฟๅ
้ๅค็ฏ้`);
|
|
106
|
+
|
|
107
|
+
lines.push("โ");
|
|
108
|
+
lines.push("โ ๐งฉ Patterns & Struggles");
|
|
109
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
110
|
+
lines.push(`โ ๆจกๅผ: ${stats.facets} ๆก`);
|
|
111
|
+
lines.push(` ๅฐๅข: ๅทฒ่ฏๅซ็่กไธบๆจกๅผ`);
|
|
112
|
+
|
|
113
|
+
lines.push("โ");
|
|
114
|
+
lines.push("โ ๐ Session History");
|
|
115
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
116
|
+
lines.push(`โ ไผ่ฏ่ฎฐๅฝ: ${stats.episodes} ๆก`);
|
|
117
|
+
lines.push(` ๆปไผ่ฏๆฐ: ${stats.totalSessions}`);
|
|
118
|
+
|
|
119
|
+
lines.push("โ");
|
|
120
|
+
lines.push("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
121
|
+
|
|
122
|
+
return lines.join("\n");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Create a visual bar for counts
|
|
127
|
+
*/
|
|
128
|
+
function createBar(filled: number, width: number): string {
|
|
129
|
+
const intFilled = Math.floor(filled);
|
|
130
|
+
const partial = Math.floor((filled - intFilled) * 8);
|
|
131
|
+
|
|
132
|
+
let bar = "โ".repeat(intFilled);
|
|
133
|
+
if (partial > 0) {
|
|
134
|
+
bar += "โ".repeat(1); // Partial fill
|
|
135
|
+
}
|
|
136
|
+
bar += "โ".repeat(width - intFilled - (partial > 0 ? 1 : 0));
|
|
137
|
+
|
|
138
|
+
return bar;
|
|
139
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PencilLoader - Custom loader with โ breathing animation
|
|
3
|
+
* Replaces the default spinner with a pencil icon that pulses
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { Container, Spacer, Text, type TUI } from "@mariozechner/pi-tui";
|
|
7
|
+
import type { Theme } from "../theme/theme.js";
|
|
8
|
+
|
|
9
|
+
export class PencilLoader extends Container {
|
|
10
|
+
private tui: TUI;
|
|
11
|
+
private theme: Theme;
|
|
12
|
+
private message: string;
|
|
13
|
+
private interval: NodeJS.Timeout | undefined;
|
|
14
|
+
private currentFrame = 0;
|
|
15
|
+
private textComponent: Text;
|
|
16
|
+
private messageComponent: Text;
|
|
17
|
+
private isStopped = false;
|
|
18
|
+
|
|
19
|
+
// Breathing animation frames - opacity levels for โ
|
|
20
|
+
private readonly frames = [
|
|
21
|
+
"โ", // very dim
|
|
22
|
+
"โ", // dim
|
|
23
|
+
"โ", // medium
|
|
24
|
+
"โ", // bright
|
|
25
|
+
"โ", // medium
|
|
26
|
+
"โ", // dim
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
constructor(tui: TUI, theme: Theme, message: string) {
|
|
30
|
+
super();
|
|
31
|
+
this.tui = tui;
|
|
32
|
+
this.theme = theme;
|
|
33
|
+
this.message = message;
|
|
34
|
+
|
|
35
|
+
this.textComponent = new Text("", 0, 0);
|
|
36
|
+
this.messageComponent = new Text("", 0, 0);
|
|
37
|
+
|
|
38
|
+
this.addChild(new Spacer(1));
|
|
39
|
+
this.addChild(this.textComponent);
|
|
40
|
+
this.addChild(this.messageComponent);
|
|
41
|
+
this.addChild(new Spacer(1));
|
|
42
|
+
|
|
43
|
+
this.startAnimation();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private startAnimation(): void {
|
|
47
|
+
const updateFrame = () => {
|
|
48
|
+
if (this.isStopped) return;
|
|
49
|
+
|
|
50
|
+
const frameChar = this.frames[this.currentFrame];
|
|
51
|
+
const pencil = this.theme.fg("accent", `โ${frameChar}`);
|
|
52
|
+
|
|
53
|
+
this.textComponent.setText(`${pencil} ${this.message}`);
|
|
54
|
+
this.tui.requestRender();
|
|
55
|
+
|
|
56
|
+
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// Initial render
|
|
60
|
+
updateFrame();
|
|
61
|
+
|
|
62
|
+
// Update every 200ms for smooth breathing effect
|
|
63
|
+
this.interval = setInterval(updateFrame, 200);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
setMessage(message: string): void {
|
|
67
|
+
this.message = message;
|
|
68
|
+
const frameChar = this.frames[this.currentFrame];
|
|
69
|
+
const pencil = this.theme.fg("accent", `โ${frameChar}`);
|
|
70
|
+
this.messageComponent.setText(`${pencil} ${this.message}`);
|
|
71
|
+
this.tui.requestRender();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
stop(): void {
|
|
75
|
+
this.isStopped = true;
|
|
76
|
+
if (this.interval) {
|
|
77
|
+
clearInterval(this.interval);
|
|
78
|
+
this.interval = undefined;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
dispose(): void {
|
|
83
|
+
this.stop();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* [INPUT]: Soul profile and memory manager
|
|
3
|
+
* [OUTPUT]: Formatted display of Soul stats and personality
|
|
4
|
+
* [POS]: Interactive mode component for /soul command
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { SoulManager } from "nanosoul";
|
|
8
|
+
|
|
9
|
+
interface DisplayOptions {
|
|
10
|
+
compact?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Format Soul stats for display
|
|
15
|
+
*/
|
|
16
|
+
export function formatSoulStats(
|
|
17
|
+
soul: SoulManager,
|
|
18
|
+
options: DisplayOptions = {},
|
|
19
|
+
): string {
|
|
20
|
+
const profile = soul.getProfile();
|
|
21
|
+
const stats = soul.getStats();
|
|
22
|
+
|
|
23
|
+
if (options.compact) {
|
|
24
|
+
return formatCompactSoul(profile, stats);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return formatFullSoul(profile, stats);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Format compact Soul stats (single line)
|
|
32
|
+
*/
|
|
33
|
+
function formatCompactSoul(profile: any, stats: any): string {
|
|
34
|
+
const personality = profile.personality;
|
|
35
|
+
const expertise = stats.expertise.slice(0, 3);
|
|
36
|
+
|
|
37
|
+
const topTraits = Object.entries(personality)
|
|
38
|
+
.filter(
|
|
39
|
+
([_, value]) => typeof value === "number" && (value > 0.6 || value < 0.4),
|
|
40
|
+
)
|
|
41
|
+
.map(([key, value]) => {
|
|
42
|
+
const label = getTraitLabel(key);
|
|
43
|
+
const numValue = typeof value === "number" ? value : 0.5;
|
|
44
|
+
const status = numValue > 0.6 ? "โ" : numValue < 0.4 ? "โ" : "โ";
|
|
45
|
+
return `${label}${status} ${(numValue * 100).toFixed(0)}%`;
|
|
46
|
+
})
|
|
47
|
+
.slice(0, 3)
|
|
48
|
+
.join(", ");
|
|
49
|
+
|
|
50
|
+
const topExpertise = expertise
|
|
51
|
+
.map((e: any) => `${e.domain}(${(e.confidence * 100).toFixed(0)}%)`)
|
|
52
|
+
.join(", ");
|
|
53
|
+
|
|
54
|
+
return `๐ง Soul: ${topTraits} | Expertise: ${topExpertise} | Interactions: ${stats.stats.totalInteractions}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Format full Soul stats (detailed view)
|
|
59
|
+
*/
|
|
60
|
+
function formatFullSoul(profile: any, stats: any): string {
|
|
61
|
+
const lines: string[] = [];
|
|
62
|
+
|
|
63
|
+
lines.push("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
64
|
+
lines.push("โ ๐ง AI Soul - Personality & Stats โ");
|
|
65
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ");
|
|
66
|
+
lines.push("โ");
|
|
67
|
+
|
|
68
|
+
// Personality Section
|
|
69
|
+
lines.push("โ ๐ Personality Traits");
|
|
70
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
71
|
+
|
|
72
|
+
const personality = profile.personality;
|
|
73
|
+
const traits = [
|
|
74
|
+
{ key: "openness", label: "ๅผๆพๆง", emoji: "๐จ" },
|
|
75
|
+
{ key: "conscientiousness", label: "ๅฐฝ่ดฃๆง", emoji: "๐" },
|
|
76
|
+
{ key: "codeVerbosity", label: "ไปฃ็ ๅ้ฟ", emoji: "๐" },
|
|
77
|
+
{ key: "abstractionLevel", label: "ๆฝ่ฑกๅฑ็บง", emoji: "๐๏ธ" },
|
|
78
|
+
{ key: "safetyMargin", label: "ๅฎๅ
จ่พน้
", emoji: "๐ก๏ธ" },
|
|
79
|
+
{ key: "explorationDrive", label: "ๆข็ดขๆฌฒๆ", emoji: "๐" },
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
for (const trait of traits) {
|
|
83
|
+
const value = personality[trait.key];
|
|
84
|
+
const bar = createBar(value, 10);
|
|
85
|
+
const percent = (value * 100).toFixed(0).padStart(3);
|
|
86
|
+
lines.push(`โ ${trait.emoji} ${trait.label.padEnd(12)} ${bar} ${percent}%`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
lines.push("โ");
|
|
90
|
+
lines.push("โ ๐ฏ Top Expertise Areas");
|
|
91
|
+
|
|
92
|
+
const expertise = stats.expertise.slice(0, 5);
|
|
93
|
+
if (expertise.length === 0) {
|
|
94
|
+
lines.push("โ (ๆๆ ไธ้ฟๆฐๆฎ๏ผ็ปง็ปญไฝฟ็จไปฅ็งฏ็ดฏ)");
|
|
95
|
+
} else {
|
|
96
|
+
for (const exp of expertise) {
|
|
97
|
+
const confidence = (exp.confidence * 100).toFixed(0).padStart(3);
|
|
98
|
+
const examples = exp.examples.toString().padStart(3);
|
|
99
|
+
lines.push(
|
|
100
|
+
`โ โข ${exp.domain.padEnd(20)} ไฟกๅฟ: ${confidence}% ๆๅ: ${examples} ๆฌก`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
lines.push("โ");
|
|
106
|
+
lines.push("โ ๐ญ Current Mood");
|
|
107
|
+
|
|
108
|
+
const emotional = profile.emotionalState;
|
|
109
|
+
const mood = [
|
|
110
|
+
{ label: "ไฟกๅฟ", value: emotional.confidence, emoji: "๐" },
|
|
111
|
+
{ label: "ๅฅฝๅฅๅฟ", value: emotional.curiosity, emoji: "๐ค" },
|
|
112
|
+
{ label: "ๆซ่ดฅๆ", value: emotional.frustration, emoji: "๐ค" },
|
|
113
|
+
{ label: "ๅฟๆต", value: emotional.flow, emoji: "โจ" },
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
for (const m of mood) {
|
|
117
|
+
const bar = createBar(m.value, 8);
|
|
118
|
+
const percent = (m.value * 100).toFixed(0).padStart(3);
|
|
119
|
+
lines.push(`โ ${m.emoji} ${m.label.padEnd(8)} ${bar} ${percent}%`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
lines.push("โ");
|
|
123
|
+
lines.push("โ ๐ Development Stats");
|
|
124
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
125
|
+
lines.push(`โ ๆปไบคไบๆฌกๆฐ: ${stats.stats.totalInteractions}`);
|
|
126
|
+
lines.push(`โ ๆๅ็: ${(stats.stats.successRate * 100).toFixed(1)}%`);
|
|
127
|
+
lines.push(`โ Soul ็ๆฌ: ${profile.version}`);
|
|
128
|
+
lines.push(
|
|
129
|
+
`โ Soul ๅนด้พ: ${Math.floor((Date.now() - profile.createdAt.getTime()) / (1000 * 60 * 60 * 24))} ๅคฉ`,
|
|
130
|
+
);
|
|
131
|
+
lines.push(`โ ๆๅ่ฟๅ: ${formatTimeAgo(profile.lastEvolved)}`);
|
|
132
|
+
|
|
133
|
+
lines.push("โ");
|
|
134
|
+
lines.push("โ ๐ง User Relationship");
|
|
135
|
+
lines.push("โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
136
|
+
const rel = profile.userRelationship;
|
|
137
|
+
lines.push(`โ ไบคไบๆฌกๆฐ: ${rel.interactionCount}`);
|
|
138
|
+
lines.push(`โ ๆปกๆๅบฆ: ${(rel.satisfactionScore * 100).toFixed(0)}%`);
|
|
139
|
+
lines.push(` ๆฒ้้ฃๆ ผ: ${rel.communicationStyle}`);
|
|
140
|
+
|
|
141
|
+
if (rel.knownPreferences.length > 0) {
|
|
142
|
+
lines.push(`โ ๅทฒ็ฅๅๅฅฝ: ${rel.knownPreferences.slice(0, 3).join(", ")}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
lines.push("โ");
|
|
146
|
+
lines.push("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
147
|
+
|
|
148
|
+
return lines.join("\n");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Create a visual bar for values
|
|
153
|
+
*/
|
|
154
|
+
function createBar(value: number, width: number): string {
|
|
155
|
+
const filled = Math.round(value * width);
|
|
156
|
+
const empty = width - filled;
|
|
157
|
+
return "โ".repeat(filled) + "โ".repeat(empty);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Get trait label in Chinese
|
|
162
|
+
*/
|
|
163
|
+
function getTraitLabel(key: string): string {
|
|
164
|
+
const labels: Record<string, string> = {
|
|
165
|
+
openness: "ๅผๆพๆง",
|
|
166
|
+
conscientiousness: "ๅฐฝ่ดฃๆง",
|
|
167
|
+
extraversion: "ๅคๅๆง",
|
|
168
|
+
agreeableness: "ๅฎไบบๆง",
|
|
169
|
+
neuroticism: "็ฅ็ป่ดจ",
|
|
170
|
+
codeVerbosity: "ไปฃ็ ๅ้ฟ",
|
|
171
|
+
abstractionLevel: "ๆฝ่ฑกๅฑ็บง",
|
|
172
|
+
safetyMargin: "ๅฎๅ
จ่พน้
",
|
|
173
|
+
explorationDrive: "ๆข็ดข",
|
|
174
|
+
};
|
|
175
|
+
return labels[key] || key;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Format time ago in Chinese
|
|
180
|
+
*/
|
|
181
|
+
function formatTimeAgo(date: Date): string {
|
|
182
|
+
const now = Date.now();
|
|
183
|
+
const diff = now - date.getTime();
|
|
184
|
+
|
|
185
|
+
const minutes = Math.floor(diff / (1000 * 60));
|
|
186
|
+
const hours = Math.floor(diff / (1000 * 60 * 60));
|
|
187
|
+
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
188
|
+
|
|
189
|
+
if (minutes < 1) return "ๅๅ";
|
|
190
|
+
if (minutes < 60) return `${minutes} ๅ้ๅ`;
|
|
191
|
+
if (hours < 24) return `${hours} ๅฐๆถๅ`;
|
|
192
|
+
return `${days} ๅคฉๅ`;
|
|
193
|
+
}
|
|
@@ -95,6 +95,7 @@ import { promptForApiKey } from "./components/apikey-input.js";
|
|
|
95
95
|
import { BashExecutionComponent } from "./components/bash-execution.js";
|
|
96
96
|
import { BorderedLoader } from "./components/bordered-loader.js";
|
|
97
97
|
import { BranchSummaryMessageComponent } from "./components/branch-summary-message.js";
|
|
98
|
+
import { PencilLoader } from "./components/pencil-loader.js";
|
|
98
99
|
import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.js";
|
|
99
100
|
import { CustomEditor } from "./components/custom-editor.js";
|
|
100
101
|
import { CustomMessageComponent } from "./components/custom-message.js";
|
|
@@ -193,7 +194,7 @@ export class InteractiveMode {
|
|
|
193
194
|
private version: string;
|
|
194
195
|
private isInitialized = false;
|
|
195
196
|
private onInputCallback?: (text: string) => void;
|
|
196
|
-
private loadingAnimation:
|
|
197
|
+
private loadingAnimation: Component | undefined = undefined;
|
|
197
198
|
private pendingWorkingMessage: string | undefined = undefined;
|
|
198
199
|
private readonly defaultWorkingMessage = "Working...";
|
|
199
200
|
|
|
@@ -233,11 +234,11 @@ export class InteractiveMode {
|
|
|
233
234
|
private pendingBashComponents: BashExecutionComponent[] = [];
|
|
234
235
|
|
|
235
236
|
// Auto-compaction state
|
|
236
|
-
private autoCompactionLoader:
|
|
237
|
+
private autoCompactionLoader: Component | undefined = undefined;
|
|
237
238
|
private autoCompactionEscapeHandler?: () => void;
|
|
238
239
|
|
|
239
240
|
// Auto-retry state
|
|
240
|
-
private retryLoader:
|
|
241
|
+
private retryLoader: Component | undefined = undefined;
|
|
241
242
|
private retryEscapeHandler?: () => void;
|
|
242
243
|
|
|
243
244
|
// Messages queued while compaction is running
|
|
@@ -1153,7 +1154,7 @@ export class InteractiveMode {
|
|
|
1153
1154
|
waitForIdle: () => this.session.agent.waitForIdle(),
|
|
1154
1155
|
newSession: async (options) => {
|
|
1155
1156
|
if (this.loadingAnimation) {
|
|
1156
|
-
this.loadingAnimation.stop();
|
|
1157
|
+
(this.loadingAnimation as PencilLoader).stop();
|
|
1157
1158
|
this.loadingAnimation = undefined;
|
|
1158
1159
|
}
|
|
1159
1160
|
this.statusContainer.clear();
|
|
@@ -1439,7 +1440,7 @@ export class InteractiveMode {
|
|
|
1439
1440
|
this.defaultEditor.onExtensionShortcut = undefined;
|
|
1440
1441
|
this.updateTerminalTitle();
|
|
1441
1442
|
if (this.loadingAnimation) {
|
|
1442
|
-
this.loadingAnimation.setMessage(
|
|
1443
|
+
(this.loadingAnimation as PencilLoader).setMessage(
|
|
1443
1444
|
`${this.defaultWorkingMessage} (${appKey(this.keybindings, "interrupt")} to interrupt)`,
|
|
1444
1445
|
);
|
|
1445
1446
|
}
|
|
@@ -1606,9 +1607,9 @@ export class InteractiveMode {
|
|
|
1606
1607
|
setWorkingMessage: (message) => {
|
|
1607
1608
|
if (this.loadingAnimation) {
|
|
1608
1609
|
if (message) {
|
|
1609
|
-
this.loadingAnimation.setMessage(message);
|
|
1610
|
+
(this.loadingAnimation as PencilLoader).setMessage(message);
|
|
1610
1611
|
} else {
|
|
1611
|
-
this.loadingAnimation.setMessage(
|
|
1612
|
+
(this.loadingAnimation as PencilLoader).setMessage(
|
|
1612
1613
|
`${this.defaultWorkingMessage} (${appKey(this.keybindings, "interrupt")} to interrupt)`,
|
|
1613
1614
|
);
|
|
1614
1615
|
}
|
|
@@ -2237,6 +2238,16 @@ export class InteractiveMode {
|
|
|
2237
2238
|
await this.handleReloadCommand();
|
|
2238
2239
|
return;
|
|
2239
2240
|
}
|
|
2241
|
+
if (text === "/soul") {
|
|
2242
|
+
this.handleSoulCommand();
|
|
2243
|
+
this.editor.setText("");
|
|
2244
|
+
return;
|
|
2245
|
+
}
|
|
2246
|
+
if (text === "/memory") {
|
|
2247
|
+
this.handleMemoryCommand();
|
|
2248
|
+
this.editor.setText("");
|
|
2249
|
+
return;
|
|
2250
|
+
}
|
|
2240
2251
|
if (text === "/debug") {
|
|
2241
2252
|
this.handleDebugCommand();
|
|
2242
2253
|
this.editor.setText("");
|
|
@@ -2349,24 +2360,25 @@ export class InteractiveMode {
|
|
|
2349
2360
|
this.retryEscapeHandler = undefined;
|
|
2350
2361
|
}
|
|
2351
2362
|
if (this.retryLoader) {
|
|
2352
|
-
this.retryLoader.stop();
|
|
2363
|
+
(this.retryLoader as PencilLoader).stop();
|
|
2353
2364
|
this.retryLoader = undefined;
|
|
2354
2365
|
}
|
|
2355
2366
|
if (this.loadingAnimation) {
|
|
2356
|
-
this.loadingAnimation.stop();
|
|
2367
|
+
(this.loadingAnimation as PencilLoader).stop();
|
|
2357
2368
|
}
|
|
2358
2369
|
this.statusContainer.clear();
|
|
2359
|
-
this.loadingAnimation = new
|
|
2370
|
+
this.loadingAnimation = new PencilLoader(
|
|
2360
2371
|
this.ui,
|
|
2361
|
-
|
|
2362
|
-
(text) => theme.fg("muted", text),
|
|
2372
|
+
theme,
|
|
2363
2373
|
this.defaultWorkingMessage,
|
|
2364
2374
|
);
|
|
2365
2375
|
this.statusContainer.addChild(this.loadingAnimation);
|
|
2366
2376
|
// Apply any pending working message queued before loader existed
|
|
2367
2377
|
if (this.pendingWorkingMessage !== undefined) {
|
|
2368
2378
|
if (this.pendingWorkingMessage) {
|
|
2369
|
-
this.loadingAnimation.setMessage(
|
|
2379
|
+
(this.loadingAnimation as PencilLoader).setMessage(
|
|
2380
|
+
this.pendingWorkingMessage,
|
|
2381
|
+
);
|
|
2370
2382
|
}
|
|
2371
2383
|
this.pendingWorkingMessage = undefined;
|
|
2372
2384
|
}
|
|
@@ -2512,7 +2524,7 @@ export class InteractiveMode {
|
|
|
2512
2524
|
|
|
2513
2525
|
case "agent_end":
|
|
2514
2526
|
if (this.loadingAnimation) {
|
|
2515
|
-
this.loadingAnimation.stop();
|
|
2527
|
+
(this.loadingAnimation as PencilLoader).stop();
|
|
2516
2528
|
this.loadingAnimation = undefined;
|
|
2517
2529
|
this.statusContainer.clear();
|
|
2518
2530
|
}
|
|
@@ -2539,10 +2551,9 @@ export class InteractiveMode {
|
|
|
2539
2551
|
this.statusContainer.clear();
|
|
2540
2552
|
const reasonText =
|
|
2541
2553
|
event.reason === "overflow" ? "Context overflow detected, " : "";
|
|
2542
|
-
this.autoCompactionLoader = new
|
|
2554
|
+
this.autoCompactionLoader = new PencilLoader(
|
|
2543
2555
|
this.ui,
|
|
2544
|
-
|
|
2545
|
-
(text) => theme.fg("muted", text),
|
|
2556
|
+
theme,
|
|
2546
2557
|
`${reasonText}Auto-compacting... (${appKey(this.keybindings, "interrupt")} to cancel)`,
|
|
2547
2558
|
);
|
|
2548
2559
|
this.statusContainer.addChild(this.autoCompactionLoader);
|
|
@@ -2558,7 +2569,7 @@ export class InteractiveMode {
|
|
|
2558
2569
|
}
|
|
2559
2570
|
// Stop loader
|
|
2560
2571
|
if (this.autoCompactionLoader) {
|
|
2561
|
-
this.autoCompactionLoader.stop();
|
|
2572
|
+
(this.autoCompactionLoader as PencilLoader).stop();
|
|
2562
2573
|
this.autoCompactionLoader = undefined;
|
|
2563
2574
|
this.statusContainer.clear();
|
|
2564
2575
|
}
|
|
@@ -2598,10 +2609,9 @@ export class InteractiveMode {
|
|
|
2598
2609
|
// Show retry indicator
|
|
2599
2610
|
this.statusContainer.clear();
|
|
2600
2611
|
const delaySeconds = Math.round(event.delayMs / 1000);
|
|
2601
|
-
this.retryLoader = new
|
|
2612
|
+
this.retryLoader = new PencilLoader(
|
|
2602
2613
|
this.ui,
|
|
2603
|
-
|
|
2604
|
-
(text) => theme.fg("muted", text),
|
|
2614
|
+
theme,
|
|
2605
2615
|
`Retrying (${event.attempt}/${event.maxAttempts}) in ${delaySeconds}s... (${appKey(this.keybindings, "interrupt")} to cancel)`,
|
|
2606
2616
|
);
|
|
2607
2617
|
this.statusContainer.addChild(this.retryLoader);
|
|
@@ -2617,7 +2627,7 @@ export class InteractiveMode {
|
|
|
2617
2627
|
}
|
|
2618
2628
|
// Stop loader
|
|
2619
2629
|
if (this.retryLoader) {
|
|
2620
|
-
this.retryLoader.stop();
|
|
2630
|
+
(this.retryLoader as PencilLoader).stop();
|
|
2621
2631
|
this.retryLoader = undefined;
|
|
2622
2632
|
this.statusContainer.clear();
|
|
2623
2633
|
}
|
|
@@ -4033,7 +4043,7 @@ export class InteractiveMode {
|
|
|
4033
4043
|
}
|
|
4034
4044
|
|
|
4035
4045
|
// Set up escape handler and loader if summarizing
|
|
4036
|
-
let summaryLoader:
|
|
4046
|
+
let summaryLoader: Component | undefined;
|
|
4037
4047
|
const originalOnEscape = this.defaultEditor.onEscape;
|
|
4038
4048
|
|
|
4039
4049
|
if (wantsSummary) {
|
|
@@ -4041,10 +4051,9 @@ export class InteractiveMode {
|
|
|
4041
4051
|
this.session.abortBranchSummary();
|
|
4042
4052
|
};
|
|
4043
4053
|
this.chatContainer.addChild(new Spacer(1));
|
|
4044
|
-
summaryLoader = new
|
|
4054
|
+
summaryLoader = new PencilLoader(
|
|
4045
4055
|
this.ui,
|
|
4046
|
-
|
|
4047
|
-
(text) => theme.fg("muted", text),
|
|
4056
|
+
theme,
|
|
4048
4057
|
`Summarizing branch... (${appKey(this.keybindings, "interrupt")} to cancel)`,
|
|
4049
4058
|
);
|
|
4050
4059
|
this.statusContainer.addChild(summaryLoader);
|
|
@@ -4081,7 +4090,7 @@ export class InteractiveMode {
|
|
|
4081
4090
|
);
|
|
4082
4091
|
} finally {
|
|
4083
4092
|
if (summaryLoader) {
|
|
4084
|
-
summaryLoader.stop();
|
|
4093
|
+
(summaryLoader as PencilLoader).stop();
|
|
4085
4094
|
this.statusContainer.clear();
|
|
4086
4095
|
}
|
|
4087
4096
|
this.defaultEditor.onEscape = originalOnEscape;
|
|
@@ -4146,7 +4155,7 @@ export class InteractiveMode {
|
|
|
4146
4155
|
private async handleResumeSession(sessionPath: string): Promise<void> {
|
|
4147
4156
|
// Stop loading animation
|
|
4148
4157
|
if (this.loadingAnimation) {
|
|
4149
|
-
this.loadingAnimation.stop();
|
|
4158
|
+
(this.loadingAnimation as PencilLoader).stop();
|
|
4150
4159
|
this.loadingAnimation = undefined;
|
|
4151
4160
|
}
|
|
4152
4161
|
this.statusContainer.clear();
|
|
@@ -4794,7 +4803,7 @@ export class InteractiveMode {
|
|
|
4794
4803
|
private async handleClearCommand(): Promise<void> {
|
|
4795
4804
|
// Stop loading animation
|
|
4796
4805
|
if (this.loadingAnimation) {
|
|
4797
|
-
this.loadingAnimation.stop();
|
|
4806
|
+
(this.loadingAnimation as PencilLoader).stop();
|
|
4798
4807
|
this.loadingAnimation = undefined;
|
|
4799
4808
|
}
|
|
4800
4809
|
this.statusContainer.clear();
|
|
@@ -5011,7 +5020,7 @@ export class InteractiveMode {
|
|
|
5011
5020
|
): Promise<CompactionResult | undefined> {
|
|
5012
5021
|
// Stop loading animation
|
|
5013
5022
|
if (this.loadingAnimation) {
|
|
5014
|
-
this.loadingAnimation.stop();
|
|
5023
|
+
(this.loadingAnimation as PencilLoader).stop();
|
|
5015
5024
|
this.loadingAnimation = undefined;
|
|
5016
5025
|
}
|
|
5017
5026
|
this.statusContainer.clear();
|
|
@@ -5028,12 +5037,7 @@ export class InteractiveMode {
|
|
|
5028
5037
|
const label = isAuto
|
|
5029
5038
|
? `Auto-compacting context... ${cancelHint}`
|
|
5030
5039
|
: `Compacting context... ${cancelHint}`;
|
|
5031
|
-
const compactingLoader = new
|
|
5032
|
-
this.ui,
|
|
5033
|
-
(spinner) => theme.fg("accent", spinner),
|
|
5034
|
-
(text) => theme.fg("muted", text),
|
|
5035
|
-
label,
|
|
5036
|
-
);
|
|
5040
|
+
const compactingLoader = new PencilLoader(this.ui, theme, label);
|
|
5037
5041
|
this.statusContainer.addChild(compactingLoader);
|
|
5038
5042
|
this.ui.requestRender();
|
|
5039
5043
|
|
|
@@ -5065,7 +5069,7 @@ export class InteractiveMode {
|
|
|
5065
5069
|
this.showError(`Compaction failed: ${message}`);
|
|
5066
5070
|
}
|
|
5067
5071
|
} finally {
|
|
5068
|
-
compactingLoader.stop();
|
|
5072
|
+
(compactingLoader as PencilLoader).stop();
|
|
5069
5073
|
this.statusContainer.clear();
|
|
5070
5074
|
this.defaultEditor.onEscape = originalOnEscape;
|
|
5071
5075
|
}
|
|
@@ -5075,7 +5079,7 @@ export class InteractiveMode {
|
|
|
5075
5079
|
|
|
5076
5080
|
stop(): void {
|
|
5077
5081
|
if (this.loadingAnimation) {
|
|
5078
|
-
this.loadingAnimation.stop();
|
|
5082
|
+
(this.loadingAnimation as PencilLoader).stop();
|
|
5079
5083
|
this.loadingAnimation = undefined;
|
|
5080
5084
|
}
|
|
5081
5085
|
this.clearExtensionTerminalInputListeners();
|
|
@@ -5089,4 +5093,56 @@ export class InteractiveMode {
|
|
|
5089
5093
|
this.isInitialized = false;
|
|
5090
5094
|
}
|
|
5091
5095
|
}
|
|
5096
|
+
|
|
5097
|
+
private handleSoulCommand(): void {
|
|
5098
|
+
const soulManager = (this.session as any)._soulManager;
|
|
5099
|
+
if (!soulManager) {
|
|
5100
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
5101
|
+
this.chatContainer.addChild(
|
|
5102
|
+
new Text(theme.fg("warning", "โ ๏ธ Soul ๆชๅฏ็จ"), 1, 0),
|
|
5103
|
+
);
|
|
5104
|
+
this.chatContainer.addChild(
|
|
5105
|
+
new Text(
|
|
5106
|
+
theme.fg(
|
|
5107
|
+
"dim",
|
|
5108
|
+
"Soul (AI ๆงๆ ผ็ณป็ป) ๆชๅฏ็จใ่ฏท็กฎไฟไฝฟ็จ NanoPencil 1.3.0 ๆๆด้ซ็ๆฌใ",
|
|
5109
|
+
),
|
|
5110
|
+
1,
|
|
5111
|
+
0,
|
|
5112
|
+
),
|
|
5113
|
+
);
|
|
5114
|
+
this.ui.requestRender();
|
|
5115
|
+
return;
|
|
5116
|
+
}
|
|
5117
|
+
|
|
5118
|
+
const { formatSoulStats } = require("./components/soul-stats.js");
|
|
5119
|
+
const stats = formatSoulStats(soulManager, { compact: false });
|
|
5120
|
+
|
|
5121
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
5122
|
+
this.chatContainer.addChild(new Text(stats, 1, 0));
|
|
5123
|
+
this.ui.requestRender();
|
|
5124
|
+
}
|
|
5125
|
+
|
|
5126
|
+
private handleMemoryCommand(): void {
|
|
5127
|
+
const lines: string[] = [];
|
|
5128
|
+
lines.push(theme.fg("accent", "๐ Project Memory - NanoMem"));
|
|
5129
|
+
lines.push("");
|
|
5130
|
+
lines.push(theme.fg("dim", "ๅญๅจไฝ็ฝฎ: ~/.nanopencil/agent/memory/"));
|
|
5131
|
+
lines.push(theme.fg("dim", " - knowledge.json (้กน็ฎ็ฅ่ฏ)"));
|
|
5132
|
+
lines.push(theme.fg("dim", " - lessons.json (็ป้ชๆ่ฎญ)"));
|
|
5133
|
+
lines.push(theme.fg("dim", " - preferences.json (็จๆทๅๅฅฝ)"));
|
|
5134
|
+
lines.push(theme.fg("dim", " - patterns.json (่กไธบๆจกๅผ)"));
|
|
5135
|
+
lines.push(theme.fg("dim", " - facets.json (ๆจกๅผ/ๅฐๅข)"));
|
|
5136
|
+
lines.push("");
|
|
5137
|
+
lines.push(
|
|
5138
|
+
theme.fg("dim", "๐ก ๆ็คบ: NanoMem ่ชๅจไปๅฏน่ฏไธญๆๅๅ่ฎฐๅฟ้กน็ฎ็ฅ่ฏ"),
|
|
5139
|
+
);
|
|
5140
|
+
lines.push(theme.fg("dim", " - ่ฎฐไฝ API ็ซฏ็นใ้
็ฝฎ้้กน"));
|
|
5141
|
+
lines.push(theme.fg("dim", " - ๅญฆไน ้่ฏฏๆจกๅผๅ่งฃๅณๆนๆก"));
|
|
5142
|
+
lines.push(theme.fg("dim", " - ่ฏๅซ็จๆทๅๅฅฝๅ็ผ็ ้ฃๆ ผ"));
|
|
5143
|
+
|
|
5144
|
+
this.chatContainer.addChild(new Spacer(1));
|
|
5145
|
+
this.chatContainer.addChild(new Text(lines.join("\n"), 1, 0));
|
|
5146
|
+
this.ui.requestRender();
|
|
5147
|
+
}
|
|
5092
5148
|
}
|
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3
|
+
"name": "warm",
|
|
4
|
+
"vars": {
|
|
5
|
+
"warmBrown": "#c4a574",
|
|
6
|
+
"warmLight": "#d4a574",
|
|
7
|
+
"warmBorder": "#a08060",
|
|
8
|
+
"blue": "#5f87ff",
|
|
9
|
+
"green": "#b5bd68",
|
|
10
|
+
"red": "#cc6666",
|
|
11
|
+
"yellow": "#d4a84b",
|
|
12
|
+
"gray": "#808080",
|
|
13
|
+
"dimGray": "#666666",
|
|
14
|
+
"darkGray": "#505050",
|
|
15
|
+
"accent": "warmBrown",
|
|
16
|
+
"selectedBg": "#3d362a",
|
|
17
|
+
"userMsgBg": "#2e2a24",
|
|
18
|
+
"toolPendingBg": "#2a2820",
|
|
19
|
+
"toolSuccessBg": "#2a3024",
|
|
20
|
+
"toolErrorBg": "#3c2828",
|
|
21
|
+
"customMsgBg": "#2d2838"
|
|
22
|
+
},
|
|
23
|
+
"colors": {
|
|
24
|
+
"accent": "accent",
|
|
25
|
+
"border": "warmBorder",
|
|
26
|
+
"borderAccent": "warmLight",
|
|
27
|
+
"borderMuted": "darkGray",
|
|
28
|
+
"success": "green",
|
|
29
|
+
"error": "red",
|
|
30
|
+
"warning": "yellow",
|
|
31
|
+
"muted": "gray",
|
|
32
|
+
"dim": "dimGray",
|
|
33
|
+
"text": "",
|
|
34
|
+
"thinkingText": "gray",
|
|
35
|
+
"selectedBg": "selectedBg",
|
|
36
|
+
"userMessageBg": "userMsgBg",
|
|
37
|
+
"userMessageText": "warmLight",
|
|
38
|
+
"customMessageBg": "customMsgBg",
|
|
39
|
+
"customMessageText": "",
|
|
40
|
+
"customMessageLabel": "#b8956b",
|
|
41
|
+
"toolPendingBg": "toolPendingBg",
|
|
42
|
+
"toolSuccessBg": "toolSuccessBg",
|
|
43
|
+
"toolErrorBg": "toolErrorBg",
|
|
44
|
+
"toolTitle": "",
|
|
45
|
+
"toolOutput": "gray",
|
|
46
|
+
"mdHeading": "warmLight",
|
|
47
|
+
"mdLink": "#81a2be",
|
|
48
|
+
"mdLinkUrl": "dimGray",
|
|
49
|
+
"mdCode": "accent",
|
|
50
|
+
"mdCodeBlock": "green",
|
|
51
|
+
"mdCodeBlockBorder": "gray",
|
|
52
|
+
"mdQuote": "gray",
|
|
53
|
+
"mdQuoteBorder": "gray",
|
|
54
|
+
"mdHr": "gray",
|
|
55
|
+
"mdListBullet": "accent",
|
|
56
|
+
"toolDiffAdded": "green",
|
|
57
|
+
"toolDiffRemoved": "red",
|
|
58
|
+
"toolDiffContext": "gray",
|
|
59
|
+
"syntaxComment": "#6A9955",
|
|
60
|
+
"syntaxKeyword": "#569CD6",
|
|
61
|
+
"syntaxFunction": "#DCDCAA",
|
|
62
|
+
"syntaxVariable": "#9CDCFE",
|
|
63
|
+
"syntaxString": "#CE9178",
|
|
64
|
+
"syntaxNumber": "#B5CEA8",
|
|
65
|
+
"syntaxType": "#4EC9B0",
|
|
66
|
+
"syntaxOperator": "#D4D4D4",
|
|
67
|
+
"syntaxPunctuation": "#D4D4D4",
|
|
68
|
+
"thinkingOff": "darkGray",
|
|
69
|
+
"thinkingMinimal": "#6e6e6e",
|
|
70
|
+
"thinkingLow": "#5f87af",
|
|
71
|
+
"thinkingMedium": "warmBrown",
|
|
72
|
+
"thinkingHigh": "#b294bb",
|
|
73
|
+
"thinkingXhigh": "#d183e8",
|
|
74
|
+
"bashMode": "green"
|
|
75
|
+
},
|
|
76
|
+
"export": {
|
|
77
|
+
"pageBg": "#1a1814",
|
|
78
|
+
"cardBg": "#242018",
|
|
79
|
+
"infoBg": "#3c3728"
|
|
80
|
+
}
|
|
81
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pencil-agent/nano-pencil",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "CLI writing agent with read, bash, edit, write tools and session management. Based on pi; supports DashScope Coding Plan. Soul enabled by default for AI personality evolution.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|