homaruscc 0.2.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/.env.example +8 -0
- package/LICENSE +21 -0
- package/README.md +307 -0
- package/bin/event-loop +60 -0
- package/config.example.json +55 -0
- package/dist/agent-registry.d.ts +38 -0
- package/dist/agent-registry.d.ts.map +1 -0
- package/dist/agent-registry.js +207 -0
- package/dist/agent-registry.js.map +1 -0
- package/dist/backend.d.ts +3 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/backend.js +59 -0
- package/dist/backend.js.map +1 -0
- package/dist/browser-service.d.ts +19 -0
- package/dist/browser-service.d.ts.map +1 -0
- package/dist/browser-service.js +101 -0
- package/dist/browser-service.js.map +1 -0
- package/dist/channel-adapter.d.ts +22 -0
- package/dist/channel-adapter.d.ts.map +1 -0
- package/dist/channel-adapter.js +62 -0
- package/dist/channel-adapter.js.map +1 -0
- package/dist/channel-manager.d.ts +18 -0
- package/dist/channel-manager.d.ts.map +1 -0
- package/dist/channel-manager.js +73 -0
- package/dist/channel-manager.js.map +1 -0
- package/dist/compaction-manager.d.ts +23 -0
- package/dist/compaction-manager.d.ts.map +1 -0
- package/dist/compaction-manager.js +135 -0
- package/dist/compaction-manager.js.map +1 -0
- package/dist/config.d.ts +21 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +169 -0
- package/dist/config.js.map +1 -0
- package/dist/dashboard-adapter.d.ts +17 -0
- package/dist/dashboard-adapter.d.ts.map +1 -0
- package/dist/dashboard-adapter.js +41 -0
- package/dist/dashboard-adapter.js.map +1 -0
- package/dist/dashboard-server.d.ts +29 -0
- package/dist/dashboard-server.d.ts.map +1 -0
- package/dist/dashboard-server.js +381 -0
- package/dist/dashboard-server.js.map +1 -0
- package/dist/embedding-provider.d.ts +28 -0
- package/dist/embedding-provider.d.ts.map +1 -0
- package/dist/embedding-provider.js +91 -0
- package/dist/embedding-provider.js.map +1 -0
- package/dist/event-bus.d.ts +18 -0
- package/dist/event-bus.d.ts.map +1 -0
- package/dist/event-bus.js +41 -0
- package/dist/event-bus.js.map +1 -0
- package/dist/event-queue.d.ts +18 -0
- package/dist/event-queue.d.ts.map +1 -0
- package/dist/event-queue.js +68 -0
- package/dist/event-queue.js.map +1 -0
- package/dist/homaruscc.d.ts +69 -0
- package/dist/homaruscc.d.ts.map +1 -0
- package/dist/homaruscc.js +337 -0
- package/dist/homaruscc.js.map +1 -0
- package/dist/identity-manager.d.ts +36 -0
- package/dist/identity-manager.d.ts.map +1 -0
- package/dist/identity-manager.js +142 -0
- package/dist/identity-manager.js.map +1 -0
- package/dist/mcp-proxy.d.ts +3 -0
- package/dist/mcp-proxy.d.ts.map +1 -0
- package/dist/mcp-proxy.js +259 -0
- package/dist/mcp-proxy.js.map +1 -0
- package/dist/mcp-resources.d.ts +10 -0
- package/dist/mcp-resources.d.ts.map +1 -0
- package/dist/mcp-resources.js +67 -0
- package/dist/mcp-resources.js.map +1 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +169 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mcp-tools.d.ts +14 -0
- package/dist/mcp-tools.d.ts.map +1 -0
- package/dist/mcp-tools.js +408 -0
- package/dist/mcp-tools.js.map +1 -0
- package/dist/memory-index.d.ts +79 -0
- package/dist/memory-index.d.ts.map +1 -0
- package/dist/memory-index.js +437 -0
- package/dist/memory-index.js.map +1 -0
- package/dist/session-checkpoint.d.ts +22 -0
- package/dist/session-checkpoint.d.ts.map +1 -0
- package/dist/session-checkpoint.js +100 -0
- package/dist/session-checkpoint.js.map +1 -0
- package/dist/skill-manager.d.ts +26 -0
- package/dist/skill-manager.d.ts.map +1 -0
- package/dist/skill-manager.js +156 -0
- package/dist/skill-manager.js.map +1 -0
- package/dist/skill-transport.d.ts +45 -0
- package/dist/skill-transport.d.ts.map +1 -0
- package/dist/skill-transport.js +111 -0
- package/dist/skill-transport.js.map +1 -0
- package/dist/skill.d.ts +22 -0
- package/dist/skill.d.ts.map +1 -0
- package/dist/skill.js +106 -0
- package/dist/skill.js.map +1 -0
- package/dist/telegram-adapter.d.ts +43 -0
- package/dist/telegram-adapter.d.ts.map +1 -0
- package/dist/telegram-adapter.js +188 -0
- package/dist/telegram-adapter.js.map +1 -0
- package/dist/timer-service.d.ts +30 -0
- package/dist/timer-service.d.ts.map +1 -0
- package/dist/timer-service.js +176 -0
- package/dist/timer-service.js.map +1 -0
- package/dist/tool-registry.d.ts +30 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +108 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tools/bash.d.ts +3 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +67 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/browser.d.ts +4 -0
- package/dist/tools/browser.d.ts.map +1 -0
- package/dist/tools/browser.js +138 -0
- package/dist/tools/browser.js.map +1 -0
- package/dist/tools/edit.d.ts +3 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +47 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/git.d.ts +3 -0
- package/dist/tools/git.d.ts.map +1 -0
- package/dist/tools/git.js +105 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/glob.d.ts +3 -0
- package/dist/tools/glob.d.ts.map +1 -0
- package/dist/tools/glob.js +84 -0
- package/dist/tools/glob.js.map +1 -0
- package/dist/tools/grep.d.ts +3 -0
- package/dist/tools/grep.d.ts.map +1 -0
- package/dist/tools/grep.js +168 -0
- package/dist/tools/grep.js.map +1 -0
- package/dist/tools/index.d.ts +6 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +46 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/memory.d.ts +4 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +64 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/read.d.ts +3 -0
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +50 -0
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/web-fetch.d.ts +3 -0
- package/dist/tools/web-fetch.d.ts.map +1 -0
- package/dist/tools/web-fetch.js +51 -0
- package/dist/tools/web-fetch.js.map +1 -0
- package/dist/tools/web-search.d.ts +3 -0
- package/dist/tools/web-search.d.ts.map +1 -0
- package/dist/tools/web-search.js +65 -0
- package/dist/tools/web-search.js.map +1 -0
- package/dist/tools/write.d.ts +3 -0
- package/dist/tools/write.d.ts.map +1 -0
- package/dist/tools/write.js +32 -0
- package/dist/tools/write.js.map +1 -0
- package/dist/transcript-logger.d.ts +23 -0
- package/dist/transcript-logger.d.ts.map +1 -0
- package/dist/transcript-logger.js +101 -0
- package/dist/transcript-logger.js.map +1 -0
- package/dist/types.d.ts +190 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/identity.example/disagreements.md +9 -0
- package/identity.example/preferences.md +11 -0
- package/identity.example/soul.md +12 -0
- package/identity.example/state.md +21 -0
- package/identity.example/user.md +14 -0
- package/package.json +60 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ToolRegistry } from "../tool-registry.js";
|
|
2
|
+
import type { MemoryIndex } from "../memory-index.js";
|
|
3
|
+
import type { BrowserService } from "../browser-service.js";
|
|
4
|
+
import type { Logger } from "../types.js";
|
|
5
|
+
export declare function registerBuiltinTools(registry: ToolRegistry, memoryIndex: MemoryIndex, logger: Logger, browserService?: BrowserService): void;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAa1C,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,YAAY,EACtB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,cAAc,GAC9B,IAAI,CAuCN"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { bashTool } from "./bash.js";
|
|
2
|
+
import { readTool } from "./read.js";
|
|
3
|
+
import { writeTool } from "./write.js";
|
|
4
|
+
import { editTool } from "./edit.js";
|
|
5
|
+
import { globTool } from "./glob.js";
|
|
6
|
+
import { grepTool } from "./grep.js";
|
|
7
|
+
import { gitTool } from "./git.js";
|
|
8
|
+
import { webFetchTool } from "./web-fetch.js";
|
|
9
|
+
import { webSearchTool } from "./web-search.js";
|
|
10
|
+
import { createMemoryTools } from "./memory.js";
|
|
11
|
+
import { createBrowserTools } from "./browser.js";
|
|
12
|
+
export function registerBuiltinTools(registry, memoryIndex, logger, browserService) {
|
|
13
|
+
// group:fs
|
|
14
|
+
registry.register(readTool);
|
|
15
|
+
registry.register(writeTool);
|
|
16
|
+
registry.register(editTool);
|
|
17
|
+
registry.register(globTool);
|
|
18
|
+
registry.register(grepTool);
|
|
19
|
+
// group:runtime
|
|
20
|
+
registry.register(bashTool);
|
|
21
|
+
registry.register(gitTool);
|
|
22
|
+
// group:web
|
|
23
|
+
registry.register(webFetchTool);
|
|
24
|
+
registry.register(webSearchTool);
|
|
25
|
+
// group:memory
|
|
26
|
+
for (const tool of createMemoryTools(memoryIndex)) {
|
|
27
|
+
registry.register(tool);
|
|
28
|
+
}
|
|
29
|
+
// group:browser
|
|
30
|
+
if (browserService) {
|
|
31
|
+
for (const tool of createBrowserTools(browserService)) {
|
|
32
|
+
registry.register(tool);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const tools = [
|
|
36
|
+
readTool.name, writeTool.name, editTool.name, globTool.name, grepTool.name,
|
|
37
|
+
bashTool.name, gitTool.name,
|
|
38
|
+
webFetchTool.name, webSearchTool.name,
|
|
39
|
+
"memory_search", "memory_get", "memory_store",
|
|
40
|
+
];
|
|
41
|
+
if (browserService) {
|
|
42
|
+
tools.push("browser_navigate", "browser_snapshot", "browser_screenshot", "browser_click", "browser_type", "browser_evaluate", "browser_content");
|
|
43
|
+
}
|
|
44
|
+
logger.info("Built-in tools registered", { count: tools.length, tools });
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,UAAU,oBAAoB,CAClC,QAAsB,EACtB,WAAwB,EACxB,MAAc,EACd,cAA+B;IAE/B,WAAW;IACX,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE5B,gBAAgB;IAChB,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAE3B,YAAY;IACZ,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IAEjC,eAAe;IACf,KAAK,MAAM,IAAI,IAAI,iBAAiB,CAAC,WAAW,CAAC,EAAE,CAAC;QAClD,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,gBAAgB;IAChB,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,MAAM,IAAI,IAAI,kBAAkB,CAAC,cAAc,CAAC,EAAE,CAAC;YACtD,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG;QACZ,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI;QAC1E,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI;QAC3B,YAAY,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI;QACrC,eAAe,EAAE,YAAY,EAAE,cAAc;KAC9C,CAAC;IACF,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,eAAe,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,CAAC,CAAC;IACnJ,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/tools/memory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,aAAa,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAgBtD,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,WAAW,GAAG,cAAc,EAAE,CAyE5E"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export function createMemoryTools(memoryIndex) {
|
|
2
|
+
const memorySearchTool = {
|
|
3
|
+
name: "memory_search",
|
|
4
|
+
description: "Search the memory index using hybrid vector + text search.",
|
|
5
|
+
parameters: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
query: { type: "string", description: "The search query" },
|
|
9
|
+
limit: { type: "number", description: "Maximum number of results (default 10)" },
|
|
10
|
+
},
|
|
11
|
+
required: ["query"],
|
|
12
|
+
},
|
|
13
|
+
source: "builtin",
|
|
14
|
+
async execute(params) {
|
|
15
|
+
const { query, limit } = params;
|
|
16
|
+
const results = await memoryIndex.search(query, { limit });
|
|
17
|
+
if (results.length === 0) {
|
|
18
|
+
return { output: "No results found." };
|
|
19
|
+
}
|
|
20
|
+
const formatted = results.map((r, i) => `[${i + 1}] ${r.path} (score: ${r.score.toFixed(3)})\n${r.content.slice(0, 500)}`).join("\n\n---\n\n");
|
|
21
|
+
return { output: formatted };
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
const memoryGetTool = {
|
|
25
|
+
name: "memory_get",
|
|
26
|
+
description: "Retrieve the full content of a specific file from memory.",
|
|
27
|
+
parameters: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
path: { type: "string", description: "The file path to retrieve" },
|
|
31
|
+
},
|
|
32
|
+
required: ["path"],
|
|
33
|
+
},
|
|
34
|
+
source: "builtin",
|
|
35
|
+
async execute(params) {
|
|
36
|
+
const { path } = params;
|
|
37
|
+
const content = memoryIndex.get(path);
|
|
38
|
+
if (!content) {
|
|
39
|
+
return { output: "", error: `File not found: ${path}` };
|
|
40
|
+
}
|
|
41
|
+
return { output: content };
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
const memoryStoreTool = {
|
|
45
|
+
name: "memory_store",
|
|
46
|
+
description: "Store content to a file in memory and index it for future search.",
|
|
47
|
+
parameters: {
|
|
48
|
+
type: "object",
|
|
49
|
+
properties: {
|
|
50
|
+
content: { type: "string", description: "The content to store" },
|
|
51
|
+
path: { type: "string", description: "The file path to store at" },
|
|
52
|
+
},
|
|
53
|
+
required: ["content", "path"],
|
|
54
|
+
},
|
|
55
|
+
source: "builtin",
|
|
56
|
+
async execute(params) {
|
|
57
|
+
const { content, path } = params;
|
|
58
|
+
await memoryIndex.store(content, path);
|
|
59
|
+
return { output: `Stored and indexed: ${path}` };
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
return [memorySearchTool, memoryGetTool, memoryStoreTool];
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/tools/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,aAAa,CAAC;AAW3E,eAAO,MAAM,QAAQ,EAAE,cAkDtB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// CRC: crc-ToolRegistry.md
|
|
2
|
+
// Built-in tool: read — from HomarUS
|
|
3
|
+
import { readFileSync, existsSync, statSync } from "node:fs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
const MAX_FILE_SIZE = 2 * 1024 * 1024;
|
|
6
|
+
const MAX_LINES = 2000;
|
|
7
|
+
export const readTool = {
|
|
8
|
+
name: "read",
|
|
9
|
+
description: "Read the contents of a file. Returns numbered lines.",
|
|
10
|
+
parameters: {
|
|
11
|
+
type: "object",
|
|
12
|
+
properties: {
|
|
13
|
+
path: { type: "string", description: "Absolute or relative path to the file" },
|
|
14
|
+
offset: { type: "number", description: "Line number to start reading from (1-based)" },
|
|
15
|
+
limit: { type: "number", description: "Maximum number of lines to return" },
|
|
16
|
+
},
|
|
17
|
+
required: ["path"],
|
|
18
|
+
},
|
|
19
|
+
source: "builtin",
|
|
20
|
+
async execute(params, context) {
|
|
21
|
+
const { path: filePath, offset, limit } = params;
|
|
22
|
+
const absPath = resolve(context.workingDir, filePath);
|
|
23
|
+
if (!existsSync(absPath)) {
|
|
24
|
+
return { output: "", error: `File not found: ${absPath}` };
|
|
25
|
+
}
|
|
26
|
+
const stat = statSync(absPath);
|
|
27
|
+
if (stat.isDirectory()) {
|
|
28
|
+
return { output: "", error: `Path is a directory: ${absPath}` };
|
|
29
|
+
}
|
|
30
|
+
if (stat.size > MAX_FILE_SIZE) {
|
|
31
|
+
return { output: "", error: `File too large (${stat.size} bytes). Max: ${MAX_FILE_SIZE}` };
|
|
32
|
+
}
|
|
33
|
+
const content = readFileSync(absPath, "utf-8");
|
|
34
|
+
const allLines = content.split("\n");
|
|
35
|
+
const startLine = (offset ?? 1) - 1;
|
|
36
|
+
const maxLines = limit ?? MAX_LINES;
|
|
37
|
+
const lines = allLines.slice(startLine, startLine + maxLines);
|
|
38
|
+
const numbered = lines.map((line, i) => {
|
|
39
|
+
const lineNum = startLine + i + 1;
|
|
40
|
+
const truncated = line.length > 2000 ? line.slice(0, 2000) + "..." : line;
|
|
41
|
+
return `${String(lineNum).padStart(6)}\t${truncated}`;
|
|
42
|
+
});
|
|
43
|
+
let output = numbered.join("\n");
|
|
44
|
+
if (startLine + maxLines < allLines.length) {
|
|
45
|
+
output += `\n... (${allLines.length - startLine - maxLines} more lines)`;
|
|
46
|
+
}
|
|
47
|
+
return { output };
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=read.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-fetch.d.ts","sourceRoot":"","sources":["../../src/tools/web-fetch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,aAAa,CAAC;AAW3E,eAAO,MAAM,YAAY,EAAE,cAuD1B,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const MAX_RESPONSE = 100_000;
|
|
2
|
+
export const webFetchTool = {
|
|
3
|
+
name: "web_fetch",
|
|
4
|
+
description: "Fetch content from a URL. Returns the response body as text.",
|
|
5
|
+
parameters: {
|
|
6
|
+
type: "object",
|
|
7
|
+
properties: {
|
|
8
|
+
url: { type: "string", description: "The URL to fetch" },
|
|
9
|
+
method: { type: "string", description: "HTTP method (default GET)", enum: ["GET", "POST", "PUT", "DELETE", "PATCH"] },
|
|
10
|
+
headers: { type: "object", description: "Optional request headers" },
|
|
11
|
+
body: { type: "string", description: "Optional request body" },
|
|
12
|
+
},
|
|
13
|
+
required: ["url"],
|
|
14
|
+
},
|
|
15
|
+
source: "builtin",
|
|
16
|
+
async execute(params, context) {
|
|
17
|
+
const { url, method = "GET", headers, body } = params;
|
|
18
|
+
if (context.sandbox) {
|
|
19
|
+
return { output: "", error: "web_fetch tool is not available in sandbox mode" };
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const response = await fetch(url, {
|
|
23
|
+
method,
|
|
24
|
+
headers: headers ? new Headers(headers) : undefined,
|
|
25
|
+
body: body ?? undefined,
|
|
26
|
+
signal: AbortSignal.timeout(30_000),
|
|
27
|
+
});
|
|
28
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
29
|
+
let text;
|
|
30
|
+
if (contentType.includes("application/json")) {
|
|
31
|
+
const json = await response.json();
|
|
32
|
+
text = JSON.stringify(json, null, 2);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
text = await response.text();
|
|
36
|
+
}
|
|
37
|
+
if (text.length > MAX_RESPONSE) {
|
|
38
|
+
text = text.slice(0, MAX_RESPONSE) + `\n... (truncated, ${text.length} total chars)`;
|
|
39
|
+
}
|
|
40
|
+
const statusLine = `HTTP ${response.status} ${response.statusText}`;
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
return { output: text, error: statusLine };
|
|
43
|
+
}
|
|
44
|
+
return { output: `${statusLine}\n\n${text}` };
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
return { output: "", error: `Fetch failed: ${String(err.message ?? err)}` };
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=web-fetch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-fetch.js","sourceRoot":"","sources":["../../src/tools/web-fetch.ts"],"names":[],"mappings":"AAIA,MAAM,YAAY,GAAG,OAAO,CAAC;AAS7B,MAAM,CAAC,MAAM,YAAY,GAAmB;IAC1C,IAAI,EAAE,WAAW;IACjB,WAAW,EAAE,8DAA8D;IAC3E,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,GAAG,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;YACxD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE;YACrH,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;YACpE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uBAAuB,EAAE;SAC/D;QACD,QAAQ,EAAE,CAAC,KAAK,CAAC;KAClB;IACD,MAAM,EAAE,SAAS;IAEjB,KAAK,CAAC,OAAO,CAAC,MAAe,EAAE,OAAoB;QACjD,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAwB,CAAC;QAExE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,iDAAiD,EAAE,CAAC;QAClF,CAAC;QAED,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM;gBACN,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS;gBACnD,IAAI,EAAE,IAAI,IAAI,SAAS;gBACvB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;aACpC,CAAC,CAAC;YAEH,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YAC/D,IAAI,IAAY,CAAC;YAEjB,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC7C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACnC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACvC,CAAC;iBAAM,CAAC;gBACN,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC/B,CAAC;YAED,IAAI,IAAI,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;gBAC/B,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,qBAAqB,IAAI,CAAC,MAAM,eAAe,CAAC;YACvF,CAAC;YAED,MAAM,UAAU,GAAG,QAAQ,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;YAEpE,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;YAC7C,CAAC;YAED,OAAO,EAAE,MAAM,EAAE,GAAG,UAAU,OAAO,IAAI,EAAE,EAAE,CAAC;QAChD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,iBAAiB,MAAM,CAAE,GAAa,CAAC,OAAO,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;QACzF,CAAC;IACH,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.d.ts","sourceRoot":"","sources":["../../src/tools/web-search.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,aAAa,CAAC;AA0D3E,eAAO,MAAM,aAAa,EAAE,cAoC3B,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
async function duckduckgoSearch(query, limit) {
|
|
2
|
+
const encoded = encodeURIComponent(query);
|
|
3
|
+
const url = `https://html.duckduckgo.com/html/?q=${encoded}`;
|
|
4
|
+
const response = await fetch(url, {
|
|
5
|
+
headers: { "User-Agent": "Mozilla/5.0 (compatible; HomarUScc/1.0)" },
|
|
6
|
+
signal: AbortSignal.timeout(15_000),
|
|
7
|
+
});
|
|
8
|
+
if (!response.ok) {
|
|
9
|
+
throw new Error(`Search failed: HTTP ${response.status}`);
|
|
10
|
+
}
|
|
11
|
+
const html = await response.text();
|
|
12
|
+
const results = [];
|
|
13
|
+
const resultBlocks = html.split("class=\"result__body\"");
|
|
14
|
+
for (let i = 1; i < resultBlocks.length && results.length < limit; i++) {
|
|
15
|
+
const block = resultBlocks[i];
|
|
16
|
+
const linkMatch = block.match(/class="result__a"[^>]*href="([^"]*)"[^>]*>([\s\S]*?)<\/a>/);
|
|
17
|
+
if (!linkMatch)
|
|
18
|
+
continue;
|
|
19
|
+
let resultUrl = linkMatch[1];
|
|
20
|
+
const uddgMatch = resultUrl.match(/uddg=([^&]*)/);
|
|
21
|
+
if (uddgMatch) {
|
|
22
|
+
resultUrl = decodeURIComponent(uddgMatch[1]);
|
|
23
|
+
}
|
|
24
|
+
const title = linkMatch[2].replace(/<[^>]+>/g, "").trim();
|
|
25
|
+
const snippetMatch = block.match(/class="result__snippet"[^>]*>([\s\S]*?)<\/a>/);
|
|
26
|
+
const snippet = snippetMatch
|
|
27
|
+
? snippetMatch[1].replace(/<[^>]+>/g, "").trim()
|
|
28
|
+
: "";
|
|
29
|
+
if (title && resultUrl) {
|
|
30
|
+
results.push({ title, url: resultUrl, snippet });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return results;
|
|
34
|
+
}
|
|
35
|
+
export const webSearchTool = {
|
|
36
|
+
name: "web_search",
|
|
37
|
+
description: "Search the web and return results with titles, URLs, and snippets.",
|
|
38
|
+
parameters: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
query: { type: "string", description: "The search query" },
|
|
42
|
+
limit: { type: "number", description: "Maximum number of results (default 10)" },
|
|
43
|
+
},
|
|
44
|
+
required: ["query"],
|
|
45
|
+
},
|
|
46
|
+
source: "builtin",
|
|
47
|
+
async execute(params, context) {
|
|
48
|
+
if (context.sandbox) {
|
|
49
|
+
return { output: "", error: "web_search tool is not available in sandbox mode" };
|
|
50
|
+
}
|
|
51
|
+
const { query, limit = 10 } = params;
|
|
52
|
+
try {
|
|
53
|
+
const results = await duckduckgoSearch(query, limit);
|
|
54
|
+
if (results.length === 0) {
|
|
55
|
+
return { output: "No results found." };
|
|
56
|
+
}
|
|
57
|
+
const formatted = results.map((r, i) => `[${i + 1}] ${r.title}\n ${r.url}\n ${r.snippet}`).join("\n\n");
|
|
58
|
+
return { output: formatted };
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
return { output: "", error: `Search failed: ${String(err.message ?? err)}` };
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=web-search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-search.js","sourceRoot":"","sources":["../../src/tools/web-search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAA2B,MAAM,aAAa,CAAC;AAO3E,eAAO,MAAM,SAAS,EAAE,cA8BvB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// CRC: crc-ToolRegistry.md
|
|
2
|
+
// Built-in tool: write — from HomarUS
|
|
3
|
+
import { writeFileSync, mkdirSync, existsSync } from "node:fs";
|
|
4
|
+
import { resolve, dirname } from "node:path";
|
|
5
|
+
export const writeTool = {
|
|
6
|
+
name: "write",
|
|
7
|
+
description: "Write content to a file, creating it if it doesn't exist.",
|
|
8
|
+
parameters: {
|
|
9
|
+
type: "object",
|
|
10
|
+
properties: {
|
|
11
|
+
path: { type: "string", description: "Absolute or relative path to the file" },
|
|
12
|
+
content: { type: "string", description: "The content to write" },
|
|
13
|
+
},
|
|
14
|
+
required: ["path", "content"],
|
|
15
|
+
},
|
|
16
|
+
source: "builtin",
|
|
17
|
+
async execute(params, context) {
|
|
18
|
+
const { path: filePath, content } = params;
|
|
19
|
+
const absPath = resolve(context.workingDir, filePath);
|
|
20
|
+
if (context.sandbox) {
|
|
21
|
+
return { output: "", error: "write tool is not available in sandbox mode" };
|
|
22
|
+
}
|
|
23
|
+
const dir = dirname(absPath);
|
|
24
|
+
if (!existsSync(dir)) {
|
|
25
|
+
mkdirSync(dir, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
writeFileSync(absPath, content);
|
|
28
|
+
const lines = content.split("\n").length;
|
|
29
|
+
return { output: `Wrote ${lines} lines to ${absPath}` };
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,sCAAsC;AACtC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQ7C,MAAM,CAAC,MAAM,SAAS,GAAmB;IACvC,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,2DAA2D;IACxE,UAAU,EAAE;QACV,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uCAAuC,EAAE;YAC9E,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;SACjE;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;KAC9B;IACD,MAAM,EAAE,SAAS;IAEjB,KAAK,CAAC,OAAO,CAAC,MAAe,EAAE,OAAoB;QACjD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAqB,CAAC;QAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAEtD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,6CAA6C,EAAE,CAAC;QAC9E,CAAC;QAED,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QAED,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;QACzC,OAAO,EAAE,MAAM,EAAE,SAAS,KAAK,aAAa,OAAO,EAAE,EAAE,CAAC;IAC1D,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Logger, Event } from "./types.js";
|
|
2
|
+
import type { MemoryIndex } from "./memory-index.js";
|
|
3
|
+
export declare class TranscriptLogger {
|
|
4
|
+
private buffer;
|
|
5
|
+
private transcriptDir;
|
|
6
|
+
private flushIntervalMs;
|
|
7
|
+
private flushTimer;
|
|
8
|
+
private enabled;
|
|
9
|
+
private memoryIndex;
|
|
10
|
+
private logger;
|
|
11
|
+
constructor(logger: Logger, memoryIndex: MemoryIndex, options?: {
|
|
12
|
+
enabled?: boolean;
|
|
13
|
+
directory?: string;
|
|
14
|
+
flushIntervalMs?: number;
|
|
15
|
+
});
|
|
16
|
+
start(): void;
|
|
17
|
+
stop(): Promise<void>;
|
|
18
|
+
logInbound(event: Event): void;
|
|
19
|
+
logOutbound(channel: string, text: string): void;
|
|
20
|
+
flush(): Promise<void>;
|
|
21
|
+
getBufferSize(): number;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=transcript-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-logger.d.ts","sourceRoot":"","sources":["../src/transcript-logger.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,KAAK,EAAkB,MAAM,YAAY,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAUrD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,UAAU,CAA+C;IACjE,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE;QAC9D,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B;IASD,KAAK,IAAI,IAAI;IAiBP,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAa9B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAW1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkC5B,aAAa,IAAI,MAAM;CAGxB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
// CRC: crc-TranscriptLogger.md | Seq: seq-transcript-capture.md
|
|
2
|
+
// Session transcript capture and indexing
|
|
3
|
+
import { existsSync, mkdirSync, appendFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
export class TranscriptLogger {
|
|
6
|
+
buffer = [];
|
|
7
|
+
transcriptDir;
|
|
8
|
+
flushIntervalMs;
|
|
9
|
+
flushTimer = null;
|
|
10
|
+
enabled;
|
|
11
|
+
memoryIndex;
|
|
12
|
+
logger;
|
|
13
|
+
constructor(logger, memoryIndex, options) {
|
|
14
|
+
this.logger = logger;
|
|
15
|
+
this.memoryIndex = memoryIndex;
|
|
16
|
+
this.enabled = options?.enabled ?? true;
|
|
17
|
+
this.transcriptDir = options?.directory ?? `${process.env.HOME ?? "."}/.homaruscc/transcripts`;
|
|
18
|
+
this.flushIntervalMs = options?.flushIntervalMs ?? 300_000;
|
|
19
|
+
}
|
|
20
|
+
// CRC: crc-TranscriptLogger.md | R98, R102
|
|
21
|
+
start() {
|
|
22
|
+
if (!this.enabled)
|
|
23
|
+
return;
|
|
24
|
+
// R106: Ensure directory exists once at startup
|
|
25
|
+
if (!existsSync(this.transcriptDir)) {
|
|
26
|
+
mkdirSync(this.transcriptDir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
this.flushTimer = setInterval(() => {
|
|
29
|
+
this.flush().catch((err) => this.logger.warn("Transcript flush failed", { error: String(err) }));
|
|
30
|
+
}, this.flushIntervalMs);
|
|
31
|
+
this.logger.info("TranscriptLogger started", { dir: this.transcriptDir, intervalMs: this.flushIntervalMs });
|
|
32
|
+
}
|
|
33
|
+
// CRC: crc-TranscriptLogger.md | R103
|
|
34
|
+
async stop() {
|
|
35
|
+
if (this.flushTimer) {
|
|
36
|
+
clearInterval(this.flushTimer);
|
|
37
|
+
this.flushTimer = null;
|
|
38
|
+
}
|
|
39
|
+
await this.flush();
|
|
40
|
+
this.logger.info("TranscriptLogger stopped");
|
|
41
|
+
}
|
|
42
|
+
// CRC: crc-TranscriptLogger.md | R98
|
|
43
|
+
logInbound(event) {
|
|
44
|
+
if (!this.enabled)
|
|
45
|
+
return;
|
|
46
|
+
const payload = event.payload;
|
|
47
|
+
this.buffer.push({
|
|
48
|
+
timestamp: event.timestamp,
|
|
49
|
+
channel: payload.channel ?? event.source,
|
|
50
|
+
direction: "in",
|
|
51
|
+
sender: payload.from,
|
|
52
|
+
text: payload.text,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// CRC: crc-TranscriptLogger.md | R99
|
|
56
|
+
logOutbound(channel, text) {
|
|
57
|
+
if (!this.enabled)
|
|
58
|
+
return;
|
|
59
|
+
this.buffer.push({
|
|
60
|
+
timestamp: Date.now(),
|
|
61
|
+
channel,
|
|
62
|
+
direction: "out",
|
|
63
|
+
text,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
// CRC: crc-TranscriptLogger.md | R100, R101, R104, R107
|
|
67
|
+
async flush() {
|
|
68
|
+
if (this.buffer.length === 0)
|
|
69
|
+
return;
|
|
70
|
+
const turns = this.buffer.splice(0);
|
|
71
|
+
const date = new Date().toISOString().slice(0, 10);
|
|
72
|
+
const filePath = join(this.transcriptDir, `${date}.md`);
|
|
73
|
+
const isNewFile = !existsSync(filePath);
|
|
74
|
+
const lines = [];
|
|
75
|
+
if (isNewFile) {
|
|
76
|
+
lines.push(`# Transcript: ${date}`, "");
|
|
77
|
+
}
|
|
78
|
+
for (const turn of turns) {
|
|
79
|
+
const time = new Date(turn.timestamp).toTimeString().slice(0, 8);
|
|
80
|
+
const label = `${turn.channel}:${turn.direction}`;
|
|
81
|
+
const header = turn.sender
|
|
82
|
+
? `## ${time} [${label}] ${turn.sender}`
|
|
83
|
+
: `## ${time} [${label}]`;
|
|
84
|
+
lines.push(header, "", turn.text, "");
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
appendFileSync(filePath, lines.join("\n"));
|
|
88
|
+
await this.memoryIndex.indexFile(filePath);
|
|
89
|
+
this.logger.debug("Transcript flushed", { file: filePath, turns: turns.length });
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
// R107: Retain buffer on failure
|
|
93
|
+
this.buffer.unshift(...turns);
|
|
94
|
+
this.logger.warn("Transcript flush failed, retained buffer", { error: String(err) });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
getBufferSize() {
|
|
98
|
+
return this.buffer.length;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=transcript-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transcript-logger.js","sourceRoot":"","sources":["../src/transcript-logger.ts"],"names":[],"mappings":"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"}
|