@pyxmate/memory 1.1.2 → 1.1.3
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/cli/pyx-mem.mjs +229 -121
- package/package.json +1 -1
package/dist/cli/pyx-mem.mjs
CHANGED
|
@@ -352,7 +352,7 @@ async function promptMasked(label) {
|
|
|
352
352
|
`);
|
|
353
353
|
return value;
|
|
354
354
|
}
|
|
355
|
-
return new Promise((
|
|
355
|
+
return new Promise((resolve4, reject) => {
|
|
356
356
|
const previousEncoding = stdin.readableEncoding;
|
|
357
357
|
stdin.setEncoding("utf8");
|
|
358
358
|
stdin.setRawMode(true);
|
|
@@ -370,7 +370,7 @@ async function promptMasked(label) {
|
|
|
370
370
|
if (ch === "\n" || ch === "\r") {
|
|
371
371
|
cleanup();
|
|
372
372
|
stdout.write("\n");
|
|
373
|
-
|
|
373
|
+
resolve4(buf.trim());
|
|
374
374
|
return;
|
|
375
375
|
}
|
|
376
376
|
if (ch === "") {
|
|
@@ -564,6 +564,8 @@ function createReadCredentials(providerFactory) {
|
|
|
564
564
|
}
|
|
565
565
|
|
|
566
566
|
// src/mcp/proxy-server.ts
|
|
567
|
+
import { readFile, stat } from "fs/promises";
|
|
568
|
+
import { basename, isAbsolute, resolve } from "path";
|
|
567
569
|
import { Client as McpClient } from "@modelcontextprotocol/sdk/client/index.js";
|
|
568
570
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
569
571
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -574,108 +576,6 @@ import {
|
|
|
574
576
|
ListPromptsRequestSchema,
|
|
575
577
|
ListToolsRequestSchema
|
|
576
578
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
577
|
-
var REMOTE_MCP_PATH = "/mcp";
|
|
578
|
-
function createProxyServer(client, version) {
|
|
579
|
-
const caps = client.getServerCapabilities();
|
|
580
|
-
const server = new Server(client.getServerVersion() ?? { name: "pyx-memory", version }, {
|
|
581
|
-
capabilities: {
|
|
582
|
-
// Advertise the PRESENCE of tools/prompts, but NOT their `listChanged`
|
|
583
|
-
// sub-capability: this proxy does not relay the remote's list_changed
|
|
584
|
-
// notifications, so claiming listChanged would be a capability the host
|
|
585
|
-
// could rely on but we never honor (Codex: keep the proxy transparent).
|
|
586
|
-
...caps?.tools ? { tools: {} } : {},
|
|
587
|
-
...caps?.prompts ? { prompts: {} } : {}
|
|
588
|
-
},
|
|
589
|
-
instructions: client.getInstructions()
|
|
590
|
-
});
|
|
591
|
-
if (caps?.tools) {
|
|
592
|
-
server.setRequestHandler(
|
|
593
|
-
ListToolsRequestSchema,
|
|
594
|
-
(req) => client.listTools(req.params)
|
|
595
|
-
);
|
|
596
|
-
server.setRequestHandler(
|
|
597
|
-
CallToolRequestSchema,
|
|
598
|
-
(req) => client.callTool(req.params)
|
|
599
|
-
);
|
|
600
|
-
}
|
|
601
|
-
if (caps?.prompts) {
|
|
602
|
-
server.setRequestHandler(
|
|
603
|
-
ListPromptsRequestSchema,
|
|
604
|
-
(req) => client.listPrompts(req.params)
|
|
605
|
-
);
|
|
606
|
-
server.setRequestHandler(
|
|
607
|
-
GetPromptRequestSchema,
|
|
608
|
-
(req) => client.getPrompt(req.params)
|
|
609
|
-
);
|
|
610
|
-
}
|
|
611
|
-
return server;
|
|
612
|
-
}
|
|
613
|
-
async function runMcpProxyServer(opts) {
|
|
614
|
-
const version = opts.version ?? (true ? "1.1.2" : "0.0.0-dev");
|
|
615
|
-
const read = await opts.readCredentials();
|
|
616
|
-
if (!read.ok) {
|
|
617
|
-
const text = read.result.content.map((c) => c.type === "text" ? c.text : "").join(" ").trim();
|
|
618
|
-
throw new Error(text || "pyx-memory credentials are unavailable. Run: pyx-mem login");
|
|
619
|
-
}
|
|
620
|
-
const { endpoint, apiKey } = read.credentials;
|
|
621
|
-
const url = new URL(`${endpoint.replace(/\/+$/, "")}${REMOTE_MCP_PATH}`);
|
|
622
|
-
const client = new McpClient({ name: "pyx-mem-proxy", version }, { capabilities: {} });
|
|
623
|
-
const clientTransport = new StreamableHTTPClientTransport(url, {
|
|
624
|
-
requestInit: { headers: { Authorization: `Bearer ${apiKey}` } }
|
|
625
|
-
});
|
|
626
|
-
try {
|
|
627
|
-
await client.connect(clientTransport);
|
|
628
|
-
} catch (err) {
|
|
629
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
630
|
-
throw new Error(
|
|
631
|
-
`Could not reach the pyx-memory remote MCP at ${url.href}: ${msg}. Verify the endpoint and key with \`pyx-mem doctor\`, or run the bundled server with \`pyx-mem mcp\`.`
|
|
632
|
-
);
|
|
633
|
-
}
|
|
634
|
-
try {
|
|
635
|
-
const server = createProxyServer(client, version);
|
|
636
|
-
const transport = new StdioServerTransport();
|
|
637
|
-
const closed = new Promise((resolve3) => {
|
|
638
|
-
transport.onclose = () => resolve3();
|
|
639
|
-
});
|
|
640
|
-
await server.connect(transport);
|
|
641
|
-
await closed;
|
|
642
|
-
} finally {
|
|
643
|
-
await client.close().catch(() => {
|
|
644
|
-
});
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
// src/mcp/server.ts
|
|
649
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
650
|
-
import { StdioServerTransport as StdioServerTransport2 } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
651
|
-
|
|
652
|
-
// src/mcp/prompts/index.ts
|
|
653
|
-
import { z } from "zod";
|
|
654
|
-
var structureGraphPrompt = {
|
|
655
|
-
name: "structure_graph",
|
|
656
|
-
description: STRUCTURE_GRAPH_PROMPT_DESC,
|
|
657
|
-
register(server) {
|
|
658
|
-
server.registerPrompt(
|
|
659
|
-
"structure_graph",
|
|
660
|
-
{
|
|
661
|
-
title: "Structure content into a knowledge graph",
|
|
662
|
-
description: STRUCTURE_GRAPH_PROMPT_DESC,
|
|
663
|
-
argsSchema: {
|
|
664
|
-
content: z.string().min(1).describe("The memory content to extract graph fields from.")
|
|
665
|
-
}
|
|
666
|
-
},
|
|
667
|
-
({ content }) => ({
|
|
668
|
-
messages: [
|
|
669
|
-
{ role: "user", content: { type: "text", text: buildGraphStructuringPrompt(content) } }
|
|
670
|
-
]
|
|
671
|
-
})
|
|
672
|
-
);
|
|
673
|
-
}
|
|
674
|
-
};
|
|
675
|
-
var ALL_PROMPTS = [structureGraphPrompt];
|
|
676
|
-
|
|
677
|
-
// src/mcp/tools/corrections.ts
|
|
678
|
-
import { z as z3 } from "zod";
|
|
679
579
|
|
|
680
580
|
// src/mcp/http-client.ts
|
|
681
581
|
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
@@ -781,6 +681,202 @@ function extractEnvelopeError(parsed) {
|
|
|
781
681
|
return null;
|
|
782
682
|
}
|
|
783
683
|
|
|
684
|
+
// src/mcp/tools/shared.ts
|
|
685
|
+
var LOCAL_UPLOAD_META_KEY = "pyx.dev/local-upload";
|
|
686
|
+
|
|
687
|
+
// src/mcp/proxy-server.ts
|
|
688
|
+
var REMOTE_MCP_PATH = "/mcp";
|
|
689
|
+
function extractLocalUpload(meta) {
|
|
690
|
+
if (meta === null || typeof meta !== "object") return void 0;
|
|
691
|
+
const descriptor = meta[LOCAL_UPLOAD_META_KEY];
|
|
692
|
+
if (descriptor === null || typeof descriptor !== "object") return void 0;
|
|
693
|
+
const obj = descriptor;
|
|
694
|
+
if (typeof obj.pathArg !== "string" || typeof obj.endpoint !== "string" || typeof obj.fileField !== "string") {
|
|
695
|
+
return void 0;
|
|
696
|
+
}
|
|
697
|
+
if (!obj.endpoint.startsWith("/") || obj.endpoint.startsWith("//")) {
|
|
698
|
+
return void 0;
|
|
699
|
+
}
|
|
700
|
+
return obj;
|
|
701
|
+
}
|
|
702
|
+
async function readCappedLocalFile(rawPath, descriptor) {
|
|
703
|
+
if (typeof rawPath !== "string" || rawPath.length === 0) {
|
|
704
|
+
return {
|
|
705
|
+
ok: false,
|
|
706
|
+
result: mcpText(`\`${descriptor.pathArg}\` must be a non-empty local file path.`, true)
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
const abs = isAbsolute(rawPath) ? rawPath : resolve(rawPath);
|
|
710
|
+
try {
|
|
711
|
+
if (typeof descriptor.maxBytes === "number") {
|
|
712
|
+
const info = await stat(abs);
|
|
713
|
+
if (info.size > descriptor.maxBytes) {
|
|
714
|
+
return {
|
|
715
|
+
ok: false,
|
|
716
|
+
result: mcpText(`File too large: ${info.size} bytes > ${descriptor.maxBytes} cap.`, true)
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return { ok: true, bytes: await readFile(abs), name: basename(abs) };
|
|
721
|
+
} catch (err) {
|
|
722
|
+
return {
|
|
723
|
+
ok: false,
|
|
724
|
+
result: mcpText(
|
|
725
|
+
`Failed to read ${abs}: ${err instanceof Error ? err.message : String(err)}.`,
|
|
726
|
+
true
|
|
727
|
+
)
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
function createLocalFileUploader(credentials, fetchImpl = fetch) {
|
|
732
|
+
return async (descriptor, args) => {
|
|
733
|
+
const file = await readCappedLocalFile(args[descriptor.pathArg], descriptor);
|
|
734
|
+
if (!file.ok) return file.result;
|
|
735
|
+
const http = createHttpClient(credentials, fetchImpl);
|
|
736
|
+
const res = await http.requestMultipart({
|
|
737
|
+
path: descriptor.endpoint,
|
|
738
|
+
formData: () => {
|
|
739
|
+
const form = new FormData();
|
|
740
|
+
form.set(descriptor.fileField, new File([new Uint8Array(file.bytes)], file.name));
|
|
741
|
+
for (const key of descriptor.optionalArgs ?? []) {
|
|
742
|
+
const value = args[key];
|
|
743
|
+
if (typeof value === "string" && value.length > 0) form.set(key, value);
|
|
744
|
+
}
|
|
745
|
+
return form;
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
return res.ok ? mcpJson(res.data) : res.result;
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
function createProxyServer(client, version, uploadLocalFile) {
|
|
752
|
+
const caps = client.getServerCapabilities();
|
|
753
|
+
const server = new Server(client.getServerVersion() ?? { name: "pyx-memory", version }, {
|
|
754
|
+
capabilities: {
|
|
755
|
+
// Advertise the PRESENCE of tools/prompts, but NOT their `listChanged`
|
|
756
|
+
// sub-capability: this proxy does not relay the remote's list_changed
|
|
757
|
+
// notifications, so claiming listChanged would be a capability the host
|
|
758
|
+
// could rely on but we never honor (Codex: keep the proxy transparent).
|
|
759
|
+
...caps?.tools ? { tools: {} } : {},
|
|
760
|
+
...caps?.prompts ? { prompts: {} } : {}
|
|
761
|
+
},
|
|
762
|
+
instructions: client.getInstructions()
|
|
763
|
+
});
|
|
764
|
+
const localUploads = /* @__PURE__ */ new Map();
|
|
765
|
+
let listedOnce = false;
|
|
766
|
+
const refreshFromList = (result) => {
|
|
767
|
+
const tools = result.tools;
|
|
768
|
+
if (Array.isArray(tools)) {
|
|
769
|
+
listedOnce = true;
|
|
770
|
+
for (const tool of tools) {
|
|
771
|
+
const descriptor = uploadLocalFile ? extractLocalUpload(tool._meta) : void 0;
|
|
772
|
+
if (descriptor) localUploads.set(tool.name, descriptor);
|
|
773
|
+
else localUploads.delete(tool.name);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
return result;
|
|
777
|
+
};
|
|
778
|
+
if (caps?.tools) {
|
|
779
|
+
server.setRequestHandler(
|
|
780
|
+
ListToolsRequestSchema,
|
|
781
|
+
async (req) => refreshFromList(await client.listTools(req.params))
|
|
782
|
+
);
|
|
783
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
784
|
+
if (uploadLocalFile && !listedOnce) {
|
|
785
|
+
try {
|
|
786
|
+
refreshFromList(await client.listTools());
|
|
787
|
+
} catch {
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
const descriptor = uploadLocalFile ? localUploads.get(req.params.name) : void 0;
|
|
791
|
+
if (uploadLocalFile && descriptor) {
|
|
792
|
+
const result = await uploadLocalFile(
|
|
793
|
+
descriptor,
|
|
794
|
+
req.params.arguments ?? {}
|
|
795
|
+
);
|
|
796
|
+
return result;
|
|
797
|
+
}
|
|
798
|
+
return client.callTool(req.params);
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
if (caps?.prompts) {
|
|
802
|
+
server.setRequestHandler(
|
|
803
|
+
ListPromptsRequestSchema,
|
|
804
|
+
(req) => client.listPrompts(req.params)
|
|
805
|
+
);
|
|
806
|
+
server.setRequestHandler(
|
|
807
|
+
GetPromptRequestSchema,
|
|
808
|
+
(req) => client.getPrompt(req.params)
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
return server;
|
|
812
|
+
}
|
|
813
|
+
async function runMcpProxyServer(opts) {
|
|
814
|
+
const version = opts.version ?? (true ? "1.1.3" : "0.0.0-dev");
|
|
815
|
+
const read = await opts.readCredentials();
|
|
816
|
+
if (!read.ok) {
|
|
817
|
+
const text = read.result.content.map((c) => c.type === "text" ? c.text : "").join(" ").trim();
|
|
818
|
+
throw new Error(text || "pyx-memory credentials are unavailable. Run: pyx-mem login");
|
|
819
|
+
}
|
|
820
|
+
const { endpoint, apiKey } = read.credentials;
|
|
821
|
+
const url = new URL(`${endpoint.replace(/\/+$/, "")}${REMOTE_MCP_PATH}`);
|
|
822
|
+
const client = new McpClient({ name: "pyx-mem-proxy", version }, { capabilities: {} });
|
|
823
|
+
const clientTransport = new StreamableHTTPClientTransport(url, {
|
|
824
|
+
requestInit: { headers: { Authorization: `Bearer ${apiKey}` } }
|
|
825
|
+
});
|
|
826
|
+
try {
|
|
827
|
+
await client.connect(clientTransport);
|
|
828
|
+
} catch (err) {
|
|
829
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
830
|
+
throw new Error(
|
|
831
|
+
`Could not reach the pyx-memory remote MCP at ${url.href}: ${msg}. Verify the endpoint and key with \`pyx-mem doctor\`, or run the bundled server with \`pyx-mem mcp\`.`
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
try {
|
|
835
|
+
const server = createProxyServer(client, version, createLocalFileUploader(read.credentials));
|
|
836
|
+
const transport = new StdioServerTransport();
|
|
837
|
+
const closed = new Promise((resolve4) => {
|
|
838
|
+
transport.onclose = () => resolve4();
|
|
839
|
+
});
|
|
840
|
+
await server.connect(transport);
|
|
841
|
+
await closed;
|
|
842
|
+
} finally {
|
|
843
|
+
await client.close().catch(() => {
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// src/mcp/server.ts
|
|
849
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
850
|
+
import { StdioServerTransport as StdioServerTransport2 } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
851
|
+
|
|
852
|
+
// src/mcp/prompts/index.ts
|
|
853
|
+
import { z } from "zod";
|
|
854
|
+
var structureGraphPrompt = {
|
|
855
|
+
name: "structure_graph",
|
|
856
|
+
description: STRUCTURE_GRAPH_PROMPT_DESC,
|
|
857
|
+
register(server) {
|
|
858
|
+
server.registerPrompt(
|
|
859
|
+
"structure_graph",
|
|
860
|
+
{
|
|
861
|
+
title: "Structure content into a knowledge graph",
|
|
862
|
+
description: STRUCTURE_GRAPH_PROMPT_DESC,
|
|
863
|
+
argsSchema: {
|
|
864
|
+
content: z.string().min(1).describe("The memory content to extract graph fields from.")
|
|
865
|
+
}
|
|
866
|
+
},
|
|
867
|
+
({ content }) => ({
|
|
868
|
+
messages: [
|
|
869
|
+
{ role: "user", content: { type: "text", text: buildGraphStructuringPrompt(content) } }
|
|
870
|
+
]
|
|
871
|
+
})
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
var ALL_PROMPTS = [structureGraphPrompt];
|
|
876
|
+
|
|
877
|
+
// src/mcp/tools/corrections.ts
|
|
878
|
+
import { z as z3 } from "zod";
|
|
879
|
+
|
|
784
880
|
// src/mcp/tools/scopes.ts
|
|
785
881
|
import { z as z2 } from "zod";
|
|
786
882
|
var scopeShape = {
|
|
@@ -923,11 +1019,12 @@ var getMemoryTool = {
|
|
|
923
1019
|
};
|
|
924
1020
|
|
|
925
1021
|
// src/mcp/tools/ingest.ts
|
|
926
|
-
import { readFile, stat } from "fs/promises";
|
|
927
|
-
import { basename, extname, isAbsolute, resolve } from "path";
|
|
1022
|
+
import { readFile as readFile2, stat as stat2 } from "fs/promises";
|
|
1023
|
+
import { basename as basename2, extname, isAbsolute as isAbsolute2, resolve as resolve2 } from "path";
|
|
928
1024
|
import { z as z6 } from "zod";
|
|
929
1025
|
var IMAGE_EXT = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".webp", ".gif", ".bmp", ".tiff", ".svg"]);
|
|
930
1026
|
var MAX_BYTES = 50 * 1024 * 1024;
|
|
1027
|
+
var INGEST_ENDPOINT = "/api/memory/ingest/file";
|
|
931
1028
|
var inputShape3 = {
|
|
932
1029
|
path: z6.string().min(1).describe(
|
|
933
1030
|
"Local file path readable by the pyx-mem process. Uploaded as multipart `file`. Images require `description`; documents auto-extract text."
|
|
@@ -946,6 +1043,17 @@ var ingestMemoryFileTool = {
|
|
|
946
1043
|
inputSchema: inputShape3,
|
|
947
1044
|
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: true }
|
|
948
1045
|
},
|
|
1046
|
+
// `path` is a host-local file. On the remote `/mcp` route the server cannot
|
|
1047
|
+
// read it, so this descriptor lets the local proxy bridge the upload (read
|
|
1048
|
+
// bytes here, multipart-POST to the declared endpoint). The bundled handler
|
|
1049
|
+
// below ignores it. Field names map 1:1 to the multipart form built below.
|
|
1050
|
+
localUpload: {
|
|
1051
|
+
pathArg: "path",
|
|
1052
|
+
endpoint: INGEST_ENDPOINT,
|
|
1053
|
+
fileField: "file",
|
|
1054
|
+
optionalArgs: ["description", "namespaceId"],
|
|
1055
|
+
maxBytes: MAX_BYTES
|
|
1056
|
+
},
|
|
949
1057
|
handler: (deps) => async (raw) => {
|
|
950
1058
|
const args = raw;
|
|
951
1059
|
const ext = extname(args.path).toLowerCase();
|
|
@@ -956,14 +1064,14 @@ var ingestMemoryFileTool = {
|
|
|
956
1064
|
true
|
|
957
1065
|
);
|
|
958
1066
|
}
|
|
959
|
-
const abs =
|
|
1067
|
+
const abs = isAbsolute2(args.path) ? args.path : resolve2(args.path);
|
|
960
1068
|
let bytes;
|
|
961
1069
|
try {
|
|
962
|
-
const info = await
|
|
1070
|
+
const info = await stat2(abs);
|
|
963
1071
|
if (info.size > MAX_BYTES) {
|
|
964
1072
|
return mcpText(`File too large: ${info.size} bytes > 50MB cap.`, true);
|
|
965
1073
|
}
|
|
966
|
-
bytes = await
|
|
1074
|
+
bytes = await readFile2(abs);
|
|
967
1075
|
} catch (err) {
|
|
968
1076
|
return mcpText(
|
|
969
1077
|
`Failed to read ${abs}: ${err instanceof Error ? err.message : String(err)}.`,
|
|
@@ -974,11 +1082,11 @@ var ingestMemoryFileTool = {
|
|
|
974
1082
|
if (!creds.ok) return creds.result;
|
|
975
1083
|
const http = createHttpClient(creds.credentials, deps.fetchImpl);
|
|
976
1084
|
const res = await http.requestMultipart({
|
|
977
|
-
path:
|
|
1085
|
+
path: INGEST_ENDPOINT,
|
|
978
1086
|
scope: args,
|
|
979
1087
|
formData: () => {
|
|
980
1088
|
const form = new FormData();
|
|
981
|
-
const file = new File([new Uint8Array(bytes)],
|
|
1089
|
+
const file = new File([new Uint8Array(bytes)], basename2(abs));
|
|
982
1090
|
form.set("file", file);
|
|
983
1091
|
if (args.description) form.set("description", args.description);
|
|
984
1092
|
if (args.namespaceId) form.set("namespaceId", args.namespaceId);
|
|
@@ -1459,7 +1567,7 @@ var ALL_TOOL_NAMES = ALL_TOOLS.map((t) => t.name);
|
|
|
1459
1567
|
// src/mcp/server.ts
|
|
1460
1568
|
async function runMcpServer(opts) {
|
|
1461
1569
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
1462
|
-
const version = opts.version ?? (true ? "1.1.
|
|
1570
|
+
const version = opts.version ?? (true ? "1.1.3" : "0.0.0-dev");
|
|
1463
1571
|
const server = new McpServer(
|
|
1464
1572
|
{ name: "pyx-memory", version },
|
|
1465
1573
|
{ instructions: PYX_MEMORY_INSTRUCTIONS, capabilities: { tools: {}, prompts: {} } }
|
|
@@ -1479,8 +1587,8 @@ async function runMcpServer(opts) {
|
|
|
1479
1587
|
prompt.register(server);
|
|
1480
1588
|
}
|
|
1481
1589
|
const transport = new StdioServerTransport2();
|
|
1482
|
-
const closed = new Promise((
|
|
1483
|
-
transport.onclose = () =>
|
|
1590
|
+
const closed = new Promise((resolve4) => {
|
|
1591
|
+
transport.onclose = () => resolve4();
|
|
1484
1592
|
});
|
|
1485
1593
|
await server.connect(transport);
|
|
1486
1594
|
await closed;
|
|
@@ -1489,9 +1597,9 @@ async function runMcpServer(opts) {
|
|
|
1489
1597
|
// src/cli/commands/mcp.ts
|
|
1490
1598
|
async function mcpCommand(opts = {}) {
|
|
1491
1599
|
const readCredentials = createReadCredentials(() => getDefaultKeychain());
|
|
1492
|
-
const onStdinEnd = new Promise((
|
|
1493
|
-
process.stdin.once("end",
|
|
1494
|
-
process.stdin.once("close",
|
|
1600
|
+
const onStdinEnd = new Promise((resolve4) => {
|
|
1601
|
+
process.stdin.once("end", resolve4);
|
|
1602
|
+
process.stdin.once("close", resolve4);
|
|
1495
1603
|
});
|
|
1496
1604
|
try {
|
|
1497
1605
|
const run = opts.remote ? runMcpProxyServer({ readCredentials }) : runMcpServer({ readCredentials });
|
|
@@ -1959,7 +2067,7 @@ function writeJsonAndReport(filePath, agentLabel, entry, opts = {}) {
|
|
|
1959
2067
|
|
|
1960
2068
|
// src/cli/commands/scaffold.ts
|
|
1961
2069
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, statSync, writeFileSync as writeFileSync2 } from "fs";
|
|
1962
|
-
import { basename as
|
|
2070
|
+
import { basename as basename3, join as join2, resolve as resolve3 } from "path";
|
|
1963
2071
|
var SERVER_IMAGE = "ghcr.io/pyx-corp/pyx-memory-v1:latest";
|
|
1964
2072
|
var DOCKER_COMPOSE = `services:
|
|
1965
2073
|
pyx-memory:
|
|
@@ -2082,8 +2190,8 @@ function resolveTarget(args) {
|
|
|
2082
2190
|
process.stderr.write("Error: --name requires a non-empty directory name.\n");
|
|
2083
2191
|
return null;
|
|
2084
2192
|
}
|
|
2085
|
-
const targetDir = trimmedName ?
|
|
2086
|
-
const appName = trimmedName ||
|
|
2193
|
+
const targetDir = trimmedName ? resolve3(cwd, trimmedName) : cwd;
|
|
2194
|
+
const appName = trimmedName || basename3(resolve3(cwd));
|
|
2087
2195
|
return { targetDir, appName };
|
|
2088
2196
|
}
|
|
2089
2197
|
function buildFiles(targetDir, appName) {
|
|
@@ -2109,7 +2217,7 @@ function scaffoldCommand(args = {}) {
|
|
|
2109
2217
|
const created = [];
|
|
2110
2218
|
const skipped = [];
|
|
2111
2219
|
for (const file of buildFiles(target.targetDir, target.appName)) {
|
|
2112
|
-
const relativePath =
|
|
2220
|
+
const relativePath = basename3(file.path);
|
|
2113
2221
|
if (existsSync2(file.path)) {
|
|
2114
2222
|
skipped.push(relativePath);
|
|
2115
2223
|
continue;
|