haansi 0.1.9 → 0.1.10
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 +206 -19
- 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.10",
|
|
43
43
|
description: "Haansi CLI - Session collector and MCP server for Claude Code",
|
|
44
44
|
bin: {
|
|
45
45
|
haansi: "./dist/haansi.js"
|
|
@@ -557,6 +557,56 @@ function edgeScrub(content) {
|
|
|
557
557
|
}
|
|
558
558
|
return result;
|
|
559
559
|
}
|
|
560
|
+
function extractGitInfo(projectDir) {
|
|
561
|
+
const empty = {
|
|
562
|
+
gitRemoteUrl: null,
|
|
563
|
+
gitCommit: null,
|
|
564
|
+
gitBranch: null
|
|
565
|
+
};
|
|
566
|
+
const opts = { cwd: projectDir, timeout: 5e3, encoding: "utf-8" };
|
|
567
|
+
try {
|
|
568
|
+
(0, import_child_process.execSync)("git rev-parse --is-inside-work-tree", { ...opts, stdio: "pipe" });
|
|
569
|
+
} catch {
|
|
570
|
+
return empty;
|
|
571
|
+
}
|
|
572
|
+
const result = { ...empty };
|
|
573
|
+
try {
|
|
574
|
+
result.gitRemoteUrl = (0, import_child_process.execSync)("git remote get-url origin", {
|
|
575
|
+
...opts,
|
|
576
|
+
stdio: "pipe"
|
|
577
|
+
}).trim() || null;
|
|
578
|
+
} catch {
|
|
579
|
+
}
|
|
580
|
+
try {
|
|
581
|
+
result.gitCommit = (0, import_child_process.execSync)("git rev-parse HEAD", { ...opts, stdio: "pipe" }).trim() || null;
|
|
582
|
+
} catch {
|
|
583
|
+
}
|
|
584
|
+
try {
|
|
585
|
+
result.gitBranch = (0, import_child_process.execSync)("git rev-parse --abbrev-ref HEAD", {
|
|
586
|
+
...opts,
|
|
587
|
+
stdio: "pipe"
|
|
588
|
+
}).trim() || null;
|
|
589
|
+
} catch {
|
|
590
|
+
}
|
|
591
|
+
return result;
|
|
592
|
+
}
|
|
593
|
+
function extractCwdFromJsonl(filePath) {
|
|
594
|
+
try {
|
|
595
|
+
const content = (0, import_fs.readFileSync)(filePath, "utf-8");
|
|
596
|
+
const lines = content.split("\n").filter((l) => l.trim()).slice(0, 10);
|
|
597
|
+
for (const line of lines) {
|
|
598
|
+
try {
|
|
599
|
+
const entry = JSON.parse(line);
|
|
600
|
+
if (entry.cwd && typeof entry.cwd === "string") {
|
|
601
|
+
return entry.cwd;
|
|
602
|
+
}
|
|
603
|
+
} catch {
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
} catch {
|
|
607
|
+
}
|
|
608
|
+
return null;
|
|
609
|
+
}
|
|
560
610
|
function resolveToken() {
|
|
561
611
|
if (process.env.HAANSI_TOKEN) return process.env.HAANSI_TOKEN;
|
|
562
612
|
if ((0, import_fs.existsSync)(CREDENTIALS_FILE2)) {
|
|
@@ -627,16 +677,20 @@ async function getUploadedSessions(apiUrl, token) {
|
|
|
627
677
|
return /* @__PURE__ */ new Map();
|
|
628
678
|
}
|
|
629
679
|
}
|
|
630
|
-
async function uploadSession(sessionId, content, apiUrl, token) {
|
|
680
|
+
async function uploadSession(sessionId, content, apiUrl, token, gitInfo) {
|
|
631
681
|
const body = (0, import_zlib.gzipSync)(Buffer.from(content, "utf-8"));
|
|
682
|
+
const headers = {
|
|
683
|
+
Authorization: `Bearer ${token}`,
|
|
684
|
+
"Content-Type": "application/x-ndjson",
|
|
685
|
+
"Content-Encoding": "gzip",
|
|
686
|
+
"x-session-id": sessionId
|
|
687
|
+
};
|
|
688
|
+
if (gitInfo?.gitRemoteUrl) headers["x-git-remote-url"] = gitInfo.gitRemoteUrl;
|
|
689
|
+
if (gitInfo?.gitCommit) headers["x-git-commit"] = gitInfo.gitCommit;
|
|
690
|
+
if (gitInfo?.gitBranch) headers["x-git-branch"] = gitInfo.gitBranch;
|
|
632
691
|
const response = await fetch(`${apiUrl}/api/v1/sessions/raw`, {
|
|
633
692
|
method: "POST",
|
|
634
|
-
headers
|
|
635
|
-
Authorization: `Bearer ${token}`,
|
|
636
|
-
"Content-Type": "application/x-ndjson",
|
|
637
|
-
"Content-Encoding": "gzip",
|
|
638
|
-
"x-session-id": sessionId
|
|
639
|
-
},
|
|
693
|
+
headers,
|
|
640
694
|
body: new Uint8Array(body)
|
|
641
695
|
});
|
|
642
696
|
if (!response.ok) {
|
|
@@ -682,16 +736,25 @@ async function collect(options) {
|
|
|
682
736
|
try {
|
|
683
737
|
const rawContent = (0, import_fs.readFileSync)(session.filePath, "utf-8");
|
|
684
738
|
const scrubbed = edgeScrub(rawContent);
|
|
739
|
+
const cwd = extractCwdFromJsonl(session.filePath);
|
|
740
|
+
const gitInfo = cwd ? extractGitInfo(cwd) : { gitRemoteUrl: null, gitCommit: null, gitBranch: null };
|
|
685
741
|
if (options.dryRun) {
|
|
686
742
|
logger.info(
|
|
687
|
-
`[dry-run] Would upload ${shortId} (${session.lineCount} lines)
|
|
743
|
+
`[dry-run] Would upload ${shortId} (${session.lineCount} lines)`,
|
|
744
|
+
{
|
|
745
|
+
gitRemoteUrl: gitInfo.gitRemoteUrl,
|
|
746
|
+
gitCommit: gitInfo.gitCommit?.slice(0, 8)
|
|
747
|
+
}
|
|
688
748
|
);
|
|
689
749
|
uploaded++;
|
|
690
750
|
continue;
|
|
691
751
|
}
|
|
692
|
-
await uploadSession(session.sessionId, scrubbed, apiUrl, token);
|
|
752
|
+
await uploadSession(session.sessionId, scrubbed, apiUrl, token, gitInfo);
|
|
693
753
|
uploaded++;
|
|
694
|
-
logger.info(`Uploaded ${shortId} (${session.lineCount} lines)
|
|
754
|
+
logger.info(`Uploaded ${shortId} (${session.lineCount} lines)`, {
|
|
755
|
+
gitRemoteUrl: gitInfo.gitRemoteUrl,
|
|
756
|
+
gitCommit: gitInfo.gitCommit?.slice(0, 8)
|
|
757
|
+
});
|
|
695
758
|
} catch (err) {
|
|
696
759
|
errors++;
|
|
697
760
|
logger.error(`Failed to upload ${shortId}`, { err: err.message });
|
|
@@ -716,7 +779,7 @@ Collector done: ${uploaded} uploaded, ${skipped} unchanged, ${errors} errors`
|
|
|
716
779
|
);
|
|
717
780
|
if (errors > 0) process.exit(1);
|
|
718
781
|
}
|
|
719
|
-
var import_dotenv, import_path, import_fs, import_os, import_zlib, logger, DEFAULT_API_URL2, CREDENTIALS_FILE2, CLAUDE_PROJECTS_DIR, MIN_LINES, EDGE_SCRUB_PATTERNS;
|
|
782
|
+
var import_dotenv, import_path, import_fs, import_os, import_zlib, import_child_process, logger, DEFAULT_API_URL2, CREDENTIALS_FILE2, CLAUDE_PROJECTS_DIR, MIN_LINES, EDGE_SCRUB_PATTERNS;
|
|
720
783
|
var init_collector = __esm({
|
|
721
784
|
"../service-capture/claude-sessions/collector.ts"() {
|
|
722
785
|
"use strict";
|
|
@@ -725,6 +788,7 @@ var init_collector = __esm({
|
|
|
725
788
|
import_fs = require("fs");
|
|
726
789
|
import_os = require("os");
|
|
727
790
|
import_zlib = require("zlib");
|
|
791
|
+
import_child_process = require("child_process");
|
|
728
792
|
init_logger();
|
|
729
793
|
(0, import_dotenv.config)({ path: (0, import_path.resolve)(__dirname, "../../../.env") });
|
|
730
794
|
logger = createLogger("claude-collector");
|
|
@@ -1742,6 +1806,128 @@ var init_collector_daemon = __esm({
|
|
|
1742
1806
|
}
|
|
1743
1807
|
});
|
|
1744
1808
|
|
|
1809
|
+
// ../../packages/@company/types/src/knowledge.ts
|
|
1810
|
+
var init_knowledge = __esm({
|
|
1811
|
+
"../../packages/@company/types/src/knowledge.ts"() {
|
|
1812
|
+
"use strict";
|
|
1813
|
+
}
|
|
1814
|
+
});
|
|
1815
|
+
|
|
1816
|
+
// ../../packages/@company/types/src/user.ts
|
|
1817
|
+
var init_user = __esm({
|
|
1818
|
+
"../../packages/@company/types/src/user.ts"() {
|
|
1819
|
+
"use strict";
|
|
1820
|
+
}
|
|
1821
|
+
});
|
|
1822
|
+
|
|
1823
|
+
// ../../packages/@company/types/src/integration.ts
|
|
1824
|
+
var init_integration = __esm({
|
|
1825
|
+
"../../packages/@company/types/src/integration.ts"() {
|
|
1826
|
+
"use strict";
|
|
1827
|
+
}
|
|
1828
|
+
});
|
|
1829
|
+
|
|
1830
|
+
// ../../packages/@company/types/src/timeline.ts
|
|
1831
|
+
var init_timeline = __esm({
|
|
1832
|
+
"../../packages/@company/types/src/timeline.ts"() {
|
|
1833
|
+
"use strict";
|
|
1834
|
+
}
|
|
1835
|
+
});
|
|
1836
|
+
|
|
1837
|
+
// ../../packages/@company/types/src/artifact.ts
|
|
1838
|
+
var init_artifact = __esm({
|
|
1839
|
+
"../../packages/@company/types/src/artifact.ts"() {
|
|
1840
|
+
"use strict";
|
|
1841
|
+
}
|
|
1842
|
+
});
|
|
1843
|
+
|
|
1844
|
+
// ../../packages/@company/types/src/taxonomy.ts
|
|
1845
|
+
function normalizeSessionType(raw) {
|
|
1846
|
+
if (!raw) return "general";
|
|
1847
|
+
const lower = raw.toLowerCase().trim();
|
|
1848
|
+
if (lower in SESSION_TYPES) return lower;
|
|
1849
|
+
if (lower in SESSION_TYPE_ALIASES) return SESSION_TYPE_ALIASES[lower];
|
|
1850
|
+
return "general";
|
|
1851
|
+
}
|
|
1852
|
+
function normalizeComplexity(raw) {
|
|
1853
|
+
if (!raw) return "moderate";
|
|
1854
|
+
const lower = raw.toLowerCase().trim();
|
|
1855
|
+
if (lower in COMPLEXITIES) return lower;
|
|
1856
|
+
return "moderate";
|
|
1857
|
+
}
|
|
1858
|
+
var SESSION_TYPES, SESSION_TYPE_ALIASES, COMPLEXITIES;
|
|
1859
|
+
var init_taxonomy = __esm({
|
|
1860
|
+
"../../packages/@company/types/src/taxonomy.ts"() {
|
|
1861
|
+
"use strict";
|
|
1862
|
+
SESSION_TYPES = {
|
|
1863
|
+
debugging: {
|
|
1864
|
+
label: "Debugging",
|
|
1865
|
+
description: "Investigating and fixing bugs or errors"
|
|
1866
|
+
},
|
|
1867
|
+
feature_implementation: {
|
|
1868
|
+
label: "Feature Implementation",
|
|
1869
|
+
description: "Building new functionality or features"
|
|
1870
|
+
},
|
|
1871
|
+
code_review: {
|
|
1872
|
+
label: "Code Review",
|
|
1873
|
+
description: "Reviewing code for quality, correctness, or style"
|
|
1874
|
+
},
|
|
1875
|
+
deployment: {
|
|
1876
|
+
label: "Deployment",
|
|
1877
|
+
description: "Deploying, releasing, or provisioning infrastructure"
|
|
1878
|
+
},
|
|
1879
|
+
refactoring: {
|
|
1880
|
+
label: "Refactoring",
|
|
1881
|
+
description: "Restructuring existing code without changing behavior"
|
|
1882
|
+
},
|
|
1883
|
+
configuration: {
|
|
1884
|
+
label: "Configuration",
|
|
1885
|
+
description: "Setting up or modifying project/tool configuration"
|
|
1886
|
+
},
|
|
1887
|
+
question_answer: {
|
|
1888
|
+
label: "Question & Answer",
|
|
1889
|
+
description: "Asking or answering questions about code or systems"
|
|
1890
|
+
},
|
|
1891
|
+
general: {
|
|
1892
|
+
label: "General",
|
|
1893
|
+
description: "General-purpose session not fitting other categories"
|
|
1894
|
+
}
|
|
1895
|
+
};
|
|
1896
|
+
SESSION_TYPE_ALIASES = {
|
|
1897
|
+
bug_fix: "debugging",
|
|
1898
|
+
feature: "feature_implementation",
|
|
1899
|
+
refactor: "refactoring",
|
|
1900
|
+
config: "configuration"
|
|
1901
|
+
};
|
|
1902
|
+
COMPLEXITIES = {
|
|
1903
|
+
simple: {
|
|
1904
|
+
label: "Simple",
|
|
1905
|
+
description: "Straightforward task with few steps"
|
|
1906
|
+
},
|
|
1907
|
+
moderate: {
|
|
1908
|
+
label: "Moderate",
|
|
1909
|
+
description: "Multi-step task requiring some investigation"
|
|
1910
|
+
},
|
|
1911
|
+
complex: {
|
|
1912
|
+
label: "Complex",
|
|
1913
|
+
description: "Involved task with many steps or deep analysis"
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
});
|
|
1918
|
+
|
|
1919
|
+
// ../../packages/@company/types/src/index.ts
|
|
1920
|
+
var init_src = __esm({
|
|
1921
|
+
"../../packages/@company/types/src/index.ts"() {
|
|
1922
|
+
init_knowledge();
|
|
1923
|
+
init_user();
|
|
1924
|
+
init_integration();
|
|
1925
|
+
init_timeline();
|
|
1926
|
+
init_artifact();
|
|
1927
|
+
init_taxonomy();
|
|
1928
|
+
}
|
|
1929
|
+
});
|
|
1930
|
+
|
|
1745
1931
|
// ../../node_modules/zod/v3/helpers/util.js
|
|
1746
1932
|
var util, objectUtil, ZodParsedType, getParsedType;
|
|
1747
1933
|
var init_util = __esm({
|
|
@@ -56556,6 +56742,7 @@ var init_mcp_server2 = __esm({
|
|
|
56556
56742
|
import_fs2 = require("fs");
|
|
56557
56743
|
import_os2 = require("os");
|
|
56558
56744
|
init_collector();
|
|
56745
|
+
init_src();
|
|
56559
56746
|
init_mcp();
|
|
56560
56747
|
init_stdio2();
|
|
56561
56748
|
init_types2();
|
|
@@ -56666,7 +56853,9 @@ var init_mcp_server2 = __esm({
|
|
|
56666
56853
|
},
|
|
56667
56854
|
session_type: {
|
|
56668
56855
|
type: "string",
|
|
56669
|
-
description:
|
|
56856
|
+
description: `Type of session: ${Object.keys(SESSION_TYPES).map((t) => `"${t}"`).join(", ")} (default: "general"). Aliases: ${Object.entries(
|
|
56857
|
+
SESSION_TYPE_ALIASES
|
|
56858
|
+
).map(([k, v]) => `"${k}" -> "${v}"`).join(", ")}`
|
|
56670
56859
|
},
|
|
56671
56860
|
steps: {
|
|
56672
56861
|
type: "array",
|
|
@@ -56697,7 +56886,7 @@ var init_mcp_server2 = __esm({
|
|
|
56697
56886
|
},
|
|
56698
56887
|
complexity: {
|
|
56699
56888
|
type: "string",
|
|
56700
|
-
description:
|
|
56889
|
+
description: `${Object.keys(COMPLEXITIES).map((c) => `"${c}"`).join(", ")} (default: "moderate")`
|
|
56701
56890
|
},
|
|
56702
56891
|
project_path: {
|
|
56703
56892
|
type: "string",
|
|
@@ -56859,11 +57048,11 @@ var init_mcp_server2 = __esm({
|
|
|
56859
57048
|
{
|
|
56860
57049
|
problem_description,
|
|
56861
57050
|
solution_summary,
|
|
56862
|
-
session_type,
|
|
57051
|
+
session_type: normalizeSessionType(session_type),
|
|
56863
57052
|
steps,
|
|
56864
57053
|
tools_used,
|
|
56865
57054
|
files_modified,
|
|
56866
|
-
complexity,
|
|
57055
|
+
complexity: normalizeComplexity(complexity),
|
|
56867
57056
|
project_path,
|
|
56868
57057
|
git_branch,
|
|
56869
57058
|
git_remote_url,
|
|
@@ -56879,7 +57068,6 @@ var init_mcp_server2 = __esm({
|
|
|
56879
57068
|
type: "text",
|
|
56880
57069
|
text: [
|
|
56881
57070
|
"Solution saved successfully.",
|
|
56882
|
-
`ID: ${data.id}`,
|
|
56883
57071
|
`Problem: ${data.problem_description}`,
|
|
56884
57072
|
`Solution: ${data.solution_summary}`,
|
|
56885
57073
|
"This is now searchable via search_solutions."
|
|
@@ -57261,7 +57449,6 @@ async function saveKnowledge(options) {
|
|
|
57261
57449
|
if (options.tags) body.tags = options.tags;
|
|
57262
57450
|
const data = await apiPost2("/sessions/knowledge", body, token, apiUrl);
|
|
57263
57451
|
console.log("Knowledge saved successfully.");
|
|
57264
|
-
console.log(` ID: ${data.id}`);
|
|
57265
57452
|
console.log(` Problem: ${data.problem_description}`);
|
|
57266
57453
|
console.log(` Solution: ${data.solution_summary}`);
|
|
57267
57454
|
console.log("\nThis is now searchable via `haansi search-solutions`.");
|
|
@@ -57439,7 +57626,7 @@ Options for search-knowledge:
|
|
|
57439
57626
|
Options for save-knowledge:
|
|
57440
57627
|
--problem "description" Problem description (required)
|
|
57441
57628
|
--solution "summary" Solution summary (required)
|
|
57442
|
-
--type <session_type> Session type (
|
|
57629
|
+
--type <session_type> Session type (debugging, feature_implementation, code_review, deployment, refactoring, configuration, question_answer, general)
|
|
57443
57630
|
--complexity <level> simple, moderate, or complex
|
|
57444
57631
|
--tags tag1,tag2 Comma-separated tags
|
|
57445
57632
|
|