@phren/cli 0.0.56 → 0.0.58
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/capabilities/cli.d.ts +2 -0
- package/dist/capabilities/index.d.ts +7 -0
- package/dist/capabilities/mcp.d.ts +2 -0
- package/dist/capabilities/types.d.ts +12 -0
- package/dist/capabilities/vscode.d.ts +2 -0
- package/dist/capabilities/web-ui.d.ts +2 -0
- package/dist/cli/actions.d.ts +16 -0
- package/dist/cli/cli.d.ts +3 -0
- package/dist/cli/config.d.ts +24 -0
- package/dist/cli/extract.d.ts +22 -0
- package/dist/cli/govern.d.ts +11 -0
- package/dist/cli/graph.d.ts +15 -0
- package/dist/cli/hooks-citations.d.ts +8 -0
- package/dist/cli/hooks-context.d.ts +34 -0
- package/dist/cli/hooks-globs.d.ts +2 -0
- package/dist/cli/hooks-output.d.ts +2 -0
- package/dist/cli/hooks-session.d.ts +38 -0
- package/dist/cli/hooks.d.ts +12 -0
- package/dist/cli/namespaces.d.ts +11 -0
- package/dist/cli/ops.d.ts +5 -0
- package/dist/cli/search.d.ts +38 -0
- package/dist/cli/team.d.ts +1 -0
- package/dist/cli-hooks-git.d.ts +35 -0
- package/dist/cli-hooks-prompt.d.ts +18 -0
- package/dist/cli-hooks-session-handlers.d.ts +3 -0
- package/dist/cli-hooks-stop.d.ts +11 -0
- package/dist/content/archive.d.ts +13 -0
- package/dist/content/citation.d.ts +50 -0
- package/dist/content/dedup.d.ts +55 -0
- package/dist/content/learning.d.ts +29 -0
- package/dist/content/metadata.d.ts +107 -0
- package/dist/content/validate.d.ts +70 -0
- package/dist/core/finding.d.ts +25 -0
- package/dist/core/project.d.ts +16 -0
- package/dist/core/search.d.ts +13 -0
- package/dist/data/access.d.ts +83 -0
- package/dist/data/tasks.d.ts +89 -0
- package/dist/embedding.d.ts +54 -0
- package/dist/entrypoint.d.ts +1 -0
- package/dist/finding/context.d.ts +8 -0
- package/dist/finding/impact.d.ts +11 -0
- package/dist/finding/journal.d.ts +40 -0
- package/dist/finding/lifecycle.d.ts +40 -0
- package/dist/governance/audit.d.ts +1 -0
- package/dist/governance/locks.d.ts +3 -0
- package/dist/governance/policy.d.ts +109 -0
- package/dist/governance/rbac.d.ts +25 -0
- package/dist/governance/scores.d.ts +12 -0
- package/dist/hooks.d.ts +59 -0
- package/dist/index-query.d.ts +33 -0
- package/dist/index.d.ts +2 -0
- package/dist/init/config.d.ts +43 -0
- package/dist/init/init-configure.d.ts +21 -0
- package/dist/init/init-hooks-mode.d.ts +1 -0
- package/dist/init/init-mcp-mode.d.ts +1 -0
- package/dist/init/init-uninstall.d.ts +3 -0
- package/dist/init/init-walkthrough.d.ts +61 -0
- package/dist/init/init.d.ts +84 -0
- package/dist/init/preferences.d.ts +28 -0
- package/dist/init/setup.d.ts +86 -0
- package/dist/init/shared.d.ts +13 -0
- package/dist/init-bootstrap.d.ts +5 -0
- package/dist/init-detect.d.ts +8 -0
- package/dist/init-env.d.ts +6 -0
- package/dist/init-fresh.d.ts +10 -0
- package/dist/init-hooks.d.ts +5 -0
- package/dist/init-mcp.d.ts +8 -0
- package/dist/init-modes.d.ts +4 -0
- package/dist/init-npm.d.ts +10 -0
- package/dist/init-project-local.d.ts +2 -0
- package/dist/init-semantic.d.ts +4 -0
- package/dist/init-types.d.ts +59 -0
- package/dist/init-uninstall.d.ts +3 -0
- package/dist/init-update.d.ts +10 -0
- package/dist/init-walkthrough.d.ts +55 -0
- package/dist/link/checksums.d.ts +8 -0
- package/dist/link/context.d.ts +7 -0
- package/dist/link/doctor.d.ts +2 -0
- package/dist/link/link.d.ts +29 -0
- package/dist/link/skills.d.ts +47 -0
- package/dist/logger.d.ts +9 -0
- package/dist/machine-identity.d.ts +4 -0
- package/dist/package-metadata.d.ts +4 -0
- package/dist/phren-art.d.ts +26 -0
- package/dist/phren-core.d.ts +64 -0
- package/dist/phren-dotenv.d.ts +2 -0
- package/dist/phren-paths.d.ts +60 -0
- package/dist/proactivity.d.ts +13 -0
- package/dist/profile-store.d.ts +34 -0
- package/dist/project-config.d.ts +60 -0
- package/dist/project-locator.d.ts +1 -0
- package/dist/project-topics.d.ts +122 -0
- package/dist/provider-adapters.d.ts +34 -0
- package/dist/query-correlation.d.ts +31 -0
- package/dist/runtime-profile.d.ts +6 -0
- package/dist/session/checkpoints.d.ts +25 -0
- package/dist/session/utils.d.ts +43 -0
- package/dist/shared/content.d.ts +7 -0
- package/dist/shared/data-utils.d.ts +8 -0
- package/dist/shared/embedding-cache.d.ts +30 -0
- package/dist/shared/fragment-graph.d.ts +60 -0
- package/dist/shared/governance.d.ts +4 -0
- package/dist/shared/index.d.ts +29 -0
- package/dist/shared/ollama.d.ts +28 -0
- package/dist/shared/process.d.ts +17 -0
- package/dist/shared/retrieval.d.ts +84 -0
- package/dist/shared/search-fallback.d.ts +23 -0
- package/dist/shared/sqljs.d.ts +5 -0
- package/dist/shared/stemmer.d.ts +5 -0
- package/dist/shared/vector-index.d.ts +18 -0
- package/dist/shared.d.ts +9 -0
- package/dist/shell/entry.d.ts +26 -0
- package/dist/shell/input.d.ts +57 -0
- package/dist/shell/palette.d.ts +13 -0
- package/dist/shell/render-api.d.ts +29 -0
- package/dist/shell/render-api.js +101 -0
- package/dist/shell/render.d.ts +50 -0
- package/dist/shell/shell.d.ts +61 -0
- package/dist/shell/state-store.d.ts +14 -0
- package/dist/shell/types.d.ts +29 -0
- package/dist/shell/view-list.d.ts +5 -0
- package/dist/shell/view.d.ts +34 -0
- package/dist/skill/files.d.ts +5 -0
- package/dist/skill/registry.d.ts +55 -0
- package/dist/skill/state.d.ts +3 -0
- package/dist/startup-embedding.d.ts +15 -0
- package/dist/status.d.ts +1 -0
- package/dist/store-registry.d.ts +60 -0
- package/dist/store-routing.d.ts +37 -0
- package/dist/task/github.d.ts +22 -0
- package/dist/task/hygiene.d.ts +13 -0
- package/dist/task/lifecycle.d.ts +26 -0
- package/dist/telemetry.d.ts +10 -0
- package/dist/test-global-setup.d.ts +14 -0
- package/dist/tool-registry.d.ts +14 -0
- package/dist/tools/config.d.ts +3 -0
- package/dist/tools/data.d.ts +3 -0
- package/dist/tools/extract-facts.d.ts +17 -0
- package/dist/tools/extract.d.ts +3 -0
- package/dist/tools/finding.d.ts +3 -0
- package/dist/tools/graph.d.ts +3 -0
- package/dist/tools/hooks.d.ts +3 -0
- package/dist/tools/memory.d.ts +3 -0
- package/dist/tools/ops.d.ts +3 -0
- package/dist/tools/search.d.ts +8 -0
- package/dist/tools/session.d.ts +44 -0
- package/dist/tools/skills.d.ts +3 -0
- package/dist/tools/tasks.d.ts +3 -0
- package/dist/tools/types.d.ts +50 -0
- package/dist/ui/assets.d.ts +2 -0
- package/dist/ui/data.d.ts +113 -0
- package/dist/ui/graph.d.ts +1 -0
- package/dist/ui/memory-ui.d.ts +4 -0
- package/dist/ui/page.d.ts +2 -0
- package/dist/ui/scripts.d.ts +17 -0
- package/dist/ui/server.d.ts +17 -0
- package/dist/ui/styles.d.ts +4 -0
- package/dist/update.d.ts +9 -0
- package/dist/utils-fts.d.ts +12 -0
- package/dist/utils-fts.js +450 -0
- package/dist/utils-helpers.d.ts +12 -0
- package/dist/utils-helpers.js +80 -0
- package/dist/utils-paths.d.ts +3 -0
- package/dist/utils-paths.js +61 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +8 -587
- package/package.json +45 -10
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command palette and input handling for the phren interactive shell.
|
|
3
|
+
* Extracted from shell.ts to keep the orchestrator under 300 lines.
|
|
4
|
+
*/
|
|
5
|
+
import { ShellState } from "../data/access.js";
|
|
6
|
+
import { type DoctorResultLike, type ShellDeps, type ShellView } from "./types.js";
|
|
7
|
+
/** Interface for the shell methods that executePalette needs */
|
|
8
|
+
interface PaletteHost {
|
|
9
|
+
phrenPath: string;
|
|
10
|
+
profile: string;
|
|
11
|
+
state: ShellState;
|
|
12
|
+
deps: ShellDeps;
|
|
13
|
+
showHelp: boolean;
|
|
14
|
+
healthCache: {
|
|
15
|
+
at: number;
|
|
16
|
+
result: DoctorResultLike;
|
|
17
|
+
} | undefined;
|
|
18
|
+
setMessage(msg: string): void;
|
|
19
|
+
setView(view: ShellState["view"]): void;
|
|
20
|
+
confirmThen(label: string, action: () => void): void;
|
|
21
|
+
snapshotForUndo(label: string, file: string): void;
|
|
22
|
+
ensureProjectSelected(): string | null;
|
|
23
|
+
invalidateSubsectionsCache(): void;
|
|
24
|
+
popUndo(): string;
|
|
25
|
+
}
|
|
26
|
+
/** Extended host interface for navigation and view-action methods */
|
|
27
|
+
export interface NavigationHost extends PaletteHost {
|
|
28
|
+
currentCursor(): number;
|
|
29
|
+
setCursor(n: number): void;
|
|
30
|
+
moveCursor(delta: number): void;
|
|
31
|
+
getListItems(): {
|
|
32
|
+
id?: string;
|
|
33
|
+
name?: string;
|
|
34
|
+
text?: string;
|
|
35
|
+
line?: string;
|
|
36
|
+
}[];
|
|
37
|
+
startInput(ctx: string, initial: string): void;
|
|
38
|
+
inputMqId: string;
|
|
39
|
+
prevHealthView: ShellView | undefined;
|
|
40
|
+
filter: string | undefined;
|
|
41
|
+
setFilter(value: string): void;
|
|
42
|
+
}
|
|
43
|
+
export declare function executePalette(host: PaletteHost, input: string): Promise<void>;
|
|
44
|
+
export declare function completeInput(line: string, phrenPath: string, profile: string, state: ShellState): string[];
|
|
45
|
+
export declare function getListItems(phrenPath: string, profile: string, state: ShellState, healthLineCount: number): {
|
|
46
|
+
id?: string;
|
|
47
|
+
name?: string;
|
|
48
|
+
text?: string;
|
|
49
|
+
line?: string;
|
|
50
|
+
}[];
|
|
51
|
+
/**
|
|
52
|
+
* Handle p/b/l/m/s/k/h shortcut keys that switch the active view.
|
|
53
|
+
* Returns true if the key was handled.
|
|
54
|
+
*/
|
|
55
|
+
export declare function applyViewShortcut(host: NavigationHost, key: string): boolean;
|
|
56
|
+
export declare function handleNavigateKey(host: NavigationHost, key: string): Promise<boolean>;
|
|
57
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TaskItem, QueueItem } from "../data/access.js";
|
|
2
|
+
import { type PhrenResult } from "../shared.js";
|
|
3
|
+
export declare function resultMsg(r: PhrenResult<unknown>): string;
|
|
4
|
+
export declare function editDistance(a: string, b: string): number;
|
|
5
|
+
export declare function tokenize(input: string): string[];
|
|
6
|
+
export declare function tasksByFilter(items: TaskItem[], filter: string): TaskItem[];
|
|
7
|
+
export declare function queueByFilter(items: QueueItem[], filter: string): QueueItem[];
|
|
8
|
+
export declare function expandIds(input: string): string[];
|
|
9
|
+
export declare function normalizeSection(sectionRaw: string): "Active" | "Queue" | "Done" | null;
|
|
10
|
+
export declare function resolveEntryScript(): string;
|
|
11
|
+
export declare function defaultRunHooks(phrenPath: string): Promise<string>;
|
|
12
|
+
export declare function defaultRunUpdate(): Promise<string>;
|
|
13
|
+
export declare function defaultRunRelink(phrenPath: string): Promise<string>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read-only rendering API for the shell views, consumable by external packages
|
|
3
|
+
* (e.g. @phren/agent) via the "@phren/cli/shell/render-api" subpath export.
|
|
4
|
+
*
|
|
5
|
+
* Exposes renderMenuFrame (render a full shell view frame) and handleMenuKey
|
|
6
|
+
* (pure navigation logic) without pulling in mutation or MCP dependencies.
|
|
7
|
+
*/
|
|
8
|
+
import type { ShellState } from "./state-store.js";
|
|
9
|
+
export type MenuView = ShellState["view"];
|
|
10
|
+
export interface MenuState {
|
|
11
|
+
view: MenuView;
|
|
12
|
+
project?: string;
|
|
13
|
+
filter?: string;
|
|
14
|
+
cursor: number;
|
|
15
|
+
scroll: number;
|
|
16
|
+
}
|
|
17
|
+
export interface MenuRenderResult {
|
|
18
|
+
/** Full ANSI-rendered frame (multi-line string, no trailing newline) */
|
|
19
|
+
output: string;
|
|
20
|
+
/** Number of list items in the current view (for cursor clamping) */
|
|
21
|
+
listCount: number;
|
|
22
|
+
}
|
|
23
|
+
/** Render a full shell frame for the given state. Read-only, no mutations. */
|
|
24
|
+
export declare function renderMenuFrame(phrenPath: string, profile: string, state: MenuState): Promise<MenuRenderResult>;
|
|
25
|
+
/**
|
|
26
|
+
* Apply a key to the menu state. Returns a new state, or null to signal
|
|
27
|
+
* "exit menu mode" (Tab or Escape at top level).
|
|
28
|
+
*/
|
|
29
|
+
export declare function handleMenuKey(state: MenuState, keyName: string, listCount: number, phrenPath?: string, profile?: string): MenuState | null;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { listProjectCards } from "../data/access.js";
|
|
2
|
+
import { renderShell } from "./view.js";
|
|
3
|
+
import { getListItems } from "./input.js";
|
|
4
|
+
// ── View cycling order (same as the shell tab bar) ──────────────────────────
|
|
5
|
+
const VIEW_ORDER = [
|
|
6
|
+
"Projects", "Tasks", "Findings", "Review Queue", "Skills", "Hooks",
|
|
7
|
+
];
|
|
8
|
+
// ── Render ──────────────────────────────────────────────────────────────────
|
|
9
|
+
/** Render a full shell frame for the given state. Read-only, no mutations. */
|
|
10
|
+
export async function renderMenuFrame(phrenPath, profile, state) {
|
|
11
|
+
const shellState = {
|
|
12
|
+
version: 3,
|
|
13
|
+
view: state.view,
|
|
14
|
+
project: state.project,
|
|
15
|
+
filter: state.filter,
|
|
16
|
+
};
|
|
17
|
+
const ctx = {
|
|
18
|
+
phrenPath,
|
|
19
|
+
profile,
|
|
20
|
+
state: shellState,
|
|
21
|
+
currentCursor: () => state.cursor,
|
|
22
|
+
currentScroll: () => state.scroll,
|
|
23
|
+
setScroll: () => { },
|
|
24
|
+
};
|
|
25
|
+
const stubDoctor = async () => ({
|
|
26
|
+
ok: true,
|
|
27
|
+
checks: [],
|
|
28
|
+
});
|
|
29
|
+
const output = await renderShell(ctx, "navigate", // always navigate mode (no input mode in agent menu)
|
|
30
|
+
"", // no inputCtx
|
|
31
|
+
"", // no inputBuf
|
|
32
|
+
false, // no help
|
|
33
|
+
"Tab: Chat ←→: Views ↑↓: Navigate Enter: Select /: Filter Esc: Back", stubDoctor, null, // subsectionsCache
|
|
34
|
+
() => { }, // setHealthLineCount
|
|
35
|
+
() => { });
|
|
36
|
+
const listCount = getListItems(phrenPath, profile, shellState, 0).length;
|
|
37
|
+
return { output, listCount };
|
|
38
|
+
}
|
|
39
|
+
// ── Navigation (pure function) ──────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Apply a key to the menu state. Returns a new state, or null to signal
|
|
42
|
+
* "exit menu mode" (Tab or Escape at top level).
|
|
43
|
+
*/
|
|
44
|
+
export function handleMenuKey(state, keyName, listCount, phrenPath, profile) {
|
|
45
|
+
switch (keyName) {
|
|
46
|
+
// Exit menu
|
|
47
|
+
case "tab":
|
|
48
|
+
case "q":
|
|
49
|
+
return null;
|
|
50
|
+
// View cycling
|
|
51
|
+
case "left": {
|
|
52
|
+
const idx = VIEW_ORDER.indexOf(state.view);
|
|
53
|
+
const next = idx <= 0 ? VIEW_ORDER[VIEW_ORDER.length - 1] : VIEW_ORDER[idx - 1];
|
|
54
|
+
return { ...state, view: next, cursor: 0, scroll: 0, filter: undefined };
|
|
55
|
+
}
|
|
56
|
+
case "right": {
|
|
57
|
+
const idx = VIEW_ORDER.indexOf(state.view);
|
|
58
|
+
const next = idx >= VIEW_ORDER.length - 1 ? VIEW_ORDER[0] : VIEW_ORDER[idx + 1];
|
|
59
|
+
return { ...state, view: next, cursor: 0, scroll: 0, filter: undefined };
|
|
60
|
+
}
|
|
61
|
+
// Cursor movement
|
|
62
|
+
case "up":
|
|
63
|
+
return { ...state, cursor: Math.max(0, state.cursor - 1) };
|
|
64
|
+
case "down":
|
|
65
|
+
return { ...state, cursor: Math.min(Math.max(0, listCount - 1), state.cursor + 1) };
|
|
66
|
+
// Enter: drill into project (Projects view only)
|
|
67
|
+
case "return": {
|
|
68
|
+
if (state.view === "Projects" && phrenPath && profile) {
|
|
69
|
+
const cards = listProjectCards(phrenPath, profile);
|
|
70
|
+
const filtered = state.filter
|
|
71
|
+
? cards.filter((c) => `${c.name} ${c.summary} ${c.docs.join(" ")}`.toLowerCase().includes(state.filter.toLowerCase()))
|
|
72
|
+
: cards;
|
|
73
|
+
const selected = filtered[state.cursor];
|
|
74
|
+
if (selected) {
|
|
75
|
+
return { ...state, view: "Tasks", project: selected.name, cursor: 0, scroll: 0 };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Escape from sub-view back to Projects
|
|
79
|
+
if (state.view !== "Projects" && state.project) {
|
|
80
|
+
return state; // no-op for non-projects views on enter
|
|
81
|
+
}
|
|
82
|
+
return state;
|
|
83
|
+
}
|
|
84
|
+
// Escape: clear filter, or go back to projects, or exit
|
|
85
|
+
case "escape": {
|
|
86
|
+
if (state.filter)
|
|
87
|
+
return { ...state, filter: undefined, cursor: 0, scroll: 0 };
|
|
88
|
+
if (state.view !== "Projects" && state.project) {
|
|
89
|
+
return { ...state, view: "Projects", project: undefined, cursor: 0, scroll: 0 };
|
|
90
|
+
}
|
|
91
|
+
return null; // exit menu
|
|
92
|
+
}
|
|
93
|
+
// Health shortcut
|
|
94
|
+
case "h":
|
|
95
|
+
if (state.view === "Health")
|
|
96
|
+
return { ...state, view: "Projects", cursor: 0, scroll: 0 };
|
|
97
|
+
return { ...state, view: "Health", cursor: 0, scroll: 0 };
|
|
98
|
+
default:
|
|
99
|
+
return state;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export declare const RESET = "\u001B[0m";
|
|
2
|
+
export declare const BOLD = "\u001B[1m";
|
|
3
|
+
export declare const DIM = "\u001B[2m";
|
|
4
|
+
export declare const GREEN = "\u001B[32m";
|
|
5
|
+
export declare const YELLOW = "\u001B[33m";
|
|
6
|
+
export declare const RED = "\u001B[31m";
|
|
7
|
+
export declare const CYAN = "\u001B[36m";
|
|
8
|
+
export declare const style: {
|
|
9
|
+
bold: (s: string) => string;
|
|
10
|
+
dim: (s: string) => string;
|
|
11
|
+
italic: (s: string) => string;
|
|
12
|
+
cyan: (s: string) => string;
|
|
13
|
+
green: (s: string) => string;
|
|
14
|
+
yellow: (s: string) => string;
|
|
15
|
+
red: (s: string) => string;
|
|
16
|
+
magenta: (s: string) => string;
|
|
17
|
+
blue: (s: string) => string;
|
|
18
|
+
white: (s: string) => string;
|
|
19
|
+
gray: (s: string) => string;
|
|
20
|
+
boldCyan: (s: string) => string;
|
|
21
|
+
boldGreen: (s: string) => string;
|
|
22
|
+
boldYellow: (s: string) => string;
|
|
23
|
+
boldRed: (s: string) => string;
|
|
24
|
+
boldMagenta: (s: string) => string;
|
|
25
|
+
boldBlue: (s: string) => string;
|
|
26
|
+
dimItalic: (s: string) => string;
|
|
27
|
+
invert: (s: string) => string;
|
|
28
|
+
};
|
|
29
|
+
export declare function badge(label: string, colorFn: (s: string) => string): string;
|
|
30
|
+
export declare function separator(width?: number): string;
|
|
31
|
+
export declare function stripAnsi(s: string): string;
|
|
32
|
+
export declare function padToWidth(s: string, width: number): string;
|
|
33
|
+
export declare function truncateLine(s: string, cols: number): string;
|
|
34
|
+
export declare function renderWidth(columns?: number): number;
|
|
35
|
+
interface WrapSegmentsOptions {
|
|
36
|
+
indent?: string;
|
|
37
|
+
maxLines?: number;
|
|
38
|
+
separator?: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function wrapSegments(segments: string[], cols: number, opts?: WrapSegmentsOptions): string;
|
|
41
|
+
export declare function gradient(text: string, colors?: string[]): string;
|
|
42
|
+
export declare function lineViewport(allLines: string[], cursorFirstLine: number, cursorLastLine: number, height: number, prevStart: number): {
|
|
43
|
+
lines: string[];
|
|
44
|
+
scrollStart: number;
|
|
45
|
+
};
|
|
46
|
+
export declare function shellHelpText(): string;
|
|
47
|
+
export declare function clearScreen(): void;
|
|
48
|
+
export declare function clearToEnd(): void;
|
|
49
|
+
export declare function shellStartupFrames(version: string): string[];
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ShellView, type ShellDeps, type DoctorResultLike } from "./types.js";
|
|
2
|
+
export type { ShellView, ShellDeps } from "./types.js";
|
|
3
|
+
export declare class PhrenShell {
|
|
4
|
+
readonly phrenPath: string;
|
|
5
|
+
readonly profile: string;
|
|
6
|
+
readonly deps: ShellDeps;
|
|
7
|
+
private state;
|
|
8
|
+
private message;
|
|
9
|
+
healthCache?: {
|
|
10
|
+
at: number;
|
|
11
|
+
result: DoctorResultLike;
|
|
12
|
+
};
|
|
13
|
+
prevHealthView: ShellView | undefined;
|
|
14
|
+
showHelp: boolean;
|
|
15
|
+
private pendingConfirm?;
|
|
16
|
+
private undoStack;
|
|
17
|
+
private navMode;
|
|
18
|
+
private inputBuf;
|
|
19
|
+
private inputCtx;
|
|
20
|
+
inputMqId: string;
|
|
21
|
+
private cursorMap;
|
|
22
|
+
private viewScrollMap;
|
|
23
|
+
private healthLineCount;
|
|
24
|
+
private _subsectionsCache;
|
|
25
|
+
get mode(): "navigate" | "input";
|
|
26
|
+
get inputBuffer(): string;
|
|
27
|
+
get filter(): string | undefined;
|
|
28
|
+
constructor(phrenPath: string, profile: string, deps?: ShellDeps);
|
|
29
|
+
close(): void;
|
|
30
|
+
setMessage(msg: string): void;
|
|
31
|
+
confirmThen(label: string, action: () => void): void;
|
|
32
|
+
setView(view: ShellView): void;
|
|
33
|
+
setFilter(value: string): void;
|
|
34
|
+
snapshotForUndo(label: string, file: string): void;
|
|
35
|
+
popUndo(): string;
|
|
36
|
+
ensureProjectSelected(): string | null;
|
|
37
|
+
invalidateSubsectionsCache(): void;
|
|
38
|
+
currentCursor(): number;
|
|
39
|
+
setCursor(n: number): void;
|
|
40
|
+
moveCursor(delta: number): void;
|
|
41
|
+
private currentScroll;
|
|
42
|
+
private setScroll;
|
|
43
|
+
getListItems(): {
|
|
44
|
+
id?: string;
|
|
45
|
+
name?: string;
|
|
46
|
+
text?: string;
|
|
47
|
+
line?: string;
|
|
48
|
+
}[];
|
|
49
|
+
startInput(ctx: string, initial: string): void;
|
|
50
|
+
private cancelInput;
|
|
51
|
+
private submitInput;
|
|
52
|
+
handleRawKey(key: string): Promise<boolean>;
|
|
53
|
+
private handleInputKey;
|
|
54
|
+
private doctorSnapshot;
|
|
55
|
+
render(): Promise<string>;
|
|
56
|
+
private asNavigationHost;
|
|
57
|
+
private runPalette;
|
|
58
|
+
handleInput(raw: string): Promise<boolean>;
|
|
59
|
+
completeInput(line: string): string[];
|
|
60
|
+
}
|
|
61
|
+
export { startShell } from "./entry.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type PhrenResult } from "../shared.js";
|
|
2
|
+
export interface ShellState {
|
|
3
|
+
version: number;
|
|
4
|
+
view: "Projects" | "Tasks" | "Findings" | "Review Queue" | "Skills" | "Hooks" | "Machines/Profiles" | "Health";
|
|
5
|
+
project?: string;
|
|
6
|
+
filter?: string;
|
|
7
|
+
page?: number;
|
|
8
|
+
perPage?: number;
|
|
9
|
+
introMode?: "always" | "once-per-version" | "off";
|
|
10
|
+
introSeenVersion?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function loadShellState(phrenPath: string): ShellState;
|
|
13
|
+
export declare function saveShellState(phrenPath: string, state: ShellState): void;
|
|
14
|
+
export declare function resetShellState(phrenPath: string): PhrenResult<string>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { ShellState } from "../data/access.js";
|
|
2
|
+
import type { runDoctor } from "../link/link.js";
|
|
3
|
+
export declare const SUB_VIEWS: readonly ["Tasks", "Findings", "Review Queue", "Skills", "Hooks"];
|
|
4
|
+
export declare const TAB_ICONS: Record<string, string>;
|
|
5
|
+
export interface UndoEntry {
|
|
6
|
+
label: string;
|
|
7
|
+
file: string;
|
|
8
|
+
content: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const MAX_UNDO_STACK = 10;
|
|
11
|
+
export type ShellView = ShellState["view"];
|
|
12
|
+
export interface ShellDeps {
|
|
13
|
+
runDoctor: typeof runDoctor;
|
|
14
|
+
runRelink: (phrenPath: string) => Promise<string>;
|
|
15
|
+
runHooks: (phrenPath: string) => Promise<string>;
|
|
16
|
+
runUpdate: () => Promise<string>;
|
|
17
|
+
}
|
|
18
|
+
interface DoctorCheck {
|
|
19
|
+
name: string;
|
|
20
|
+
ok: boolean;
|
|
21
|
+
detail: string;
|
|
22
|
+
}
|
|
23
|
+
export interface DoctorResultLike {
|
|
24
|
+
ok: boolean;
|
|
25
|
+
machine?: string;
|
|
26
|
+
profile?: string;
|
|
27
|
+
checks: DoctorCheck[];
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function formatSelectableLine(line: string, cols: number, selected: boolean): string;
|
|
2
|
+
export declare function viewportWithStatus(allLines: string[], cursorFirstLine: number, cursorLastLine: number, usableHeight: number, previousScroll: number, currentIndex: number, totalItems: number): {
|
|
3
|
+
lines: string[];
|
|
4
|
+
scrollStart: number;
|
|
5
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View rendering functions for the phren interactive shell.
|
|
3
|
+
* Extracted from shell.ts to keep the orchestrator under 300 lines.
|
|
4
|
+
*/
|
|
5
|
+
import { ShellState } from "../data/access.js";
|
|
6
|
+
import { type DoctorResultLike } from "./types.js";
|
|
7
|
+
/** Shared rendering state passed from the orchestrator */
|
|
8
|
+
export interface ViewContext {
|
|
9
|
+
phrenPath: string;
|
|
10
|
+
profile: string;
|
|
11
|
+
state: ShellState;
|
|
12
|
+
currentCursor: () => number;
|
|
13
|
+
currentScroll: () => number;
|
|
14
|
+
setScroll: (n: number) => void;
|
|
15
|
+
}
|
|
16
|
+
export interface SubsectionsCache {
|
|
17
|
+
project: string;
|
|
18
|
+
/** Keys are stable item IDs (bid hash when present, else "row:N") mapped to subsection name */
|
|
19
|
+
map: Map<string, string>;
|
|
20
|
+
}
|
|
21
|
+
export interface SkillEntry {
|
|
22
|
+
name: string;
|
|
23
|
+
path: string;
|
|
24
|
+
enabled: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function getProjectSkills(phrenPath: string, project: string): SkillEntry[];
|
|
27
|
+
export interface HookEntry {
|
|
28
|
+
event: string;
|
|
29
|
+
description: string;
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function getHookEntries(phrenPath: string, project?: string | null): HookEntry[];
|
|
33
|
+
export { writeInstallPreferences } from "../init/preferences.js";
|
|
34
|
+
export declare function renderShell(ctx: ViewContext, navMode: "navigate" | "input", inputCtx: string, inputBuf: string, showHelp: boolean, message: string, doctorSnapshot: () => Promise<DoctorResultLike>, subsectionsCache: SubsectionsCache | null, setHealthLineCount: (n: number) => void, setSubsectionsCache: (c: SubsectionsCache | null) => void): Promise<string>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type SkillManifest } from "./registry.js";
|
|
2
|
+
export declare function syncScopeSkillsToDir(phrenPath: string, scope: string, destDir: string): SkillManifest;
|
|
3
|
+
export declare function syncSkillLinksForScope(phrenPath: string, scope: string): SkillManifest | null;
|
|
4
|
+
export declare function setSkillEnabledAndSync(phrenPath: string, scope: string, name: string, enabled: boolean): void;
|
|
5
|
+
export declare function removeSkillPath(skillPath: string): string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface SkillEntry {
|
|
2
|
+
name: string;
|
|
3
|
+
source: string;
|
|
4
|
+
scopeType: "global" | "project";
|
|
5
|
+
sourceKind: "canonical";
|
|
6
|
+
format: "flat" | "folder";
|
|
7
|
+
path: string;
|
|
8
|
+
root: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
command: string;
|
|
12
|
+
aliases: string[];
|
|
13
|
+
}
|
|
14
|
+
interface ResolvedSkill extends Pick<SkillEntry, "path" | "format" | "root" | "name" | "source" | "enabled" | "description" | "command" | "aliases" | "scopeType" | "sourceKind"> {
|
|
15
|
+
visibleToAgents: boolean;
|
|
16
|
+
commandRegistered: boolean;
|
|
17
|
+
overrides: Array<{
|
|
18
|
+
source: string;
|
|
19
|
+
path: string;
|
|
20
|
+
sourceKind: "canonical";
|
|
21
|
+
}>;
|
|
22
|
+
mirrorTargets: string[];
|
|
23
|
+
}
|
|
24
|
+
interface SkillCommandRegistration {
|
|
25
|
+
command: string;
|
|
26
|
+
type: "skill";
|
|
27
|
+
skillId: string;
|
|
28
|
+
source: string;
|
|
29
|
+
path: string;
|
|
30
|
+
kind: "primary" | "alias";
|
|
31
|
+
registered: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface SkillManifestProblem {
|
|
34
|
+
code: string;
|
|
35
|
+
message: string;
|
|
36
|
+
command?: string;
|
|
37
|
+
skillIds?: string[];
|
|
38
|
+
}
|
|
39
|
+
export interface SkillManifest {
|
|
40
|
+
scope: string;
|
|
41
|
+
project?: string;
|
|
42
|
+
generatedAt: string;
|
|
43
|
+
skills: ResolvedSkill[];
|
|
44
|
+
commands: SkillCommandRegistration[];
|
|
45
|
+
problems: SkillManifestProblem[];
|
|
46
|
+
}
|
|
47
|
+
export declare function getAllSkills(phrenPath: string, profile: string): SkillEntry[];
|
|
48
|
+
export declare function buildSkillManifest(phrenPath: string, profile: string, scope: string, mirrorDir?: string): SkillManifest;
|
|
49
|
+
export declare function getScopedSkills(phrenPath: string, profile: string, project?: string): ResolvedSkill[];
|
|
50
|
+
export declare function findLocalSkill(phrenPath: string, scope: string, name: string): ResolvedSkill | null;
|
|
51
|
+
export declare function findSkill(phrenPath: string, profile: string, project: string | undefined, name: string): ResolvedSkill | {
|
|
52
|
+
error: string;
|
|
53
|
+
} | null;
|
|
54
|
+
export declare function renderSkillInstructionsSection(manifest: SkillManifest): string;
|
|
55
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type SqlJsDatabase } from "./shared/index.js";
|
|
2
|
+
import type { EmbeddingCache } from "./shared/embedding-cache.js";
|
|
3
|
+
export interface EmbeddingWarmupDeps {
|
|
4
|
+
checkOllamaAvailable(): Promise<boolean>;
|
|
5
|
+
embedText(text: string): Promise<number[] | null>;
|
|
6
|
+
getEmbeddingModel(): string;
|
|
7
|
+
getOllamaUrl(): string | null | undefined;
|
|
8
|
+
sleep(ms: number): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export type EmbeddingCacheLike = Pick<EmbeddingCache, "load" | "get" | "set" | "flush">;
|
|
11
|
+
export declare function startEmbeddingWarmup(db: SqlJsDatabase, cache: EmbeddingCacheLike, deps?: Partial<EmbeddingWarmupDeps>): {
|
|
12
|
+
loadPromise: Promise<void>;
|
|
13
|
+
backgroundPromise: Promise<number>;
|
|
14
|
+
};
|
|
15
|
+
export declare function backgroundEmbedMissingDocs(db: SqlJsDatabase, cache: EmbeddingCacheLike, deps?: Partial<EmbeddingWarmupDeps>): Promise<number>;
|
package/dist/status.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runStatus(): Promise<void>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type StoreRole = "primary" | "team" | "readonly";
|
|
2
|
+
export type StoreSyncMode = "managed-git" | "pull-only";
|
|
3
|
+
export interface StoreEntry {
|
|
4
|
+
/** Immutable 8-char hex identifier. */
|
|
5
|
+
id: string;
|
|
6
|
+
/** Human-readable name (unique within registry). */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Absolute path to the store root directory. */
|
|
9
|
+
path: string;
|
|
10
|
+
/** Store role — determines read/write/sync behavior. */
|
|
11
|
+
role: StoreRole;
|
|
12
|
+
/** Git remote URL (optional). */
|
|
13
|
+
remote?: string;
|
|
14
|
+
/** Sync mode for git operations. */
|
|
15
|
+
sync: StoreSyncMode;
|
|
16
|
+
/** Projects claimed by this store (for write routing in phase 2). */
|
|
17
|
+
projects?: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface StoreRegistry {
|
|
20
|
+
version: 1;
|
|
21
|
+
stores: StoreEntry[];
|
|
22
|
+
}
|
|
23
|
+
/** Bootstrap metadata committed to a team store repo root. */
|
|
24
|
+
export interface TeamBootstrap {
|
|
25
|
+
name: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
default_role?: StoreRole;
|
|
28
|
+
}
|
|
29
|
+
export declare function storesFilePath(phrenPath: string): string;
|
|
30
|
+
export declare function generateStoreId(): string;
|
|
31
|
+
export declare function readStoreRegistry(phrenPath: string): StoreRegistry | null;
|
|
32
|
+
export declare function writeStoreRegistry(phrenPath: string, registry: StoreRegistry): void;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the full list of stores. This is the **key backward-compat function**:
|
|
35
|
+
* - If stores.yaml exists → parse and return entries
|
|
36
|
+
* - If stores.yaml is missing → return a single implicit primary entry for phrenPath
|
|
37
|
+
* - In both cases, append PHREN_FEDERATION_PATHS entries as readonly stores
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveAllStores(phrenPath: string): StoreEntry[];
|
|
40
|
+
/** The primary store (role=primary). Falls back to implicit entry. */
|
|
41
|
+
export declare function getPrimaryStore(phrenPath: string): StoreEntry;
|
|
42
|
+
/** All stores that can be read (all roles). */
|
|
43
|
+
export declare function getReadableStores(phrenPath: string): StoreEntry[];
|
|
44
|
+
/** Non-primary stores (for federation search, multi-store sync). */
|
|
45
|
+
export declare function getNonPrimaryStores(phrenPath: string): StoreEntry[];
|
|
46
|
+
/** Find a store by name. */
|
|
47
|
+
export declare function findStoreByName(phrenPath: string, name: string): StoreEntry | undefined;
|
|
48
|
+
/** Get project directories for a store, filtered by the store's subscription list (if set). */
|
|
49
|
+
export declare function getStoreProjectDirs(store: StoreEntry): string[];
|
|
50
|
+
export declare function readTeamBootstrap(storePath: string): TeamBootstrap | null;
|
|
51
|
+
/** Add a store entry to the registry. Creates stores.yaml if needed. Uses file locking. */
|
|
52
|
+
export declare function addStoreToRegistry(phrenPath: string, entry: StoreEntry): void;
|
|
53
|
+
/** Remove a store entry by name. Refuses to remove primary. Uses file locking. */
|
|
54
|
+
export declare function removeStoreFromRegistry(phrenPath: string, name: string): StoreEntry;
|
|
55
|
+
/** Update the projects[] claim list for a store. Uses file locking. */
|
|
56
|
+
export declare function updateStoreProjects(phrenPath: string, storeName: string, projects: string[]): void;
|
|
57
|
+
/** Add projects to a store's subscription list. Deduplicates. Uses file locking. */
|
|
58
|
+
export declare function subscribeStoreProjects(phrenPath: string, storeName: string, projects: string[]): void;
|
|
59
|
+
/** Remove projects from a store's subscription list. Uses file locking. */
|
|
60
|
+
export declare function unsubscribeStoreProjects(phrenPath: string, storeName: string, projects: string[]): void;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type StoreEntry } from "./store-registry.js";
|
|
2
|
+
export interface ResolvedProject {
|
|
3
|
+
store: StoreEntry;
|
|
4
|
+
projectName: string;
|
|
5
|
+
projectDir: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ParsedProjectRef {
|
|
8
|
+
storeName?: string;
|
|
9
|
+
projectName: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse a project reference that may be store-qualified.
|
|
13
|
+
*
|
|
14
|
+
* "arc" → { projectName: "arc" }
|
|
15
|
+
* "arc-team/arc" → { storeName: "arc-team", projectName: "arc" }
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseStoreQualified(input: string): ParsedProjectRef;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve a project reference to a specific store + directory.
|
|
20
|
+
*
|
|
21
|
+
* Resolution rules:
|
|
22
|
+
* 1. If store-qualified ("store/project"), find that store and project within it
|
|
23
|
+
* 2. If bare ("project"), scan all readable stores for a matching project dir
|
|
24
|
+
* 3. Exactly one match → return it
|
|
25
|
+
* 4. Zero matches → throw NOT_FOUND
|
|
26
|
+
* 5. Multiple matches → throw VALIDATION_ERROR with disambiguation message
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveProject(phrenPath: string, input: string, profile?: string): ResolvedProject;
|
|
29
|
+
/**
|
|
30
|
+
* List all projects across all readable stores.
|
|
31
|
+
* Returns entries with store context for display.
|
|
32
|
+
*/
|
|
33
|
+
export declare function listAllProjects(phrenPath: string, profile?: string): Array<{
|
|
34
|
+
store: StoreEntry;
|
|
35
|
+
projectName: string;
|
|
36
|
+
projectDir: string;
|
|
37
|
+
}>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type PhrenResult } from "../shared.js";
|
|
2
|
+
import type { TaskItem } from "../data/tasks.js";
|
|
3
|
+
interface GithubIssueRef {
|
|
4
|
+
repo?: string;
|
|
5
|
+
issueNumber?: number;
|
|
6
|
+
url?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseGithubIssueUrl(url: string): GithubIssueRef | null;
|
|
9
|
+
/** @internal Exported for tests. */
|
|
10
|
+
export declare function extractGithubRepoFromText(content: string): string | undefined;
|
|
11
|
+
export declare function resolveProjectGithubRepo(phrenPath: string, project: string): string | undefined;
|
|
12
|
+
export declare function buildTaskIssueBody(project: string, item: TaskItem): string;
|
|
13
|
+
export declare function createGithubIssueForTask(args: {
|
|
14
|
+
repo: string;
|
|
15
|
+
title: string;
|
|
16
|
+
body: string;
|
|
17
|
+
}): PhrenResult<{
|
|
18
|
+
repo: string;
|
|
19
|
+
issueNumber?: number;
|
|
20
|
+
url: string;
|
|
21
|
+
}>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
interface TaskHygieneIssue {
|
|
2
|
+
id: string;
|
|
3
|
+
line: string;
|
|
4
|
+
reason: "anchors-missing" | "keywords-missing";
|
|
5
|
+
evidence: string[];
|
|
6
|
+
}
|
|
7
|
+
interface TaskHygieneResult {
|
|
8
|
+
ok: boolean;
|
|
9
|
+
detail: string;
|
|
10
|
+
issues: TaskHygieneIssue[];
|
|
11
|
+
}
|
|
12
|
+
export declare function inspectTaskHygiene(phrenPath: string, project: string, repoPath?: string | null): TaskHygieneResult;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type ProactivityLevel } from "../proactivity.js";
|
|
2
|
+
export type TaskMode = "off" | "manual" | "suggest" | "auto";
|
|
3
|
+
interface TaskPromptLifecycleResult {
|
|
4
|
+
mode: TaskMode;
|
|
5
|
+
noticeLines: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function handleTaskPromptLifecycle(args: {
|
|
8
|
+
phrenPath: string;
|
|
9
|
+
prompt: string;
|
|
10
|
+
project: string | null;
|
|
11
|
+
sessionId?: string;
|
|
12
|
+
intent: string;
|
|
13
|
+
taskLevel?: ProactivityLevel;
|
|
14
|
+
}): TaskPromptLifecycleResult;
|
|
15
|
+
export declare function finalizeTaskSession(args: {
|
|
16
|
+
phrenPath: string;
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
status: "clean" | "saved-local" | "saved-pushed" | "no-upstream" | "error";
|
|
19
|
+
detail: string;
|
|
20
|
+
}): void;
|
|
21
|
+
/**
|
|
22
|
+
* Return the active TaskItem tracked for a session+project, if any.
|
|
23
|
+
* Used by mcp-finding.ts to link findings to active tasks.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getActiveTaskForSession(phrenPath: string, sessionId: string, project: string): import("../data/tasks.js").TaskItem | null;
|
|
26
|
+
export {};
|