pi-graphnav 0.2.2 → 0.3.0

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/README.md CHANGED
@@ -83,6 +83,7 @@ pi install npm:pi-graphnav
83
83
  | `/codegraph` or `/codegraph status` | project, index state, mode, blocked/nudged counts |
84
84
  | `/codegraph [on\|off]` | switch it all (remembered across sessions) |
85
85
  | `/codegraph mode <mode>` | symbol searches: `enforce` (default), `nudge` or `off` |
86
+ | `/codegraph statusline <when>` | status line: `always` (default), `problems` or `never`; CodeGraph keeps working |
86
87
  | `/codegraph sync` | sync the index with changed files |
87
88
  | `/codegraph reindex` | rebuild the index from scratch |
88
89
  | `/codegraph init` | create the index (for a directory that is not a git repo) |
@@ -92,7 +93,7 @@ Settings live in `<pi agent dir>/codegraph.json` (`PI_CODING_AGENT_DIR`, else `~
92
93
  | Key | Default | |
93
94
  |---|---|---|
94
95
  | `enabled` | `true` | master switch |
95
- | `showStatus` | `true` | status line entry |
96
+ | `showStatus` | `"always"` | status line entry: `"always"`, `"problems"` (only while indexing, or when the index is missing, failing or unavailable) or `"never"`; `true`/`false` still work |
96
97
  | `mode` | `"enforce"` | `enforce`, `nudge` or `off` |
97
98
  | `autoInit` | `true` | init a git repo that has no index |
98
99
  | `autoSync` | `true` | sync or rebuild a stale index at session start |
@@ -1,17 +1,18 @@
1
1
  /** `/codegraph ...`: parsing and argument completion. Pure: the handler in graphnav.ts acts on the result. */
2
- import { MODES, type Mode } from "../core/config.ts";
2
+ import { MODES, type Mode, STATUS_SHOWS, type StatusShow } from "../core/config.ts";
3
3
 
4
4
  export type Command =
5
5
  | { kind: "status" }
6
6
  | { kind: "on" }
7
7
  | { kind: "off" }
8
8
  | { kind: "mode"; mode: Mode }
9
+ | { kind: "statusline"; show: StatusShow }
9
10
  | { kind: "sync" }
10
11
  | { kind: "reindex" }
11
12
  | { kind: "init" }
12
13
  | { kind: "invalid"; message: string };
13
14
 
14
- export const USAGE = "Usage: /codegraph [status] · on · off · mode <enforce|nudge|off> · sync · reindex · init";
15
+ export const USAGE = "Usage: /codegraph [status] · on · off · mode <enforce|nudge|off> · statusline <always|problems|never> · sync · reindex · init";
15
16
 
16
17
  export function parseCommand(args: string | undefined): Command {
17
18
  const [cmd, ...rest] = (args ?? "").trim().split(/\s+/).filter(Boolean);
@@ -31,6 +32,12 @@ export function parseCommand(args: string | undefined): Command {
31
32
  ? { kind: "mode", mode: m as Mode }
32
33
  : { kind: "invalid", message: "Usage: /codegraph mode <enforce|nudge|off>" };
33
34
  }
35
+ case "statusline": {
36
+ const v = rest[0]?.toLowerCase();
37
+ return STATUS_SHOWS.includes(v as StatusShow) && rest.length === 1
38
+ ? { kind: "statusline", show: v as StatusShow }
39
+ : { kind: "invalid", message: "Usage: /codegraph statusline <always|problems|never>" };
40
+ }
34
41
  case "sync":
35
42
  return { kind: "sync" };
36
43
  case "reindex":
@@ -55,6 +62,7 @@ const TOP_LEVEL: CompletionItem[] = [
55
62
  { value: "on", label: "on", description: "Turn CodeGraph-first on" },
56
63
  { value: "off", label: "off", description: "Turn CodeGraph-first off" },
57
64
  { value: "mode ", label: "mode", description: "Symbol searches: enforce, nudge or off" },
65
+ { value: "statusline ", label: "statusline", description: "Status line: always, only problems, or never" },
58
66
  { value: "sync", label: "sync", description: "Sync the index with changed files" },
59
67
  { value: "reindex", label: "reindex", description: "Rebuild the index from scratch" },
60
68
  { value: "init", label: "init", description: "Create the index for this project" },
@@ -66,10 +74,16 @@ const MODE_ITEMS: CompletionItem[] = [
66
74
  { value: "mode off", label: "off", description: "Leave text searches alone" },
67
75
  ];
68
76
 
77
+ const STATUSLINE_ITEMS: CompletionItem[] = [
78
+ { value: "statusline always", label: "always", description: "Always show the CodeGraph status" },
79
+ { value: "statusline problems", label: "problems", description: "Only while indexing, or when the index is missing, failing or unavailable" },
80
+ { value: "statusline never", label: "never", description: "Never show it (CodeGraph keeps working)" },
81
+ ];
82
+
69
83
  /** `prefix` is the whole argument text typed so far (pi replaces it with `value`). */
70
84
  export function completions(prefix: string): CompletionItem[] | null {
71
85
  const text = (prefix ?? "").toLowerCase().replace(/^\s+/, "");
72
- const pool = text.startsWith("mode ") ? MODE_ITEMS : TOP_LEVEL;
86
+ const pool = text.startsWith("mode ") ? MODE_ITEMS : text.startsWith("statusline ") ? STATUSLINE_ITEMS : TOP_LEVEL;
73
87
  const out = pool.filter((i) => i.value.startsWith(text));
74
88
  return out.length > 0 ? out : null;
75
89
  }
@@ -11,11 +11,22 @@ import { join } from "node:path";
11
11
  export type Mode = "enforce" | "nudge" | "off";
12
12
  export const MODES: readonly Mode[] = ["enforce", "nudge", "off"];
13
13
 
14
+ /** Status line: always, only when something needs attention (indexing, missing, error, unavailable), or never. */
15
+ export type StatusShow = "always" | "problems" | "never";
16
+ export const STATUS_SHOWS: readonly StatusShow[] = ["always", "problems", "never"];
17
+
18
+ /** `showStatus` from a config file: one of STATUS_SHOWS, or the 0.2 booleans (true = always, false = never). */
19
+ export function parseStatusShow(v: unknown): StatusShow | undefined {
20
+ if (v === true) return "always";
21
+ if (v === false) return "never";
22
+ return STATUS_SHOWS.includes(v as StatusShow) ? (v as StatusShow) : undefined;
23
+ }
24
+
14
25
  export interface Config {
15
26
  /** Master switch: when false the extension adds no guidance, gates nothing and indexes nothing. */
16
27
  enabled: boolean;
17
- /** Show the status line entry. */
18
- showStatus: boolean;
28
+ /** When to show the status line entry. */
29
+ showStatus: StatusShow;
19
30
  /** Symbol searches with rg/grep: block once (`enforce`), only add a hint (`nudge`) or leave alone (`off`). */
20
31
  mode: Mode;
21
32
  /** Create the index (`codegraph init`) for a git repo that has none. */
@@ -32,7 +43,7 @@ export interface Config {
32
43
 
33
44
  export const DEFAULT_CONFIG: Config = {
34
45
  enabled: true,
35
- showStatus: true,
46
+ showStatus: "always",
36
47
  mode: "enforce",
37
48
  autoInit: true,
38
49
  autoSync: true,
@@ -49,7 +60,7 @@ export function sanitizeConfig(raw: unknown): Config {
49
60
  const d = DEFAULT_CONFIG;
50
61
  return {
51
62
  enabled: typeof r.enabled === "boolean" ? r.enabled : d.enabled,
52
- showStatus: typeof r.showStatus === "boolean" ? r.showStatus : d.showStatus,
63
+ showStatus: parseStatusShow(r.showStatus) ?? d.showStatus,
53
64
  mode: MODES.includes(r.mode as Mode) ? (r.mode as Mode) : d.mode,
54
65
  autoInit: typeof r.autoInit === "boolean" ? r.autoInit : d.autoInit,
55
66
  autoSync: typeof r.autoSync === "boolean" ? r.autoSync : d.autoSync,
@@ -14,7 +14,7 @@ import { homedir } from "node:os";
14
14
  import { resolve } from "node:path";
15
15
  import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
16
16
  import { completions, parseCommand } from "./command/parse.ts";
17
- import { type Config, DEFAULT_CONFIG, type ProjectOverrides, readConfig, readProjectConfig, saveConfig } from "./core/config.ts";
17
+ import { type Config, DEFAULT_CONFIG, type ProjectOverrides, readConfig, readProjectConfig, saveConfig, type StatusShow } from "./core/config.ts";
18
18
  import {
19
19
  codemodeSearches,
20
20
  candidateSymbols,
@@ -54,6 +54,13 @@ export interface Status {
54
54
  error?: string;
55
55
  }
56
56
 
57
+ /** Does the status line show for this setting? `problems`: only when the user may need to act or wait. */
58
+ export function showsStatus(show: StatusShow, s: Status): boolean {
59
+ if (show === "never") return false;
60
+ if (show === "always") return true;
61
+ return !!s.unavailable || s.state === "indexing" || s.state === "missing" || s.state === "error";
62
+ }
63
+
57
64
  export function statusText(s: Status): string {
58
65
  if (!s.config.enabled) return "codegraph: off";
59
66
  if (s.unavailable) return `codegraph: unavailable · ${s.config.mode}`;
@@ -170,7 +177,7 @@ export function createExtension(deps: Deps = {}) {
170
177
  const guardNow = new Map<string, Guard>();
171
178
  const unavailable = (root = project?.root) => (root ? (guardNow.get(root)?.open ?? false) : false);
172
179
  const snapshot = (): Status => ({ config, project, state, index, error: lastError, ...counts, unavailable: unavailable(), overrides });
173
- const refresh = () => ui?.setStatus("codegraph", config.enabled && config.showStatus ? statusText(snapshot()) : "");
180
+ const refresh = () => ui?.setStatus("codegraph", config.enabled && showsStatus(config.showStatus, snapshot()) ? statusText(snapshot()) : "");
174
181
 
175
182
  const server = (root: string) => {
176
183
  let s = servers.get(root);
@@ -421,6 +428,11 @@ export function createExtension(deps: Deps = {}) {
421
428
  await persist();
422
429
  ctx.ui.notify(`codegraph: mode ${cmd.mode}`, "info");
423
430
  return;
431
+ case "statusline":
432
+ config.showStatus = base.showStatus = cmd.show;
433
+ await persist();
434
+ ctx.ui.notify(`codegraph: status line ${cmd.show}`, "info");
435
+ return;
424
436
  case "sync":
425
437
  case "reindex":
426
438
  case "init": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-graphnav",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "CodeGraph-first code navigation for pi: persistent index, auto init/sync, and a gate that steers structural searches to codegraph_* tools.",
5
5
  "keywords": [
6
6
  "pi-package",