@pyxmate/memory 1.17.18 → 1.17.19
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 +157 -9
- package/package.json +1 -1
package/dist/cli/pyx-mem.mjs
CHANGED
|
@@ -836,7 +836,7 @@ function createProxyServer(client, version, uploadLocalFile) {
|
|
|
836
836
|
return server;
|
|
837
837
|
}
|
|
838
838
|
async function runMcpProxyServer(opts) {
|
|
839
|
-
const version = opts.version ?? (true ? "1.17.
|
|
839
|
+
const version = opts.version ?? (true ? "1.17.19" : "0.0.0-dev");
|
|
840
840
|
const read = await opts.readCredentials();
|
|
841
841
|
if (!read.ok) {
|
|
842
842
|
const text = read.result.content.map((c) => c.type === "text" ? c.text : "").join(" ").trim();
|
|
@@ -1540,6 +1540,147 @@ function resolveMcpMode(flags) {
|
|
|
1540
1540
|
return { ok: true };
|
|
1541
1541
|
}
|
|
1542
1542
|
|
|
1543
|
+
// src/cli/commands/overview.ts
|
|
1544
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
1545
|
+
import { z } from "zod";
|
|
1546
|
+
var OVERVIEW_SCHEMA_VERSION = 1;
|
|
1547
|
+
var RECENT_ENTRY_LIMIT = 3;
|
|
1548
|
+
var MAX_TOPIC_CHARS = 160;
|
|
1549
|
+
var MAX_PROJECT_CHARS = 80;
|
|
1550
|
+
var entrySchema = z.object({
|
|
1551
|
+
id: z.string().min(1),
|
|
1552
|
+
metadata: z.record(z.string(), z.unknown())
|
|
1553
|
+
}).passthrough();
|
|
1554
|
+
var hostedEntriesResponseSchema = z.object({
|
|
1555
|
+
memories: z.array(entrySchema),
|
|
1556
|
+
total: z.number().int().nonnegative()
|
|
1557
|
+
}).passthrough();
|
|
1558
|
+
var selfHostedEntriesResponseSchema = z.object({
|
|
1559
|
+
success: z.literal(true),
|
|
1560
|
+
data: z.object({
|
|
1561
|
+
entries: z.array(entrySchema),
|
|
1562
|
+
totalCount: z.number().int().nonnegative()
|
|
1563
|
+
}).passthrough()
|
|
1564
|
+
}).passthrough();
|
|
1565
|
+
var entriesResponseSchema = z.union([
|
|
1566
|
+
hostedEntriesResponseSchema.transform(({ memories, total }) => ({
|
|
1567
|
+
entries: memories,
|
|
1568
|
+
totalCount: total
|
|
1569
|
+
})),
|
|
1570
|
+
selfHostedEntriesResponseSchema.transform(({ data }) => data)
|
|
1571
|
+
]);
|
|
1572
|
+
async function overviewCommand(opts = {}) {
|
|
1573
|
+
const provider = opts.keychain ?? getDefaultKeychain();
|
|
1574
|
+
let credentials;
|
|
1575
|
+
try {
|
|
1576
|
+
credentials = await provider.read();
|
|
1577
|
+
} catch (error) {
|
|
1578
|
+
const detail = error instanceof KeychainError ? [error.message, error.guidance].filter(Boolean).join(" ") : "The OS credential store could not be read.";
|
|
1579
|
+
emit(report("error", null, null, detail));
|
|
1580
|
+
return error instanceof KeychainError ? error.exit : EXIT.CRED_UNAVAILABLE;
|
|
1581
|
+
}
|
|
1582
|
+
if (!credentials) {
|
|
1583
|
+
emit(report("signed_out", null, null, null));
|
|
1584
|
+
return EXIT.NOT_LOGGED_IN;
|
|
1585
|
+
}
|
|
1586
|
+
if (!isHttpUrl2(credentials.endpoint)) {
|
|
1587
|
+
emit(
|
|
1588
|
+
report(
|
|
1589
|
+
"error",
|
|
1590
|
+
null,
|
|
1591
|
+
"keychain",
|
|
1592
|
+
"The stored pyx-memory endpoint is invalid. Run: pyx-mem login"
|
|
1593
|
+
)
|
|
1594
|
+
);
|
|
1595
|
+
return EXIT.DOCTOR_FAIL;
|
|
1596
|
+
}
|
|
1597
|
+
const http = createHttpClient(credentials, opts.fetchImpl ?? fetch);
|
|
1598
|
+
const response = await http.requestJson({
|
|
1599
|
+
method: "GET",
|
|
1600
|
+
path: "/api/memory/entries",
|
|
1601
|
+
query: { status: "active", limit: RECENT_ENTRY_LIMIT },
|
|
1602
|
+
idempotencyKey: `cli-overview-${randomUUID3()}`
|
|
1603
|
+
});
|
|
1604
|
+
if (!response.ok) {
|
|
1605
|
+
const signedOut = response.status === 401;
|
|
1606
|
+
emit(
|
|
1607
|
+
report(
|
|
1608
|
+
signedOut ? "signed_out" : "error",
|
|
1609
|
+
credentials.endpoint,
|
|
1610
|
+
"keychain",
|
|
1611
|
+
overviewFailure(response.status)
|
|
1612
|
+
)
|
|
1613
|
+
);
|
|
1614
|
+
return signedOut ? EXIT.NOT_LOGGED_IN : EXIT.DOCTOR_FAIL;
|
|
1615
|
+
}
|
|
1616
|
+
const parsed = entriesResponseSchema.safeParse(response.data);
|
|
1617
|
+
if (!parsed.success) {
|
|
1618
|
+
emit(
|
|
1619
|
+
report(
|
|
1620
|
+
"error",
|
|
1621
|
+
credentials.endpoint,
|
|
1622
|
+
"keychain",
|
|
1623
|
+
"pyx-memory returned an invalid overview response. Run: pyx-mem doctor"
|
|
1624
|
+
)
|
|
1625
|
+
);
|
|
1626
|
+
return EXIT.DOCTOR_FAIL;
|
|
1627
|
+
}
|
|
1628
|
+
emit({
|
|
1629
|
+
...report("ready", credentials.endpoint, "keychain", null),
|
|
1630
|
+
totalCount: parsed.data.totalCount,
|
|
1631
|
+
entries: parsed.data.entries.slice(0, RECENT_ENTRY_LIMIT).map((entry) => ({
|
|
1632
|
+
id: entry.id,
|
|
1633
|
+
topic: boundedLabel(entry.metadata.topic, "Untitled", MAX_TOPIC_CHARS),
|
|
1634
|
+
project: boundedLabel(entry.metadata.project, "Unscoped", MAX_PROJECT_CHARS)
|
|
1635
|
+
}))
|
|
1636
|
+
});
|
|
1637
|
+
return EXIT.OK;
|
|
1638
|
+
}
|
|
1639
|
+
function report(state, endpoint, keySource, problem) {
|
|
1640
|
+
return {
|
|
1641
|
+
schemaVersion: OVERVIEW_SCHEMA_VERSION,
|
|
1642
|
+
state,
|
|
1643
|
+
endpoint,
|
|
1644
|
+
keySource,
|
|
1645
|
+
totalCount: 0,
|
|
1646
|
+
entries: [],
|
|
1647
|
+
problem
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1650
|
+
function emit(value) {
|
|
1651
|
+
process.stdout.write(`${JSON.stringify(value)}
|
|
1652
|
+
`);
|
|
1653
|
+
}
|
|
1654
|
+
function overviewFailure(status) {
|
|
1655
|
+
if (status === 401) {
|
|
1656
|
+
return "Stored pyx-memory credentials were rejected. Run: pyx-mem login";
|
|
1657
|
+
}
|
|
1658
|
+
if (status === 403) {
|
|
1659
|
+
return "pyx-memory denied access (HTTP 403). Check the key scope and project access.";
|
|
1660
|
+
}
|
|
1661
|
+
if (status === void 0) {
|
|
1662
|
+
return "Unable to reach pyx-memory. Run: pyx-mem doctor";
|
|
1663
|
+
}
|
|
1664
|
+
if (status >= 500) {
|
|
1665
|
+
return `pyx-memory is unavailable (HTTP ${status}). Run: pyx-mem doctor`;
|
|
1666
|
+
}
|
|
1667
|
+
return `pyx-memory overview failed (HTTP ${status}). Run: pyx-mem doctor`;
|
|
1668
|
+
}
|
|
1669
|
+
function boundedLabel(value, fallback, maxChars) {
|
|
1670
|
+
if (typeof value !== "string" || value.trim().length === 0) return fallback;
|
|
1671
|
+
const normalized = value.trim();
|
|
1672
|
+
const chars = [...normalized];
|
|
1673
|
+
return chars.length > maxChars ? `${chars.slice(0, maxChars).join("")}\u2026` : normalized;
|
|
1674
|
+
}
|
|
1675
|
+
function isHttpUrl2(value) {
|
|
1676
|
+
try {
|
|
1677
|
+
const url = new URL(value);
|
|
1678
|
+
return url.protocol === "http:" || url.protocol === "https:";
|
|
1679
|
+
} catch {
|
|
1680
|
+
return false;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1543
1684
|
// src/cli/commands/scaffold.ts
|
|
1544
1685
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
1545
1686
|
import { basename as basename2, join as join2, resolve as resolve2 } from "path";
|
|
@@ -1720,10 +1861,10 @@ function scaffoldCommand(args = {}) {
|
|
|
1720
1861
|
// src/cli/commands/status.ts
|
|
1721
1862
|
async function statusCommand(opts = {}) {
|
|
1722
1863
|
const provider = opts.keychain ?? getDefaultKeychain();
|
|
1723
|
-
let
|
|
1864
|
+
let report2;
|
|
1724
1865
|
try {
|
|
1725
1866
|
const creds = await provider.read();
|
|
1726
|
-
|
|
1867
|
+
report2 = {
|
|
1727
1868
|
endpoint: creds?.endpoint ?? null,
|
|
1728
1869
|
keyPresent: creds !== null,
|
|
1729
1870
|
keySource: creds !== null ? "keychain" : null,
|
|
@@ -1734,17 +1875,17 @@ async function statusCommand(opts = {}) {
|
|
|
1734
1875
|
throw err;
|
|
1735
1876
|
}
|
|
1736
1877
|
if (opts.json) {
|
|
1737
|
-
process.stdout.write(`${JSON.stringify(
|
|
1878
|
+
process.stdout.write(`${JSON.stringify(report2)}
|
|
1738
1879
|
`);
|
|
1739
1880
|
} else {
|
|
1740
1881
|
const lines = [
|
|
1741
|
-
`endpoint: ${
|
|
1742
|
-
`credentials: ${
|
|
1882
|
+
`endpoint: ${report2.endpoint ?? "(not set)"}`,
|
|
1883
|
+
`credentials: ${report2.loggedIn ? "present (keychain)" : "not logged in \u2014 run: pyx-mem login"}`
|
|
1743
1884
|
];
|
|
1744
1885
|
process.stdout.write(`${lines.join("\n")}
|
|
1745
1886
|
`);
|
|
1746
1887
|
}
|
|
1747
|
-
return
|
|
1888
|
+
return report2.loggedIn ? EXIT.OK : EXIT.NOT_LOGGED_IN;
|
|
1748
1889
|
}
|
|
1749
1890
|
function emitError(err, json) {
|
|
1750
1891
|
if (json) {
|
|
@@ -1769,6 +1910,7 @@ Usage:
|
|
|
1769
1910
|
Commands:
|
|
1770
1911
|
login [--endpoint <url>] [--api-key <key>] Store endpoint and API key in OS credential store.
|
|
1771
1912
|
status [--json] Show endpoint, key presence, MCP config status.
|
|
1913
|
+
overview --json Read memory count and three recent safe labels.
|
|
1772
1914
|
logout Delete stored pyx-memory credentials.
|
|
1773
1915
|
doctor [--json] Diagnose keychain, credentials, backend, MCP startup.
|
|
1774
1916
|
scaffold [--name <dir>] Generate Docker, env, SDK, and memory design-guide starter files.
|
|
@@ -1915,6 +2057,12 @@ async function main() {
|
|
|
1915
2057
|
});
|
|
1916
2058
|
case "status":
|
|
1917
2059
|
return statusCommand({ json: parsed.flags.json === true });
|
|
2060
|
+
case "overview":
|
|
2061
|
+
if (parsed.flags.json !== true) {
|
|
2062
|
+
process.stderr.write("Error: `pyx-mem overview` requires --json.\n");
|
|
2063
|
+
return EXIT.USAGE;
|
|
2064
|
+
}
|
|
2065
|
+
return overviewCommand();
|
|
1918
2066
|
case "logout":
|
|
1919
2067
|
return logoutCommand();
|
|
1920
2068
|
case "doctor":
|
|
@@ -1932,10 +2080,10 @@ async function main() {
|
|
|
1932
2080
|
}
|
|
1933
2081
|
}
|
|
1934
2082
|
main().then((code) => {
|
|
1935
|
-
process.
|
|
2083
|
+
process.exitCode = code;
|
|
1936
2084
|
}).catch((err) => {
|
|
1937
2085
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1938
2086
|
process.stderr.write(`Internal error: ${msg}
|
|
1939
2087
|
`);
|
|
1940
|
-
process.
|
|
2088
|
+
process.exitCode = 1;
|
|
1941
2089
|
});
|