@phren/cli 0.0.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/LICENSE +21 -0
- package/README.md +590 -0
- package/mcp/dist/capabilities/cli.js +61 -0
- package/mcp/dist/capabilities/index.js +15 -0
- package/mcp/dist/capabilities/mcp.js +61 -0
- package/mcp/dist/capabilities/types.js +57 -0
- package/mcp/dist/capabilities/vscode.js +61 -0
- package/mcp/dist/capabilities/web-ui.js +61 -0
- package/mcp/dist/cli-actions.js +302 -0
- package/mcp/dist/cli-config.js +580 -0
- package/mcp/dist/cli-extract.js +305 -0
- package/mcp/dist/cli-govern.js +371 -0
- package/mcp/dist/cli-graph.js +169 -0
- package/mcp/dist/cli-hooks-citations.js +44 -0
- package/mcp/dist/cli-hooks-context.js +56 -0
- package/mcp/dist/cli-hooks-globs.js +83 -0
- package/mcp/dist/cli-hooks-output.js +130 -0
- package/mcp/dist/cli-hooks-retrieval.js +2 -0
- package/mcp/dist/cli-hooks-session.js +1402 -0
- package/mcp/dist/cli-hooks.js +350 -0
- package/mcp/dist/cli-namespaces.js +989 -0
- package/mcp/dist/cli-ops.js +253 -0
- package/mcp/dist/cli-search.js +407 -0
- package/mcp/dist/cli.js +108 -0
- package/mcp/dist/content-archive.js +278 -0
- package/mcp/dist/content-citation.js +391 -0
- package/mcp/dist/content-dedup.js +622 -0
- package/mcp/dist/content-learning.js +472 -0
- package/mcp/dist/content-metadata.js +186 -0
- package/mcp/dist/content-validate.js +462 -0
- package/mcp/dist/core-finding.js +54 -0
- package/mcp/dist/core-project.js +36 -0
- package/mcp/dist/core-search.js +50 -0
- package/mcp/dist/data-access.js +400 -0
- package/mcp/dist/data-tasks.js +821 -0
- package/mcp/dist/embedding.js +344 -0
- package/mcp/dist/entrypoint.js +387 -0
- package/mcp/dist/finding-context.js +172 -0
- package/mcp/dist/finding-impact.js +181 -0
- package/mcp/dist/finding-journal.js +122 -0
- package/mcp/dist/finding-lifecycle.js +259 -0
- package/mcp/dist/governance-audit.js +22 -0
- package/mcp/dist/governance-locks.js +96 -0
- package/mcp/dist/governance-policy.js +648 -0
- package/mcp/dist/governance-scores.js +355 -0
- package/mcp/dist/hooks.js +449 -0
- package/mcp/dist/impact-scoring.js +22 -0
- package/mcp/dist/index-query.js +168 -0
- package/mcp/dist/index.js +205 -0
- package/mcp/dist/init-config.js +336 -0
- package/mcp/dist/init-preferences.js +62 -0
- package/mcp/dist/init-setup.js +1305 -0
- package/mcp/dist/init-shared.js +29 -0
- package/mcp/dist/init.js +1730 -0
- package/mcp/dist/link-checksums.js +62 -0
- package/mcp/dist/link-context.js +257 -0
- package/mcp/dist/link-doctor.js +591 -0
- package/mcp/dist/link-skills.js +212 -0
- package/mcp/dist/link.js +596 -0
- package/mcp/dist/logger.js +15 -0
- package/mcp/dist/machine-identity.js +38 -0
- package/mcp/dist/mcp-config.js +254 -0
- package/mcp/dist/mcp-data.js +315 -0
- package/mcp/dist/mcp-extract-facts.js +78 -0
- package/mcp/dist/mcp-extract.js +133 -0
- package/mcp/dist/mcp-finding.js +557 -0
- package/mcp/dist/mcp-graph.js +339 -0
- package/mcp/dist/mcp-hooks.js +256 -0
- package/mcp/dist/mcp-memory.js +58 -0
- package/mcp/dist/mcp-ops.js +328 -0
- package/mcp/dist/mcp-search.js +628 -0
- package/mcp/dist/mcp-session.js +651 -0
- package/mcp/dist/mcp-skills.js +189 -0
- package/mcp/dist/mcp-tasks.js +551 -0
- package/mcp/dist/mcp-types.js +7 -0
- package/mcp/dist/memory-ui-assets.js +6 -0
- package/mcp/dist/memory-ui-data.js +513 -0
- package/mcp/dist/memory-ui-graph.js +1910 -0
- package/mcp/dist/memory-ui-page.js +353 -0
- package/mcp/dist/memory-ui-scripts.js +1387 -0
- package/mcp/dist/memory-ui-server.js +1218 -0
- package/mcp/dist/memory-ui-styles.js +555 -0
- package/mcp/dist/memory-ui.js +9 -0
- package/mcp/dist/package-metadata.js +13 -0
- package/mcp/dist/phren-art.js +52 -0
- package/mcp/dist/phren-core.js +108 -0
- package/mcp/dist/phren-dotenv.js +67 -0
- package/mcp/dist/phren-paths.js +476 -0
- package/mcp/dist/proactivity.js +172 -0
- package/mcp/dist/profile-store.js +228 -0
- package/mcp/dist/project-config.js +85 -0
- package/mcp/dist/project-locator.js +25 -0
- package/mcp/dist/project-topics.js +1134 -0
- package/mcp/dist/provider-adapters.js +176 -0
- package/mcp/dist/runtime-profile.js +18 -0
- package/mcp/dist/session-checkpoints.js +131 -0
- package/mcp/dist/session-utils.js +68 -0
- package/mcp/dist/shared-content.js +8 -0
- package/mcp/dist/shared-embedding-cache.js +143 -0
- package/mcp/dist/shared-fragment-graph.js +456 -0
- package/mcp/dist/shared-governance.js +4 -0
- package/mcp/dist/shared-index.js +1334 -0
- package/mcp/dist/shared-ollama.js +192 -0
- package/mcp/dist/shared-paths.js +1 -0
- package/mcp/dist/shared-retrieval.js +796 -0
- package/mcp/dist/shared-search-fallback.js +375 -0
- package/mcp/dist/shared-sqljs.js +42 -0
- package/mcp/dist/shared-stemmer.js +171 -0
- package/mcp/dist/shared-vector-index.js +199 -0
- package/mcp/dist/shared.js +114 -0
- package/mcp/dist/shell-entry.js +209 -0
- package/mcp/dist/shell-input.js +943 -0
- package/mcp/dist/shell-palette.js +119 -0
- package/mcp/dist/shell-render.js +252 -0
- package/mcp/dist/shell-state-store.js +81 -0
- package/mcp/dist/shell-types.js +13 -0
- package/mcp/dist/shell-view-list.js +14 -0
- package/mcp/dist/shell-view.js +707 -0
- package/mcp/dist/shell.js +352 -0
- package/mcp/dist/skill-files.js +117 -0
- package/mcp/dist/skill-registry.js +279 -0
- package/mcp/dist/skill-state.js +28 -0
- package/mcp/dist/startup-embedding.js +57 -0
- package/mcp/dist/status.js +323 -0
- package/mcp/dist/synonyms.json +670 -0
- package/mcp/dist/task-hygiene.js +251 -0
- package/mcp/dist/task-lifecycle.js +347 -0
- package/mcp/dist/tasks-github.js +76 -0
- package/mcp/dist/telemetry.js +165 -0
- package/mcp/dist/test-global-setup.js +37 -0
- package/mcp/dist/tool-registry.js +104 -0
- package/mcp/dist/update.js +97 -0
- package/mcp/dist/utils.js +543 -0
- package/package.json +67 -0
- package/skills/README.md +7 -0
- package/skills/consolidate/SKILL.md +152 -0
- package/skills/discover/SKILL.md +175 -0
- package/skills/init/SKILL.md +216 -0
- package/skills/profiles/SKILL.md +121 -0
- package/skills/sync/SKILL.md +261 -0
- package/starter/README.md +74 -0
- package/starter/global/CLAUDE.md +89 -0
- package/starter/global/skills/humanize.md +30 -0
- package/starter/global/skills/pipeline.md +35 -0
- package/starter/global/skills/release.md +35 -0
- package/starter/machines.yaml +8 -0
- package/starter/my-api/.claude/skills/README.md +7 -0
- package/starter/my-api/CLAUDE.md +33 -0
- package/starter/my-api/FINDINGS.md +9 -0
- package/starter/my-api/summary.md +7 -0
- package/starter/my-api/tasks.md +7 -0
- package/starter/my-first-project/.claude/skills/README.md +7 -0
- package/starter/my-first-project/CLAUDE.md +49 -0
- package/starter/my-first-project/FINDINGS.md +24 -0
- package/starter/my-first-project/summary.md +11 -0
- package/starter/my-first-project/tasks.md +25 -0
- package/starter/my-frontend/.claude/skills/README.md +7 -0
- package/starter/my-frontend/CLAUDE.md +33 -0
- package/starter/my-frontend/FINDINGS.md +9 -0
- package/starter/my-frontend/summary.md +7 -0
- package/starter/my-frontend/tasks.md +7 -0
- package/starter/profiles/default.yaml +4 -0
- package/starter/profiles/personal.yaml +4 -0
- package/starter/profiles/work.yaml +4 -0
- package/starter/templates/README.md +7 -0
- package/starter/templates/frontend/CLAUDE.md +23 -0
- package/starter/templates/frontend/FINDINGS.md +7 -0
- package/starter/templates/frontend/reference/README.md +4 -0
- package/starter/templates/frontend/summary.md +7 -0
- package/starter/templates/frontend/tasks.md +11 -0
- package/starter/templates/library/CLAUDE.md +22 -0
- package/starter/templates/library/FINDINGS.md +7 -0
- package/starter/templates/library/reference/README.md +4 -0
- package/starter/templates/library/summary.md +7 -0
- package/starter/templates/library/tasks.md +11 -0
- package/starter/templates/monorepo/CLAUDE.md +21 -0
- package/starter/templates/monorepo/FINDINGS.md +7 -0
- package/starter/templates/monorepo/reference/README.md +4 -0
- package/starter/templates/monorepo/summary.md +7 -0
- package/starter/templates/monorepo/tasks.md +11 -0
- package/starter/templates/python-project/CLAUDE.md +21 -0
- package/starter/templates/python-project/FINDINGS.md +7 -0
- package/starter/templates/python-project/reference/README.md +4 -0
- package/starter/templates/python-project/summary.md +7 -0
- package/starter/templates/python-project/tasks.md +10 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { debugLog } from "./shared.js";
|
|
2
|
+
const DEFAULT_OLLAMA_URL = "http://localhost:11434";
|
|
3
|
+
const DEFAULT_EMBEDDING_MODEL = "nomic-embed-text";
|
|
4
|
+
const DEFAULT_EXTRACT_MODEL = "llama3.2";
|
|
5
|
+
const MAX_EMBED_INPUT_CHARS = 6000;
|
|
6
|
+
export function prepareEmbeddingInput(text) {
|
|
7
|
+
return text
|
|
8
|
+
.replace(/<!--[\s\S]*?-->/g, " ")
|
|
9
|
+
.replace(/```[\s\S]*?```/g, (block) => block.replace(/```/g, " "))
|
|
10
|
+
.replace(/`([^`]+)`/g, " $1 ")
|
|
11
|
+
.replace(/\[([^\]]+)\]\([^)]+\)/g, " $1 ")
|
|
12
|
+
.replace(/\|/g, " ")
|
|
13
|
+
.replace(/\r\n/g, "\n")
|
|
14
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
15
|
+
.replace(/[ \t]+\n/g, "\n")
|
|
16
|
+
.replace(/\s+/g, " ")
|
|
17
|
+
.trim()
|
|
18
|
+
.slice(0, MAX_EMBED_INPUT_CHARS);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Cloud embedding API support (Item 6).
|
|
22
|
+
* Set PHREN_EMBEDDING_API_URL to an OpenAI-compatible /embeddings endpoint.
|
|
23
|
+
* Set PHREN_EMBEDDING_API_KEY for the Authorization: Bearer header.
|
|
24
|
+
* When set, cloud embedding takes priority over Ollama.
|
|
25
|
+
*
|
|
26
|
+
* Example (OpenAI):
|
|
27
|
+
* PHREN_EMBEDDING_API_URL=https://api.openai.com/v1
|
|
28
|
+
* PHREN_EMBEDDING_API_KEY=sk-...
|
|
29
|
+
* PHREN_EMBEDDING_MODEL=text-embedding-3-small
|
|
30
|
+
*/
|
|
31
|
+
export function getCloudEmbeddingUrl() {
|
|
32
|
+
const val = process.env["PHREN_EMBEDDING_API_URL"];
|
|
33
|
+
if (!val || ["off", "0", "false", "no"].includes(val.trim().toLowerCase()))
|
|
34
|
+
return null;
|
|
35
|
+
return val.trim().replace(/\/$/, ""); // strip trailing slash
|
|
36
|
+
}
|
|
37
|
+
function getCloudEmbeddingKey() {
|
|
38
|
+
return process.env["PHREN_EMBEDDING_API_KEY"] ?? null;
|
|
39
|
+
}
|
|
40
|
+
/** Embed text via OpenAI-compatible /embeddings endpoint. */
|
|
41
|
+
async function embedTextCloud(input, baseUrl, model, apiKey) {
|
|
42
|
+
const headers = { "Content-Type": "application/json" };
|
|
43
|
+
if (apiKey)
|
|
44
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
45
|
+
try {
|
|
46
|
+
const controller = new AbortController();
|
|
47
|
+
const id = setTimeout(() => controller.abort(), 15000);
|
|
48
|
+
const res = await fetch(`${baseUrl}/embeddings`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers,
|
|
51
|
+
body: JSON.stringify({ model, input }),
|
|
52
|
+
signal: controller.signal,
|
|
53
|
+
});
|
|
54
|
+
clearTimeout(id);
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
debugLog(`embedTextCloud: API returned ${res.status}`);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const data = await res.json();
|
|
60
|
+
return data.data?.[0]?.embedding ?? null;
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
debugLog(`embedTextCloud error: ${e instanceof Error ? e.message : String(e)}`);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export function getOllamaUrl() {
|
|
68
|
+
const val = process.env["PHREN_OLLAMA_URL"];
|
|
69
|
+
if (val !== undefined && ["off", "0", "false", "no"].includes(val.trim().toLowerCase()))
|
|
70
|
+
return null;
|
|
71
|
+
return val ?? DEFAULT_OLLAMA_URL;
|
|
72
|
+
}
|
|
73
|
+
export function getEmbeddingModel() {
|
|
74
|
+
return process.env["PHREN_EMBEDDING_MODEL"] ?? DEFAULT_EMBEDDING_MODEL;
|
|
75
|
+
}
|
|
76
|
+
export function getExtractModel() {
|
|
77
|
+
return process.env["PHREN_EXTRACT_MODEL"] ?? DEFAULT_EXTRACT_MODEL;
|
|
78
|
+
}
|
|
79
|
+
export async function checkOllamaAvailable(url) {
|
|
80
|
+
// When cloud embedding is configured, report as "available" (skip Ollama probe)
|
|
81
|
+
if (!url && getCloudEmbeddingUrl())
|
|
82
|
+
return true;
|
|
83
|
+
const baseUrl = url ?? getOllamaUrl();
|
|
84
|
+
if (!baseUrl)
|
|
85
|
+
return false;
|
|
86
|
+
try {
|
|
87
|
+
const controller = new AbortController();
|
|
88
|
+
const id = setTimeout(() => controller.abort(), 2000);
|
|
89
|
+
const res = await fetch(`${baseUrl}/api/tags`, { signal: controller.signal });
|
|
90
|
+
clearTimeout(id);
|
|
91
|
+
return res.ok;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export async function checkModelAvailable(model, url) {
|
|
98
|
+
// When cloud embedding is configured, assume model is available (no /api/tags equivalent)
|
|
99
|
+
if (!url && getCloudEmbeddingUrl())
|
|
100
|
+
return true;
|
|
101
|
+
const baseUrl = url ?? getOllamaUrl();
|
|
102
|
+
if (!baseUrl)
|
|
103
|
+
return false;
|
|
104
|
+
const modelName = model ?? getEmbeddingModel();
|
|
105
|
+
try {
|
|
106
|
+
const controller = new AbortController();
|
|
107
|
+
const id = setTimeout(() => controller.abort(), 2000);
|
|
108
|
+
const res = await fetch(`${baseUrl}/api/tags`, { signal: controller.signal });
|
|
109
|
+
clearTimeout(id);
|
|
110
|
+
if (!res.ok)
|
|
111
|
+
return false;
|
|
112
|
+
const data = await res.json();
|
|
113
|
+
return (data.models ?? []).some(m => m.name.startsWith(modelName));
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export async function embedText(text, model, url) {
|
|
120
|
+
const modelName = model ?? getEmbeddingModel();
|
|
121
|
+
const input = prepareEmbeddingInput(text);
|
|
122
|
+
if (!input)
|
|
123
|
+
return null;
|
|
124
|
+
// Cloud embedding takes priority when PHREN_EMBEDDING_API_URL is set
|
|
125
|
+
const cloudUrl = url ? null : getCloudEmbeddingUrl();
|
|
126
|
+
if (cloudUrl) {
|
|
127
|
+
return embedTextCloud(input, cloudUrl, modelName, getCloudEmbeddingKey());
|
|
128
|
+
}
|
|
129
|
+
const baseUrl = url ?? getOllamaUrl();
|
|
130
|
+
if (!baseUrl)
|
|
131
|
+
return null;
|
|
132
|
+
try {
|
|
133
|
+
const controller = new AbortController();
|
|
134
|
+
const id = setTimeout(() => controller.abort(), 10000);
|
|
135
|
+
const res = await fetch(`${baseUrl}/api/embed`, {
|
|
136
|
+
method: "POST",
|
|
137
|
+
headers: { "Content-Type": "application/json" },
|
|
138
|
+
body: JSON.stringify({ model: modelName, input }),
|
|
139
|
+
signal: controller.signal,
|
|
140
|
+
});
|
|
141
|
+
clearTimeout(id);
|
|
142
|
+
if (!res.ok) {
|
|
143
|
+
debugLog(`embedText: Ollama returned ${res.status}`);
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
const data = await res.json();
|
|
147
|
+
return data.embeddings?.[0] ?? null;
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
debugLog(`embedText error: ${e instanceof Error ? e.message : String(e)}`);
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
export async function generateText(prompt, model, url) {
|
|
155
|
+
const baseUrl = url ?? getOllamaUrl();
|
|
156
|
+
if (!baseUrl)
|
|
157
|
+
return null;
|
|
158
|
+
const modelName = model ?? getExtractModel();
|
|
159
|
+
try {
|
|
160
|
+
const controller = new AbortController();
|
|
161
|
+
const id = setTimeout(() => controller.abort(), 60000);
|
|
162
|
+
const res = await fetch(`${baseUrl}/api/generate`, {
|
|
163
|
+
method: "POST",
|
|
164
|
+
headers: { "Content-Type": "application/json" },
|
|
165
|
+
body: JSON.stringify({ model: modelName, prompt, stream: false }),
|
|
166
|
+
signal: controller.signal,
|
|
167
|
+
});
|
|
168
|
+
clearTimeout(id);
|
|
169
|
+
if (!res.ok) {
|
|
170
|
+
debugLog(`generateText: Ollama returned ${res.status}`);
|
|
171
|
+
return null;
|
|
172
|
+
}
|
|
173
|
+
const data = await res.json();
|
|
174
|
+
return data.response ?? null;
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
debugLog(`generateText error: ${e instanceof Error ? e.message : String(e)}`);
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
export function cosineSimilarity(a, b) {
|
|
182
|
+
if (a.length !== b.length || a.length === 0)
|
|
183
|
+
return 0;
|
|
184
|
+
let dot = 0, normA = 0, normB = 0;
|
|
185
|
+
for (let i = 0; i < a.length; i++) {
|
|
186
|
+
dot += a[i] * b[i];
|
|
187
|
+
normA += a[i] * a[i];
|
|
188
|
+
normB += b[i] * b[i];
|
|
189
|
+
}
|
|
190
|
+
const denom = Math.sqrt(normA) * Math.sqrt(normB);
|
|
191
|
+
return denom === 0 ? 0 : dot / denom;
|
|
192
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./phren-paths.js";
|