haansi 0.1.7 → 0.1.9
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 +180 -26
- package/package.json +1 -1
package/dist/haansi.js
CHANGED
|
@@ -34,6 +34,36 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
34
34
|
));
|
|
35
35
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
36
|
|
|
37
|
+
// package.json
|
|
38
|
+
var require_package = __commonJS({
|
|
39
|
+
"package.json"(exports2, module2) {
|
|
40
|
+
module2.exports = {
|
|
41
|
+
name: "haansi",
|
|
42
|
+
version: "0.1.9",
|
|
43
|
+
description: "Haansi CLI - Session collector and MCP server for Claude Code",
|
|
44
|
+
bin: {
|
|
45
|
+
haansi: "./dist/haansi.js"
|
|
46
|
+
},
|
|
47
|
+
files: [
|
|
48
|
+
"dist/",
|
|
49
|
+
"README.md"
|
|
50
|
+
],
|
|
51
|
+
scripts: {
|
|
52
|
+
build: "node build.mjs",
|
|
53
|
+
prepublishOnly: "npm run build"
|
|
54
|
+
},
|
|
55
|
+
devDependencies: {
|
|
56
|
+
esbuild: "^0.27.0",
|
|
57
|
+
typescript: "^5.7.2",
|
|
58
|
+
"@types/node": "^22.10.1"
|
|
59
|
+
},
|
|
60
|
+
engines: {
|
|
61
|
+
node: ">=18.0.0"
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
37
67
|
// src/commands/init.ts
|
|
38
68
|
var init_exports = {};
|
|
39
69
|
__export(init_exports, {
|
|
@@ -106,7 +136,7 @@ var init_init = __esm({
|
|
|
106
136
|
});
|
|
107
137
|
|
|
108
138
|
// ../../node_modules/dotenv/package.json
|
|
109
|
-
var
|
|
139
|
+
var require_package2 = __commonJS({
|
|
110
140
|
"../../node_modules/dotenv/package.json"(exports2, module2) {
|
|
111
141
|
module2.exports = {
|
|
112
142
|
name: "dotenv",
|
|
@@ -180,7 +210,7 @@ var require_main = __commonJS({
|
|
|
180
210
|
var path = require("path");
|
|
181
211
|
var os = require("os");
|
|
182
212
|
var crypto6 = require("crypto");
|
|
183
|
-
var packageJson =
|
|
213
|
+
var packageJson = require_package2();
|
|
184
214
|
var version3 = packageJson.version;
|
|
185
215
|
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
186
216
|
function parse4(src) {
|
|
@@ -56673,6 +56703,14 @@ var init_mcp_server2 = __esm({
|
|
|
56673
56703
|
type: "string",
|
|
56674
56704
|
description: "Project path or identifier"
|
|
56675
56705
|
},
|
|
56706
|
+
git_branch: {
|
|
56707
|
+
type: "string",
|
|
56708
|
+
description: "Current git branch name"
|
|
56709
|
+
},
|
|
56710
|
+
git_remote_url: {
|
|
56711
|
+
type: "string",
|
|
56712
|
+
description: "Git remote origin URL (e.g. github.com/org/repo)"
|
|
56713
|
+
},
|
|
56676
56714
|
tags: {
|
|
56677
56715
|
type: "array",
|
|
56678
56716
|
items: { type: "string" },
|
|
@@ -56802,6 +56840,8 @@ var init_mcp_server2 = __esm({
|
|
|
56802
56840
|
files_modified,
|
|
56803
56841
|
complexity,
|
|
56804
56842
|
project_path,
|
|
56843
|
+
git_branch,
|
|
56844
|
+
git_remote_url,
|
|
56805
56845
|
tags,
|
|
56806
56846
|
model,
|
|
56807
56847
|
source_tool,
|
|
@@ -56825,6 +56865,8 @@ var init_mcp_server2 = __esm({
|
|
|
56825
56865
|
files_modified,
|
|
56826
56866
|
complexity,
|
|
56827
56867
|
project_path,
|
|
56868
|
+
git_branch,
|
|
56869
|
+
git_remote_url,
|
|
56828
56870
|
tags,
|
|
56829
56871
|
model,
|
|
56830
56872
|
source_tool
|
|
@@ -57123,7 +57165,9 @@ var init_config = __esm({
|
|
|
57123
57165
|
// src/commands/list.ts
|
|
57124
57166
|
var list_exports = {};
|
|
57125
57167
|
__export(list_exports, {
|
|
57126
|
-
list: () => list
|
|
57168
|
+
list: () => list,
|
|
57169
|
+
saveKnowledge: () => saveKnowledge,
|
|
57170
|
+
searchKnowledge: () => searchKnowledge
|
|
57127
57171
|
});
|
|
57128
57172
|
function resolveToken4() {
|
|
57129
57173
|
if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
|
|
@@ -57146,6 +57190,21 @@ async function apiGet3(path, token, apiUrl) {
|
|
|
57146
57190
|
}
|
|
57147
57191
|
return response.json();
|
|
57148
57192
|
}
|
|
57193
|
+
async function apiPost2(path, body, token, apiUrl) {
|
|
57194
|
+
const response = await fetch(`${apiUrl}/api/v1${path}`, {
|
|
57195
|
+
method: "POST",
|
|
57196
|
+
headers: {
|
|
57197
|
+
Authorization: `Bearer ${token}`,
|
|
57198
|
+
"Content-Type": "application/json"
|
|
57199
|
+
},
|
|
57200
|
+
body: JSON.stringify(body)
|
|
57201
|
+
});
|
|
57202
|
+
if (!response.ok) {
|
|
57203
|
+
const text = await response.text().catch(() => "");
|
|
57204
|
+
throw new Error(`API error ${response.status}: ${text.slice(0, 200)}`);
|
|
57205
|
+
}
|
|
57206
|
+
return response.json();
|
|
57207
|
+
}
|
|
57149
57208
|
async function list(options) {
|
|
57150
57209
|
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL5;
|
|
57151
57210
|
const token = resolveToken4();
|
|
@@ -57172,6 +57231,41 @@ async function list(options) {
|
|
|
57172
57231
|
console.log(`
|
|
57173
57232
|
${data.results.length} result(s)`);
|
|
57174
57233
|
}
|
|
57234
|
+
async function searchKnowledge(options) {
|
|
57235
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL5;
|
|
57236
|
+
const token = resolveToken4();
|
|
57237
|
+
let url2 = `/sessions/knowledge/search?q=${encodeURIComponent(options.query)}&limit=${options.limit}`;
|
|
57238
|
+
if (options.artifactType) {
|
|
57239
|
+
url2 += `&artifact_type=${encodeURIComponent(options.artifactType)}`;
|
|
57240
|
+
}
|
|
57241
|
+
const data = await apiGet3(url2, token, apiUrl);
|
|
57242
|
+
if (!data.results || data.results.length === 0) {
|
|
57243
|
+
console.log("No knowledge artifacts found matching your query.");
|
|
57244
|
+
return;
|
|
57245
|
+
}
|
|
57246
|
+
const separator = "\n" + "\u2500".repeat(60) + "\n";
|
|
57247
|
+
console.log(data.results.join(separator));
|
|
57248
|
+
console.log(`
|
|
57249
|
+
${data.results.length} result(s)`);
|
|
57250
|
+
}
|
|
57251
|
+
async function saveKnowledge(options) {
|
|
57252
|
+
const apiUrl = process.env.HAANSI_API_URL ?? DEFAULT_API_URL5;
|
|
57253
|
+
const token = resolveToken4();
|
|
57254
|
+
const body = {
|
|
57255
|
+
problem_description: options.problem,
|
|
57256
|
+
solution_summary: options.solution,
|
|
57257
|
+
source_tool: "haansi-cli"
|
|
57258
|
+
};
|
|
57259
|
+
if (options.sessionType) body.session_type = options.sessionType;
|
|
57260
|
+
if (options.complexity) body.complexity = options.complexity;
|
|
57261
|
+
if (options.tags) body.tags = options.tags;
|
|
57262
|
+
const data = await apiPost2("/sessions/knowledge", body, token, apiUrl);
|
|
57263
|
+
console.log("Knowledge saved successfully.");
|
|
57264
|
+
console.log(` ID: ${data.id}`);
|
|
57265
|
+
console.log(` Problem: ${data.problem_description}`);
|
|
57266
|
+
console.log(` Solution: ${data.solution_summary}`);
|
|
57267
|
+
console.log("\nThis is now searchable via `haansi search-solutions`.");
|
|
57268
|
+
}
|
|
57175
57269
|
var import_node_fs5, import_node_path5, import_node_os5, DEFAULT_API_URL5, CREDENTIALS_FILE5;
|
|
57176
57270
|
var init_list = __esm({
|
|
57177
57271
|
"src/commands/list.ts"() {
|
|
@@ -57185,8 +57279,13 @@ var init_list = __esm({
|
|
|
57185
57279
|
});
|
|
57186
57280
|
|
|
57187
57281
|
// src/index.ts
|
|
57282
|
+
var { version: VERSION } = require_package();
|
|
57188
57283
|
var command = process.argv[2];
|
|
57189
57284
|
async function run2() {
|
|
57285
|
+
if (command === "--version" || command === "-v") {
|
|
57286
|
+
console.log(VERSION);
|
|
57287
|
+
return;
|
|
57288
|
+
}
|
|
57190
57289
|
switch (command) {
|
|
57191
57290
|
case "init": {
|
|
57192
57291
|
const { init: init2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
@@ -57237,11 +57336,13 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57237
57336
|
await config6(process.argv.slice(3));
|
|
57238
57337
|
break;
|
|
57239
57338
|
}
|
|
57339
|
+
// ── Solution & Knowledge commands (consistent with MCP tool names) ──
|
|
57340
|
+
case "search-solutions":
|
|
57240
57341
|
case "search": {
|
|
57241
57342
|
const { list: list2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
57242
57343
|
const query = process.argv[3];
|
|
57243
57344
|
if (!query || query.startsWith("--")) {
|
|
57244
|
-
console.error("Usage: haansi search <query> [--limit <n>]");
|
|
57345
|
+
console.error("Usage: haansi search-solutions <query> [--limit <n>]");
|
|
57245
57346
|
process.exit(1);
|
|
57246
57347
|
}
|
|
57247
57348
|
const limitIdx = process.argv.indexOf("--limit");
|
|
@@ -57249,6 +57350,7 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57249
57350
|
await list2({ search: query, limit });
|
|
57250
57351
|
break;
|
|
57251
57352
|
}
|
|
57353
|
+
case "list-solutions":
|
|
57252
57354
|
case "list": {
|
|
57253
57355
|
const { list: list2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
57254
57356
|
const searchIdx = process.argv.indexOf("--search");
|
|
@@ -57258,6 +57360,43 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57258
57360
|
await list2({ search, limit });
|
|
57259
57361
|
break;
|
|
57260
57362
|
}
|
|
57363
|
+
case "search-knowledge": {
|
|
57364
|
+
const { searchKnowledge: searchKnowledge2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
57365
|
+
const query = process.argv[3];
|
|
57366
|
+
if (!query || query.startsWith("--")) {
|
|
57367
|
+
console.error(
|
|
57368
|
+
"Usage: haansi search-knowledge <query> [--type <artifact_type>] [--limit <n>]"
|
|
57369
|
+
);
|
|
57370
|
+
process.exit(1);
|
|
57371
|
+
}
|
|
57372
|
+
const typeIdx = process.argv.indexOf("--type");
|
|
57373
|
+
const artifactType = typeIdx !== -1 ? process.argv[typeIdx + 1] : void 0;
|
|
57374
|
+
const limitIdx = process.argv.indexOf("--limit");
|
|
57375
|
+
const limit = limitIdx !== -1 ? parseInt(process.argv[limitIdx + 1], 10) : 10;
|
|
57376
|
+
await searchKnowledge2({ query, artifactType, limit });
|
|
57377
|
+
break;
|
|
57378
|
+
}
|
|
57379
|
+
case "save-knowledge": {
|
|
57380
|
+
const { saveKnowledge: saveKnowledge2 } = await Promise.resolve().then(() => (init_list(), list_exports));
|
|
57381
|
+
const problemIdx = process.argv.indexOf("--problem");
|
|
57382
|
+
const solutionIdx = process.argv.indexOf("--solution");
|
|
57383
|
+
if (problemIdx === -1 || solutionIdx === -1) {
|
|
57384
|
+
console.error(
|
|
57385
|
+
'Usage: haansi save-knowledge --problem "description" --solution "summary" [--type <session_type>] [--complexity <simple|moderate|complex>] [--tags tag1,tag2]'
|
|
57386
|
+
);
|
|
57387
|
+
process.exit(1);
|
|
57388
|
+
}
|
|
57389
|
+
const problem = process.argv[problemIdx + 1];
|
|
57390
|
+
const solution = process.argv[solutionIdx + 1];
|
|
57391
|
+
const typeIdx = process.argv.indexOf("--type");
|
|
57392
|
+
const sessionType = typeIdx !== -1 ? process.argv[typeIdx + 1] : void 0;
|
|
57393
|
+
const complexityIdx = process.argv.indexOf("--complexity");
|
|
57394
|
+
const complexity = complexityIdx !== -1 ? process.argv[complexityIdx + 1] : void 0;
|
|
57395
|
+
const tagsIdx = process.argv.indexOf("--tags");
|
|
57396
|
+
const tags = tagsIdx !== -1 ? process.argv[tagsIdx + 1].split(",") : void 0;
|
|
57397
|
+
await saveKnowledge2({ problem, solution, sessionType, complexity, tags });
|
|
57398
|
+
break;
|
|
57399
|
+
}
|
|
57261
57400
|
case "help":
|
|
57262
57401
|
default: {
|
|
57263
57402
|
printUsage();
|
|
@@ -57268,37 +57407,52 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
57268
57407
|
}
|
|
57269
57408
|
function printUsage() {
|
|
57270
57409
|
console.log(`
|
|
57271
|
-
Haansi CLI \u2014 Session collector and MCP server for Claude Code
|
|
57410
|
+
Haansi CLI v${VERSION} \u2014 Session collector and MCP server for Claude Code
|
|
57272
57411
|
|
|
57273
57412
|
Usage:
|
|
57274
57413
|
haansi <command> [options]
|
|
57275
57414
|
|
|
57276
57415
|
Commands:
|
|
57277
|
-
init
|
|
57278
|
-
collect
|
|
57279
|
-
config get [key]
|
|
57280
|
-
config set <key> <val>
|
|
57281
|
-
|
|
57282
|
-
|
|
57283
|
-
|
|
57284
|
-
|
|
57285
|
-
|
|
57286
|
-
|
|
57287
|
-
|
|
57288
|
-
|
|
57289
|
-
|
|
57290
|
-
|
|
57416
|
+
init Authenticate and save your API token
|
|
57417
|
+
collect Upload new/changed Claude sessions once
|
|
57418
|
+
config get [key] Show your preferences (e.g. session_mode)
|
|
57419
|
+
config set <key> <val> Update a preference
|
|
57420
|
+
|
|
57421
|
+
search-solutions <query> Semantic search over mined solutions
|
|
57422
|
+
list-solutions List recent mined solutions
|
|
57423
|
+
search-knowledge <query> Search knowledge artifacts (cards, decisions, etc.)
|
|
57424
|
+
save-knowledge Save a problem/solution for future retrieval
|
|
57425
|
+
|
|
57426
|
+
daemon Run the collector on a schedule (every 30 min)
|
|
57427
|
+
mcp-server Start the Haansi MCP server (used by Claude Code)
|
|
57428
|
+
setup-mcp Add haansi-solutions MCP entry to ~/.claude.json
|
|
57429
|
+
setup-daemon Install launchd service to auto-start daemon on login (macOS)
|
|
57430
|
+
help Show this help message
|
|
57431
|
+
|
|
57432
|
+
Options:
|
|
57433
|
+
--version, -v Show installed version
|
|
57434
|
+
--limit <n> Number of results (default: 5 for search, 10 for list)
|
|
57435
|
+
|
|
57436
|
+
Options for search-knowledge:
|
|
57437
|
+
--type <artifact_type> Filter by type (knowledge_card, decision_record, etc.)
|
|
57438
|
+
|
|
57439
|
+
Options for save-knowledge:
|
|
57440
|
+
--problem "description" Problem description (required)
|
|
57441
|
+
--solution "summary" Solution summary (required)
|
|
57442
|
+
--type <session_type> Session type (bug_fix, feature, refactor, general)
|
|
57443
|
+
--complexity <level> simple, moderate, or complex
|
|
57444
|
+
--tags tag1,tag2 Comma-separated tags
|
|
57291
57445
|
|
|
57292
57446
|
Options for collect:
|
|
57293
|
-
--force-all
|
|
57294
|
-
--dry-run
|
|
57295
|
-
--limit <n>
|
|
57447
|
+
--force-all Re-upload all sessions, not just new ones
|
|
57448
|
+
--dry-run Scan without uploading
|
|
57449
|
+
--limit <n> Upload at most n sessions
|
|
57296
57450
|
|
|
57297
57451
|
Environment variables:
|
|
57298
|
-
HAANSI_TOKEN
|
|
57299
|
-
HAANSI_API_URL
|
|
57300
|
-
CLAUDE_PROJECT_PATH
|
|
57301
|
-
CLAUDE_COLLECT_SCHEDULE
|
|
57452
|
+
HAANSI_TOKEN API token (or use \`haansi init\` to save it)
|
|
57453
|
+
HAANSI_API_URL API base URL (default: https://api.haansi.co)
|
|
57454
|
+
CLAUDE_PROJECT_PATH Collect from a specific project path only
|
|
57455
|
+
CLAUDE_COLLECT_SCHEDULE Cron expression for daemon (default: */30 * * * *)
|
|
57302
57456
|
`);
|
|
57303
57457
|
}
|
|
57304
57458
|
run2().catch((err) => {
|