haansi 0.1.17 → 0.1.19
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/haansi.js +116 -45
- package/package.json +1 -1
package/dist/haansi.js
CHANGED
|
@@ -39,7 +39,7 @@ var require_package = __commonJS({
|
|
|
39
39
|
"package.json"(exports2, module2) {
|
|
40
40
|
module2.exports = {
|
|
41
41
|
name: "haansi",
|
|
42
|
-
version: "0.1.
|
|
42
|
+
version: "0.1.19",
|
|
43
43
|
description: "Haansi CLI - Session collector and MCP server for Claude Code",
|
|
44
44
|
bin: {
|
|
45
45
|
haansi: "./dist/haansi.js"
|
|
@@ -1917,6 +1917,17 @@ var require_node_cron = __commonJS({
|
|
|
1917
1917
|
|
|
1918
1918
|
// ../service-capture/claude-sessions/collector-daemon.ts
|
|
1919
1919
|
var collector_daemon_exports = {};
|
|
1920
|
+
function getOnDiskVersion() {
|
|
1921
|
+
try {
|
|
1922
|
+
const realEntry = (0, import_fs2.realpathSync)(process.argv[1]);
|
|
1923
|
+
const pkgPath = (0, import_path2.resolve)((0, import_path2.dirname)(realEntry), "..", "package.json");
|
|
1924
|
+
if (!(0, import_fs2.existsSync)(pkgPath)) return null;
|
|
1925
|
+
const pkg = JSON.parse((0, import_fs2.readFileSync)(pkgPath, "utf-8"));
|
|
1926
|
+
return pkg.version ?? null;
|
|
1927
|
+
} catch {
|
|
1928
|
+
return null;
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1920
1931
|
async function run() {
|
|
1921
1932
|
const projectPath = process.env.CLAUDE_PROJECT_PATH || void 0;
|
|
1922
1933
|
logger2.info("Collect run starting", { projectPath: projectPath ?? "all" });
|
|
@@ -1934,9 +1945,20 @@ async function run() {
|
|
|
1934
1945
|
}
|
|
1935
1946
|
}
|
|
1936
1947
|
async function main2() {
|
|
1937
|
-
logger2.info("Collector daemon starting", {
|
|
1948
|
+
logger2.info("Collector daemon starting", {
|
|
1949
|
+
schedule: SCHEDULE,
|
|
1950
|
+
version: IN_MEMORY_VERSION
|
|
1951
|
+
});
|
|
1938
1952
|
await run();
|
|
1939
1953
|
import_node_cron.default.schedule(SCHEDULE, async () => {
|
|
1954
|
+
const diskVersion = getOnDiskVersion();
|
|
1955
|
+
if (diskVersion && diskVersion !== IN_MEMORY_VERSION) {
|
|
1956
|
+
logger2.info("Version mismatch detected \u2014 restarting", {
|
|
1957
|
+
inMemory: IN_MEMORY_VERSION,
|
|
1958
|
+
onDisk: diskVersion
|
|
1959
|
+
});
|
|
1960
|
+
process.exit(0);
|
|
1961
|
+
}
|
|
1940
1962
|
logger2.info("Scheduled collect run triggered");
|
|
1941
1963
|
await run();
|
|
1942
1964
|
});
|
|
@@ -1948,17 +1970,19 @@ async function main2() {
|
|
|
1948
1970
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
1949
1971
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
1950
1972
|
}
|
|
1951
|
-
var import_dotenv2, import_path2, import_node_cron, logger2, SCHEDULE;
|
|
1973
|
+
var import_dotenv2, import_fs2, import_path2, import_node_cron, logger2, IN_MEMORY_VERSION, SCHEDULE;
|
|
1952
1974
|
var init_collector_daemon = __esm({
|
|
1953
1975
|
"../service-capture/claude-sessions/collector-daemon.ts"() {
|
|
1954
1976
|
"use strict";
|
|
1955
1977
|
import_dotenv2 = __toESM(require_main());
|
|
1978
|
+
import_fs2 = require("fs");
|
|
1956
1979
|
import_path2 = require("path");
|
|
1957
1980
|
import_node_cron = __toESM(require_node_cron());
|
|
1958
1981
|
init_collector();
|
|
1959
1982
|
init_logger();
|
|
1960
1983
|
(0, import_dotenv2.config)({ path: (0, import_path2.resolve)(__dirname, "../../../.env") });
|
|
1961
1984
|
logger2 = createLogger("collector-daemon");
|
|
1985
|
+
IN_MEMORY_VERSION = require_package().version;
|
|
1962
1986
|
SCHEDULE = process.env.CLAUDE_COLLECT_SCHEDULE ?? "*/30 * * * *";
|
|
1963
1987
|
main2().catch((err) => {
|
|
1964
1988
|
logger2.error("Daemon failed to start", err);
|
|
@@ -50669,7 +50693,7 @@ var require_view = __commonJS({
|
|
|
50669
50693
|
var debug = require_src()("express:view");
|
|
50670
50694
|
var path = require("node:path");
|
|
50671
50695
|
var fs = require("node:fs");
|
|
50672
|
-
var
|
|
50696
|
+
var dirname2 = path.dirname;
|
|
50673
50697
|
var basename2 = path.basename;
|
|
50674
50698
|
var extname = path.extname;
|
|
50675
50699
|
var join9 = path.join;
|
|
@@ -50708,7 +50732,7 @@ var require_view = __commonJS({
|
|
|
50708
50732
|
for (var i = 0; i < roots.length && !path2; i++) {
|
|
50709
50733
|
var root = roots[i];
|
|
50710
50734
|
var loc = resolve4(root, name);
|
|
50711
|
-
var dir =
|
|
50735
|
+
var dir = dirname2(loc);
|
|
50712
50736
|
var file2 = basename2(loc);
|
|
50713
50737
|
path2 = this.resolve(dir, file2);
|
|
50714
50738
|
}
|
|
@@ -56786,9 +56810,9 @@ var init_streamableHttp = __esm({
|
|
|
56786
56810
|
var mcp_server_exports = {};
|
|
56787
56811
|
function resolveToken2() {
|
|
56788
56812
|
if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
|
|
56789
|
-
if ((0,
|
|
56813
|
+
if ((0, import_fs3.existsSync)(CREDENTIALS_FILE4)) {
|
|
56790
56814
|
try {
|
|
56791
|
-
const creds = JSON.parse((0,
|
|
56815
|
+
const creds = JSON.parse((0, import_fs3.readFileSync)(CREDENTIALS_FILE4, "utf-8"));
|
|
56792
56816
|
if (creds.token) return creds.token;
|
|
56793
56817
|
} catch {
|
|
56794
56818
|
}
|
|
@@ -56872,13 +56896,13 @@ async function main3() {
|
|
|
56872
56896
|
await mcpServer.connect(transport);
|
|
56873
56897
|
}
|
|
56874
56898
|
}
|
|
56875
|
-
var import_dotenv3, import_path3,
|
|
56899
|
+
var import_dotenv3, import_path3, import_fs3, import_os2, DEFAULT_API_URL4, CREDENTIALS_FILE4, API_URL, TOKEN, contextSchema, isCollecting, lastCollectTime, COLLECT_COOLDOWN_MS, mcpServer, server;
|
|
56876
56900
|
var init_mcp_server2 = __esm({
|
|
56877
56901
|
"../service-capture/claude-sessions/mcp-server.ts"() {
|
|
56878
56902
|
"use strict";
|
|
56879
56903
|
import_dotenv3 = __toESM(require_main());
|
|
56880
56904
|
import_path3 = require("path");
|
|
56881
|
-
|
|
56905
|
+
import_fs3 = require("fs");
|
|
56882
56906
|
import_os2 = require("os");
|
|
56883
56907
|
init_collector();
|
|
56884
56908
|
init_src();
|
|
@@ -57194,7 +57218,26 @@ function resolveHaansiBin() {
|
|
|
57194
57218
|
}
|
|
57195
57219
|
return "haansi";
|
|
57196
57220
|
}
|
|
57197
|
-
|
|
57221
|
+
function resolveToken3() {
|
|
57222
|
+
if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
|
|
57223
|
+
if ((0, import_node_fs3.existsSync)(CREDENTIALS_FILE5)) {
|
|
57224
|
+
try {
|
|
57225
|
+
const creds = JSON.parse((0, import_node_fs3.readFileSync)(CREDENTIALS_FILE5, "utf-8"));
|
|
57226
|
+
if (typeof creds.token === "string" && creds.token) return creds.token;
|
|
57227
|
+
} catch {
|
|
57228
|
+
}
|
|
57229
|
+
}
|
|
57230
|
+
return null;
|
|
57231
|
+
}
|
|
57232
|
+
function parseTarget(arg) {
|
|
57233
|
+
if (!arg || arg === "all") return "all";
|
|
57234
|
+
if (arg === "solutions" || arg === "exchange") return arg;
|
|
57235
|
+
throw new Error(
|
|
57236
|
+
`Unknown target: ${arg}. Use one of: solutions, exchange, all (default).`
|
|
57237
|
+
);
|
|
57238
|
+
}
|
|
57239
|
+
async function setupMcp(targetArg) {
|
|
57240
|
+
const target = parseTarget(targetArg);
|
|
57198
57241
|
let config6 = {};
|
|
57199
57242
|
if ((0, import_node_fs3.existsSync)(CLAUDE_JSON)) {
|
|
57200
57243
|
try {
|
|
@@ -57205,22 +57248,44 @@ async function setupMcp() {
|
|
|
57205
57248
|
);
|
|
57206
57249
|
}
|
|
57207
57250
|
}
|
|
57208
|
-
if (!config6.mcpServers) {
|
|
57209
|
-
|
|
57251
|
+
if (!config6.mcpServers) config6.mcpServers = {};
|
|
57252
|
+
const installed = [];
|
|
57253
|
+
const warnings = [];
|
|
57254
|
+
if (target === "all" || target === "solutions") {
|
|
57255
|
+
const haansiBin = resolveHaansiBin();
|
|
57256
|
+
config6.mcpServers["haansi-solutions"] = {
|
|
57257
|
+
command: haansiBin,
|
|
57258
|
+
args: ["mcp-server"]
|
|
57259
|
+
};
|
|
57260
|
+
installed.push(`haansi-solutions (stdio \u2192 ${haansiBin} mcp-server)`);
|
|
57261
|
+
}
|
|
57262
|
+
if (target === "all" || target === "exchange") {
|
|
57263
|
+
const token = resolveToken3();
|
|
57264
|
+
if (!token) {
|
|
57265
|
+
const msg = "haansi-exchange not registered: no token found. Run `haansi auth login` first, or set HAANSI_TOKEN.";
|
|
57266
|
+
if (target === "exchange") {
|
|
57267
|
+
console.error(msg);
|
|
57268
|
+
process.exit(1);
|
|
57269
|
+
}
|
|
57270
|
+
warnings.push(msg);
|
|
57271
|
+
} else {
|
|
57272
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL5;
|
|
57273
|
+
const exchangeUrl = `${apiUrl.replace(/\/+$/, "")}/api/v1/mcp/exchange`;
|
|
57274
|
+
config6.mcpServers["haansi-exchange"] = {
|
|
57275
|
+
type: "http",
|
|
57276
|
+
url: exchangeUrl,
|
|
57277
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
57278
|
+
};
|
|
57279
|
+
installed.push(`haansi-exchange (http \u2192 ${exchangeUrl})`);
|
|
57280
|
+
}
|
|
57210
57281
|
}
|
|
57211
|
-
const haansiBin = resolveHaansiBin();
|
|
57212
|
-
config6.mcpServers["haansi-solutions"] = {
|
|
57213
|
-
command: haansiBin,
|
|
57214
|
-
args: ["mcp-server"]
|
|
57215
|
-
};
|
|
57216
57282
|
(0, import_node_fs3.writeFileSync)(CLAUDE_JSON, JSON.stringify(config6, null, 2) + "\n", "utf-8");
|
|
57217
|
-
console.log(`MCP
|
|
57218
|
-
console.log(`
|
|
57219
|
-
console.log(
|
|
57220
|
-
|
|
57221
|
-
);
|
|
57283
|
+
console.log(`MCP servers configured in ${CLAUDE_JSON}`);
|
|
57284
|
+
for (const entry of installed) console.log(` \u2022 ${entry}`);
|
|
57285
|
+
for (const w of warnings) console.log(` ! ${w}`);
|
|
57286
|
+
console.log("\nRestart Claude Code to activate the changes.");
|
|
57222
57287
|
}
|
|
57223
|
-
var import_node_fs3, import_node_path3, import_node_os3, import_node_child_process2, CLAUDE_JSON;
|
|
57288
|
+
var import_node_fs3, import_node_path3, import_node_os3, import_node_child_process2, CLAUDE_JSON, CREDENTIALS_FILE5, DEFAULT_API_URL5;
|
|
57224
57289
|
var init_setup_mcp = __esm({
|
|
57225
57290
|
"src/commands/setup-mcp.ts"() {
|
|
57226
57291
|
"use strict";
|
|
@@ -57229,6 +57294,8 @@ var init_setup_mcp = __esm({
|
|
|
57229
57294
|
import_node_os3 = require("node:os");
|
|
57230
57295
|
import_node_child_process2 = require("node:child_process");
|
|
57231
57296
|
CLAUDE_JSON = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".claude.json");
|
|
57297
|
+
CREDENTIALS_FILE5 = (0, import_node_path3.join)((0, import_node_os3.homedir)(), ".haansi", "credentials.json");
|
|
57298
|
+
DEFAULT_API_URL5 = "https://api.haansi.co";
|
|
57232
57299
|
}
|
|
57233
57300
|
});
|
|
57234
57301
|
|
|
@@ -57331,11 +57398,11 @@ var config_exports = {};
|
|
|
57331
57398
|
__export(config_exports, {
|
|
57332
57399
|
config: () => config5
|
|
57333
57400
|
});
|
|
57334
|
-
function
|
|
57401
|
+
function resolveToken4() {
|
|
57335
57402
|
if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
|
|
57336
|
-
if ((0, import_node_fs5.existsSync)(
|
|
57403
|
+
if ((0, import_node_fs5.existsSync)(CREDENTIALS_FILE6)) {
|
|
57337
57404
|
try {
|
|
57338
|
-
const creds = JSON.parse((0, import_node_fs5.readFileSync)(
|
|
57405
|
+
const creds = JSON.parse((0, import_node_fs5.readFileSync)(CREDENTIALS_FILE6, "utf-8"));
|
|
57339
57406
|
if (creds.token) return creds.token;
|
|
57340
57407
|
} catch (err) {
|
|
57341
57408
|
console.error("Failed to read credentials file:", err);
|
|
@@ -57344,7 +57411,7 @@ function resolveToken3() {
|
|
|
57344
57411
|
return null;
|
|
57345
57412
|
}
|
|
57346
57413
|
async function config5(args) {
|
|
57347
|
-
const token =
|
|
57414
|
+
const token = resolveToken4();
|
|
57348
57415
|
if (!token) {
|
|
57349
57416
|
console.error(
|
|
57350
57417
|
"Error: No token found. Run `haansi init` or set HAANSI_TOKEN."
|
|
@@ -57352,7 +57419,7 @@ async function config5(args) {
|
|
|
57352
57419
|
process.exit(1);
|
|
57353
57420
|
return;
|
|
57354
57421
|
}
|
|
57355
|
-
const apiUrl = process.env.HAANSI_API_URL ??
|
|
57422
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL6;
|
|
57356
57423
|
const subcommand = args[0];
|
|
57357
57424
|
if (subcommand === "get") {
|
|
57358
57425
|
const key = args[1];
|
|
@@ -57427,15 +57494,15 @@ Supported keys:
|
|
|
57427
57494
|
if (subcommand !== void 0) process.exit(1);
|
|
57428
57495
|
}
|
|
57429
57496
|
}
|
|
57430
|
-
var import_node_fs5, import_node_path5, import_node_os5,
|
|
57497
|
+
var import_node_fs5, import_node_path5, import_node_os5, DEFAULT_API_URL6, CREDENTIALS_FILE6, VALID_SESSION_MODES;
|
|
57431
57498
|
var init_config = __esm({
|
|
57432
57499
|
"src/commands/config.ts"() {
|
|
57433
57500
|
"use strict";
|
|
57434
57501
|
import_node_fs5 = require("node:fs");
|
|
57435
57502
|
import_node_path5 = require("node:path");
|
|
57436
57503
|
import_node_os5 = require("node:os");
|
|
57437
|
-
|
|
57438
|
-
|
|
57504
|
+
DEFAULT_API_URL6 = "https://api.haansi.co";
|
|
57505
|
+
CREDENTIALS_FILE6 = (0, import_node_path5.join)((0, import_node_os5.homedir)(), ".haansi", "credentials.json");
|
|
57439
57506
|
VALID_SESSION_MODES = ["private", "org"];
|
|
57440
57507
|
}
|
|
57441
57508
|
});
|
|
@@ -57447,11 +57514,11 @@ __export(list_exports, {
|
|
|
57447
57514
|
saveKnowledge: () => saveKnowledge,
|
|
57448
57515
|
searchKnowledge: () => searchKnowledge
|
|
57449
57516
|
});
|
|
57450
|
-
function
|
|
57517
|
+
function resolveToken5() {
|
|
57451
57518
|
if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
|
|
57452
|
-
if ((0, import_node_fs6.existsSync)(
|
|
57519
|
+
if ((0, import_node_fs6.existsSync)(CREDENTIALS_FILE7)) {
|
|
57453
57520
|
try {
|
|
57454
|
-
const creds = JSON.parse((0, import_node_fs6.readFileSync)(
|
|
57521
|
+
const creds = JSON.parse((0, import_node_fs6.readFileSync)(CREDENTIALS_FILE7, "utf-8"));
|
|
57455
57522
|
if (creds.token) return creds.token;
|
|
57456
57523
|
} catch (err) {
|
|
57457
57524
|
console.error("Failed to read credentials file:", err);
|
|
@@ -57485,8 +57552,8 @@ async function apiPost2(path, body, token, apiUrl) {
|
|
|
57485
57552
|
return response.json();
|
|
57486
57553
|
}
|
|
57487
57554
|
async function list(options) {
|
|
57488
|
-
const apiUrl = process.env.HAANSI_API_URL ??
|
|
57489
|
-
const token =
|
|
57555
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL7;
|
|
57556
|
+
const token = resolveToken5();
|
|
57490
57557
|
let data;
|
|
57491
57558
|
if (options.search) {
|
|
57492
57559
|
data = await apiGet3(
|
|
@@ -57511,8 +57578,8 @@ async function list(options) {
|
|
|
57511
57578
|
${data.results.length} result(s)`);
|
|
57512
57579
|
}
|
|
57513
57580
|
async function searchKnowledge(options) {
|
|
57514
|
-
const apiUrl = process.env.HAANSI_API_URL ??
|
|
57515
|
-
const token =
|
|
57581
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL7;
|
|
57582
|
+
const token = resolveToken5();
|
|
57516
57583
|
let url2 = `/sessions/knowledge/search?q=${encodeURIComponent(options.query)}&limit=${options.limit}`;
|
|
57517
57584
|
if (options.artifactType) {
|
|
57518
57585
|
url2 += `&artifact_type=${encodeURIComponent(options.artifactType)}`;
|
|
@@ -57528,8 +57595,8 @@ async function searchKnowledge(options) {
|
|
|
57528
57595
|
${data.results.length} result(s)`);
|
|
57529
57596
|
}
|
|
57530
57597
|
async function saveKnowledge(options) {
|
|
57531
|
-
const apiUrl = process.env.HAANSI_API_URL ??
|
|
57532
|
-
const token =
|
|
57598
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL7;
|
|
57599
|
+
const token = resolveToken5();
|
|
57533
57600
|
const body = {
|
|
57534
57601
|
problem_description: options.problem,
|
|
57535
57602
|
solution_summary: options.solution,
|
|
@@ -57544,15 +57611,15 @@ async function saveKnowledge(options) {
|
|
|
57544
57611
|
console.log(` Solution: ${data.solution_summary}`);
|
|
57545
57612
|
console.log("\nThis is now searchable via `haansi search-solutions`.");
|
|
57546
57613
|
}
|
|
57547
|
-
var import_node_fs6, import_node_path6, import_node_os6,
|
|
57614
|
+
var import_node_fs6, import_node_path6, import_node_os6, DEFAULT_API_URL7, CREDENTIALS_FILE7;
|
|
57548
57615
|
var init_list = __esm({
|
|
57549
57616
|
"src/commands/list.ts"() {
|
|
57550
57617
|
"use strict";
|
|
57551
57618
|
import_node_fs6 = require("node:fs");
|
|
57552
57619
|
import_node_path6 = require("node:path");
|
|
57553
57620
|
import_node_os6 = require("node:os");
|
|
57554
|
-
|
|
57555
|
-
|
|
57621
|
+
DEFAULT_API_URL7 = "https://api.haansi.co";
|
|
57622
|
+
CREDENTIALS_FILE7 = (0, import_node_path6.join)((0, import_node_os6.homedir)(), ".haansi", "credentials.json");
|
|
57556
57623
|
}
|
|
57557
57624
|
});
|
|
57558
57625
|
|
|
@@ -57614,7 +57681,8 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57614
57681
|
}
|
|
57615
57682
|
case "setup-mcp": {
|
|
57616
57683
|
const { setupMcp: setupMcp2 } = await Promise.resolve().then(() => (init_setup_mcp(), setup_mcp_exports));
|
|
57617
|
-
|
|
57684
|
+
const targetArg = process.argv[3];
|
|
57685
|
+
await setupMcp2(targetArg);
|
|
57618
57686
|
break;
|
|
57619
57687
|
}
|
|
57620
57688
|
case "setup-daemon": {
|
|
@@ -57718,7 +57786,10 @@ Commands:
|
|
|
57718
57786
|
|
|
57719
57787
|
daemon Run the collector on a schedule (every 30 min)
|
|
57720
57788
|
mcp-server Start the Haansi MCP server (used by Claude Code)
|
|
57721
|
-
setup-mcp
|
|
57789
|
+
setup-mcp [target] Register MCP servers in ~/.claude.json
|
|
57790
|
+
target: solutions | exchange | all (default: all)
|
|
57791
|
+
- solutions: stdio, per-org search/save tools
|
|
57792
|
+
- exchange: http, cross-org marketplace (read-only)
|
|
57722
57793
|
setup-daemon Install launchd service to auto-start daemon on login (macOS)
|
|
57723
57794
|
help Show this help message
|
|
57724
57795
|
|