oh-pi 0.1.9 β†’ 0.1.11

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/index.js CHANGED
@@ -36,7 +36,7 @@ async function quickFlow(env) {
36
36
  providers,
37
37
  theme,
38
38
  keybindings: "default",
39
- extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer", "startup-banner"],
39
+ extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer"],
40
40
  skills: ["quick-setup", "debug-helper", "git-workflow"],
41
41
  prompts: ["review", "fix", "explain", "commit", "test"],
42
42
  agents: "general-developer",
@@ -5,7 +5,7 @@ const PRESETS = {
5
5
  labelKey: "preset.starter", hintKey: "preset.starterHint",
6
6
  config: {
7
7
  theme: "oh-p-dark", keybindings: "default", thinking: "medium",
8
- extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer", "startup-banner"],
8
+ extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer"],
9
9
  skills: ["quick-setup", "debug-helper"],
10
10
  prompts: ["review", "fix", "explain", "commit"],
11
11
  agents: "general-developer",
@@ -15,7 +15,7 @@ const PRESETS = {
15
15
  labelKey: "preset.pro", hintKey: "preset.proHint",
16
16
  config: {
17
17
  theme: "catppuccin-mocha", keybindings: "default", thinking: "high",
18
- extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer", "startup-banner"],
18
+ extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer"],
19
19
  skills: ["quick-setup", "debug-helper", "git-workflow"],
20
20
  prompts: ["review", "fix", "explain", "commit", "test", "refactor", "optimize", "document", "pr"],
21
21
  agents: "fullstack-developer",
@@ -25,7 +25,7 @@ const PRESETS = {
25
25
  labelKey: "preset.security", hintKey: "preset.securityHint",
26
26
  config: {
27
27
  theme: "cyberpunk", keybindings: "default", thinking: "high",
28
- extensions: ["safe-guard", "custom-footer", "startup-banner"],
28
+ extensions: ["safe-guard", "custom-footer"],
29
29
  skills: ["debug-helper"],
30
30
  prompts: ["review", "security", "fix", "explain"],
31
31
  agents: "security-researcher",
@@ -35,7 +35,7 @@ const PRESETS = {
35
35
  labelKey: "preset.dataai", hintKey: "preset.dataaiHint",
36
36
  config: {
37
37
  theme: "tokyo-night", keybindings: "default", thinking: "medium",
38
- extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer", "startup-banner"],
38
+ extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer"],
39
39
  skills: ["quick-setup", "debug-helper"],
40
40
  prompts: ["review", "fix", "explain", "optimize", "document", "test"],
41
41
  agents: "data-ai-engineer",
@@ -52,7 +52,7 @@ const PRESETS = {
52
52
  labelKey: "preset.full", hintKey: "preset.fullHint",
53
53
  config: {
54
54
  theme: "oh-p-dark", keybindings: "default", thinking: "high",
55
- extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer", "startup-banner", "ant-colony"],
55
+ extensions: ["safe-guard", "git-guard", "auto-session-name", "custom-footer", "ant-colony"],
56
56
  skills: ["quick-setup", "debug-helper", "git-workflow", "ant-colony"],
57
57
  prompts: ["review", "fix", "explain", "commit", "test", "refactor", "optimize", "security", "document", "pr"],
58
58
  agents: "colony-operator",
package/dist/types.js CHANGED
@@ -42,7 +42,6 @@ export const EXTENSIONS = [
42
42
  { name: "git-guard", label: "πŸ“¦ Git Guard β€” Auto stash checkpoint + dirty repo warning + notify", default: true },
43
43
  { name: "auto-session-name", label: "πŸ“ Auto Session Name β€” Name sessions from first message", default: true },
44
44
  { name: "custom-footer", label: "πŸ“Š Custom Footer β€” Enhanced status bar with tokens, cost, time, git, cwd", default: true },
45
- { name: "startup-banner", label: "⚑ Startup Banner β€” Clean compact startup info (replaces verbose output)", default: true },
46
45
  { name: "ant-colony", label: "🐜 Ant Colony β€” Autonomous multi-agent swarm with adaptive concurrency", default: false },
47
46
  ];
48
47
  export const KEYBINDING_SCHEMES = {
@@ -1,4 +1,4 @@
1
- import { writeFileSync, mkdirSync, readFileSync, copyFileSync, existsSync, readdirSync, statSync } from "node:fs";
1
+ import { writeFileSync, mkdirSync, readFileSync, copyFileSync, existsSync, readdirSync, statSync, rmSync } from "node:fs";
2
2
  import { join, dirname } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { homedir } from "node:os";
@@ -8,6 +8,12 @@ const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
8
8
  function ensureDir(dir) {
9
9
  mkdirSync(dir, { recursive: true });
10
10
  }
11
+ /** Remove and recreate a directory */
12
+ function cleanDir(dir) {
13
+ if (existsSync(dir))
14
+ rmSync(dir, { recursive: true });
15
+ ensureDir(dir);
16
+ }
11
17
  /** Recursively copy a directory */
12
18
  function copyDir(src, dest) {
13
19
  ensureDir(dest);
@@ -115,7 +121,7 @@ export function applyConfig(config) {
115
121
  catch { /* template not found, skip */ }
116
122
  // 6. Copy extensions (single file .ts or directory with index.ts)
117
123
  const extDir = join(agentDir, "extensions");
118
- ensureDir(extDir);
124
+ cleanDir(extDir);
119
125
  for (const ext of config.extensions) {
120
126
  const dirSrc = join(PKG_ROOT, "pi-package", "extensions", ext);
121
127
  const fileSrc = join(PKG_ROOT, "pi-package", "extensions", `${ext}.ts`);
@@ -131,7 +137,7 @@ export function applyConfig(config) {
131
137
  }
132
138
  // 7. Copy prompts
133
139
  const promptDir = join(agentDir, "prompts");
134
- ensureDir(promptDir);
140
+ cleanDir(promptDir);
135
141
  for (const p of config.prompts) {
136
142
  const src = join(PKG_ROOT, "pi-package", "prompts", `${p}.md`);
137
143
  try {
@@ -141,7 +147,7 @@ export function applyConfig(config) {
141
147
  }
142
148
  // 8. Copy skills
143
149
  const skillDir = join(agentDir, "skills");
144
- ensureDir(skillDir);
150
+ cleanDir(skillDir);
145
151
  for (const s of config.skills) {
146
152
  const srcDir = join(PKG_ROOT, "pi-package", "skills", s);
147
153
  const destDir = join(skillDir, s);
@@ -153,7 +159,7 @@ export function applyConfig(config) {
153
159
  }
154
160
  // 9. Copy themes (only custom ones)
155
161
  const themeDir = join(agentDir, "themes");
156
- ensureDir(themeDir);
162
+ cleanDir(themeDir);
157
163
  const themeSrc = join(PKG_ROOT, "pi-package", "themes", `${config.theme}.json`);
158
164
  try {
159
165
  copyFileSync(themeSrc, join(themeDir, `${config.theme}.json`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-pi",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "One-click setup for pi-coding-agent. Like oh-my-zsh for pi.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Custom Footer Extension β€” Enhanced status bar
3
3
  *
4
- * Displays: ↑input ↓output Rremaining $cost percent/contextWindow (auto) | ⏱ elapsed | πŸ“‚ cwd | 🌿 branch | model β€’ thinking
4
+ * Displays: in/out/remaining tokens, cost, context%, elapsed, cwd, git branch, model
5
5
  * Color-coded context usage: green <50%, yellow 50-75%, red >75%
6
6
  */
7
7
 
@@ -39,7 +39,6 @@ export default function (pi: ExtensionAPI) {
39
39
  dispose() { unsub(); clearInterval(timer); },
40
40
  invalidate() {},
41
41
  render(width: number): string[] {
42
- // --- Tokens & Cost ---
43
42
  let input = 0, output = 0, cost = 0;
44
43
  for (const e of ctx.sessionManager.getBranch()) {
45
44
  if (e.type === "message" && e.message.role === "assistant") {
@@ -50,47 +49,35 @@ export default function (pi: ExtensionAPI) {
50
49
  }
51
50
  }
52
51
 
53
- // --- Context usage ---
54
52
  const usage = ctx.getContextUsage();
55
- const tokens = usage?.tokens ?? 0;
56
53
  const ctxWindow = usage?.contextWindow ?? 0;
57
54
  const pct = usage?.percent ?? 0;
58
- const remaining = Math.max(0, ctxWindow - tokens);
55
+ const remaining = Math.max(0, ctxWindow - (usage?.tokens ?? 0));
59
56
 
60
- // Color by usage level
61
57
  const pctColor = pct > 75 ? "error" : pct > 50 ? "warning" : "success";
62
- const pctStr = `${pct.toFixed(1)}%/${fmt(ctxWindow)}`;
63
58
 
64
59
  const tokenStats = [
65
- theme.fg("accent", `↑${fmt(input)}`),
66
- theme.fg("dim", ` ↓${fmt(output)}`),
67
- theme.fg("muted", ` R${fmt(remaining)}`),
68
- theme.fg("warning", ` $${cost.toFixed(3)}`),
69
- " ",
70
- theme.fg(pctColor, pctStr),
71
- theme.fg("dim", " (auto)"),
72
- ].join("");
73
-
74
- // --- Elapsed ---
75
- const elapsed = theme.fg("dim", `⏱ ${formatElapsed(Date.now() - sessionStart)}`);
76
-
77
- // --- CWD (last 2 segments) ---
78
- const cwd = process.cwd();
79
- const parts = cwd.split("/");
80
- const short = parts.length > 2 ? parts.slice(-2).join("/") : cwd;
81
- const cwdStr = theme.fg("muted", `πŸ“‚ ${short}`);
82
-
83
- // --- Git branch ---
60
+ theme.fg("accent", `i${fmt(input)}`),
61
+ theme.fg("dim", `o${fmt(output)}`),
62
+ theme.fg("muted", `r${fmt(remaining)}`),
63
+ theme.fg("warning", `$${cost.toFixed(3)}`),
64
+ theme.fg(pctColor, `${pct.toFixed(0)}%`),
65
+ ].join(" ");
66
+
67
+ const elapsed = theme.fg("dim", formatElapsed(Date.now() - sessionStart));
68
+
69
+ const parts = process.cwd().split("/");
70
+ const short = parts.length > 2 ? parts.slice(-2).join("/") : process.cwd();
71
+ const cwdStr = theme.fg("muted", short);
72
+
84
73
  const branch = footerData.getGitBranch();
85
- const branchStr = branch ? theme.fg("accent", `🌿 ${branch}`) : "";
74
+ const branchStr = branch ? theme.fg("accent", branch) : "";
86
75
 
87
- // --- Right: model + thinking ---
88
76
  const thinking = pi.getThinkingLevel();
89
77
  const modelId = ctx.model?.id || "no-model";
90
- const right = theme.fg("dim", `${modelId} β€’ ${thinking}`);
78
+ const right = theme.fg("dim", `${modelId} ${thinking}`);
91
79
 
92
- // --- Layout ---
93
- const sep = theme.fg("dim", " β”‚ ");
80
+ const sep = theme.fg("dim", " | ");
94
81
  const leftParts = [tokenStats, elapsed, cwdStr];
95
82
  if (branchStr) leftParts.push(branchStr);
96
83
  const left = leftParts.join(sep);
@@ -99,10 +86,8 @@ export default function (pi: ExtensionAPI) {
99
86
  const rightW = visibleWidth(right);
100
87
  const gap = width - leftW - rightW;
101
88
  if (gap >= 2) {
102
- const pad = " ".repeat(gap);
103
- return [truncateToWidth(left + pad + right, width)];
89
+ return [truncateToWidth(left + " ".repeat(gap) + right, width)];
104
90
  }
105
- // Not enough space for right side β€” just show left truncated
106
91
  return [truncateToWidth(left, width)];
107
92
  },
108
93
  };
@@ -1,56 +0,0 @@
1
- /**
2
- * oh-pi Startup Banner Extension
3
- *
4
- * Replaces the built-in verbose header with a compact one-line info display.
5
- * Auto-restores the default header after 8 seconds.
6
- */
7
- import type { AssistantMessage } from "@mariozechner/pi-ai";
8
- import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
9
- import { truncateToWidth } from "@mariozechner/pi-tui";
10
-
11
- export default function (pi: ExtensionAPI) {
12
- pi.on("session_start", async (_event, ctx) => {
13
- if (!ctx.hasUI) return;
14
-
15
- const model = ctx.model;
16
- const thinking = pi.getThinkingLevel();
17
- const usage = ctx.getContextUsage();
18
- const cwd = process.cwd().replace(process.env.HOME ?? "", "~");
19
-
20
- // Sum cost from branch
21
- let totalCost = 0;
22
- for (const e of ctx.sessionManager.getBranch()) {
23
- if (e.type === "message" && e.message.role === "assistant") {
24
- totalCost += (e.message as AssistantMessage).usage.cost.total;
25
- }
26
- }
27
-
28
- // Git branch
29
- let git = "";
30
- try {
31
- const { stdout } = await pi.exec("git", ["rev-parse", "--abbrev-ref", "HEAD"], { timeout: 2000 });
32
- git = stdout.trim();
33
- } catch { /* not a git repo */ }
34
-
35
- const modelStr = model ? `${model.provider}/${model.id}` : "no model";
36
- const thinkStr = thinking !== "off" ? ` β€’ 🧠 ${thinking}` : "";
37
- const ctxStr = usage ? ` β€’ πŸ“Š ${Math.round(usage.percent)}%` : "";
38
- const gitStr = git ? ` β€’ 🌿 ${git}` : "";
39
- const costStr = totalCost > 0 ? ` β€’ $${totalCost.toFixed(3)}` : "";
40
-
41
- const session = ctx.sessionManager.getSessionFile?.() ?? "ephemeral";
42
- const sessionName = session.split("/").pop();
43
-
44
- const line = `⚑ ${modelStr}${thinkStr}${ctxStr}${costStr} β”‚ πŸ“‚ ${cwd}${gitStr} β”‚ πŸ“‹ ${sessionName}`;
45
-
46
- ctx.ui.setHeader((_tui, theme) => ({
47
- render(width: number): string[] {
48
- return ["", truncateToWidth(theme.fg("accent", line), width), ""];
49
- },
50
- invalidate() {},
51
- }));
52
-
53
- // Restore default header after 8 seconds
54
- setTimeout(() => ctx.ui.setHeader(undefined), 8000);
55
- });
56
- }