cohvu 2.21.1 → 3.0.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 +37 -0
- package/cli.js +15501 -0
- package/package.json +15 -26
- package/dist/__tests__/instruction-file.unit.test.d.ts +0 -1
- package/dist/__tests__/instruction-file.unit.test.js +0 -296
- package/dist/__tests__/instruction-file.unit.test.js.map +0 -1
- package/dist/__tests__/teardown.unit.test.d.ts +0 -1
- package/dist/__tests__/teardown.unit.test.js +0 -196
- package/dist/__tests__/teardown.unit.test.js.map +0 -1
- package/dist/api.d.ts +0 -292
- package/dist/api.js +0 -337
- package/dist/api.js.map +0 -1
- package/dist/auth.d.ts +0 -4
- package/dist/auth.js +0 -96
- package/dist/auth.js.map +0 -1
- package/dist/constants.d.ts +0 -2
- package/dist/constants.js +0 -10
- package/dist/constants.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -259
- package/dist/index.js.map +0 -1
- package/dist/instructions.d.ts +0 -33
- package/dist/instructions.js +0 -238
- package/dist/instructions.js.map +0 -1
- package/dist/log.d.ts +0 -6
- package/dist/log.js +0 -51
- package/dist/log.js.map +0 -1
- package/dist/pause.d.ts +0 -3
- package/dist/pause.js +0 -24
- package/dist/pause.js.map +0 -1
- package/dist/platforms.d.ts +0 -22
- package/dist/platforms.js +0 -79
- package/dist/platforms.js.map +0 -1
- package/dist/postinstall.d.ts +0 -2
- package/dist/postinstall.js +0 -11
- package/dist/postinstall.js.map +0 -1
- package/dist/proxy.d.ts +0 -1
- package/dist/proxy.js +0 -371
- package/dist/proxy.js.map +0 -1
- package/dist/setup.d.ts +0 -15
- package/dist/setup.js +0 -295
- package/dist/setup.js.map +0 -1
- package/dist/teardown.d.ts +0 -15
- package/dist/teardown.js +0 -235
- package/dist/teardown.js.map +0 -1
- package/dist/tui/App.d.ts +0 -1
- package/dist/tui/App.js +0 -2245
- package/dist/tui/App.js.map +0 -1
- package/dist/tui/components/Banner.d.ts +0 -4
- package/dist/tui/components/Banner.js +0 -71
- package/dist/tui/components/Banner.js.map +0 -1
- package/dist/tui/components/Divider.d.ts +0 -1
- package/dist/tui/components/Divider.js +0 -8
- package/dist/tui/components/Divider.js.map +0 -1
- package/dist/tui/components/Footer.d.ts +0 -4
- package/dist/tui/components/Footer.js +0 -214
- package/dist/tui/components/Footer.js.map +0 -1
- package/dist/tui/components/Header.d.ts +0 -4
- package/dist/tui/components/Header.js +0 -126
- package/dist/tui/components/Header.js.map +0 -1
- package/dist/tui/components/LockCard.d.ts +0 -17
- package/dist/tui/components/LockCard.js +0 -37
- package/dist/tui/components/LockCard.js.map +0 -1
- package/dist/tui/components/Modal.d.ts +0 -5
- package/dist/tui/components/Modal.js +0 -195
- package/dist/tui/components/Modal.js.map +0 -1
- package/dist/tui/components/TabBar.d.ts +0 -4
- package/dist/tui/components/TabBar.js +0 -17
- package/dist/tui/components/TabBar.js.map +0 -1
- package/dist/tui/components/Toast.d.ts +0 -4
- package/dist/tui/components/Toast.js +0 -9
- package/dist/tui/components/Toast.js.map +0 -1
- package/dist/tui/index.d.ts +0 -1
- package/dist/tui/index.js +0 -20
- package/dist/tui/index.js.map +0 -1
- package/dist/tui/platform-detect.d.ts +0 -2
- package/dist/tui/platform-detect.js +0 -79
- package/dist/tui/platform-detect.js.map +0 -1
- package/dist/tui/state.d.ts +0 -414
- package/dist/tui/state.js +0 -397
- package/dist/tui/state.js.map +0 -1
- package/dist/tui/tabs/BillingTab.d.ts +0 -5
- package/dist/tui/tabs/BillingTab.js +0 -72
- package/dist/tui/tabs/BillingTab.js.map +0 -1
- package/dist/tui/tabs/KeysTab.d.ts +0 -5
- package/dist/tui/tabs/KeysTab.js +0 -87
- package/dist/tui/tabs/KeysTab.js.map +0 -1
- package/dist/tui/tabs/KnowledgeTab.d.ts +0 -5
- package/dist/tui/tabs/KnowledgeTab.js +0 -143
- package/dist/tui/tabs/KnowledgeTab.js.map +0 -1
- package/dist/tui/tabs/ProjectTab.d.ts +0 -5
- package/dist/tui/tabs/ProjectTab.js +0 -34
- package/dist/tui/tabs/ProjectTab.js.map +0 -1
- package/dist/tui/tabs/TeamTab.d.ts +0 -5
- package/dist/tui/tabs/TeamTab.js +0 -57
- package/dist/tui/tabs/TeamTab.js.map +0 -1
- package/dist/tui/tabs/YouTab.d.ts +0 -5
- package/dist/tui/tabs/YouTab.js +0 -25
- package/dist/tui/tabs/YouTab.js.map +0 -1
- package/dist/tui/utils.d.ts +0 -6
- package/dist/tui/utils.js +0 -58
- package/dist/tui/utils.js.map +0 -1
package/dist/auth.js
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
// Device auth flow + API key storage for the Cohvu CLI.
|
|
2
|
-
// Stores API key in ~/.cohvu/credentials.
|
|
3
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from "fs";
|
|
4
|
-
import { homedir } from "os";
|
|
5
|
-
import { join } from "path";
|
|
6
|
-
import { exec, execFile } from "child_process";
|
|
7
|
-
import chalk from "chalk";
|
|
8
|
-
import ora from "ora";
|
|
9
|
-
const CONFIG_DIR = join(homedir(), ".cohvu");
|
|
10
|
-
const API_KEY_FILE = join(CONFIG_DIR, "credentials");
|
|
11
|
-
const POLL_INTERVAL_MS = 5000;
|
|
12
|
-
function ensureConfigDir() {
|
|
13
|
-
if (!existsSync(CONFIG_DIR)) {
|
|
14
|
-
mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
/** Read the long-lived API key. Returns null if not stored. */
|
|
18
|
-
export function getApiKey() {
|
|
19
|
-
if (!existsSync(API_KEY_FILE))
|
|
20
|
-
return null;
|
|
21
|
-
try {
|
|
22
|
-
const key = readFileSync(API_KEY_FILE, "utf-8").trim();
|
|
23
|
-
return key.startsWith("chv_") ? key : null;
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export function storeApiKey(key) {
|
|
30
|
-
ensureConfigDir();
|
|
31
|
-
const tmp = `${API_KEY_FILE}.${process.pid}.tmp`;
|
|
32
|
-
writeFileSync(tmp, key, { mode: 0o600 });
|
|
33
|
-
renameSync(tmp, API_KEY_FILE);
|
|
34
|
-
}
|
|
35
|
-
function openBrowser(url) {
|
|
36
|
-
if (process.platform === "win32") {
|
|
37
|
-
exec(`start "" "${url}"`);
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
const cmd = process.platform === "darwin" ? "open" : "xdg-open";
|
|
41
|
-
execFile(cmd, [url], () => { });
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
export async function deviceAuthFlow(baseUrl) {
|
|
45
|
-
// Request device code
|
|
46
|
-
const deviceRes = await fetch(`${baseUrl}/v1/auth/device`, {
|
|
47
|
-
method: "POST",
|
|
48
|
-
headers: { "Content-Type": "application/json" },
|
|
49
|
-
});
|
|
50
|
-
if (!deviceRes.ok) {
|
|
51
|
-
throw new Error(`Device auth request failed: ${deviceRes.status}`);
|
|
52
|
-
}
|
|
53
|
-
const deviceData = (await deviceRes.json());
|
|
54
|
-
console.log('');
|
|
55
|
-
console.log(chalk.dim(' sign in at ') + deviceData.verification_url);
|
|
56
|
-
console.log(chalk.dim(' code: ') + deviceData.user_code);
|
|
57
|
-
console.log('');
|
|
58
|
-
openBrowser(deviceData.verification_url);
|
|
59
|
-
const spinner = ora({ text: 'waiting for sign in', indent: 2 }).start();
|
|
60
|
-
// If the browser didn't open (missing xdg-open, SSH session, etc.) the
|
|
61
|
-
// printed URL may have scrolled past. After ~10 seconds without
|
|
62
|
-
// resolution, surface it on the spinner itself.
|
|
63
|
-
const hintTimer = setTimeout(() => {
|
|
64
|
-
spinner.text = 'sign in at ' + deviceData.verification_url;
|
|
65
|
-
}, 10_000);
|
|
66
|
-
// Poll for API key
|
|
67
|
-
const deadline = Date.now() + deviceData.expires_in * 1000;
|
|
68
|
-
while (Date.now() < deadline) {
|
|
69
|
-
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
70
|
-
const tokenRes = await fetch(`${baseUrl}/v1/auth/device/token`, {
|
|
71
|
-
method: "POST",
|
|
72
|
-
headers: { "Content-Type": "application/json" },
|
|
73
|
-
body: JSON.stringify({ device_code: deviceData.device_code }),
|
|
74
|
-
});
|
|
75
|
-
if (!tokenRes.ok) {
|
|
76
|
-
const body = (await tokenRes.json());
|
|
77
|
-
if (body.error === "authorization_pending")
|
|
78
|
-
continue;
|
|
79
|
-
if (body.error === "expired_token") {
|
|
80
|
-
clearTimeout(hintTimer);
|
|
81
|
-
spinner.fail('sign in expired');
|
|
82
|
-
throw new Error("Device code expired");
|
|
83
|
-
}
|
|
84
|
-
continue;
|
|
85
|
-
}
|
|
86
|
-
const data = (await tokenRes.json());
|
|
87
|
-
storeApiKey(data.api_key);
|
|
88
|
-
clearTimeout(hintTimer);
|
|
89
|
-
spinner.succeed('signed in');
|
|
90
|
-
return data.api_key;
|
|
91
|
-
}
|
|
92
|
-
clearTimeout(hintTimer);
|
|
93
|
-
spinner.fail('sign in timed out');
|
|
94
|
-
throw new Error("Device auth timed out");
|
|
95
|
-
}
|
|
96
|
-
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/constants.d.ts
DELETED
package/dist/constants.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from "fs";
|
|
2
|
-
import { dirname, join } from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
export const DEFAULT_BASE_URL = "https://api.cohvu.com";
|
|
5
|
-
// CLI_VERSION pulled from the published package.json at module load — the
|
|
6
|
-
// dist is always shipped alongside its package.json, so the resolve path
|
|
7
|
-
// is stable. Prefer this over a hand-edited constant because it can't drift.
|
|
8
|
-
const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
9
|
-
export const CLI_VERSION = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
|
|
10
|
-
//# sourceMappingURL=constants.js.map
|
package/dist/constants.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAExD,0EAA0E;AAC1E,yEAAyE;AACzE,6EAA6E;AAC7E,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;AACpF,MAAM,CAAC,MAAM,WAAW,GAAI,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAyB,CAAC,OAAO,CAAC"}
|
package/dist/index.d.ts
DELETED
package/dist/index.js
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Cohvu CLI
|
|
3
|
-
//
|
|
4
|
-
// cohvu — TUI dashboard (interactive) or MCP proxy (piped)
|
|
5
|
-
// cohvu pause — pause Cohvu (agents won't see tools)
|
|
6
|
-
// cohvu resume — resume Cohvu
|
|
7
|
-
// cohvu status — quick check: auth, project, connectivity
|
|
8
|
-
// cohvu update — update to the latest version
|
|
9
|
-
// cohvu disconnect — remove Cohvu from all agents and sign out
|
|
10
|
-
import { createInterface } from "readline";
|
|
11
|
-
import chalk from "chalk";
|
|
12
|
-
import ora from "ora";
|
|
13
|
-
import { getApiKey, deviceAuthFlow } from "./auth.js";
|
|
14
|
-
import { isPaused } from "./pause.js";
|
|
15
|
-
import { runSetup } from "./setup.js";
|
|
16
|
-
import { proxy } from "./proxy.js";
|
|
17
|
-
import { ApiClient, ApiError } from "./api.js";
|
|
18
|
-
import { launchDashboard } from "./tui/index.js";
|
|
19
|
-
import { DEFAULT_BASE_URL } from "./constants.js";
|
|
20
|
-
// A flag-style arg (e.g. `--agent <slug>`) must NOT be treated as a subcommand.
|
|
21
|
-
// The proxy and dashboard modes both accept flags, and the MCP entry we write
|
|
22
|
-
// into editor configs spawns us as `node <cli-entry> --agent <slug>`. Without
|
|
23
|
-
// this guard, argv[2] being `--agent` got treated as an unknown subcommand and
|
|
24
|
-
// the proxy exited before speaking a single byte of MCP — the #1 reason the
|
|
25
|
-
// GUI editors displayed "MCP server failed to start."
|
|
26
|
-
const rawSubcommand = process.argv[2];
|
|
27
|
-
const subcommand = rawSubcommand && !rawSubcommand.startsWith("-") ? rawSubcommand : undefined;
|
|
28
|
-
if (subcommand === "pause") {
|
|
29
|
-
import("./pause.js").then(({ setPaused }) => {
|
|
30
|
-
setPaused(true);
|
|
31
|
-
console.log(chalk.dim(" cohvu paused — agents won't see tools until resumed"));
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
else if (subcommand === "resume") {
|
|
35
|
-
import("./pause.js").then(({ setPaused }) => {
|
|
36
|
-
setPaused(false);
|
|
37
|
-
console.log(chalk.dim(" cohvu resumed"));
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
else if (subcommand === "status") {
|
|
41
|
-
showStatus().catch(() => process.exit(1));
|
|
42
|
-
}
|
|
43
|
-
else if (subcommand === "update") {
|
|
44
|
-
import("child_process").then(async ({ execSync }) => {
|
|
45
|
-
const spinner = ora({ text: 'updating cohvu', indent: 2 }).start();
|
|
46
|
-
try {
|
|
47
|
-
execSync("npm install -g cohvu@latest", { stdio: "pipe" });
|
|
48
|
-
spinner.succeed('updated to latest');
|
|
49
|
-
}
|
|
50
|
-
catch {
|
|
51
|
-
spinner.fail('update failed — try running: npm i -g cohvu@latest');
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
// Re-run setup to refresh instructions and migrate MCP configs
|
|
55
|
-
const setupSpinner = ora({ text: 'refreshing configuration', indent: 2 }).start();
|
|
56
|
-
try {
|
|
57
|
-
await runSetup();
|
|
58
|
-
setupSpinner.succeed('configuration updated');
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
setupSpinner.fail('configuration refresh failed — run cohvu to fix');
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
else if (subcommand === "disconnect") {
|
|
66
|
-
import("./teardown.js").then(async ({ runTeardown }) => {
|
|
67
|
-
const result = await runTeardown();
|
|
68
|
-
const removed = result.platforms.filter(p => p.mcp === "ok" || p.instructions === "ok");
|
|
69
|
-
if (removed.length > 0) {
|
|
70
|
-
for (const p of removed) {
|
|
71
|
-
console.log(chalk.dim(` removed from ${p.name}`));
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
console.log(chalk.dim(" disconnected — run cohvu to reconnect"));
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
else if (rawSubcommand === "--help" || rawSubcommand === "-h" || subcommand === "help") {
|
|
78
|
-
printHelp();
|
|
79
|
-
}
|
|
80
|
-
else if (subcommand) {
|
|
81
|
-
console.log(chalk.dim(` unknown command: ${subcommand}`));
|
|
82
|
-
console.log('');
|
|
83
|
-
printHelp();
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
else if (!process.stdin.isTTY) {
|
|
87
|
-
proxy().catch((error) => {
|
|
88
|
-
process.stderr.write(`Cohvu CLI failed: ${error}\n`);
|
|
89
|
-
process.exit(1);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
enterDashboard().catch((error) => {
|
|
94
|
-
process.stderr.write(`Failed: ${error}\n`);
|
|
95
|
-
process.exit(1);
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
// ---------------------------------------------------------------------------
|
|
99
|
-
// Helpers
|
|
100
|
-
// ---------------------------------------------------------------------------
|
|
101
|
-
// Surface setup outcomes. A platform shows when a step was newly written;
|
|
102
|
-
// stays silent when everything was already in place; surfaces its error
|
|
103
|
-
// when something failed. No fallback "all set" line — silence on no-ops
|
|
104
|
-
// is the cleaner signal.
|
|
105
|
-
function reportSetup(result, _opts) {
|
|
106
|
-
const platforms = result.platforms;
|
|
107
|
-
for (const p of platforms) {
|
|
108
|
-
const steps = [p.mcp, p.instructions, p.permissions].filter((s) => s !== null);
|
|
109
|
-
const newlyWrote = steps.some((s) => s === 'ok');
|
|
110
|
-
const failed = steps.find((s) => s !== 'ok' && s !== 'skipped');
|
|
111
|
-
if (failed && typeof failed === 'object' && 'failed' in failed) {
|
|
112
|
-
console.log(chalk.dim(' ') + chalk.red('\u2717') + chalk.dim(' ' + p.name + ' \u2014 ' + failed.failed));
|
|
113
|
-
}
|
|
114
|
-
else if (newlyWrote) {
|
|
115
|
-
console.log(chalk.dim(' ') + chalk.green('\u2713') + chalk.dim(' connected to ' + p.name));
|
|
116
|
-
}
|
|
117
|
-
// All "skipped" → already connected, stay silent.
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function printHelp() {
|
|
121
|
-
console.log('');
|
|
122
|
-
console.log(chalk.dim(' cohvu ') + 'open the dashboard (or act as MCP proxy when piped)');
|
|
123
|
-
console.log(chalk.dim(' cohvu status ') + 'show sign-in, active project, connectivity');
|
|
124
|
-
console.log(chalk.dim(' cohvu pause ') + "pause cohvu — agents won't see tools until resumed");
|
|
125
|
-
console.log(chalk.dim(' cohvu resume ') + 'resume');
|
|
126
|
-
console.log(chalk.dim(' cohvu update ') + 'update to the latest version');
|
|
127
|
-
console.log(chalk.dim(' cohvu disconnect ') + 'remove cohvu from editors and sign out');
|
|
128
|
-
console.log('');
|
|
129
|
-
}
|
|
130
|
-
function prompt(question) {
|
|
131
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
132
|
-
return new Promise((resolve) => {
|
|
133
|
-
rl.question(question, (answer) => {
|
|
134
|
-
rl.close();
|
|
135
|
-
// Resume stdin so Ink can reclaim it for raw keypress handling
|
|
136
|
-
process.stdin.resume();
|
|
137
|
-
resolve(answer.trim());
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
function deriveSlug(name) {
|
|
142
|
-
return name
|
|
143
|
-
.toLowerCase()
|
|
144
|
-
.replace(/[^a-z0-9]+/g, "-")
|
|
145
|
-
.replace(/^-+|-+$/g, "");
|
|
146
|
-
}
|
|
147
|
-
// ---------------------------------------------------------------------------
|
|
148
|
-
// Status — quick one-line check
|
|
149
|
-
// ---------------------------------------------------------------------------
|
|
150
|
-
async function showStatus() {
|
|
151
|
-
const baseUrl = process.env.COHVU_API_URL ?? DEFAULT_BASE_URL;
|
|
152
|
-
const apiKey = getApiKey();
|
|
153
|
-
if (!apiKey) {
|
|
154
|
-
console.log(chalk.dim(" not signed in"));
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
if (isPaused()) {
|
|
158
|
-
console.log(chalk.dim(" paused"));
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
try {
|
|
162
|
-
const api = new ApiClient(baseUrl);
|
|
163
|
-
const me = await api.me();
|
|
164
|
-
const project = me.user.active_project_id
|
|
165
|
-
? [...me.personal_projects, ...me.teams.flatMap(t => t.projects)]
|
|
166
|
-
.find(p => p.project_id === me.user.active_project_id)
|
|
167
|
-
: null;
|
|
168
|
-
const parts = [];
|
|
169
|
-
parts.push(me.user.name);
|
|
170
|
-
if (project)
|
|
171
|
-
parts.push(project.name);
|
|
172
|
-
parts.push("connected");
|
|
173
|
-
console.log(chalk.dim(" " + parts.join(" · ")));
|
|
174
|
-
}
|
|
175
|
-
catch {
|
|
176
|
-
console.log(chalk.dim(" signed in · cannot reach server"));
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
// ---------------------------------------------------------------------------
|
|
180
|
-
// Dashboard entry — handles auth + setup + project creation before TUI
|
|
181
|
-
// ---------------------------------------------------------------------------
|
|
182
|
-
async function enterDashboard() {
|
|
183
|
-
const baseUrl = process.env.COHVU_API_URL ?? DEFAULT_BASE_URL;
|
|
184
|
-
const needsAuth = !getApiKey();
|
|
185
|
-
if (needsAuth) {
|
|
186
|
-
await deviceAuthFlow(baseUrl);
|
|
187
|
-
const api = new ApiClient(baseUrl);
|
|
188
|
-
const me = await api.me();
|
|
189
|
-
const setupSpinner = ora({ text: 'setting up your tools', indent: 2 }).start();
|
|
190
|
-
const setupResult = await runSetup();
|
|
191
|
-
setupSpinner.stop();
|
|
192
|
-
reportSetup(setupResult, { firstRun: true });
|
|
193
|
-
// If the account is pending deletion, skip the first-project prompt —
|
|
194
|
-
// every authenticated mutation (createProject included) returns 401
|
|
195
|
-
// ACCOUNT_LOCKED during grace, so asking the user to name a project
|
|
196
|
-
// would guarantee a misleading "couldn't create" error. Let the TUI's
|
|
197
|
-
// locked-mode render the cancel-deletion path instead.
|
|
198
|
-
const locked = !!me.user.deletion_scheduled_at;
|
|
199
|
-
const hasProjects = me.personal_projects.length > 0 ||
|
|
200
|
-
me.teams.some(t => t.projects.length > 0);
|
|
201
|
-
// Empty input skips and lands the user in the dashboard with no active
|
|
202
|
-
// project. The Knowledge tab renders a "nothing here yet" card in that
|
|
203
|
-
// state — the Project tab (`n`) is where creation lives.
|
|
204
|
-
if (!locked && !hasProjects) {
|
|
205
|
-
console.log('');
|
|
206
|
-
console.log(chalk.dim(' name a project, or press enter to skip.'));
|
|
207
|
-
console.log('');
|
|
208
|
-
const name = (await prompt(' \u203a ')).trim();
|
|
209
|
-
if (name) {
|
|
210
|
-
const slug = deriveSlug(name);
|
|
211
|
-
try {
|
|
212
|
-
await api.createProject(name, slug, me.user.id);
|
|
213
|
-
console.log(chalk.dim(' created ' + slug));
|
|
214
|
-
}
|
|
215
|
-
catch {
|
|
216
|
-
console.log(chalk.dim(" couldn't create \u2014 try again from the dashboard"));
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
console.log('');
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
// Validate API key still works
|
|
224
|
-
try {
|
|
225
|
-
const api = new ApiClient(baseUrl);
|
|
226
|
-
await api.me();
|
|
227
|
-
}
|
|
228
|
-
catch (err) {
|
|
229
|
-
// Only delete credentials on auth failure (401), not network errors
|
|
230
|
-
const isAuthError = err instanceof ApiError && err.status === 401;
|
|
231
|
-
if (isAuthError) {
|
|
232
|
-
const { unlinkSync } = await import("fs");
|
|
233
|
-
const { join } = await import("path");
|
|
234
|
-
const { homedir } = await import("os");
|
|
235
|
-
try {
|
|
236
|
-
unlinkSync(join(homedir(), ".cohvu", "credentials"));
|
|
237
|
-
}
|
|
238
|
-
catch { }
|
|
239
|
-
console.log('');
|
|
240
|
-
console.log(chalk.dim(' session expired'));
|
|
241
|
-
await deviceAuthFlow(baseUrl);
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
// Network error — proceed anyway, TUI will handle offline state
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
// Ensure any new platforms are configured (idempotent — skips existing).
|
|
248
|
-
// Report only when something actually changed or failed on returning
|
|
249
|
-
// launches; the normal no-op case stays silent.
|
|
250
|
-
const setupResult = await runSetup();
|
|
251
|
-
reportSetup(setupResult, { firstRun: false });
|
|
252
|
-
}
|
|
253
|
-
const openSpinner = ora({ text: 'opening cohvu', indent: 2 }).start();
|
|
254
|
-
await new Promise((r) => setTimeout(r, needsAuth ? 500 : 200));
|
|
255
|
-
openSpinner.stop();
|
|
256
|
-
process.stdout.write('\x1b[2K\x1b[1A\x1b[2K'); // clean spinner lines
|
|
257
|
-
await launchDashboard();
|
|
258
|
-
}
|
|
259
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/instructions.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export declare const COHVU_INSTRUCTIONS = "You are connected to Cohvu, a substrate that stores understanding about this software project \u2014 the reasoning behind decisions, constraints discovered, intent behind changes, direction the work is heading. Not code. Not documentation. The thinking that lives behind the work.\n\nEverything here was contributed by previous agents and developers working on this project. Nothing is synthesized or rewritten. When an agent ends a session, everything it understood but didn't write down is lost permanently \u2014 these entries are what survived.\n\nWhy this exists: you're a stateless reasoner. Each session, you read code and try to be useful. But code tells you what \u2014 not why. The reasoning behind every decision, the constraints that ruled out alternatives, the intent that shaped the architecture \u2014 those lived in someone's context window, and without a substrate, they're gone the moment a session ends. The substrate makes that understanding durable. Use it well and you start with the accumulated context of every agent and developer who worked before you \u2014 the reasoning they built, available to you now \u2014 rather than inferring everything from code alone.\n\nHow the substrate works:\n\nWhen you call `understand`, your query is searched from multiple angles \u2014 not just the literal terms you used, but related concepts, alternative phrasings, and the reasoning dimension. Results are then curated for your specific task, so what you receive is what's actually relevant, not everything that matched. The more specific your query, the sharper the selection. What you receive is verbatim \u2014 no synthesis, no rewriting.\n\nWhen you call `contribute`, your contribution is saved immediately, then the substrate processes it. Multi-topic contributions are split into focused single-topic entries, because blended entries degrade everything downstream. Each entry is then checked against the existing substrate \u2014 if it directly contradicts something, the old entry is superseded; if it says the same thing with no new detail, it's merged. Multiple layers of structural safeguards prevent wrong destructive decisions. Finally, pursue examines your contribution alongside the nearby corpus and may respond \u2014 more on this below.\n\nWhy you can trust what you read: the substrate actively maintains itself through multiple mechanisms. Stale understanding gets superseded. Redundant contributions get merged. The system is biased toward keeping \u2014 letting two similar entries coexist is harmless, while wrongly removing understanding is permanent. And pursue actively surfaces tension between new contributions and existing entries, prompting agents to update or remove stale framing. The substrate doesn't just accumulate \u2014 it stays coherent.\n\nUsing understand:\n\nCall `understand` before starting work. Describe what you're working on, what you're thinking about, what you need to understand. Be specific \u2014 \"investigating why the worker queue drops jobs\" will surface constraints, architectural decisions, and locking strategies that \"worker queue\" alone won't. Call it again whenever you encounter something unfamiliar or need deeper context.\n\nUsing contribute:\n\nContribute in the moment \u2014 not after, not as a summary. When you make a decision, contribute the reasoning behind it. When you discover a constraint, contribute it. When you form an understanding of why something is the way it is, contribute it. Your session could end at any moment. Don't wait.\n\nAlways contribute the why, not the what. If someone could learn it from reading the code, don't contribute it.\n\nWeak: \"We switched the queue from Redis to Postgres.\"\nGood: \"We moved the queue from Redis to Postgres because we needed transactional guarantees with the main data. Redis worked for isolated queueing but coupling with the primary DB meant reconciling state across two systems, which caused subtle bugs in billing reconciliation.\"\n\nDon't contribute: narration of what you're doing (\"I refactored the auth module\" is narration, not understanding), code changes, implementation details obvious from the code, general programming knowledge, things derivable from the repo. Contribute: reasoning, intent, constraints, rejected alternatives, direction, and understanding that would be lost when your session ends.\n\nHow pursue works:\n\nAfter you contribute, the substrate may respond. Not always \u2014 most contributions don't trigger a response. But when the substrate sees tension with existing entries, stale framing that your contribution reveals, a connection you likely don't know about, or a gap that matters, it will tell you specifically what it found.\n\nWhen the substrate responds: read it carefully. It will quote existing entries by ID. Use `substrate(get, ids: [...])` to fetch those entries in full before acting \u2014 pursue only sees short quotes; you should see the whole entry. Once you've read them, decide: resolve tension with `substrate(update)`, contribute a new entry that adds what's missing, or (rarely) `substrate(delete)` if the entry is genuinely obsolete.\n\nThe substrate is not always right \u2014 it sees your contribution and nearby entries, not your full session. But it's the only vantage point that sees both your fresh context and the substrate's accumulated understanding simultaneously, so when it speaks, it's usually worth listening to. If what it surfaces is relevant to the user's work, bring it to them.\n\nUsing substrate:\n\nThe `substrate` tool gives you scoped operations on existing entries. Read primitives (`search`, `get`, `history`) are open to every role; mutations (`update`, `delete`, `restore`) are scoped by ownership.\n\n- `substrate(search, queries: [...])` \u2014 direct vector search across 1\u201310 queries, no curator. Useful when you already know what you're looking for or are building a custom workflow.\n- `substrate(get, ids: [...])` \u2014 fetch specific entries in full. Use this whenever you have an ID \u2014 pursue emits IDs, search returns IDs, the user may name an ID. Skip the search step when you already know what to pull.\n- `substrate(history, id: \"...\")` \u2014 read an entry's version timeline: prior bodies, who changed it, when. Useful when you're deciding how to resolve a pursue-flagged conflict or when an entry looks like it may be churning.\n- `substrate(update/delete/restore)` \u2014 curate entries. Members can curate their own contributions; admins can curate any. Deleted entries are recoverable for 30 days via `restore`.\n\nSubstrate never creates new entries \u2014 `contribute` is the only write path. Edits affect every future agent, so when in doubt, ask the user before making substantial changes.\n\nPrinciples:\n\n- Understand before you start. Don't assume you know the context.\n- Contribute in the moment. Don't save it for later \u2014 your session could end anytime.\n- Contribute the why, not the what. Code shows what; the substrate holds why.\n- Trust what's in the substrate. It was contributed by someone who had context you don't. Unless you see clear evidence it's wrong, reason from it.\n- When the substrate speaks after a contribution, treat it like a thoughtful colleague \u2014 not infallible, but usually worth listening to.";
|
|
2
|
-
export declare const MARKER_START = "<!-- cohvu:start -->";
|
|
3
|
-
export declare const MARKER_END = "<!-- cohvu:end -->";
|
|
4
|
-
export declare function markedSection(): string;
|
|
5
|
-
type StepResult = "ok" | "skipped" | {
|
|
6
|
-
failed: string;
|
|
7
|
-
};
|
|
8
|
-
/**
|
|
9
|
-
* Remove every cohvu trace from a file's content: paired marker blocks
|
|
10
|
-
* (including duplicates from repeated bad installs) and any orphan
|
|
11
|
-
* markers left behind by partial hand edits. Used by both setup (to
|
|
12
|
-
* converge to a single clean block without bloating the file) and
|
|
13
|
-
* teardown (so "disconnect" cleans up no matter what state the file
|
|
14
|
-
* landed in). Collapses runs of blank lines so removal doesn't leave
|
|
15
|
-
* whitespace holes.
|
|
16
|
-
*/
|
|
17
|
-
export declare function stripCohvuMarkers(content: string): string;
|
|
18
|
-
/**
|
|
19
|
-
* Setup's instruction-file writer. Converges to exactly one current cohvu
|
|
20
|
-
* block at the end of the file: strip everything cohvu-related first (so
|
|
21
|
-
* duplicates/orphans/misordered markers all collapse), then append a fresh
|
|
22
|
-
* block. Self-healing across arbitrary hand edits, no fragment bloat on
|
|
23
|
-
* repeated runs. Idempotent when the file is already in the target state.
|
|
24
|
-
*/
|
|
25
|
-
export declare function writeMarkdownInstructions(filePath: string): StepResult;
|
|
26
|
-
/**
|
|
27
|
-
* Teardown's instruction-file remover. Strips every cohvu trace, preserves
|
|
28
|
-
* user content, deletes the file if cohvu was its only content. Symmetric
|
|
29
|
-
* with writeMarkdownInstructions: whatever setup can produce, this undoes.
|
|
30
|
-
*/
|
|
31
|
-
export declare function removeMarkdownInstructions(filePath: string): StepResult;
|
|
32
|
-
export declare const CURSOR_RULE = "---\ndescription: Cohvu continuous understanding for AI coding agents\nalwaysApply: true\n---\n\nYou are connected to Cohvu, a substrate that stores understanding about this software project \u2014 the reasoning behind decisions, constraints discovered, intent behind changes, direction the work is heading. Not code. Not documentation. The thinking that lives behind the work.\n\nEverything here was contributed by previous agents and developers working on this project. Nothing is synthesized or rewritten. When an agent ends a session, everything it understood but didn't write down is lost permanently \u2014 these entries are what survived.\n\nWhy this exists: you're a stateless reasoner. Each session, you read code and try to be useful. But code tells you what \u2014 not why. The reasoning behind every decision, the constraints that ruled out alternatives, the intent that shaped the architecture \u2014 those lived in someone's context window, and without a substrate, they're gone the moment a session ends. The substrate makes that understanding durable. Use it well and you start with the accumulated context of every agent and developer who worked before you \u2014 the reasoning they built, available to you now \u2014 rather than inferring everything from code alone.\n\nHow the substrate works:\n\nWhen you call `understand`, your query is searched from multiple angles \u2014 not just the literal terms you used, but related concepts, alternative phrasings, and the reasoning dimension. Results are then curated for your specific task, so what you receive is what's actually relevant, not everything that matched. The more specific your query, the sharper the selection. What you receive is verbatim \u2014 no synthesis, no rewriting.\n\nWhen you call `contribute`, your contribution is saved immediately, then the substrate processes it. Multi-topic contributions are split into focused single-topic entries, because blended entries degrade everything downstream. Each entry is then checked against the existing substrate \u2014 if it directly contradicts something, the old entry is superseded; if it says the same thing with no new detail, it's merged. Multiple layers of structural safeguards prevent wrong destructive decisions. Finally, pursue examines your contribution alongside the nearby corpus and may respond \u2014 more on this below.\n\nWhy you can trust what you read: the substrate actively maintains itself through multiple mechanisms. Stale understanding gets superseded. Redundant contributions get merged. The system is biased toward keeping \u2014 letting two similar entries coexist is harmless, while wrongly removing understanding is permanent. And pursue actively surfaces tension between new contributions and existing entries, prompting agents to update or remove stale framing. The substrate doesn't just accumulate \u2014 it stays coherent.\n\nUsing understand:\n\nCall `understand` before starting work. Describe what you're working on, what you're thinking about, what you need to understand. Be specific \u2014 \"investigating why the worker queue drops jobs\" will surface constraints, architectural decisions, and locking strategies that \"worker queue\" alone won't. Call it again whenever you encounter something unfamiliar or need deeper context.\n\nUsing contribute:\n\nContribute in the moment \u2014 not after, not as a summary. When you make a decision, contribute the reasoning behind it. When you discover a constraint, contribute it. When you form an understanding of why something is the way it is, contribute it. Your session could end at any moment. Don't wait.\n\nAlways contribute the why, not the what. If someone could learn it from reading the code, don't contribute it.\n\nWeak: \"We switched the queue from Redis to Postgres.\"\nGood: \"We moved the queue from Redis to Postgres because we needed transactional guarantees with the main data. Redis worked for isolated queueing but coupling with the primary DB meant reconciling state across two systems, which caused subtle bugs in billing reconciliation.\"\n\nDon't contribute: narration of what you're doing (\"I refactored the auth module\" is narration, not understanding), code changes, implementation details obvious from the code, general programming knowledge, things derivable from the repo. Contribute: reasoning, intent, constraints, rejected alternatives, direction, and understanding that would be lost when your session ends.\n\nHow pursue works:\n\nAfter you contribute, the substrate may respond. Not always \u2014 most contributions don't trigger a response. But when the substrate sees tension with existing entries, stale framing that your contribution reveals, a connection you likely don't know about, or a gap that matters, it will tell you specifically what it found.\n\nWhen the substrate responds: read it carefully. It will quote existing entries by ID. Use `substrate(get, ids: [...])` to fetch those entries in full before acting \u2014 pursue only sees short quotes; you should see the whole entry. Once you've read them, decide: resolve tension with `substrate(update)`, contribute a new entry that adds what's missing, or (rarely) `substrate(delete)` if the entry is genuinely obsolete.\n\nThe substrate is not always right \u2014 it sees your contribution and nearby entries, not your full session. But it's the only vantage point that sees both your fresh context and the substrate's accumulated understanding simultaneously, so when it speaks, it's usually worth listening to. If what it surfaces is relevant to the user's work, bring it to them.\n\nUsing substrate:\n\nThe `substrate` tool gives you scoped operations on existing entries. Read primitives (`search`, `get`, `history`) are open to every role; mutations (`update`, `delete`, `restore`) are scoped by ownership.\n\n- `substrate(search, queries: [...])` \u2014 direct vector search across 1\u201310 queries, no curator. Useful when you already know what you're looking for or are building a custom workflow.\n- `substrate(get, ids: [...])` \u2014 fetch specific entries in full. Use this whenever you have an ID \u2014 pursue emits IDs, search returns IDs, the user may name an ID. Skip the search step when you already know what to pull.\n- `substrate(history, id: \"...\")` \u2014 read an entry's version timeline: prior bodies, who changed it, when. Useful when you're deciding how to resolve a pursue-flagged conflict or when an entry looks like it may be churning.\n- `substrate(update/delete/restore)` \u2014 curate entries. Members can curate their own contributions; admins can curate any. Deleted entries are recoverable for 30 days via `restore`.\n\nSubstrate never creates new entries \u2014 `contribute` is the only write path. Edits affect every future agent, so when in doubt, ask the user before making substantial changes.\n\nPrinciples:\n\n- Understand before you start. Don't assume you know the context.\n- Contribute in the moment. Don't save it for later \u2014 your session could end anytime.\n- Contribute the why, not the what. Code shows what; the substrate holds why.\n- Trust what's in the substrate. It was contributed by someone who had context you don't. Unless you see clear evidence it's wrong, reason from it.\n- When the substrate speaks after a contribution, treat it like a thoughtful colleague \u2014 not infallible, but usually worth listening to.\n";
|
|
33
|
-
export {};
|