@mclawnet/agent 0.5.9 → 0.6.2
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/cli.js +168 -61
- package/dist/__tests__/cli.test.d.ts +2 -0
- package/dist/__tests__/cli.test.d.ts.map +1 -0
- package/dist/__tests__/service-config.test.d.ts +2 -0
- package/dist/__tests__/service-config.test.d.ts.map +1 -0
- package/dist/__tests__/service-linux.test.d.ts +2 -0
- package/dist/__tests__/service-linux.test.d.ts.map +1 -0
- package/dist/__tests__/service-macos.test.d.ts +2 -0
- package/dist/__tests__/service-macos.test.d.ts.map +1 -0
- package/dist/__tests__/service-windows.test.d.ts +2 -0
- package/dist/__tests__/service-windows.test.d.ts.map +1 -0
- package/dist/backend-adapter.d.ts +2 -0
- package/dist/backend-adapter.d.ts.map +1 -1
- package/dist/chunk-CBZIH6FY.js +93 -0
- package/dist/chunk-CBZIH6FY.js.map +1 -0
- package/dist/{chunk-KHPEQTWF.js → chunk-GLO5OZAY.js} +203 -213
- package/dist/chunk-GLO5OZAY.js.map +1 -0
- package/dist/chunk-RO47ET27.js +88 -0
- package/dist/chunk-RO47ET27.js.map +1 -0
- package/dist/hub-connection.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/linux-6AR7SXHW.js +176 -0
- package/dist/linux-6AR7SXHW.js.map +1 -0
- package/dist/macos-XVPWIH4C.js +174 -0
- package/dist/macos-XVPWIH4C.js.map +1 -0
- package/dist/service/config.d.ts +19 -0
- package/dist/service/config.d.ts.map +1 -0
- package/dist/service/index.d.ts +6 -0
- package/dist/service/index.d.ts.map +1 -0
- package/dist/service/index.js +47 -0
- package/dist/service/index.js.map +1 -0
- package/dist/service/linux.d.ts +18 -0
- package/dist/service/linux.d.ts.map +1 -0
- package/dist/service/macos.d.ts +18 -0
- package/dist/service/macos.d.ts.map +1 -0
- package/dist/service/types.d.ts +19 -0
- package/dist/service/types.d.ts.map +1 -0
- package/dist/service/windows.d.ts +18 -0
- package/dist/service/windows.d.ts.map +1 -0
- package/dist/session-manager.d.ts +4 -7
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/skill-loader.d.ts +8 -0
- package/dist/skill-loader.d.ts.map +1 -0
- package/dist/start.d.ts.map +1 -1
- package/dist/start.js +2 -1
- package/dist/windows-NLONSCDA.js +165 -0
- package/dist/windows-NLONSCDA.js.map +1 -0
- package/package.json +7 -5
- package/skills/academic-search/SKILL.md +147 -0
- package/skills/architecture/SKILL.md +294 -0
- package/skills/changelog-generator/SKILL.md +112 -0
- package/skills/chart-visualization/SKILL.md +183 -0
- package/skills/code-review/SKILL.md +304 -0
- package/skills/codebase-health/SKILL.md +281 -0
- package/skills/consulting-analysis/SKILL.md +584 -0
- package/skills/content-research-writer/SKILL.md +546 -0
- package/skills/data-analysis/SKILL.md +194 -0
- package/skills/deep-research/SKILL.md +198 -0
- package/skills/docx/SKILL.md +211 -0
- package/skills/github-deep-research/SKILL.md +207 -0
- package/skills/image-generation/SKILL.md +209 -0
- package/skills/lead-research-assistant/SKILL.md +207 -0
- package/skills/mcp-builder/SKILL.md +304 -0
- package/skills/meeting-insights-analyzer/SKILL.md +335 -0
- package/skills/pair-programming/SKILL.md +196 -0
- package/skills/pdf/SKILL.md +309 -0
- package/skills/performance-analysis/SKILL.md +261 -0
- package/skills/podcast-generation/SKILL.md +224 -0
- package/skills/pptx/SKILL.md +497 -0
- package/skills/project-learnings/SKILL.md +280 -0
- package/skills/security-audit/SKILL.md +211 -0
- package/skills/skill-creator/SKILL.md +200 -0
- package/skills/technical-writing/SKILL.md +286 -0
- package/skills/testing/SKILL.md +363 -0
- package/skills/video-generation/SKILL.md +247 -0
- package/skills/web-design-guidelines/SKILL.md +203 -0
- package/skills/webapp-testing/SKILL.md +162 -0
- package/skills/workflow-automation/SKILL.md +299 -0
- package/skills/xlsx/SKILL.md +305 -0
- package/dist/chunk-KHPEQTWF.js.map +0 -1
|
@@ -1,90 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { homedir, hostname } from "os";
|
|
5
|
-
import { createLogger } from "@mclawnet/logger";
|
|
6
|
-
var log = createLogger({ module: "config" });
|
|
7
|
-
var CONFIG_DIR = join(homedir(), ".clawnet");
|
|
8
|
-
var SETTINGS_FILE = join(CONFIG_DIR, "settings.json");
|
|
9
|
-
var DEFAULT_HUB_URL = process.env.CLAWNET_DEFAULT_HUB_URL || "ws://localhost:3000/ws/agent";
|
|
10
|
-
var DEFAULTS = {
|
|
11
|
-
hubUrl: DEFAULT_HUB_URL,
|
|
12
|
-
token: "",
|
|
13
|
-
name: hostname(),
|
|
14
|
-
backendType: "claude-code"
|
|
15
|
-
};
|
|
16
|
-
function normalizeHubUrl(url) {
|
|
17
|
-
url = url.replace(/^https:\/\//, "wss://").replace(/^http:\/\//, "ws://");
|
|
18
|
-
if (!/^wss?:\/\//.test(url)) url = "wss://" + url;
|
|
19
|
-
if (url.endsWith("/ws/agent")) return url;
|
|
20
|
-
return url.replace(/\/+$/, "") + "/ws/agent";
|
|
21
|
-
}
|
|
22
|
-
function applyEmbeddingConfig(embedding) {
|
|
23
|
-
const mapping = [
|
|
24
|
-
["provider", "CLAWNET_EMBEDDING_PROVIDER"],
|
|
25
|
-
["openaiBaseUrl", "CLAWNET_OPENAI_BASE_URL"],
|
|
26
|
-
["openaiApiKey", "CLAWNET_OPENAI_API_KEY"],
|
|
27
|
-
["openaiModel", "CLAWNET_OPENAI_EMBEDDING_MODEL"],
|
|
28
|
-
["ollamaUrl", "CLAWNET_OLLAMA_URL"],
|
|
29
|
-
["ollamaModel", "CLAWNET_OLLAMA_MODEL"]
|
|
30
|
-
];
|
|
31
|
-
for (const [configKey, envKey] of mapping) {
|
|
32
|
-
const value = embedding[configKey];
|
|
33
|
-
if (value !== void 0 && process.env[envKey] === void 0) {
|
|
34
|
-
process.env[envKey] = value;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
function loadConfig(cliOpts = {}) {
|
|
39
|
-
let fileConfig = {};
|
|
40
|
-
log.info({ path: SETTINGS_FILE }, "loading config");
|
|
41
|
-
if (existsSync(SETTINGS_FILE)) {
|
|
42
|
-
try {
|
|
43
|
-
fileConfig = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
|
|
44
|
-
log.info(
|
|
45
|
-
{ hubUrl: fileConfig.hubUrl, hasToken: !!fileConfig.token, name: fileConfig.name },
|
|
46
|
-
"settings.json loaded"
|
|
47
|
-
);
|
|
48
|
-
} catch (e) {
|
|
49
|
-
log.warn({ err: e }, "failed to parse settings.json");
|
|
50
|
-
}
|
|
51
|
-
} else {
|
|
52
|
-
log.warn("settings.json not found");
|
|
53
|
-
}
|
|
54
|
-
if (fileConfig.embedding) {
|
|
55
|
-
applyEmbeddingConfig(fileConfig.embedding);
|
|
56
|
-
}
|
|
57
|
-
const hubUrl = cliOpts.hubUrl ?? process.env.CLAWNET_HUB_URL ?? fileConfig.hubUrl ?? DEFAULTS.hubUrl;
|
|
58
|
-
const resolved = {
|
|
59
|
-
hubUrl: normalizeHubUrl(hubUrl),
|
|
60
|
-
token: cliOpts.token ?? process.env.CLAWNET_TOKEN ?? fileConfig.token ?? DEFAULTS.token,
|
|
61
|
-
name: cliOpts.name ?? process.env.CLAWNET_NAME ?? fileConfig.name ?? DEFAULTS.name,
|
|
62
|
-
backendType: cliOpts.backendType ?? process.env.CLAWNET_BACKEND_TYPE ?? fileConfig.backendType ?? DEFAULTS.backendType,
|
|
63
|
-
embedding: fileConfig.embedding
|
|
64
|
-
};
|
|
65
|
-
log.info(
|
|
66
|
-
{
|
|
67
|
-
hubUrl: resolved.hubUrl,
|
|
68
|
-
hubUrlSource: cliOpts.hubUrl ? "cli" : process.env.CLAWNET_HUB_URL ? "env" : fileConfig.hubUrl ? "file" : "default",
|
|
69
|
-
tokenSource: cliOpts.token ? "cli" : process.env.CLAWNET_TOKEN ? "env" : fileConfig.token ? "file" : "default",
|
|
70
|
-
hasToken: !!resolved.token
|
|
71
|
-
},
|
|
72
|
-
"config resolved"
|
|
73
|
-
);
|
|
74
|
-
return resolved;
|
|
75
|
-
}
|
|
76
|
-
function saveConfig(config) {
|
|
77
|
-
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
78
|
-
let existing = {};
|
|
79
|
-
if (existsSync(SETTINGS_FILE)) {
|
|
80
|
-
try {
|
|
81
|
-
existing = JSON.parse(readFileSync(SETTINGS_FILE, "utf-8"));
|
|
82
|
-
} catch {
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
const merged = { ...existing, ...config };
|
|
86
|
-
writeFileSync(SETTINGS_FILE, JSON.stringify(merged, null, 2) + "\n");
|
|
87
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
loadConfig
|
|
3
|
+
} from "./chunk-CBZIH6FY.js";
|
|
88
4
|
|
|
89
5
|
// src/hub-connection.ts
|
|
90
6
|
import { hostname as osHostname } from "os";
|
|
@@ -95,16 +11,16 @@ import {
|
|
|
95
11
|
MAX_RECONNECT_MS,
|
|
96
12
|
WS_CLOSE_INVALID_TOKEN
|
|
97
13
|
} from "@mclawnet/shared";
|
|
98
|
-
import { listRecoverableSwarms, recoverSwarm, listRoles, loadRole, listRecoverableSwarmIds, deleteSwarmSnapshot } from "@mclawnet/swarm";
|
|
14
|
+
import { listRecoverableSwarms, recoverSwarm, listRoles, loadRole, listRecoverableSwarmIds, deleteSwarmSnapshot, listTemplates, loadTemplate } from "@mclawnet/swarm";
|
|
99
15
|
|
|
100
16
|
// src/fs-handler.ts
|
|
101
17
|
import { readdir } from "fs/promises";
|
|
102
|
-
import { existsSync
|
|
103
|
-
import { homedir
|
|
104
|
-
import { join
|
|
18
|
+
import { existsSync, readdirSync, statSync, readFileSync } from "fs";
|
|
19
|
+
import { homedir } from "os";
|
|
20
|
+
import { join } from "path";
|
|
105
21
|
var SKIP_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "__pycache__", ".next", ".nuxt", ".cache"]);
|
|
106
22
|
async function handleListDir(path) {
|
|
107
|
-
const target = path ||
|
|
23
|
+
const target = path || homedir();
|
|
108
24
|
const dirents = await readdir(target, { withFileTypes: true });
|
|
109
25
|
const entries = dirents.filter((d) => !(d.isDirectory() && SKIP_DIRS.has(d.name))).map((d) => ({
|
|
110
26
|
name: d.name,
|
|
@@ -116,14 +32,14 @@ async function handleListDir(path) {
|
|
|
116
32
|
return { path: target, entries };
|
|
117
33
|
}
|
|
118
34
|
function getClaudeProjectsDir() {
|
|
119
|
-
return
|
|
35
|
+
return join(homedir(), ".claude", "projects");
|
|
120
36
|
}
|
|
121
37
|
function pathToProjectFolder(workDir) {
|
|
122
38
|
return workDir.replace(/:/g, "-").replace(/[/\\]/g, "-");
|
|
123
39
|
}
|
|
124
40
|
function extractWorkDirFromSessionFile(filePath) {
|
|
125
41
|
try {
|
|
126
|
-
const content =
|
|
42
|
+
const content = readFileSync(filePath, "utf-8");
|
|
127
43
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
128
44
|
for (const line of lines.slice(0, 5)) {
|
|
129
45
|
try {
|
|
@@ -141,7 +57,7 @@ function getWorkDirFromProjectFolder(folderPath, folderName) {
|
|
|
141
57
|
const files = readdirSync(folderPath);
|
|
142
58
|
for (const file of files) {
|
|
143
59
|
if (file.endsWith(".jsonl")) {
|
|
144
|
-
const workDir = extractWorkDirFromSessionFile(
|
|
60
|
+
const workDir = extractWorkDirFromSessionFile(join(folderPath, file));
|
|
145
61
|
if (workDir) return workDir;
|
|
146
62
|
}
|
|
147
63
|
}
|
|
@@ -158,10 +74,10 @@ function getWorkDirFromProjectFolder(folderPath, folderName) {
|
|
|
158
74
|
async function handleListFolders() {
|
|
159
75
|
const projectsDir = getClaudeProjectsDir();
|
|
160
76
|
const folders = [];
|
|
161
|
-
if (!
|
|
77
|
+
if (!existsSync(projectsDir)) return { folders };
|
|
162
78
|
const entries = readdirSync(projectsDir);
|
|
163
79
|
for (const entry of entries) {
|
|
164
|
-
const entryPath =
|
|
80
|
+
const entryPath = join(projectsDir, entry);
|
|
165
81
|
let entryStat;
|
|
166
82
|
try {
|
|
167
83
|
entryStat = statSync(entryPath);
|
|
@@ -179,7 +95,7 @@ async function handleListFolders() {
|
|
|
179
95
|
if (file.endsWith(".jsonl")) {
|
|
180
96
|
sessionCount++;
|
|
181
97
|
try {
|
|
182
|
-
const fileStats = statSync(
|
|
98
|
+
const fileStats = statSync(join(entryPath, file));
|
|
183
99
|
if (fileStats.mtime.getTime() > lastModified) {
|
|
184
100
|
lastModified = fileStats.mtime.getTime();
|
|
185
101
|
}
|
|
@@ -197,8 +113,8 @@ async function handleListFolders() {
|
|
|
197
113
|
async function handleListHistorySessions(workDir) {
|
|
198
114
|
const projectsDir = getClaudeProjectsDir();
|
|
199
115
|
const projectFolder = pathToProjectFolder(workDir);
|
|
200
|
-
const projectPath =
|
|
201
|
-
if (!
|
|
116
|
+
const projectPath = join(projectsDir, projectFolder);
|
|
117
|
+
if (!existsSync(projectPath)) {
|
|
202
118
|
return { workDir, sessions: [] };
|
|
203
119
|
}
|
|
204
120
|
const sessions = [];
|
|
@@ -206,7 +122,7 @@ async function handleListHistorySessions(workDir) {
|
|
|
206
122
|
for (const file of files) {
|
|
207
123
|
if (!file.endsWith(".jsonl")) continue;
|
|
208
124
|
const sessionId = file.replace(".jsonl", "");
|
|
209
|
-
const filePath =
|
|
125
|
+
const filePath = join(projectPath, file);
|
|
210
126
|
let fileStats;
|
|
211
127
|
try {
|
|
212
128
|
fileStats = statSync(filePath);
|
|
@@ -218,7 +134,7 @@ async function handleListHistorySessions(workDir) {
|
|
|
218
134
|
let customTitle = "";
|
|
219
135
|
let jsonlSummary = "";
|
|
220
136
|
try {
|
|
221
|
-
const content =
|
|
137
|
+
const content = readFileSync(filePath, "utf-8");
|
|
222
138
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
223
139
|
for (const line of lines) {
|
|
224
140
|
try {
|
|
@@ -256,13 +172,13 @@ async function handleListHistorySessions(workDir) {
|
|
|
256
172
|
async function handleLoadSessionHistory(workDir, claudeSessionId) {
|
|
257
173
|
const projectsDir = getClaudeProjectsDir();
|
|
258
174
|
const projectFolder = pathToProjectFolder(workDir);
|
|
259
|
-
const filePath =
|
|
260
|
-
if (!
|
|
175
|
+
const filePath = join(projectsDir, projectFolder, `${claudeSessionId}.jsonl`);
|
|
176
|
+
if (!existsSync(filePath)) {
|
|
261
177
|
return { messages: [] };
|
|
262
178
|
}
|
|
263
179
|
const messages = [];
|
|
264
180
|
try {
|
|
265
|
-
const content =
|
|
181
|
+
const content = readFileSync(filePath, "utf-8");
|
|
266
182
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
267
183
|
for (const line of lines) {
|
|
268
184
|
try {
|
|
@@ -324,8 +240,8 @@ async function handleLoadSessionHistory(workDir, claudeSessionId) {
|
|
|
324
240
|
}
|
|
325
241
|
|
|
326
242
|
// src/hub-connection.ts
|
|
327
|
-
import { createLogger
|
|
328
|
-
var
|
|
243
|
+
import { createLogger } from "@mclawnet/logger";
|
|
244
|
+
var log = createLogger({ module: "agent" });
|
|
329
245
|
var HubConnection = class {
|
|
330
246
|
ws = null;
|
|
331
247
|
heartbeatTimer = null;
|
|
@@ -407,7 +323,7 @@ var HubConnection = class {
|
|
|
407
323
|
return;
|
|
408
324
|
}
|
|
409
325
|
if (this.authState === "pending" && data.type === "auth_required") {
|
|
410
|
-
|
|
326
|
+
log.info("hub requires auth, sending credentials");
|
|
411
327
|
this.authState = "authenticating";
|
|
412
328
|
this.sendRaw({
|
|
413
329
|
type: "auth",
|
|
@@ -419,7 +335,7 @@ var HubConnection = class {
|
|
|
419
335
|
return;
|
|
420
336
|
}
|
|
421
337
|
if (this.authState === "authenticating" && data.type === "registered") {
|
|
422
|
-
|
|
338
|
+
log.info({ agentId: data.agentId }, "registered with hub");
|
|
423
339
|
this.authState = "authenticated";
|
|
424
340
|
this.agentId = data.agentId ?? null;
|
|
425
341
|
this.startHeartbeat();
|
|
@@ -433,18 +349,18 @@ var HubConnection = class {
|
|
|
433
349
|
}
|
|
434
350
|
});
|
|
435
351
|
this.ws.on("close", (code, reason) => {
|
|
436
|
-
|
|
352
|
+
log.warn({ code, reason: reason.toString() }, "disconnected from hub");
|
|
437
353
|
this.stopHeartbeat();
|
|
438
354
|
this.authState = "pending";
|
|
439
355
|
this.onDisconnect?.(code, reason.toString());
|
|
440
356
|
if (code === WS_CLOSE_INVALID_TOKEN) {
|
|
441
|
-
|
|
357
|
+
log.error("auth failed \u2014 not reconnecting, check your token");
|
|
442
358
|
return;
|
|
443
359
|
}
|
|
444
360
|
this.scheduleReconnect();
|
|
445
361
|
});
|
|
446
362
|
this.ws.on("error", (err) => {
|
|
447
|
-
|
|
363
|
+
log.error({ err }, "ws connection error");
|
|
448
364
|
this.onError?.(err);
|
|
449
365
|
});
|
|
450
366
|
}
|
|
@@ -462,11 +378,11 @@ var HubConnection = class {
|
|
|
462
378
|
// ── Session message handling ─────────────────────────────────────
|
|
463
379
|
handleSessionMessage(msg) {
|
|
464
380
|
if (msg.type === "fs.list_dir") {
|
|
465
|
-
|
|
381
|
+
log.info({ path: msg.path }, "fs.list_dir");
|
|
466
382
|
handleListDir(msg.path).then((result) => {
|
|
467
383
|
this.send({ type: "fs.list_dir_result", requestId: msg.requestId, ...result });
|
|
468
384
|
}).catch((err) => {
|
|
469
|
-
|
|
385
|
+
log.error({ err, path: msg.path }, "fs.list_dir failed");
|
|
470
386
|
this.send({
|
|
471
387
|
type: "fs.list_dir_result",
|
|
472
388
|
requestId: msg.requestId,
|
|
@@ -477,21 +393,21 @@ var HubConnection = class {
|
|
|
477
393
|
return true;
|
|
478
394
|
}
|
|
479
395
|
if (msg.type === "list_folders") {
|
|
480
|
-
|
|
396
|
+
log.info("list_folders");
|
|
481
397
|
handleListFolders().then((result) => {
|
|
482
398
|
this.send({ type: "folders_list_result", requestId: msg.requestId, ...result });
|
|
483
399
|
}).catch((err) => {
|
|
484
|
-
|
|
400
|
+
log.error({ err }, "list_folders failed");
|
|
485
401
|
this.send({ type: "folders_list_result", requestId: msg.requestId, folders: [] });
|
|
486
402
|
});
|
|
487
403
|
return true;
|
|
488
404
|
}
|
|
489
405
|
if (msg.type === "list_history_sessions") {
|
|
490
|
-
|
|
406
|
+
log.info({ workDir: msg.workDir }, "list_history_sessions");
|
|
491
407
|
handleListHistorySessions(msg.workDir).then((result) => {
|
|
492
408
|
this.send({ type: "history_sessions_result", requestId: msg.requestId, ...result });
|
|
493
409
|
}).catch((err) => {
|
|
494
|
-
|
|
410
|
+
log.error({ err, workDir: msg.workDir }, "list_history_sessions failed");
|
|
495
411
|
this.send({
|
|
496
412
|
type: "history_sessions_result",
|
|
497
413
|
requestId: msg.requestId,
|
|
@@ -502,26 +418,28 @@ var HubConnection = class {
|
|
|
502
418
|
return true;
|
|
503
419
|
}
|
|
504
420
|
if (msg.type === "load_session_history") {
|
|
505
|
-
|
|
421
|
+
log.info({ workDir: msg.workDir, claudeSessionId: msg.claudeSessionId }, "load_session_history");
|
|
506
422
|
handleLoadSessionHistory(msg.workDir, msg.claudeSessionId).then((result) => {
|
|
507
423
|
this.send({ type: "session_history_result", requestId: msg.requestId, ...result });
|
|
508
424
|
}).catch((err) => {
|
|
509
|
-
|
|
425
|
+
log.error({ err, workDir: msg.workDir }, "load_session_history failed");
|
|
510
426
|
this.send({ type: "session_history_result", requestId: msg.requestId, messages: [] });
|
|
511
427
|
});
|
|
512
428
|
return true;
|
|
513
429
|
}
|
|
514
430
|
if (msg.type === "list_roles") {
|
|
515
|
-
|
|
431
|
+
log.info("list_roles");
|
|
516
432
|
const roleNames = listRoles();
|
|
517
433
|
const roles = roleNames.map((name) => {
|
|
518
434
|
try {
|
|
519
435
|
const def = loadRole(name);
|
|
520
436
|
return {
|
|
521
437
|
name: def.name,
|
|
522
|
-
displayName: def.
|
|
438
|
+
displayName: def.displayName || def.description || def.name,
|
|
523
439
|
description: def.description || "",
|
|
524
440
|
capabilities: def.capabilities || [],
|
|
441
|
+
type: def.type,
|
|
442
|
+
color: def.color,
|
|
525
443
|
promptBody: def.promptBody || ""
|
|
526
444
|
};
|
|
527
445
|
} catch {
|
|
@@ -535,12 +453,41 @@ var HubConnection = class {
|
|
|
535
453
|
});
|
|
536
454
|
return true;
|
|
537
455
|
}
|
|
456
|
+
if (msg.type === "list_templates") {
|
|
457
|
+
log.info("list_templates");
|
|
458
|
+
try {
|
|
459
|
+
const names = listTemplates();
|
|
460
|
+
const templates = names.map((name) => {
|
|
461
|
+
const tpl = loadTemplate(name);
|
|
462
|
+
return {
|
|
463
|
+
name: tpl.name,
|
|
464
|
+
displayName: tpl.displayName,
|
|
465
|
+
description: tpl.description,
|
|
466
|
+
icon: tpl.icon,
|
|
467
|
+
roles: tpl.roles
|
|
468
|
+
};
|
|
469
|
+
});
|
|
470
|
+
this.send({
|
|
471
|
+
type: "templates_list_result",
|
|
472
|
+
sessionId: msg.sessionId,
|
|
473
|
+
templates
|
|
474
|
+
});
|
|
475
|
+
} catch (err) {
|
|
476
|
+
log.error({ err }, "list_templates failed");
|
|
477
|
+
this.send({
|
|
478
|
+
type: "templates_list_result",
|
|
479
|
+
sessionId: msg.sessionId,
|
|
480
|
+
templates: []
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
return true;
|
|
484
|
+
}
|
|
538
485
|
if (msg.type === "generic.request") {
|
|
539
486
|
const handler = this.namespaceHandlers.get(msg.namespace);
|
|
540
487
|
if (handler) {
|
|
541
|
-
|
|
488
|
+
log.info({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, "generic.request received");
|
|
542
489
|
handler(msg).then((result) => {
|
|
543
|
-
|
|
490
|
+
log.info({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, "generic.request handled OK");
|
|
544
491
|
this.send({
|
|
545
492
|
type: "generic.response",
|
|
546
493
|
namespace: msg.namespace,
|
|
@@ -549,7 +496,7 @@ var HubConnection = class {
|
|
|
549
496
|
requestId: msg.requestId
|
|
550
497
|
});
|
|
551
498
|
}).catch((err) => {
|
|
552
|
-
|
|
499
|
+
log.error({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId, err }, "generic.request handler error");
|
|
553
500
|
this.send({
|
|
554
501
|
type: "generic.response",
|
|
555
502
|
namespace: msg.namespace,
|
|
@@ -561,7 +508,7 @@ var HubConnection = class {
|
|
|
561
508
|
});
|
|
562
509
|
return true;
|
|
563
510
|
}
|
|
564
|
-
|
|
511
|
+
log.warn({ namespace: msg.namespace, action: msg.action, requestId: msg.requestId }, "generic.request unknown namespace");
|
|
565
512
|
this.send({
|
|
566
513
|
type: "generic.response",
|
|
567
514
|
namespace: msg.namespace,
|
|
@@ -575,7 +522,7 @@ var HubConnection = class {
|
|
|
575
522
|
if (msg.type === "swarm.execute" && this.swarmCoordinator) {
|
|
576
523
|
const { sessionId, content, workDir, targetInstance, crewConfig } = msg;
|
|
577
524
|
if (this.swarmCoordinator.hasSwarm(sessionId)) {
|
|
578
|
-
|
|
525
|
+
log.info({ sessionId, targetInstance }, "swarm.execute: forwarding to existing swarm");
|
|
579
526
|
this.swarmCoordinator.handleUserMessage(sessionId, content, targetInstance).catch((err) => {
|
|
580
527
|
this.send({
|
|
581
528
|
type: "session.error",
|
|
@@ -584,16 +531,17 @@ var HubConnection = class {
|
|
|
584
531
|
});
|
|
585
532
|
});
|
|
586
533
|
} else if (this.finishedSwarms.has(sessionId)) {
|
|
587
|
-
|
|
534
|
+
log.info({ sessionId }, "swarm.execute ignored: swarm already finished");
|
|
588
535
|
this.send({
|
|
589
536
|
type: "session.error",
|
|
590
537
|
sessionId,
|
|
591
538
|
error: "\u8702\u7FA4\u4EFB\u52A1\u5DF2\u5B8C\u6210\uFF0C\u65E0\u6CD5\u7EE7\u7EED\u64CD\u4F5C\u3002\u8BF7\u521B\u5EFA\u65B0\u7684\u8702\u7FA4\u4EFB\u52A1\u3002"
|
|
592
539
|
});
|
|
593
|
-
} else if (crewConfig?.roles) {
|
|
594
|
-
|
|
540
|
+
} else if (crewConfig?.templateName || crewConfig?.roles) {
|
|
541
|
+
const templateName = crewConfig.templateName;
|
|
595
542
|
const roles = crewConfig.roles;
|
|
596
|
-
|
|
543
|
+
log.info({ sessionId, templateName, rolesCount: roles?.length }, "swarm.execute: creating new swarm");
|
|
544
|
+
this.swarmCoordinator.create(sessionId, { workDir, templateName, roles, task: content }).catch((err) => {
|
|
597
545
|
this.send({
|
|
598
546
|
type: "session.error",
|
|
599
547
|
sessionId,
|
|
@@ -601,7 +549,7 @@ var HubConnection = class {
|
|
|
601
549
|
});
|
|
602
550
|
});
|
|
603
551
|
} else {
|
|
604
|
-
|
|
552
|
+
log.info({ sessionId }, "swarm.execute ignored: swarm not found, no config");
|
|
605
553
|
this.send({
|
|
606
554
|
type: "session.error",
|
|
607
555
|
sessionId,
|
|
@@ -613,7 +561,7 @@ var HubConnection = class {
|
|
|
613
561
|
if (!this.sessionManager) return false;
|
|
614
562
|
if (msg.type === "abort_execution") {
|
|
615
563
|
const { sessionId } = msg;
|
|
616
|
-
|
|
564
|
+
log.info({ sessionId }, "abort_execution");
|
|
617
565
|
if (this.sessionManager?.hasSession(sessionId)) {
|
|
618
566
|
this.sessionManager.abortSession(sessionId).then(() => {
|
|
619
567
|
this.send({ type: "execution_aborted", sessionId });
|
|
@@ -628,10 +576,10 @@ var HubConnection = class {
|
|
|
628
576
|
if (msg.type === "claude.execute") {
|
|
629
577
|
const { sessionId, content, workDir, claudeSessionId, useBrainCore } = msg;
|
|
630
578
|
if (this.sessionManager.hasSession(sessionId)) {
|
|
631
|
-
|
|
579
|
+
log.info({ sessionId }, "claude.execute: reusing existing session");
|
|
632
580
|
this.sessionManager.sendInput(sessionId, content);
|
|
633
581
|
} else {
|
|
634
|
-
|
|
582
|
+
log.info({ sessionId, workDir, roleId: "role-__assistant__" }, "claude.execute: creating new session with memory injection");
|
|
635
583
|
this.sessionManager.createSession({ sessionId, workDir, resumeId: claudeSessionId, useBrainCore, roleId: "role-__assistant__" }).then(() => {
|
|
636
584
|
this.sessionManager.sendInput(sessionId, content);
|
|
637
585
|
}).catch((err) => {
|
|
@@ -645,7 +593,7 @@ var HubConnection = class {
|
|
|
645
593
|
return true;
|
|
646
594
|
}
|
|
647
595
|
if (msg.type === "session.create") {
|
|
648
|
-
|
|
596
|
+
log.info({ sessionId: msg.sessionId, roleId: "role-__assistant__" }, "session.create with memory injection");
|
|
649
597
|
this.sessionManager.createSession({
|
|
650
598
|
sessionId: msg.sessionId,
|
|
651
599
|
workDir: msg.workDir,
|
|
@@ -667,13 +615,13 @@ var HubConnection = class {
|
|
|
667
615
|
return true;
|
|
668
616
|
}
|
|
669
617
|
if (msg.type === "session.close") {
|
|
670
|
-
|
|
618
|
+
log.info({ sessionId: msg.sessionId }, "session.close");
|
|
671
619
|
this.sessionManager.closeSession(msg.sessionId).catch(() => {
|
|
672
620
|
});
|
|
673
621
|
return true;
|
|
674
622
|
}
|
|
675
623
|
if (msg.type === "claude.input") {
|
|
676
|
-
|
|
624
|
+
log.info({ sessionId: msg.sessionId }, "claude.input");
|
|
677
625
|
this.sessionManager.sendInput(msg.sessionId, msg.content);
|
|
678
626
|
return true;
|
|
679
627
|
}
|
|
@@ -689,17 +637,17 @@ var HubConnection = class {
|
|
|
689
637
|
for (const id of allIds) {
|
|
690
638
|
if (!recoverableIds.has(id)) {
|
|
691
639
|
deleteSwarmSnapshot(id);
|
|
692
|
-
|
|
640
|
+
log.info({ swarmId: id }, "cleaned up non-recoverable swarm snapshot");
|
|
693
641
|
}
|
|
694
642
|
}
|
|
695
643
|
for (const snap of snapshots) {
|
|
696
|
-
|
|
644
|
+
log.info({ swarmId: snap.id }, "recovering swarm");
|
|
697
645
|
recoverSwarm(this.swarmCoordinator, snap).catch((err) => {
|
|
698
|
-
|
|
646
|
+
log.error({ err, swarmId: snap.id }, "failed to recover swarm");
|
|
699
647
|
});
|
|
700
648
|
}
|
|
701
649
|
} catch (err) {
|
|
702
|
-
|
|
650
|
+
log.error({ err }, "swarm recovery failed");
|
|
703
651
|
}
|
|
704
652
|
}
|
|
705
653
|
sendRaw(data) {
|
|
@@ -721,7 +669,7 @@ var HubConnection = class {
|
|
|
721
669
|
}
|
|
722
670
|
scheduleReconnect() {
|
|
723
671
|
if (this.destroyed) return;
|
|
724
|
-
|
|
672
|
+
log.warn({ delayMs: this.reconnectDelay }, "reconnecting to hub...");
|
|
725
673
|
this.reconnectTimer = setTimeout(() => {
|
|
726
674
|
this.connect();
|
|
727
675
|
}, this.reconnectDelay);
|
|
@@ -746,17 +694,14 @@ var HubConnection = class {
|
|
|
746
694
|
};
|
|
747
695
|
|
|
748
696
|
// src/session-manager.ts
|
|
749
|
-
import {
|
|
750
|
-
import { tmpdir } from "os";
|
|
751
|
-
import { join as join3, dirname } from "path";
|
|
752
|
-
import { createRequire } from "module";
|
|
753
|
-
import { createLogger as createLogger3 } from "@mclawnet/logger";
|
|
697
|
+
import { createLogger as createLogger2 } from "@mclawnet/logger";
|
|
754
698
|
import { buildMemorySection } from "@mclawnet/memory";
|
|
755
|
-
var
|
|
699
|
+
var log2 = createLogger2({ module: "agent/session-manager" });
|
|
700
|
+
var DEFAULT_MAX_PROCESSES = 10;
|
|
701
|
+
var MAX_PROCESSES = Number(process.env.CLAWNET_MAX_PROCESSES) || DEFAULT_MAX_PROCESSES;
|
|
756
702
|
var SessionManager = class {
|
|
757
703
|
sessions = /* @__PURE__ */ new Map();
|
|
758
704
|
conversationBuffer = /* @__PURE__ */ new Map();
|
|
759
|
-
mcpConfigPaths = /* @__PURE__ */ new Map();
|
|
760
705
|
adapter;
|
|
761
706
|
onOutput;
|
|
762
707
|
onTurnComplete;
|
|
@@ -773,23 +718,21 @@ var SessionManager = class {
|
|
|
773
718
|
if (this.sessions.has(options.sessionId)) {
|
|
774
719
|
throw new Error(`Session ${options.sessionId} already exists`);
|
|
775
720
|
}
|
|
721
|
+
if (this.sessions.size >= MAX_PROCESSES) {
|
|
722
|
+
throw new Error(`Process limit reached (${MAX_PROCESSES}). Cannot create new session.`);
|
|
723
|
+
}
|
|
776
724
|
if (options.roleId) {
|
|
777
725
|
try {
|
|
778
726
|
const memorySection = buildMemorySection(options.roleId);
|
|
779
|
-
|
|
727
|
+
const roleHint = `
|
|
780
728
|
|
|
781
|
-
${options.
|
|
782
|
-
|
|
729
|
+
[Memory Context] Your roleId is "${options.roleId}". Always use this roleId when calling memory_search, memory_store, memory_stats, or memory_reflect.`;
|
|
730
|
+
options.systemPrompt = options.systemPrompt ? `${memorySection}${roleHint}
|
|
731
|
+
|
|
732
|
+
${options.systemPrompt}` : `${memorySection}${roleHint}`;
|
|
733
|
+
log2.debug({ roleId: options.roleId, sessionId: options.sessionId }, "memory prompt + roleId hint injected");
|
|
783
734
|
} catch (err) {
|
|
784
|
-
|
|
785
|
-
}
|
|
786
|
-
if (!options.mcpConfigPath) {
|
|
787
|
-
try {
|
|
788
|
-
options.mcpConfigPath = this.createMemoryMcpConfig(options.sessionId, options.roleId);
|
|
789
|
-
log3.debug({ roleId: options.roleId, sessionId: options.sessionId }, "memory MCP config created");
|
|
790
|
-
} catch (err) {
|
|
791
|
-
log3.warn({ err, roleId: options.roleId }, "failed to create memory MCP config, proceeding without");
|
|
792
|
-
}
|
|
735
|
+
log2.warn({ err, roleId: options.roleId }, "failed to build memory section, proceeding without");
|
|
793
736
|
}
|
|
794
737
|
}
|
|
795
738
|
try {
|
|
@@ -832,7 +775,6 @@ ${options.systemPrompt}` : memorySection;
|
|
|
832
775
|
const process2 = this.sessions.get(sessionId);
|
|
833
776
|
if (!process2) return;
|
|
834
777
|
this.conversationBuffer.delete(sessionId);
|
|
835
|
-
this.cleanupMcpConfig(sessionId);
|
|
836
778
|
this.sessions.delete(sessionId);
|
|
837
779
|
await this.adapter.stop(process2);
|
|
838
780
|
}
|
|
@@ -845,7 +787,6 @@ ${options.systemPrompt}` : memorySection;
|
|
|
845
787
|
});
|
|
846
788
|
}
|
|
847
789
|
this.conversationBuffer.delete(sessionId);
|
|
848
|
-
this.cleanupMcpConfig(sessionId);
|
|
849
790
|
this.sessions.delete(sessionId);
|
|
850
791
|
await this.adapter.stop(process2);
|
|
851
792
|
}
|
|
@@ -858,7 +799,6 @@ ${options.systemPrompt}` : memorySection;
|
|
|
858
799
|
});
|
|
859
800
|
}
|
|
860
801
|
this.conversationBuffer.delete(sessionId);
|
|
861
|
-
this.cleanupMcpConfig(sessionId);
|
|
862
802
|
this.sessions.delete(sessionId);
|
|
863
803
|
await this.adapter.stop(process2).catch(() => {
|
|
864
804
|
});
|
|
@@ -872,56 +812,107 @@ ${options.systemPrompt}` : memorySection;
|
|
|
872
812
|
get activeSessionCount() {
|
|
873
813
|
return this.sessions.size;
|
|
874
814
|
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
815
|
+
};
|
|
816
|
+
|
|
817
|
+
// src/start.ts
|
|
818
|
+
import { SwarmCoordinator, initRoles } from "@mclawnet/swarm";
|
|
819
|
+
|
|
820
|
+
// src/skill-loader.ts
|
|
821
|
+
import { existsSync as existsSync2, mkdirSync, copyFileSync, readdirSync as readdirSync2, writeFileSync } from "fs";
|
|
822
|
+
import { join as join2, dirname } from "path";
|
|
823
|
+
import { homedir as homedir2 } from "os";
|
|
824
|
+
import { createRequire } from "module";
|
|
825
|
+
import { fileURLToPath } from "url";
|
|
826
|
+
import { createLogger as createLogger3 } from "@mclawnet/logger";
|
|
827
|
+
var log3 = createLogger3({ module: "agent/skill-loader" });
|
|
828
|
+
var CLAWNET_DIR = join2(homedir2(), ".clawnet");
|
|
829
|
+
var SKILLS_DIR = join2(CLAWNET_DIR, ".claude", "skills");
|
|
830
|
+
var MCP_CONFIG_PATH = join2(CLAWNET_DIR, "mcp.json");
|
|
831
|
+
async function initSkills() {
|
|
832
|
+
ensureSkillsDir();
|
|
833
|
+
copyBuiltinSkills();
|
|
834
|
+
ensureMcpConfig();
|
|
835
|
+
}
|
|
836
|
+
function ensureSkillsDir() {
|
|
837
|
+
if (!existsSync2(SKILLS_DIR)) {
|
|
838
|
+
mkdirSync(SKILLS_DIR, { recursive: true });
|
|
839
|
+
log3.info({ dir: SKILLS_DIR }, "created skills directory");
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
function copyBuiltinSkills() {
|
|
843
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
844
|
+
const srcDir = join2(dirname(thisFile), "..", "skills");
|
|
845
|
+
if (!existsSync2(srcDir)) {
|
|
846
|
+
log3.debug({ srcDir }, "no built-in skills directory found, skipping");
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
let entries;
|
|
850
|
+
try {
|
|
851
|
+
entries = readdirSync2(srcDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
852
|
+
} catch {
|
|
853
|
+
log3.warn({ srcDir }, "failed to read built-in skills directory");
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
for (const skillName of entries) {
|
|
857
|
+
const srcSkillMd = join2(srcDir, skillName, "SKILL.md");
|
|
858
|
+
const destDir = join2(SKILLS_DIR, skillName);
|
|
859
|
+
const destSkillMd = join2(destDir, "SKILL.md");
|
|
860
|
+
if (!existsSync2(srcSkillMd)) continue;
|
|
861
|
+
if (existsSync2(destSkillMd)) {
|
|
862
|
+
log3.debug({ skill: skillName }, "skill already exists, skipping");
|
|
863
|
+
continue;
|
|
864
|
+
}
|
|
865
|
+
try {
|
|
866
|
+
mkdirSync(destDir, { recursive: true });
|
|
867
|
+
copyFileSync(srcSkillMd, destSkillMd);
|
|
868
|
+
log3.info({ skill: skillName }, "copied built-in skill");
|
|
869
|
+
} catch (err) {
|
|
870
|
+
log3.warn({ skill: skillName, err }, "failed to copy built-in skill");
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
function ensureMcpConfig() {
|
|
875
|
+
if (existsSync2(MCP_CONFIG_PATH)) {
|
|
876
|
+
log3.debug("mcp.json already exists, skipping");
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
let mcpServerPath;
|
|
880
|
+
try {
|
|
878
881
|
const req = createRequire(import.meta.url);
|
|
879
882
|
const memoryPkgDir = dirname(req.resolve("@mclawnet/memory/package.json"));
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
JSON.stringify({
|
|
885
|
-
mcpServers: {
|
|
886
|
-
"clawnet-memory": {
|
|
887
|
-
command: "node",
|
|
888
|
-
args: [mcpServerPath, "--role-id", roleId]
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
})
|
|
892
|
-
);
|
|
893
|
-
this.mcpConfigPaths.set(sessionId, configPath);
|
|
894
|
-
log3.debug({ sessionId, roleId, configPath, mcpServerPath }, "memory MCP config file written");
|
|
895
|
-
return configPath;
|
|
883
|
+
mcpServerPath = join2(memoryPkgDir, "dist", "mcp", "server.js");
|
|
884
|
+
} catch {
|
|
885
|
+
log3.warn("could not resolve @mclawnet/memory package path, skipping mcp.json generation");
|
|
886
|
+
return;
|
|
896
887
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
unlinkSync(configPath);
|
|
903
|
-
} catch {
|
|
888
|
+
const config = {
|
|
889
|
+
mcpServers: {
|
|
890
|
+
"clawnet-memory": {
|
|
891
|
+
command: "node",
|
|
892
|
+
args: [mcpServerPath]
|
|
904
893
|
}
|
|
905
|
-
this.mcpConfigPaths.delete(sessionId);
|
|
906
|
-
log3.debug({ sessionId, configPath }, "memory MCP config file cleaned up");
|
|
907
894
|
}
|
|
895
|
+
};
|
|
896
|
+
try {
|
|
897
|
+
mkdirSync(CLAWNET_DIR, { recursive: true });
|
|
898
|
+
writeFileSync(MCP_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
|
|
899
|
+
log3.info({ path: MCP_CONFIG_PATH }, "generated default mcp.json");
|
|
900
|
+
} catch (err) {
|
|
901
|
+
log3.warn({ err }, "failed to generate mcp.json");
|
|
908
902
|
}
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
// src/start.ts
|
|
912
|
-
import { SwarmCoordinator, initRoles } from "@mclawnet/swarm";
|
|
903
|
+
}
|
|
913
904
|
|
|
914
905
|
// src/brain-bridge.ts
|
|
915
|
-
import { existsSync as existsSync3, readFileSync as
|
|
916
|
-
import { join as
|
|
906
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync as readdirSync3 } from "fs";
|
|
907
|
+
import { join as join3 } from "path";
|
|
917
908
|
import { createLogger as createLogger4 } from "@mclawnet/logger";
|
|
918
909
|
var log4 = createLogger4({ module: "brain-bridge" });
|
|
919
910
|
var BrainBridge = class {
|
|
920
911
|
constructor(hub, options) {
|
|
921
912
|
this.hub = hub;
|
|
922
913
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
923
|
-
this.brainHome = options?.brainHomePath || process.env.BRAIN_HOME ||
|
|
924
|
-
this.brainCorePath = options?.brainCorePath ||
|
|
914
|
+
this.brainHome = options?.brainHomePath || process.env.BRAIN_HOME || join3(home, "BrainData");
|
|
915
|
+
this.brainCorePath = options?.brainCorePath || join3(home, ".brain", "BrainCore");
|
|
925
916
|
this.hub.registerNamespace("brain", (msg) => this.handleRequest(msg));
|
|
926
917
|
log4.info(
|
|
927
918
|
{ brainHome: this.brainHome, brainCorePath: this.brainCorePath },
|
|
@@ -952,7 +943,7 @@ var BrainBridge = class {
|
|
|
952
943
|
return "not_installed";
|
|
953
944
|
}
|
|
954
945
|
const home = process.env.HOME || process.env.USERPROFILE || "";
|
|
955
|
-
const installJson =
|
|
946
|
+
const installJson = join3(home, ".brain", "install.json");
|
|
956
947
|
if (!existsSync3(installJson)) {
|
|
957
948
|
return "needs_config";
|
|
958
949
|
}
|
|
@@ -964,18 +955,18 @@ var BrainBridge = class {
|
|
|
964
955
|
/** Read the most recent daily briefing report */
|
|
965
956
|
async getBriefing(date) {
|
|
966
957
|
const targetDate = date || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
967
|
-
const reportsDir =
|
|
958
|
+
const reportsDir = join3(this.brainHome, "reports", "daily");
|
|
968
959
|
if (!existsSync3(reportsDir)) {
|
|
969
960
|
log4.info({ reportsDir }, "get_briefing: reports dir not found");
|
|
970
961
|
return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };
|
|
971
962
|
}
|
|
972
|
-
const files =
|
|
963
|
+
const files = readdirSync3(reportsDir).filter((f) => f.includes(targetDate) && f.endsWith(".md")).sort().reverse();
|
|
973
964
|
if (files.length === 0) {
|
|
974
965
|
log4.info({ targetDate }, "get_briefing: no report for date");
|
|
975
966
|
return { briefing: null, actions: [], projects: [], meetings: [], feed: [] };
|
|
976
967
|
}
|
|
977
968
|
log4.info({ targetDate, file: files[0] }, "get_briefing: reading report");
|
|
978
|
-
const content =
|
|
969
|
+
const content = readFileSync2(join3(reportsDir, files[0]), "utf-8");
|
|
979
970
|
const tldrMatch = content.match(/## TL;DR\n([\s\S]*?)(?=\n---|\n## )/);
|
|
980
971
|
const tldr = tldrMatch ? tldrMatch[1].trim() : content.slice(0, 200);
|
|
981
972
|
const actions = this.parseActions(content);
|
|
@@ -1174,12 +1165,12 @@ var BrainBridge = class {
|
|
|
1174
1165
|
if (!recapPath) {
|
|
1175
1166
|
return { error: "No recap path provided" };
|
|
1176
1167
|
}
|
|
1177
|
-
const fullPath =
|
|
1168
|
+
const fullPath = join3(this.brainHome, recapPath);
|
|
1178
1169
|
if (!existsSync3(fullPath)) {
|
|
1179
1170
|
log4.warn({ fullPath }, "meeting recap file not found");
|
|
1180
1171
|
return { error: "Recap file not found" };
|
|
1181
1172
|
}
|
|
1182
|
-
const content =
|
|
1173
|
+
const content = readFileSync2(fullPath, "utf-8");
|
|
1183
1174
|
return { recap: this.parseRecapMarkdown(content) };
|
|
1184
1175
|
}
|
|
1185
1176
|
/** Parse meeting recap markdown into structured sections */
|
|
@@ -1212,7 +1203,7 @@ var BrainBridge = class {
|
|
|
1212
1203
|
};
|
|
1213
1204
|
|
|
1214
1205
|
// src/fs-bridge.ts
|
|
1215
|
-
import { existsSync as existsSync4, readFileSync as
|
|
1206
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
|
|
1216
1207
|
import { extname, isAbsolute } from "path";
|
|
1217
1208
|
import { createLogger as createLogger5 } from "@mclawnet/logger";
|
|
1218
1209
|
var log5 = createLogger5({ module: "fs-bridge" });
|
|
@@ -1280,12 +1271,12 @@ var FsBridge = class {
|
|
|
1280
1271
|
const mimeType = getMimeType(filePath);
|
|
1281
1272
|
const totalSize = stat2.size;
|
|
1282
1273
|
if (isTextMime(mimeType)) {
|
|
1283
|
-
const raw =
|
|
1274
|
+
const raw = readFileSync3(filePath, "utf-8");
|
|
1284
1275
|
const truncated2 = raw.length > MAX_TEXT_SIZE;
|
|
1285
1276
|
const content = truncated2 ? raw.slice(0, MAX_TEXT_SIZE) : raw;
|
|
1286
1277
|
return { content, encoding: "utf-8", size: content.length, totalSize, mimeType, truncated: truncated2 };
|
|
1287
1278
|
}
|
|
1288
|
-
const buf =
|
|
1279
|
+
const buf = readFileSync3(filePath);
|
|
1289
1280
|
const truncated = buf.length > MAX_TEXT_SIZE;
|
|
1290
1281
|
const slice = truncated ? buf.subarray(0, MAX_TEXT_SIZE) : buf;
|
|
1291
1282
|
return { content: slice.toString("base64"), encoding: "base64", size: slice.length, totalSize, mimeType, truncated };
|
|
@@ -1304,6 +1295,7 @@ async function startAgent(options) {
|
|
|
1304
1295
|
log6.info({ backend: options.adapter.type }, "starting agent");
|
|
1305
1296
|
log6.info({ hubUrl: config.hubUrl }, "connecting to hub");
|
|
1306
1297
|
await initRoles();
|
|
1298
|
+
await initSkills();
|
|
1307
1299
|
const hub = new HubConnection({
|
|
1308
1300
|
hubUrl: config.hubUrl,
|
|
1309
1301
|
token: config.token,
|
|
@@ -1367,10 +1359,8 @@ async function startAgent(options) {
|
|
|
1367
1359
|
export {
|
|
1368
1360
|
HubConnection,
|
|
1369
1361
|
SessionManager,
|
|
1370
|
-
loadConfig,
|
|
1371
|
-
saveConfig,
|
|
1372
1362
|
BrainBridge,
|
|
1373
1363
|
FsBridge,
|
|
1374
1364
|
startAgent
|
|
1375
1365
|
};
|
|
1376
|
-
//# sourceMappingURL=chunk-
|
|
1366
|
+
//# sourceMappingURL=chunk-GLO5OZAY.js.map
|