@hasna/brains 0.0.2 → 0.0.4
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/index.js +27 -0
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/package-metadata.d.ts +2 -0
- package/dist/lib/package-metadata.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +74 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +329 -284
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +47 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9403,6 +9403,32 @@ class ThinkerLabsProvider {
|
|
|
9403
9403
|
return cancelJob(jobId);
|
|
9404
9404
|
}
|
|
9405
9405
|
}
|
|
9406
|
+
// src/lib/package-metadata.ts
|
|
9407
|
+
import { existsSync, readFileSync as readFileSync2 } from "fs";
|
|
9408
|
+
import { dirname as dirname2, resolve } from "path";
|
|
9409
|
+
import { fileURLToPath } from "url";
|
|
9410
|
+
var DEFAULT_VERSION = "0.0.0";
|
|
9411
|
+
var cachedVersion;
|
|
9412
|
+
function getPackageJsonPath() {
|
|
9413
|
+
return resolve(dirname2(fileURLToPath(import.meta.url)), "../../package.json");
|
|
9414
|
+
}
|
|
9415
|
+
function getPackageVersion() {
|
|
9416
|
+
if (cachedVersion) {
|
|
9417
|
+
return cachedVersion;
|
|
9418
|
+
}
|
|
9419
|
+
const packageJsonPath = getPackageJsonPath();
|
|
9420
|
+
if (!existsSync(packageJsonPath)) {
|
|
9421
|
+
cachedVersion = DEFAULT_VERSION;
|
|
9422
|
+
return cachedVersion;
|
|
9423
|
+
}
|
|
9424
|
+
try {
|
|
9425
|
+
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
9426
|
+
cachedVersion = typeof packageJson.version === "string" ? packageJson.version : DEFAULT_VERSION;
|
|
9427
|
+
} catch {
|
|
9428
|
+
cachedVersion = DEFAULT_VERSION;
|
|
9429
|
+
}
|
|
9430
|
+
return cachedVersion;
|
|
9431
|
+
}
|
|
9406
9432
|
export {
|
|
9407
9433
|
uploadTrainingFile,
|
|
9408
9434
|
uploadTrainingData,
|
|
@@ -9412,6 +9438,7 @@ export {
|
|
|
9412
9438
|
listModels,
|
|
9413
9439
|
listFineTunedModels,
|
|
9414
9440
|
getStatus,
|
|
9441
|
+
getPackageVersion,
|
|
9415
9442
|
getFineTuneStatus,
|
|
9416
9443
|
getDb,
|
|
9417
9444
|
fineTunedModels,
|
package/dist/lib/index.d.ts
CHANGED
package/dist/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AACA,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-metadata.d.ts","sourceRoot":"","sources":["../../src/lib/package-metadata.ts"],"names":[],"mappings":"AAYA,wBAAgB,iBAAiB,IAAI,MAAM,CAmB1C"}
|
package/dist/mcp/index.d.ts
CHANGED
|
@@ -1,2 +1,75 @@
|
|
|
1
|
-
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
export declare const MCP_SERVER_INFO: {
|
|
4
|
+
readonly name: "brains";
|
|
5
|
+
readonly version: string;
|
|
6
|
+
};
|
|
7
|
+
export declare function createMcpServer(): Server<{
|
|
8
|
+
method: string;
|
|
9
|
+
params?: {
|
|
10
|
+
[x: string]: unknown;
|
|
11
|
+
_meta?: {
|
|
12
|
+
[x: string]: unknown;
|
|
13
|
+
progressToken?: string | number | undefined;
|
|
14
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
15
|
+
taskId: string;
|
|
16
|
+
} | undefined;
|
|
17
|
+
} | undefined;
|
|
18
|
+
} | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
method: string;
|
|
21
|
+
params?: {
|
|
22
|
+
[x: string]: unknown;
|
|
23
|
+
_meta?: {
|
|
24
|
+
[x: string]: unknown;
|
|
25
|
+
progressToken?: string | number | undefined;
|
|
26
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
27
|
+
taskId: string;
|
|
28
|
+
} | undefined;
|
|
29
|
+
} | undefined;
|
|
30
|
+
} | undefined;
|
|
31
|
+
}, {
|
|
32
|
+
[x: string]: unknown;
|
|
33
|
+
_meta?: {
|
|
34
|
+
[x: string]: unknown;
|
|
35
|
+
progressToken?: string | number | undefined;
|
|
36
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
37
|
+
taskId: string;
|
|
38
|
+
} | undefined;
|
|
39
|
+
} | undefined;
|
|
40
|
+
}>;
|
|
41
|
+
export declare function startMcpServer(transport?: StdioServerTransport): Promise<Server<{
|
|
42
|
+
method: string;
|
|
43
|
+
params?: {
|
|
44
|
+
[x: string]: unknown;
|
|
45
|
+
_meta?: {
|
|
46
|
+
[x: string]: unknown;
|
|
47
|
+
progressToken?: string | number | undefined;
|
|
48
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
49
|
+
taskId: string;
|
|
50
|
+
} | undefined;
|
|
51
|
+
} | undefined;
|
|
52
|
+
} | undefined;
|
|
53
|
+
}, {
|
|
54
|
+
method: string;
|
|
55
|
+
params?: {
|
|
56
|
+
[x: string]: unknown;
|
|
57
|
+
_meta?: {
|
|
58
|
+
[x: string]: unknown;
|
|
59
|
+
progressToken?: string | number | undefined;
|
|
60
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
61
|
+
taskId: string;
|
|
62
|
+
} | undefined;
|
|
63
|
+
} | undefined;
|
|
64
|
+
} | undefined;
|
|
65
|
+
}, {
|
|
66
|
+
[x: string]: unknown;
|
|
67
|
+
_meta?: {
|
|
68
|
+
[x: string]: unknown;
|
|
69
|
+
progressToken?: string | number | undefined;
|
|
70
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
71
|
+
taskId: string;
|
|
72
|
+
} | undefined;
|
|
73
|
+
} | undefined;
|
|
74
|
+
}>>;
|
|
2
75
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/mcp/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AA8BjF,eAAO,MAAM,eAAe;;;CAGlB,CAAC;AAEX,wBAAgB,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4X9B;AAED,wBAAsB,cAAc,CAAC,SAAS,uBAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAI1E"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -33,8 +33,8 @@ import {
|
|
|
33
33
|
CallToolRequestSchema,
|
|
34
34
|
ListToolsRequestSchema
|
|
35
35
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
36
|
-
import { readFileSync as
|
|
37
|
-
import { resolve } from "path";
|
|
36
|
+
import { readFileSync as readFileSync3, existsSync as existsSync2 } from "fs";
|
|
37
|
+
import { resolve as resolve2 } from "path";
|
|
38
38
|
import { homedir as homedir3 } from "os";
|
|
39
39
|
|
|
40
40
|
// node_modules/drizzle-orm/entity.js
|
|
@@ -9525,6 +9525,33 @@ async function gatherFromTodos(options = {}) {
|
|
|
9525
9525
|
}
|
|
9526
9526
|
}
|
|
9527
9527
|
|
|
9528
|
+
// src/lib/package-metadata.ts
|
|
9529
|
+
import { existsSync, readFileSync as readFileSync2 } from "fs";
|
|
9530
|
+
import { dirname as dirname2, resolve } from "path";
|
|
9531
|
+
import { fileURLToPath } from "url";
|
|
9532
|
+
var DEFAULT_VERSION = "0.0.0";
|
|
9533
|
+
var cachedVersion;
|
|
9534
|
+
function getPackageJsonPath() {
|
|
9535
|
+
return resolve(dirname2(fileURLToPath(import.meta.url)), "../../package.json");
|
|
9536
|
+
}
|
|
9537
|
+
function getPackageVersion() {
|
|
9538
|
+
if (cachedVersion) {
|
|
9539
|
+
return cachedVersion;
|
|
9540
|
+
}
|
|
9541
|
+
const packageJsonPath = getPackageJsonPath();
|
|
9542
|
+
if (!existsSync(packageJsonPath)) {
|
|
9543
|
+
cachedVersion = DEFAULT_VERSION;
|
|
9544
|
+
return cachedVersion;
|
|
9545
|
+
}
|
|
9546
|
+
try {
|
|
9547
|
+
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
9548
|
+
cachedVersion = typeof packageJson.version === "string" ? packageJson.version : DEFAULT_VERSION;
|
|
9549
|
+
} catch {
|
|
9550
|
+
cachedVersion = DEFAULT_VERSION;
|
|
9551
|
+
}
|
|
9552
|
+
return cachedVersion;
|
|
9553
|
+
}
|
|
9554
|
+
|
|
9528
9555
|
// src/mcp/index.ts
|
|
9529
9556
|
function getProvider(provider) {
|
|
9530
9557
|
if (provider === "openai")
|
|
@@ -9534,312 +9561,330 @@ function getProvider(provider) {
|
|
|
9534
9561
|
throw new Error(`Unknown provider: ${provider}`);
|
|
9535
9562
|
}
|
|
9536
9563
|
function defaultOutputDir() {
|
|
9537
|
-
return
|
|
9538
|
-
}
|
|
9539
|
-
var
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9558
|
-
|
|
9559
|
-
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
name: "start_finetune",
|
|
9564
|
-
description: "Upload a training file and start a fine-tuning job",
|
|
9565
|
-
inputSchema: {
|
|
9566
|
-
type: "object",
|
|
9567
|
-
properties: {
|
|
9568
|
-
provider: {
|
|
9569
|
-
type: "string",
|
|
9570
|
-
enum: ["openai", "thinker-labs"],
|
|
9571
|
-
description: "Provider to use for fine-tuning"
|
|
9564
|
+
return resolve2(homedir3(), ".brains", "datasets");
|
|
9565
|
+
}
|
|
9566
|
+
var MCP_SERVER_INFO = {
|
|
9567
|
+
name: "brains",
|
|
9568
|
+
version: getPackageVersion()
|
|
9569
|
+
};
|
|
9570
|
+
function createMcpServer() {
|
|
9571
|
+
const server = new Server(MCP_SERVER_INFO, { capabilities: { tools: {} } });
|
|
9572
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
9573
|
+
tools: [
|
|
9574
|
+
{
|
|
9575
|
+
name: "list_models",
|
|
9576
|
+
description: "List all fine-tuned models tracked in the local DB",
|
|
9577
|
+
inputSchema: {
|
|
9578
|
+
type: "object",
|
|
9579
|
+
properties: {},
|
|
9580
|
+
required: []
|
|
9581
|
+
}
|
|
9582
|
+
},
|
|
9583
|
+
{
|
|
9584
|
+
name: "get_model",
|
|
9585
|
+
description: "Get details for a specific fine-tuned model",
|
|
9586
|
+
inputSchema: {
|
|
9587
|
+
type: "object",
|
|
9588
|
+
properties: {
|
|
9589
|
+
model_id: { type: "string", description: "Model ID" }
|
|
9572
9590
|
},
|
|
9573
|
-
|
|
9574
|
-
|
|
9575
|
-
|
|
9591
|
+
required: ["model_id"]
|
|
9592
|
+
}
|
|
9593
|
+
},
|
|
9594
|
+
{
|
|
9595
|
+
name: "start_finetune",
|
|
9596
|
+
description: "Upload a training file and start a fine-tuning job",
|
|
9597
|
+
inputSchema: {
|
|
9598
|
+
type: "object",
|
|
9599
|
+
properties: {
|
|
9600
|
+
provider: {
|
|
9601
|
+
type: "string",
|
|
9602
|
+
enum: ["openai", "thinker-labs"],
|
|
9603
|
+
description: "Provider to use for fine-tuning"
|
|
9604
|
+
},
|
|
9605
|
+
base_model: {
|
|
9606
|
+
type: "string",
|
|
9607
|
+
description: "Base model identifier (e.g. gpt-4o-mini-2024-07-18)"
|
|
9608
|
+
},
|
|
9609
|
+
dataset_path: {
|
|
9610
|
+
type: "string",
|
|
9611
|
+
description: "Absolute path to the JSONL training file"
|
|
9612
|
+
},
|
|
9613
|
+
name: {
|
|
9614
|
+
type: "string",
|
|
9615
|
+
description: "Optional friendly name for this model"
|
|
9616
|
+
}
|
|
9576
9617
|
},
|
|
9577
|
-
|
|
9578
|
-
|
|
9579
|
-
|
|
9618
|
+
required: ["provider", "base_model", "dataset_path"]
|
|
9619
|
+
}
|
|
9620
|
+
},
|
|
9621
|
+
{
|
|
9622
|
+
name: "get_finetune_status",
|
|
9623
|
+
description: "Check the status of a fine-tuning job",
|
|
9624
|
+
inputSchema: {
|
|
9625
|
+
type: "object",
|
|
9626
|
+
properties: {
|
|
9627
|
+
job_id: { type: "string", description: "Fine-tune job ID" },
|
|
9628
|
+
provider: {
|
|
9629
|
+
type: "string",
|
|
9630
|
+
enum: ["openai", "thinker-labs"],
|
|
9631
|
+
description: "Provider that owns the job"
|
|
9632
|
+
}
|
|
9580
9633
|
},
|
|
9581
|
-
|
|
9582
|
-
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9589
|
-
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9594
|
-
|
|
9595
|
-
|
|
9596
|
-
|
|
9597
|
-
|
|
9598
|
-
|
|
9599
|
-
|
|
9600
|
-
|
|
9601
|
-
|
|
9602
|
-
|
|
9603
|
-
}
|
|
9604
|
-
},
|
|
9605
|
-
{
|
|
9606
|
-
name: "gather_training_data",
|
|
9607
|
-
description: "Gather training data from ecosystem sources (todos, mementos, conversations, sessions)",
|
|
9608
|
-
inputSchema: {
|
|
9609
|
-
type: "object",
|
|
9610
|
-
properties: {
|
|
9611
|
-
sources: {
|
|
9612
|
-
type: "array",
|
|
9613
|
-
items: { type: "string" },
|
|
9614
|
-
description: "Sources to gather from: todos, mementos, conversations, sessions"
|
|
9634
|
+
required: ["job_id", "provider"]
|
|
9635
|
+
}
|
|
9636
|
+
},
|
|
9637
|
+
{
|
|
9638
|
+
name: "gather_training_data",
|
|
9639
|
+
description: "Gather training data from ecosystem sources (todos, mementos, conversations, sessions)",
|
|
9640
|
+
inputSchema: {
|
|
9641
|
+
type: "object",
|
|
9642
|
+
properties: {
|
|
9643
|
+
sources: {
|
|
9644
|
+
type: "array",
|
|
9645
|
+
items: { type: "string" },
|
|
9646
|
+
description: "Sources to gather from: todos, mementos, conversations, sessions"
|
|
9647
|
+
},
|
|
9648
|
+
limit: {
|
|
9649
|
+
type: "number",
|
|
9650
|
+
description: "Max examples per source (default: unlimited)"
|
|
9651
|
+
},
|
|
9652
|
+
output_dir: {
|
|
9653
|
+
type: "string",
|
|
9654
|
+
description: "Directory to write JSONL files (default: ~/.brains/datasets/)"
|
|
9655
|
+
}
|
|
9615
9656
|
},
|
|
9616
|
-
|
|
9617
|
-
|
|
9618
|
-
|
|
9657
|
+
required: ["sources"]
|
|
9658
|
+
}
|
|
9659
|
+
},
|
|
9660
|
+
{
|
|
9661
|
+
name: "preview_training_data",
|
|
9662
|
+
description: "Preview examples from a JSONL training file",
|
|
9663
|
+
inputSchema: {
|
|
9664
|
+
type: "object",
|
|
9665
|
+
properties: {
|
|
9666
|
+
file_path: {
|
|
9667
|
+
type: "string",
|
|
9668
|
+
description: "Absolute path to the JSONL file to preview"
|
|
9669
|
+
},
|
|
9670
|
+
limit: {
|
|
9671
|
+
type: "number",
|
|
9672
|
+
description: "Max number of examples to return (default: 5)"
|
|
9673
|
+
}
|
|
9619
9674
|
},
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
description: "Directory to write JSONL files (default: ~/.brains/datasets/)"
|
|
9623
|
-
}
|
|
9624
|
-
},
|
|
9625
|
-
required: ["sources"]
|
|
9675
|
+
required: ["file_path"]
|
|
9676
|
+
}
|
|
9626
9677
|
}
|
|
9627
|
-
|
|
9628
|
-
|
|
9629
|
-
|
|
9630
|
-
|
|
9631
|
-
|
|
9632
|
-
|
|
9633
|
-
|
|
9634
|
-
|
|
9635
|
-
|
|
9636
|
-
|
|
9637
|
-
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
|
|
9678
|
+
]
|
|
9679
|
+
}));
|
|
9680
|
+
server.setRequestHandler(CallToolRequestSchema, async (request2) => {
|
|
9681
|
+
const { name, arguments: args } = request2.params;
|
|
9682
|
+
try {
|
|
9683
|
+
switch (name) {
|
|
9684
|
+
case "list_models": {
|
|
9685
|
+
const db = getDb();
|
|
9686
|
+
const models = await db.select({
|
|
9687
|
+
id: fineTunedModels.id,
|
|
9688
|
+
name: fineTunedModels.name,
|
|
9689
|
+
provider: fineTunedModels.provider,
|
|
9690
|
+
status: fineTunedModels.status,
|
|
9691
|
+
base_model: fineTunedModels.baseModel,
|
|
9692
|
+
created_at: fineTunedModels.createdAt
|
|
9693
|
+
}).from(fineTunedModels).orderBy(fineTunedModels.createdAt);
|
|
9694
|
+
return {
|
|
9695
|
+
content: [
|
|
9696
|
+
{
|
|
9697
|
+
type: "text",
|
|
9698
|
+
text: JSON.stringify(models, null, 2)
|
|
9699
|
+
}
|
|
9700
|
+
]
|
|
9701
|
+
};
|
|
9702
|
+
}
|
|
9703
|
+
case "get_model": {
|
|
9704
|
+
const { model_id } = args;
|
|
9705
|
+
const db = getDb();
|
|
9706
|
+
const results = await db.select().from(fineTunedModels).where(eq(fineTunedModels.id, model_id));
|
|
9707
|
+
if (results.length === 0) {
|
|
9708
|
+
return {
|
|
9709
|
+
content: [{ type: "text", text: `Model not found: ${model_id}` }],
|
|
9710
|
+
isError: true
|
|
9711
|
+
};
|
|
9641
9712
|
}
|
|
9642
|
-
},
|
|
9643
|
-
required: ["file_path"]
|
|
9644
|
-
}
|
|
9645
|
-
}
|
|
9646
|
-
]
|
|
9647
|
-
}));
|
|
9648
|
-
server.setRequestHandler(CallToolRequestSchema, async (request2) => {
|
|
9649
|
-
const { name, arguments: args } = request2.params;
|
|
9650
|
-
try {
|
|
9651
|
-
switch (name) {
|
|
9652
|
-
case "list_models": {
|
|
9653
|
-
const db = getDb();
|
|
9654
|
-
const models = await db.select({
|
|
9655
|
-
id: fineTunedModels.id,
|
|
9656
|
-
name: fineTunedModels.name,
|
|
9657
|
-
provider: fineTunedModels.provider,
|
|
9658
|
-
status: fineTunedModels.status,
|
|
9659
|
-
base_model: fineTunedModels.baseModel,
|
|
9660
|
-
created_at: fineTunedModels.createdAt
|
|
9661
|
-
}).from(fineTunedModels).orderBy(fineTunedModels.createdAt);
|
|
9662
|
-
return {
|
|
9663
|
-
content: [
|
|
9664
|
-
{
|
|
9665
|
-
type: "text",
|
|
9666
|
-
text: JSON.stringify(models, null, 2)
|
|
9667
|
-
}
|
|
9668
|
-
]
|
|
9669
|
-
};
|
|
9670
|
-
}
|
|
9671
|
-
case "get_model": {
|
|
9672
|
-
const { model_id } = args;
|
|
9673
|
-
const db = getDb();
|
|
9674
|
-
const results = await db.select().from(fineTunedModels).where(eq(fineTunedModels.id, model_id));
|
|
9675
|
-
if (results.length === 0) {
|
|
9676
9713
|
return {
|
|
9677
|
-
content: [
|
|
9678
|
-
|
|
9714
|
+
content: [
|
|
9715
|
+
{ type: "text", text: JSON.stringify(results[0], null, 2) }
|
|
9716
|
+
]
|
|
9679
9717
|
};
|
|
9680
9718
|
}
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9691
|
-
|
|
9692
|
-
|
|
9693
|
-
|
|
9694
|
-
|
|
9695
|
-
|
|
9719
|
+
case "start_finetune": {
|
|
9720
|
+
const {
|
|
9721
|
+
provider,
|
|
9722
|
+
base_model,
|
|
9723
|
+
dataset_path,
|
|
9724
|
+
name: modelName
|
|
9725
|
+
} = args;
|
|
9726
|
+
const resolvedPath = resolve2(dataset_path);
|
|
9727
|
+
if (!existsSync2(resolvedPath)) {
|
|
9728
|
+
return {
|
|
9729
|
+
content: [
|
|
9730
|
+
{
|
|
9731
|
+
type: "text",
|
|
9732
|
+
text: `Dataset file not found: ${resolvedPath}`
|
|
9733
|
+
}
|
|
9734
|
+
],
|
|
9735
|
+
isError: true
|
|
9736
|
+
};
|
|
9737
|
+
}
|
|
9738
|
+
const p = getProvider(provider);
|
|
9739
|
+
const { fileId } = await p.uploadTrainingFile(resolvedPath);
|
|
9740
|
+
const { jobId, status } = await p.createFineTuneJob(fileId, base_model, modelName);
|
|
9741
|
+
const db = getDb();
|
|
9742
|
+
const now = Date.now();
|
|
9743
|
+
const id = `${provider}-${jobId}`;
|
|
9744
|
+
await db.insert(fineTunedModels).values({
|
|
9745
|
+
id,
|
|
9746
|
+
name: modelName ?? `${base_model}-finetune-${now}`,
|
|
9747
|
+
provider,
|
|
9748
|
+
baseModel: base_model,
|
|
9749
|
+
status: "pending",
|
|
9750
|
+
fineTuneJobId: jobId,
|
|
9751
|
+
createdAt: now,
|
|
9752
|
+
updatedAt: now
|
|
9753
|
+
});
|
|
9696
9754
|
return {
|
|
9697
9755
|
content: [
|
|
9698
9756
|
{
|
|
9699
9757
|
type: "text",
|
|
9700
|
-
text:
|
|
9758
|
+
text: JSON.stringify({ job_id: jobId, status, model_db_id: id }, null, 2)
|
|
9701
9759
|
}
|
|
9702
|
-
]
|
|
9703
|
-
isError: true
|
|
9760
|
+
]
|
|
9704
9761
|
};
|
|
9705
9762
|
}
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
|
|
9726
|
-
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
};
|
|
9730
|
-
}
|
|
9731
|
-
case "get_finetune_status": {
|
|
9732
|
-
const { job_id, provider } = args;
|
|
9733
|
-
const p = getProvider(provider);
|
|
9734
|
-
const result = await p.getFineTuneStatus(job_id);
|
|
9735
|
-
const db = getDb();
|
|
9736
|
-
const dbId = `${provider}-${job_id}`;
|
|
9737
|
-
const existing = await db.select().from(fineTunedModels).where(eq(fineTunedModels.id, dbId));
|
|
9738
|
-
if (existing.length > 0) {
|
|
9739
|
-
const mappedStatus = (() => {
|
|
9740
|
-
if (result.status === "succeeded")
|
|
9741
|
-
return "succeeded";
|
|
9742
|
-
if (result.status === "failed")
|
|
9743
|
-
return "failed";
|
|
9744
|
-
if (result.status === "cancelled")
|
|
9745
|
-
return "cancelled";
|
|
9746
|
-
if (result.status === "running")
|
|
9747
|
-
return "running";
|
|
9748
|
-
return "pending";
|
|
9749
|
-
})();
|
|
9750
|
-
await db.update(fineTunedModels).set({
|
|
9751
|
-
status: mappedStatus,
|
|
9752
|
-
updatedAt: Date.now()
|
|
9753
|
-
}).where(eq(fineTunedModels.id, dbId));
|
|
9754
|
-
}
|
|
9755
|
-
return {
|
|
9756
|
-
content: [
|
|
9757
|
-
{
|
|
9758
|
-
type: "text",
|
|
9759
|
-
text: JSON.stringify({
|
|
9760
|
-
job_id: result.jobId,
|
|
9761
|
-
status: result.status,
|
|
9762
|
-
model_id: result.fineTunedModel,
|
|
9763
|
-
error: result.error
|
|
9764
|
-
}, null, 2)
|
|
9765
|
-
}
|
|
9766
|
-
]
|
|
9767
|
-
};
|
|
9768
|
-
}
|
|
9769
|
-
case "gather_training_data": {
|
|
9770
|
-
const {
|
|
9771
|
-
sources,
|
|
9772
|
-
limit: limit2,
|
|
9773
|
-
output_dir
|
|
9774
|
-
} = args;
|
|
9775
|
-
const { mkdirSync: mkdirSync2, writeFileSync } = await import("fs");
|
|
9776
|
-
const { join: join3 } = await import("path");
|
|
9777
|
-
const outDir = output_dir ?? defaultOutputDir();
|
|
9778
|
-
mkdirSync2(outDir, { recursive: true });
|
|
9779
|
-
const datasets = [];
|
|
9780
|
-
let totalExamples = 0;
|
|
9781
|
-
for (const source of sources) {
|
|
9782
|
-
let examples = [];
|
|
9783
|
-
if (source === "todos") {
|
|
9784
|
-
const result = await gatherFromTodos({ limit: limit2 });
|
|
9785
|
-
examples = result.examples;
|
|
9786
|
-
} else {
|
|
9787
|
-
examples = [];
|
|
9763
|
+
case "get_finetune_status": {
|
|
9764
|
+
const { job_id, provider } = args;
|
|
9765
|
+
const p = getProvider(provider);
|
|
9766
|
+
const result = await p.getFineTuneStatus(job_id);
|
|
9767
|
+
const db = getDb();
|
|
9768
|
+
const dbId = `${provider}-${job_id}`;
|
|
9769
|
+
const existing = await db.select().from(fineTunedModels).where(eq(fineTunedModels.id, dbId));
|
|
9770
|
+
if (existing.length > 0) {
|
|
9771
|
+
const mappedStatus = (() => {
|
|
9772
|
+
if (result.status === "succeeded")
|
|
9773
|
+
return "succeeded";
|
|
9774
|
+
if (result.status === "failed")
|
|
9775
|
+
return "failed";
|
|
9776
|
+
if (result.status === "cancelled")
|
|
9777
|
+
return "cancelled";
|
|
9778
|
+
if (result.status === "running")
|
|
9779
|
+
return "running";
|
|
9780
|
+
return "pending";
|
|
9781
|
+
})();
|
|
9782
|
+
await db.update(fineTunedModels).set({
|
|
9783
|
+
status: mappedStatus,
|
|
9784
|
+
updatedAt: Date.now()
|
|
9785
|
+
}).where(eq(fineTunedModels.id, dbId));
|
|
9788
9786
|
}
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9794
|
-
|
|
9787
|
+
return {
|
|
9788
|
+
content: [
|
|
9789
|
+
{
|
|
9790
|
+
type: "text",
|
|
9791
|
+
text: JSON.stringify({
|
|
9792
|
+
job_id: result.jobId,
|
|
9793
|
+
status: result.status,
|
|
9794
|
+
model_id: result.fineTunedModel,
|
|
9795
|
+
error: result.error
|
|
9796
|
+
}, null, 2)
|
|
9797
|
+
}
|
|
9798
|
+
]
|
|
9799
|
+
};
|
|
9795
9800
|
}
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
9801
|
+
case "gather_training_data": {
|
|
9802
|
+
const {
|
|
9803
|
+
sources,
|
|
9804
|
+
limit: limit2,
|
|
9805
|
+
output_dir
|
|
9806
|
+
} = args;
|
|
9807
|
+
const { mkdirSync: mkdirSync2, writeFileSync } = await import("fs");
|
|
9808
|
+
const { join: join3 } = await import("path");
|
|
9809
|
+
const outDir = output_dir ?? defaultOutputDir();
|
|
9810
|
+
mkdirSync2(outDir, { recursive: true });
|
|
9811
|
+
const datasets = [];
|
|
9812
|
+
let totalExamples = 0;
|
|
9813
|
+
for (const source of sources) {
|
|
9814
|
+
let examples = [];
|
|
9815
|
+
if (source === "todos") {
|
|
9816
|
+
const result = await gatherFromTodos({ limit: limit2 });
|
|
9817
|
+
examples = result.examples;
|
|
9818
|
+
} else {
|
|
9819
|
+
examples = [];
|
|
9801
9820
|
}
|
|
9802
|
-
|
|
9803
|
-
|
|
9804
|
-
|
|
9805
|
-
|
|
9806
|
-
|
|
9807
|
-
|
|
9808
|
-
|
|
9821
|
+
const filePath = join3(outDir, `${source}-${Date.now()}.jsonl`);
|
|
9822
|
+
const jsonl = examples.map((ex) => JSON.stringify(ex)).join(`
|
|
9823
|
+
`);
|
|
9824
|
+
writeFileSync(filePath, jsonl, "utf-8");
|
|
9825
|
+
datasets.push({ source, count: examples.length, file_path: filePath });
|
|
9826
|
+
totalExamples += examples.length;
|
|
9827
|
+
}
|
|
9809
9828
|
return {
|
|
9810
9829
|
content: [
|
|
9811
|
-
{
|
|
9812
|
-
|
|
9813
|
-
|
|
9830
|
+
{
|
|
9831
|
+
type: "text",
|
|
9832
|
+
text: JSON.stringify({ datasets, total_examples: totalExamples }, null, 2)
|
|
9833
|
+
}
|
|
9834
|
+
]
|
|
9814
9835
|
};
|
|
9815
9836
|
}
|
|
9816
|
-
|
|
9817
|
-
|
|
9837
|
+
case "preview_training_data": {
|
|
9838
|
+
const { file_path, limit: limit2 = 5 } = args;
|
|
9839
|
+
const resolvedPath = resolve2(file_path);
|
|
9840
|
+
if (!existsSync2(resolvedPath)) {
|
|
9841
|
+
return {
|
|
9842
|
+
content: [
|
|
9843
|
+
{ type: "text", text: `File not found: ${resolvedPath}` }
|
|
9844
|
+
],
|
|
9845
|
+
isError: true
|
|
9846
|
+
};
|
|
9847
|
+
}
|
|
9848
|
+
const content = readFileSync3(resolvedPath, "utf-8");
|
|
9849
|
+
const lines = content.split(`
|
|
9818
9850
|
`).map((l) => l.trim()).filter(Boolean);
|
|
9819
|
-
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9851
|
+
const total = lines.length;
|
|
9852
|
+
const examples = lines.slice(0, limit2).map((line) => JSON.parse(line));
|
|
9853
|
+
return {
|
|
9854
|
+
content: [
|
|
9855
|
+
{
|
|
9856
|
+
type: "text",
|
|
9857
|
+
text: JSON.stringify({ examples, total }, null, 2)
|
|
9858
|
+
}
|
|
9859
|
+
]
|
|
9860
|
+
};
|
|
9861
|
+
}
|
|
9862
|
+
default:
|
|
9863
|
+
return {
|
|
9864
|
+
content: [{ type: "text", text: `Unknown tool: ${name}` }],
|
|
9865
|
+
isError: true
|
|
9866
|
+
};
|
|
9829
9867
|
}
|
|
9830
|
-
|
|
9831
|
-
|
|
9832
|
-
|
|
9833
|
-
|
|
9834
|
-
|
|
9868
|
+
} catch (err) {
|
|
9869
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
9870
|
+
return {
|
|
9871
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
9872
|
+
isError: true
|
|
9873
|
+
};
|
|
9835
9874
|
}
|
|
9836
|
-
}
|
|
9837
|
-
|
|
9838
|
-
|
|
9839
|
-
|
|
9840
|
-
|
|
9841
|
-
|
|
9842
|
-
|
|
9843
|
-
}
|
|
9844
|
-
|
|
9845
|
-
await
|
|
9875
|
+
});
|
|
9876
|
+
return server;
|
|
9877
|
+
}
|
|
9878
|
+
async function startMcpServer(transport = new StdioServerTransport) {
|
|
9879
|
+
const server = createMcpServer();
|
|
9880
|
+
await server.connect(transport);
|
|
9881
|
+
return server;
|
|
9882
|
+
}
|
|
9883
|
+
if (import.meta.main) {
|
|
9884
|
+
await startMcpServer();
|
|
9885
|
+
}
|
|
9886
|
+
export {
|
|
9887
|
+
startMcpServer,
|
|
9888
|
+
createMcpServer,
|
|
9889
|
+
MCP_SERVER_INFO
|
|
9890
|
+
};
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AASA,wBAAgB,wBAAwB,CAAC,OAAO,SAAsB,IAC5D,KAAK,OAAO,KAAG,QAAQ,CAOhC;AAED,wBAAgB,WAAW,CAAC,UAAU,SAAO,yBAM5C"}
|
package/dist/server/index.js
CHANGED
|
@@ -1,14 +1,54 @@
|
|
|
1
1
|
// @bun
|
|
2
|
+
// src/lib/package-metadata.ts
|
|
3
|
+
import { existsSync, readFileSync } from "fs";
|
|
4
|
+
import { dirname, resolve } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
6
|
+
var DEFAULT_VERSION = "0.0.0";
|
|
7
|
+
var cachedVersion;
|
|
8
|
+
function getPackageJsonPath() {
|
|
9
|
+
return resolve(dirname(fileURLToPath(import.meta.url)), "../../package.json");
|
|
10
|
+
}
|
|
11
|
+
function getPackageVersion() {
|
|
12
|
+
if (cachedVersion) {
|
|
13
|
+
return cachedVersion;
|
|
14
|
+
}
|
|
15
|
+
const packageJsonPath = getPackageJsonPath();
|
|
16
|
+
if (!existsSync(packageJsonPath)) {
|
|
17
|
+
cachedVersion = DEFAULT_VERSION;
|
|
18
|
+
return cachedVersion;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
22
|
+
cachedVersion = typeof packageJson.version === "string" ? packageJson.version : DEFAULT_VERSION;
|
|
23
|
+
} catch {
|
|
24
|
+
cachedVersion = DEFAULT_VERSION;
|
|
25
|
+
}
|
|
26
|
+
return cachedVersion;
|
|
27
|
+
}
|
|
28
|
+
|
|
2
29
|
// src/server/index.ts
|
|
3
30
|
var port = Number(process.env["PORT"] ?? 7020);
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
fetch(req) {
|
|
31
|
+
var service = "brains";
|
|
32
|
+
function createServerFetchHandler(version = getPackageVersion()) {
|
|
33
|
+
return (req) => {
|
|
8
34
|
const url = new URL(req.url);
|
|
9
35
|
if (url.pathname === "/health") {
|
|
10
|
-
return Response.json({ status: "ok", service
|
|
36
|
+
return Response.json({ status: "ok", service, version });
|
|
11
37
|
}
|
|
12
38
|
return Response.json({ error: "not found" }, { status: 404 });
|
|
13
|
-
}
|
|
14
|
-
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function startServer(serverPort = port) {
|
|
42
|
+
console.log(`${service} server starting on port ${serverPort}`);
|
|
43
|
+
return Bun.serve({
|
|
44
|
+
port: serverPort,
|
|
45
|
+
fetch: createServerFetchHandler()
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (import.meta.main) {
|
|
49
|
+
startServer();
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
startServer,
|
|
53
|
+
createServerFetchHandler
|
|
54
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/brains",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Fine-tuned model tracker and trainer — wraps OpenAI + Thinker Labs, gathers training data from todos/mementos/conversations/sessions",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|