@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 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,
@@ -1,2 +1,3 @@
1
1
  export * from "./providers/index.js";
2
+ export * from "./package-metadata.js";
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export declare function getPackageVersion(): string;
2
+ //# sourceMappingURL=package-metadata.d.ts.map
@@ -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"}
@@ -1,2 +1,75 @@
1
- export {};
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
@@ -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 readFileSync2, existsSync } from "fs";
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 resolve(homedir3(), ".brains", "datasets");
9538
- }
9539
- var server = new Server({ name: "brains", version: "0.0.1" }, { capabilities: { tools: {} } });
9540
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
9541
- tools: [
9542
- {
9543
- name: "list_models",
9544
- description: "List all fine-tuned models tracked in the local DB",
9545
- inputSchema: {
9546
- type: "object",
9547
- properties: {},
9548
- required: []
9549
- }
9550
- },
9551
- {
9552
- name: "get_model",
9553
- description: "Get details for a specific fine-tuned model",
9554
- inputSchema: {
9555
- type: "object",
9556
- properties: {
9557
- model_id: { type: "string", description: "Model ID" }
9558
- },
9559
- required: ["model_id"]
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
- base_model: {
9574
- type: "string",
9575
- description: "Base model identifier (e.g. gpt-4o-mini-2024-07-18)"
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
- dataset_path: {
9578
- type: "string",
9579
- description: "Absolute path to the JSONL training file"
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
- name: {
9582
- type: "string",
9583
- description: "Optional friendly name for this model"
9584
- }
9585
- },
9586
- required: ["provider", "base_model", "dataset_path"]
9587
- }
9588
- },
9589
- {
9590
- name: "get_finetune_status",
9591
- description: "Check the status of a fine-tuning job",
9592
- inputSchema: {
9593
- type: "object",
9594
- properties: {
9595
- job_id: { type: "string", description: "Fine-tune job ID" },
9596
- provider: {
9597
- type: "string",
9598
- enum: ["openai", "thinker-labs"],
9599
- description: "Provider that owns the job"
9600
- }
9601
- },
9602
- required: ["job_id", "provider"]
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
- limit: {
9617
- type: "number",
9618
- description: "Max examples per source (default: unlimited)"
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
- output_dir: {
9621
- type: "string",
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
- name: "preview_training_data",
9630
- description: "Preview examples from a JSONL training file",
9631
- inputSchema: {
9632
- type: "object",
9633
- properties: {
9634
- file_path: {
9635
- type: "string",
9636
- description: "Absolute path to the JSONL file to preview"
9637
- },
9638
- limit: {
9639
- type: "number",
9640
- description: "Max number of examples to return (default: 5)"
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: [{ type: "text", text: `Model not found: ${model_id}` }],
9678
- isError: true
9714
+ content: [
9715
+ { type: "text", text: JSON.stringify(results[0], null, 2) }
9716
+ ]
9679
9717
  };
9680
9718
  }
9681
- return {
9682
- content: [
9683
- { type: "text", text: JSON.stringify(results[0], null, 2) }
9684
- ]
9685
- };
9686
- }
9687
- case "start_finetune": {
9688
- const {
9689
- provider,
9690
- base_model,
9691
- dataset_path,
9692
- name: modelName
9693
- } = args;
9694
- const resolvedPath = resolve(dataset_path);
9695
- if (!existsSync(resolvedPath)) {
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: `Dataset file not found: ${resolvedPath}`
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
- const p = getProvider(provider);
9707
- const { fileId } = await p.uploadTrainingFile(resolvedPath);
9708
- const { jobId, status } = await p.createFineTuneJob(fileId, base_model, modelName);
9709
- const db = getDb();
9710
- const now = Date.now();
9711
- const id = `${provider}-${jobId}`;
9712
- await db.insert(fineTunedModels).values({
9713
- id,
9714
- name: modelName ?? `${base_model}-finetune-${now}`,
9715
- provider,
9716
- baseModel: base_model,
9717
- status: "pending",
9718
- fineTuneJobId: jobId,
9719
- createdAt: now,
9720
- updatedAt: now
9721
- });
9722
- return {
9723
- content: [
9724
- {
9725
- type: "text",
9726
- text: JSON.stringify({ job_id: jobId, status, model_db_id: id }, null, 2)
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
- const filePath = join3(outDir, `${source}-${Date.now()}.jsonl`);
9790
- const jsonl = examples.map((ex) => JSON.stringify(ex)).join(`
9791
- `);
9792
- writeFileSync(filePath, jsonl, "utf-8");
9793
- datasets.push({ source, count: examples.length, file_path: filePath });
9794
- totalExamples += examples.length;
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
- return {
9797
- content: [
9798
- {
9799
- type: "text",
9800
- text: JSON.stringify({ datasets, total_examples: totalExamples }, null, 2)
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
- case "preview_training_data": {
9806
- const { file_path, limit: limit2 = 5 } = args;
9807
- const resolvedPath = resolve(file_path);
9808
- if (!existsSync(resolvedPath)) {
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
- { type: "text", text: `File not found: ${resolvedPath}` }
9812
- ],
9813
- isError: true
9830
+ {
9831
+ type: "text",
9832
+ text: JSON.stringify({ datasets, total_examples: totalExamples }, null, 2)
9833
+ }
9834
+ ]
9814
9835
  };
9815
9836
  }
9816
- const content = readFileSync2(resolvedPath, "utf-8");
9817
- const lines = content.split(`
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
- const total = lines.length;
9820
- const examples = lines.slice(0, limit2).map((line) => JSON.parse(line));
9821
- return {
9822
- content: [
9823
- {
9824
- type: "text",
9825
- text: JSON.stringify({ examples, total }, null, 2)
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
- default:
9831
- return {
9832
- content: [{ type: "text", text: `Unknown tool: ${name}` }],
9833
- isError: true
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
- } catch (err) {
9837
- const message = err instanceof Error ? err.message : String(err);
9838
- return {
9839
- content: [{ type: "text", text: `Error: ${message}` }],
9840
- isError: true
9841
- };
9842
- }
9843
- });
9844
- var transport = new StdioServerTransport;
9845
- await server.connect(transport);
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
+ };
@@ -1,2 +1,3 @@
1
- declare const port: number;
1
+ export declare function createServerFetchHandler(version?: string): (req: Request) => Response;
2
+ export declare function startServer(serverPort?: number): Bun.Server<undefined>;
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,IAAI,QAAsC,CAAC"}
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"}
@@ -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
- console.log(`brains server starting on port ${port}`);
5
- Bun.serve({
6
- port,
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: "brains", version: "0.0.1" });
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.2",
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",