@pyxmate/memory 1.26.6 → 1.27.1
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/chunk-4DXEQC6X.mjs +16 -0
- package/dist/chunk-7IGU3HJO.mjs +70 -0
- package/dist/chunk-7TATCSSN.mjs +650 -0
- package/dist/chunk-QR5K7ETI.mjs +793 -0
- package/dist/{chunk-KZKGRND2.mjs → chunk-RWQTBXUC.mjs} +12 -0
- package/dist/chunk-S3CX323Z.mjs +34 -0
- package/dist/chunk-THLUBOGD.mjs +263 -0
- package/dist/chunk-UESIQ47D.mjs +165 -0
- package/dist/chunk-YBPODKB5.mjs +132 -0
- package/dist/cli/pyx-mem.mjs +68 -4208
- package/dist/dashboard.mjs +1 -1
- package/dist/doctor-AERNUHEZ.mjs +143 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.mjs +7 -1
- package/dist/insights-PD7Y6QDX.mjs +139 -0
- package/dist/login-4ALCAN4M.mjs +179 -0
- package/dist/login-browser-DO2O2Q2G.mjs +407 -0
- package/dist/login-recovery-AOO76PYX.mjs +97 -0
- package/dist/logout-4CO53LNA.mjs +13 -0
- package/dist/mcp-64KVRH7F.mjs +944 -0
- package/dist/mcp-install-KBB45OB2.mjs +36 -0
- package/dist/overview-COBXHLP3.mjs +88 -0
- package/dist/react.mjs +1 -1
- package/dist/scaffold-2FSCWF22.mjs +186 -0
- package/dist/status-UHJZLEPL.mjs +74 -0
- package/dist/taxonomy-EKDFDFXW.mjs +103 -0
- package/package.json +1 -1
package/dist/dashboard.mjs
CHANGED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
probeCredentials
|
|
3
|
+
} from "./chunk-S3CX323Z.mjs";
|
|
4
|
+
import {
|
|
5
|
+
KeychainError,
|
|
6
|
+
getDefaultKeychain
|
|
7
|
+
} from "./chunk-7TATCSSN.mjs";
|
|
8
|
+
import {
|
|
9
|
+
EXIT
|
|
10
|
+
} from "./chunk-4DXEQC6X.mjs";
|
|
11
|
+
|
|
12
|
+
// src/cli/commands/doctor.ts
|
|
13
|
+
async function doctorCommand(opts = {}) {
|
|
14
|
+
const provider = opts.keychain ?? getDefaultKeychain();
|
|
15
|
+
const fetcher = opts.fetchImpl ?? fetch;
|
|
16
|
+
const checks = [];
|
|
17
|
+
const accessCheck = await provider.check();
|
|
18
|
+
if (accessCheck.ok) {
|
|
19
|
+
checks.push({ id: "provider.import", status: "pass", message: "native keyring module loaded" });
|
|
20
|
+
checks.push({ id: "keychain.access", status: "pass", message: accessCheck.message });
|
|
21
|
+
} else if (accessCheck.code === "provider-import-failed") {
|
|
22
|
+
checks.push({
|
|
23
|
+
id: "provider.import",
|
|
24
|
+
status: "fail",
|
|
25
|
+
code: accessCheck.code,
|
|
26
|
+
message: accessCheck.message,
|
|
27
|
+
guidance: accessCheck.guidance
|
|
28
|
+
});
|
|
29
|
+
checks.push({
|
|
30
|
+
id: "keychain.access",
|
|
31
|
+
status: "skip",
|
|
32
|
+
message: "skipped \u2014 provider import failed"
|
|
33
|
+
});
|
|
34
|
+
} else {
|
|
35
|
+
checks.push({ id: "provider.import", status: "pass", message: "native keyring module loaded" });
|
|
36
|
+
checks.push({
|
|
37
|
+
id: "keychain.access",
|
|
38
|
+
status: "fail",
|
|
39
|
+
code: accessCheck.code,
|
|
40
|
+
message: accessCheck.message,
|
|
41
|
+
guidance: accessCheck.guidance
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const accessOk = accessCheck.ok;
|
|
45
|
+
let creds = null;
|
|
46
|
+
if (accessOk) {
|
|
47
|
+
try {
|
|
48
|
+
creds = await provider.read();
|
|
49
|
+
if (creds) {
|
|
50
|
+
checks.push({
|
|
51
|
+
id: "credentials.present",
|
|
52
|
+
status: "pass",
|
|
53
|
+
message: "credentials present in keychain",
|
|
54
|
+
endpoint: creds.endpoint
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
checks.push({
|
|
58
|
+
id: "credentials.present",
|
|
59
|
+
status: "fail",
|
|
60
|
+
code: "not-logged-in",
|
|
61
|
+
message: "no pyx-memory credentials stored",
|
|
62
|
+
guidance: "Run: pyx-mem login"
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
} catch (err) {
|
|
66
|
+
if (err instanceof KeychainError) {
|
|
67
|
+
checks.push({
|
|
68
|
+
id: "credentials.present",
|
|
69
|
+
status: "fail",
|
|
70
|
+
code: err.code,
|
|
71
|
+
message: err.message,
|
|
72
|
+
guidance: err.guidance
|
|
73
|
+
});
|
|
74
|
+
} else {
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
checks.push({
|
|
80
|
+
id: "credentials.present",
|
|
81
|
+
status: "skip",
|
|
82
|
+
message: "skipped \u2014 keychain access failed"
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (creds) {
|
|
86
|
+
const probe = await probeCredentials({
|
|
87
|
+
endpoint: creds.endpoint,
|
|
88
|
+
apiKey: creds.apiKey,
|
|
89
|
+
fetcher
|
|
90
|
+
});
|
|
91
|
+
if (probe.kind === "ok") {
|
|
92
|
+
checks.push({
|
|
93
|
+
id: "backend.reachable",
|
|
94
|
+
status: "pass",
|
|
95
|
+
message: `pyx-memory API reachable (HTTP ${probe.status})`,
|
|
96
|
+
endpoint: creds.endpoint
|
|
97
|
+
});
|
|
98
|
+
} else if (probe.kind === "invalid") {
|
|
99
|
+
checks.push({
|
|
100
|
+
id: "backend.reachable",
|
|
101
|
+
status: "fail",
|
|
102
|
+
code: "key-rejected",
|
|
103
|
+
message: `API key rejected (HTTP ${probe.status})`,
|
|
104
|
+
endpoint: creds.endpoint,
|
|
105
|
+
guidance: "Re-login with a valid key: pyx-mem login"
|
|
106
|
+
});
|
|
107
|
+
} else {
|
|
108
|
+
checks.push({
|
|
109
|
+
id: "backend.reachable",
|
|
110
|
+
status: "fail",
|
|
111
|
+
code: "unreachable",
|
|
112
|
+
message: `no pyx-memory API at this endpoint (${probe.reason})`,
|
|
113
|
+
endpoint: creds.endpoint,
|
|
114
|
+
guidance: "Verify the endpoint is the API backend, not a web UI: pyx-mem login --endpoint <API_URL>"
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
checks.push({
|
|
119
|
+
id: "backend.reachable",
|
|
120
|
+
status: "skip",
|
|
121
|
+
message: "skipped \u2014 no credentials to probe"
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
const ok = checks.every((c) => c.status !== "fail");
|
|
125
|
+
if (opts.json) {
|
|
126
|
+
process.stdout.write(`${JSON.stringify({ ok, checks })}
|
|
127
|
+
`);
|
|
128
|
+
} else {
|
|
129
|
+
for (const c of checks) {
|
|
130
|
+
const tag = c.status === "pass" ? "OK " : c.status === "skip" ? "SKIP" : "FAIL";
|
|
131
|
+
process.stdout.write(`[${tag}] ${c.id}: ${c.message}
|
|
132
|
+
`);
|
|
133
|
+
if (c.endpoint) process.stdout.write(` endpoint: ${c.endpoint}
|
|
134
|
+
`);
|
|
135
|
+
if (c.status === "fail" && c.guidance) process.stdout.write(` ${c.guidance}
|
|
136
|
+
`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return ok ? EXIT.OK : EXIT.DOCTOR_FAIL;
|
|
140
|
+
}
|
|
141
|
+
export {
|
|
142
|
+
doctorCommand
|
|
143
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -776,6 +776,9 @@ interface MemoryInsights {
|
|
|
776
776
|
topic: string | null;
|
|
777
777
|
project: string | null;
|
|
778
778
|
at: string;
|
|
779
|
+
writtenBy?: string | null;
|
|
780
|
+
writtenAt?: string | null;
|
|
781
|
+
appliedBy?: string | null;
|
|
779
782
|
}>;
|
|
780
783
|
}
|
|
781
784
|
interface GraphRepairResult {
|
|
@@ -1534,6 +1537,8 @@ declare const TAXONOMY_MAX_TOP_ENTITIES = 15;
|
|
|
1534
1537
|
declare const TAXONOMY_MAX_SAMPLE_TOPICS = 8;
|
|
1535
1538
|
declare const TAXONOMY_MAX_PROJECTS = 8;
|
|
1536
1539
|
declare const MEMORY_PROJECT_LABEL_MAX_CHARS = 80;
|
|
1540
|
+
declare const MCP_ACTOR_META_KEY = "pyx.dev/actor";
|
|
1541
|
+
declare const MEMORY_ACTOR_LABEL_MAX_CHARS = 80;
|
|
1537
1542
|
|
|
1538
1543
|
/**
|
|
1539
1544
|
* Result shape returned by an LLM entity extractor — entities + relations.
|
|
@@ -1599,6 +1604,8 @@ declare function mergeExtractedEntities(callerEntities: IngestEntity[] | undefin
|
|
|
1599
1604
|
relationships: IngestRelationship[];
|
|
1600
1605
|
};
|
|
1601
1606
|
|
|
1607
|
+
declare function normalizeMemoryActorLabel(value: unknown): string | null;
|
|
1608
|
+
|
|
1602
1609
|
declare function projectSearchResponseForMcp(payload: unknown): unknown;
|
|
1603
1610
|
|
|
1604
1611
|
/**
|
|
@@ -2004,4 +2011,4 @@ interface CreatePyxMemoryOptions {
|
|
|
2004
2011
|
}
|
|
2005
2012
|
declare function createPyxMemory(opts?: CreatePyxMemoryOptions): MemoryClient;
|
|
2006
2013
|
|
|
2007
|
-
export { type AgentId, type ApiResponse, type ConsolidationJudgementsResult, type ConsolidationMerge, type ConsolidationPair, type ConsolidationPairSide, type ConsolidationRunResult, type CorrectionInput, type CorrectionRecord, type CreatePyxMemoryOptions, DEFAULTS, DEPRECATED_RAG_STRATEGIES, DisabledMemory, type DroppedGraphRelationship, type DueScanInput, EmbeddingProviderName, type EnrichmentCallbacks, type EnrichmentPurpose, type EntityExtractionResult, type ExpandAnchorStatus, type ExpandParams, type ExpandResult, type ExtendedMemoryInterface, type FetchCorrectionsInput, type FileDownloadOptions, type GraphEnrichEvent, type GraphEnrichFileOptions, type GraphEnrichPreparedEvent, type GraphEnrichResult, type GraphEnrichResultEvent, type GraphEnrichment, type GraphEnrichmentStatus, type GraphExtractionPayload, type GraphFailureMode, type GraphNode, type GraphRelationship, type GraphRepairResult, type GraphTelemetrySnapshot, type GraphTraversalResult, type IngestEntity, type IngestErrorEvent, type IngestEvent, type IngestFileOptions, type IngestHeartbeatEvent, type IngestProgressEvent, type IngestRelationship, type IngestResultEvent, type IngestStage, type IngestionResult, type LineageParams, type LineageResult, type LineageVersion, MEMORY_PROJECT_LABEL_MAX_CHARS, MemoryClient, type MemoryClientOptions, type MemoryEntry, type MemoryIngestRequest, type MemoryInsightMetrics, type MemoryInsights, type MemoryInterface, type MemoryListParams, type MemoryListResult, type MemoryLogFilters, type MemoryProjectInsight, type MemorySearchParams, type MemorySearchResult, MemoryServerError, type MemoryStats, MemoryType, type MoveEntriesFilter, MoveFailureReason, type MoveResult, type MoveTarget, NamespaceIsolation, type PrincipalContext, RAGStrategy, type ReinforceParams, type ReinforceResult, type ReinforceSignal, SESSION_ORDINAL_MAX, SINGLE_TENANT_ID, type SecretElevationAggregate, type SecretElevationNotice, SensitivityLevel, type SourceEvidence, type StoreInput, StoreTarget, TAXONOMY_MAX_CATEGORIES, TAXONOMY_MAX_PROJECTS, TAXONOMY_MAX_SAMPLE_TOPICS, TAXONOMY_MAX_TOP_ENTITIES, type TemporalQueryFilters, type TenantScopeOptions, type Timestamp, type Topology, type TopologyExtractionProvider, type TopologyServiceVariant, type UsageHygieneSnapshot, VectorProvider, type VectorStatus, type WikiLintReport, assertGraphExtractionPayload, createPyxMemory, isSessionOrdinal, mergeExtractedEntities, normalizeGraphLabel, normalizeNameKey, projectSearchResponseForMcp, secretElevationAggregate, secretElevationNoticeFor, withSecretElevationNotice };
|
|
2014
|
+
export { type AgentId, type ApiResponse, type ConsolidationJudgementsResult, type ConsolidationMerge, type ConsolidationPair, type ConsolidationPairSide, type ConsolidationRunResult, type CorrectionInput, type CorrectionRecord, type CreatePyxMemoryOptions, DEFAULTS, DEPRECATED_RAG_STRATEGIES, DisabledMemory, type DroppedGraphRelationship, type DueScanInput, EmbeddingProviderName, type EnrichmentCallbacks, type EnrichmentPurpose, type EntityExtractionResult, type ExpandAnchorStatus, type ExpandParams, type ExpandResult, type ExtendedMemoryInterface, type FetchCorrectionsInput, type FileDownloadOptions, type GraphEnrichEvent, type GraphEnrichFileOptions, type GraphEnrichPreparedEvent, type GraphEnrichResult, type GraphEnrichResultEvent, type GraphEnrichment, type GraphEnrichmentStatus, type GraphExtractionPayload, type GraphFailureMode, type GraphNode, type GraphRelationship, type GraphRepairResult, type GraphTelemetrySnapshot, type GraphTraversalResult, type IngestEntity, type IngestErrorEvent, type IngestEvent, type IngestFileOptions, type IngestHeartbeatEvent, type IngestProgressEvent, type IngestRelationship, type IngestResultEvent, type IngestStage, type IngestionResult, type LineageParams, type LineageResult, type LineageVersion, MCP_ACTOR_META_KEY, MEMORY_ACTOR_LABEL_MAX_CHARS, MEMORY_PROJECT_LABEL_MAX_CHARS, MemoryClient, type MemoryClientOptions, type MemoryEntry, type MemoryIngestRequest, type MemoryInsightMetrics, type MemoryInsights, type MemoryInterface, type MemoryListParams, type MemoryListResult, type MemoryLogFilters, type MemoryProjectInsight, type MemorySearchParams, type MemorySearchResult, MemoryServerError, type MemoryStats, MemoryType, type MoveEntriesFilter, MoveFailureReason, type MoveResult, type MoveTarget, NamespaceIsolation, type PrincipalContext, RAGStrategy, type ReinforceParams, type ReinforceResult, type ReinforceSignal, SESSION_ORDINAL_MAX, SINGLE_TENANT_ID, type SecretElevationAggregate, type SecretElevationNotice, SensitivityLevel, type SourceEvidence, type StoreInput, StoreTarget, TAXONOMY_MAX_CATEGORIES, TAXONOMY_MAX_PROJECTS, TAXONOMY_MAX_SAMPLE_TOPICS, TAXONOMY_MAX_TOP_ENTITIES, type TemporalQueryFilters, type TenantScopeOptions, type Timestamp, type Topology, type TopologyExtractionProvider, type TopologyServiceVariant, type UsageHygieneSnapshot, VectorProvider, type VectorStatus, type WikiLintReport, assertGraphExtractionPayload, createPyxMemory, isSessionOrdinal, mergeExtractedEntities, normalizeGraphLabel, normalizeMemoryActorLabel, normalizeNameKey, projectSearchResponseForMcp, secretElevationAggregate, secretElevationNoticeFor, withSecretElevationNotice };
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,8 @@ import {
|
|
|
5
5
|
} from "./chunk-M67SXB7C.mjs";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULTS,
|
|
8
|
+
MCP_ACTOR_META_KEY,
|
|
9
|
+
MEMORY_ACTOR_LABEL_MAX_CHARS,
|
|
8
10
|
MEMORY_PROJECT_LABEL_MAX_CHARS,
|
|
9
11
|
MoveFailureReason,
|
|
10
12
|
NamespaceIsolation,
|
|
@@ -16,11 +18,12 @@ import {
|
|
|
16
18
|
documentContentSource,
|
|
17
19
|
documentGraphSource,
|
|
18
20
|
documentImageSource,
|
|
21
|
+
normalizeMemoryActorLabel,
|
|
19
22
|
projectSearchResponseForMcp,
|
|
20
23
|
secretElevationAggregate,
|
|
21
24
|
secretElevationNoticeFor,
|
|
22
25
|
withSecretElevationNotice
|
|
23
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-RWQTBXUC.mjs";
|
|
24
27
|
import {
|
|
25
28
|
DEPRECATED_RAG_STRATEGIES,
|
|
26
29
|
EmbeddingProviderName,
|
|
@@ -57,6 +60,8 @@ export {
|
|
|
57
60
|
DEPRECATED_RAG_STRATEGIES,
|
|
58
61
|
DisabledMemory,
|
|
59
62
|
EmbeddingProviderName,
|
|
63
|
+
MCP_ACTOR_META_KEY,
|
|
64
|
+
MEMORY_ACTOR_LABEL_MAX_CHARS,
|
|
60
65
|
MEMORY_PROJECT_LABEL_MAX_CHARS,
|
|
61
66
|
MemoryClient,
|
|
62
67
|
MemoryServerError,
|
|
@@ -82,6 +87,7 @@ export {
|
|
|
82
87
|
isSessionOrdinal,
|
|
83
88
|
mergeExtractedEntities,
|
|
84
89
|
normalizeGraphLabel,
|
|
90
|
+
normalizeMemoryActorLabel,
|
|
85
91
|
normalizeNameKey,
|
|
86
92
|
parseListCursorToken,
|
|
87
93
|
projectSearchResponseForMcp,
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readSurface
|
|
3
|
+
} from "./chunk-UESIQ47D.mjs";
|
|
4
|
+
import "./chunk-THLUBOGD.mjs";
|
|
5
|
+
import "./chunk-7TATCSSN.mjs";
|
|
6
|
+
import {
|
|
7
|
+
MEMORY_PROJECT_LABEL_MAX_CHARS,
|
|
8
|
+
TAXONOMY_MAX_PROJECTS,
|
|
9
|
+
normalizeMemoryActorLabel
|
|
10
|
+
} from "./chunk-RWQTBXUC.mjs";
|
|
11
|
+
import "./chunk-HTQBKJTD.mjs";
|
|
12
|
+
import {
|
|
13
|
+
EXIT
|
|
14
|
+
} from "./chunk-4DXEQC6X.mjs";
|
|
15
|
+
|
|
16
|
+
// src/cli/commands/insights.ts
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
var INSIGHTS_SCHEMA_VERSION = 1;
|
|
19
|
+
var metricsSchema = z.object({
|
|
20
|
+
activeEntries: z.number().int().nonnegative(),
|
|
21
|
+
retainedAdditions7d: z.number().int().nonnegative(),
|
|
22
|
+
appliedRecalls: z.number().int().nonnegative(),
|
|
23
|
+
reinforcedEntries: z.number().int().nonnegative(),
|
|
24
|
+
retrievedEntries: z.number().int().nonnegative(),
|
|
25
|
+
retrievals: z.number().int().nonnegative(),
|
|
26
|
+
lastAppliedAt: z.string().nullable(),
|
|
27
|
+
lastRetrievedAt: z.string().nullable()
|
|
28
|
+
});
|
|
29
|
+
var insightsSchema = z.object({
|
|
30
|
+
generatedAt: z.string(),
|
|
31
|
+
scope: z.literal("connected_memory"),
|
|
32
|
+
coverage: z.object({
|
|
33
|
+
retainedAdditions: z.object({
|
|
34
|
+
state: z.enum(["measured", "partial"]),
|
|
35
|
+
trackingSince: z.string().nullable(),
|
|
36
|
+
trackedEntries: z.number().int().nonnegative(),
|
|
37
|
+
totalEntries: z.number().int().nonnegative(),
|
|
38
|
+
reason: z.string().nullable()
|
|
39
|
+
}),
|
|
40
|
+
projectLabels: z.object({ state: z.literal("measured") }),
|
|
41
|
+
retrievalUsage: z.object({ state: z.literal("partial"), reason: z.string() }),
|
|
42
|
+
tokenEfficiency: z.object({ state: z.literal("not_instrumented"), reason: z.string() }),
|
|
43
|
+
contextAccuracy: z.object({ state: z.literal("not_instrumented"), reason: z.string() })
|
|
44
|
+
}),
|
|
45
|
+
summary: z.object({
|
|
46
|
+
activeEntries: z.number().int().nonnegative(),
|
|
47
|
+
observedProjectLabels: z.number().int().nonnegative(),
|
|
48
|
+
retainedAdditions7d: z.number().int().nonnegative().nullable(),
|
|
49
|
+
trackedEntries: z.number().int().nonnegative(),
|
|
50
|
+
appliedRecalls: z.number().int().nonnegative(),
|
|
51
|
+
reinforcedEntries: z.number().int().nonnegative(),
|
|
52
|
+
retrievedEntries: z.number().int().nonnegative(),
|
|
53
|
+
retrievals: z.number().int().nonnegative()
|
|
54
|
+
}),
|
|
55
|
+
projects: z.array(
|
|
56
|
+
metricsSchema.extend({
|
|
57
|
+
label: z.string().min(1).max(MEMORY_PROJECT_LABEL_MAX_CHARS)
|
|
58
|
+
})
|
|
59
|
+
).max(TAXONOMY_MAX_PROJECTS),
|
|
60
|
+
other: metricsSchema.nullable(),
|
|
61
|
+
recentApplied: z.array(
|
|
62
|
+
z.object({
|
|
63
|
+
topic: z.string().min(1).max(MEMORY_PROJECT_LABEL_MAX_CHARS).nullable(),
|
|
64
|
+
project: z.string().min(1).max(MEMORY_PROJECT_LABEL_MAX_CHARS).nullable(),
|
|
65
|
+
at: z.string()
|
|
66
|
+
})
|
|
67
|
+
).max(5)
|
|
68
|
+
});
|
|
69
|
+
var actorSchema = z.string().refine((value) => normalizeMemoryActorLabel(value) === value).nullable().default(null);
|
|
70
|
+
var insightsWithProvenanceSchema = insightsSchema.extend({
|
|
71
|
+
recentApplied: z.array(
|
|
72
|
+
insightsSchema.shape.recentApplied.element.extend({
|
|
73
|
+
writtenBy: actorSchema,
|
|
74
|
+
writtenAt: z.iso.datetime({ offset: true }).nullable().default(null),
|
|
75
|
+
appliedBy: actorSchema
|
|
76
|
+
})
|
|
77
|
+
).max(5)
|
|
78
|
+
});
|
|
79
|
+
async function insightsCommand(opts = {}) {
|
|
80
|
+
const schema = opts.withProvenance === true ? insightsWithProvenanceSchema : insightsSchema;
|
|
81
|
+
const result = await readSurface({
|
|
82
|
+
surface: "insights",
|
|
83
|
+
request: { method: "GET", path: "/api/memory/insights" },
|
|
84
|
+
schema: z.union([
|
|
85
|
+
schema,
|
|
86
|
+
z.object({ success: z.literal(true), data: schema }).transform(({ data }) => data)
|
|
87
|
+
]),
|
|
88
|
+
minimumServiceVersion: "1.19.0",
|
|
89
|
+
keychain: opts.keychain,
|
|
90
|
+
fetchImpl: opts.fetchImpl
|
|
91
|
+
});
|
|
92
|
+
const withIdentity = opts.withIdentity === true;
|
|
93
|
+
if (!result.ok) {
|
|
94
|
+
emit(
|
|
95
|
+
report(result.state, result.endpoint, result.keySource, result.problem, {
|
|
96
|
+
withIdentity,
|
|
97
|
+
credentialFingerprint: result.credentialFingerprint
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
return result.exit;
|
|
101
|
+
}
|
|
102
|
+
emit({
|
|
103
|
+
schemaVersion: INSIGHTS_SCHEMA_VERSION,
|
|
104
|
+
state: "ready",
|
|
105
|
+
endpoint: result.endpoint,
|
|
106
|
+
keySource: "keychain",
|
|
107
|
+
...identityField({ withIdentity, credentialFingerprint: result.credentialFingerprint }),
|
|
108
|
+
...result.data,
|
|
109
|
+
problem: null
|
|
110
|
+
});
|
|
111
|
+
return EXIT.OK;
|
|
112
|
+
}
|
|
113
|
+
function identityField(identity) {
|
|
114
|
+
return identity.withIdentity ? { credentialFingerprint: identity.credentialFingerprint } : {};
|
|
115
|
+
}
|
|
116
|
+
function report(state, endpoint, keySource, problem, identity) {
|
|
117
|
+
return {
|
|
118
|
+
schemaVersion: INSIGHTS_SCHEMA_VERSION,
|
|
119
|
+
state,
|
|
120
|
+
endpoint,
|
|
121
|
+
keySource,
|
|
122
|
+
...identityField(identity),
|
|
123
|
+
generatedAt: null,
|
|
124
|
+
scope: "connected_memory",
|
|
125
|
+
coverage: null,
|
|
126
|
+
summary: null,
|
|
127
|
+
projects: [],
|
|
128
|
+
other: null,
|
|
129
|
+
recentApplied: [],
|
|
130
|
+
problem
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function emit(value) {
|
|
134
|
+
process.stdout.write(`${JSON.stringify(value)}
|
|
135
|
+
`);
|
|
136
|
+
}
|
|
137
|
+
export {
|
|
138
|
+
insightsCommand
|
|
139
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import {
|
|
2
|
+
probeCredentials
|
|
3
|
+
} from "./chunk-S3CX323Z.mjs";
|
|
4
|
+
import {
|
|
5
|
+
BUSY,
|
|
6
|
+
KeychainError,
|
|
7
|
+
getLifecycleKeychain,
|
|
8
|
+
supersedeLogout,
|
|
9
|
+
withLifecycleLock
|
|
10
|
+
} from "./chunk-7TATCSSN.mjs";
|
|
11
|
+
import {
|
|
12
|
+
EXIT
|
|
13
|
+
} from "./chunk-4DXEQC6X.mjs";
|
|
14
|
+
|
|
15
|
+
// src/cli/prompt.ts
|
|
16
|
+
async function readApiKeySecret() {
|
|
17
|
+
if (process.stdin.isTTY) {
|
|
18
|
+
return promptMasked("API key: ");
|
|
19
|
+
}
|
|
20
|
+
return readSingleLineFromStdin();
|
|
21
|
+
}
|
|
22
|
+
async function promptMasked(label) {
|
|
23
|
+
const { stdin, stdout } = process;
|
|
24
|
+
stdout.write(label);
|
|
25
|
+
const hadRawMode = typeof stdin.setRawMode === "function";
|
|
26
|
+
if (!hadRawMode) {
|
|
27
|
+
const value = await readSingleLineFromStdin();
|
|
28
|
+
stdout.write(`${"\u2022".repeat(Math.min(value.length, 80))}
|
|
29
|
+
`);
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const previousEncoding = stdin.readableEncoding;
|
|
34
|
+
stdin.setEncoding("utf8");
|
|
35
|
+
stdin.setRawMode(true);
|
|
36
|
+
stdin.resume();
|
|
37
|
+
let buf = "";
|
|
38
|
+
const cleanup = () => {
|
|
39
|
+
stdin.removeListener("data", onData);
|
|
40
|
+
stdin.removeListener("error", onError);
|
|
41
|
+
stdin.setRawMode(false);
|
|
42
|
+
stdin.pause();
|
|
43
|
+
if (previousEncoding) stdin.setEncoding(previousEncoding);
|
|
44
|
+
};
|
|
45
|
+
const onData = (chunk) => {
|
|
46
|
+
for (const ch of chunk) {
|
|
47
|
+
if (ch === "\n" || ch === "\r") {
|
|
48
|
+
cleanup();
|
|
49
|
+
stdout.write("\n");
|
|
50
|
+
resolve(buf.trim());
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (ch === "") {
|
|
54
|
+
cleanup();
|
|
55
|
+
stdout.write("\n");
|
|
56
|
+
process.exit(130);
|
|
57
|
+
}
|
|
58
|
+
if (ch === "\x7F" || ch === "\b") {
|
|
59
|
+
if (buf.length > 0) {
|
|
60
|
+
buf = buf.slice(0, -1);
|
|
61
|
+
stdout.write("\b \b");
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (ch < " ") {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
buf += ch;
|
|
69
|
+
stdout.write("\u2022");
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const onError = (err) => {
|
|
73
|
+
cleanup();
|
|
74
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
75
|
+
};
|
|
76
|
+
stdin.on("data", onData);
|
|
77
|
+
stdin.on("error", onError);
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async function readSingleLineFromStdin() {
|
|
81
|
+
let buf = "";
|
|
82
|
+
for await (const chunk of process.stdin) {
|
|
83
|
+
buf += chunk.toString("utf8");
|
|
84
|
+
const nl = buf.indexOf("\n");
|
|
85
|
+
if (nl >= 0) return buf.slice(0, nl).trim();
|
|
86
|
+
}
|
|
87
|
+
return buf.trim();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/cli/commands/login.ts
|
|
91
|
+
var DEFAULT_ENDPOINT = "https://memory.api.pyxmate.com";
|
|
92
|
+
async function loginCommand(opts = {}) {
|
|
93
|
+
const provider = opts.keychain ?? getLifecycleKeychain();
|
|
94
|
+
const fetcher = opts.fetchImpl ?? fetch;
|
|
95
|
+
const endpoint = normalizeEndpoint(
|
|
96
|
+
opts.endpoint ?? await readExistingEndpoint(provider) ?? DEFAULT_ENDPOINT
|
|
97
|
+
);
|
|
98
|
+
if (!isHttpUrl(endpoint)) {
|
|
99
|
+
process.stderr.write(`Error: invalid --endpoint \`${endpoint}\` (expected http(s) URL).
|
|
100
|
+
`);
|
|
101
|
+
return EXIT.USAGE;
|
|
102
|
+
}
|
|
103
|
+
let apiKey;
|
|
104
|
+
try {
|
|
105
|
+
apiKey = opts.apiKey?.trim() || await readApiKeySecret();
|
|
106
|
+
} catch (err) {
|
|
107
|
+
process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
108
|
+
`);
|
|
109
|
+
return EXIT.USAGE;
|
|
110
|
+
}
|
|
111
|
+
if (!apiKey) {
|
|
112
|
+
process.stderr.write("Error: API key is empty.\n");
|
|
113
|
+
return EXIT.USAGE;
|
|
114
|
+
}
|
|
115
|
+
const probe = await probeCredentials({ endpoint, apiKey, fetcher });
|
|
116
|
+
if (probe.kind === "invalid") {
|
|
117
|
+
process.stderr.write(
|
|
118
|
+
`Error: API key was rejected by ${endpoint} (HTTP ${probe.status}).
|
|
119
|
+
No credentials were written.
|
|
120
|
+
`
|
|
121
|
+
);
|
|
122
|
+
return EXIT.NOT_LOGGED_IN;
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const written = await withLifecycleLock(provider, async () => {
|
|
126
|
+
await supersedeLogout(provider, endpoint, apiKey);
|
|
127
|
+
await provider.write({ schemaVersion: 1, endpoint, apiKey });
|
|
128
|
+
});
|
|
129
|
+
if (written === BUSY) {
|
|
130
|
+
process.stderr.write(
|
|
131
|
+
"Error: another pyx-mem sign-in or sign-out is in progress. Retry in a moment.\nNo credentials were written.\n"
|
|
132
|
+
);
|
|
133
|
+
return EXIT.BUSY;
|
|
134
|
+
}
|
|
135
|
+
} catch (err) {
|
|
136
|
+
if (err instanceof KeychainError) {
|
|
137
|
+
process.stderr.write(
|
|
138
|
+
`Error: ${err.message}
|
|
139
|
+
${err.guidance}
|
|
140
|
+
No credentials were written. pyx-mem does not write plaintext token files.
|
|
141
|
+
`
|
|
142
|
+
);
|
|
143
|
+
return err.exit;
|
|
144
|
+
}
|
|
145
|
+
throw err;
|
|
146
|
+
}
|
|
147
|
+
if (probe.kind === "unreachable") {
|
|
148
|
+
process.stdout.write(
|
|
149
|
+
`Stored credentials for ${endpoint}. Warning: validation probe failed (${probe.reason}). Run: pyx-mem doctor
|
|
150
|
+
`
|
|
151
|
+
);
|
|
152
|
+
} else {
|
|
153
|
+
process.stdout.write(`Logged in to ${endpoint}. Run: pyx-mem doctor
|
|
154
|
+
`);
|
|
155
|
+
}
|
|
156
|
+
return EXIT.OK;
|
|
157
|
+
}
|
|
158
|
+
async function readExistingEndpoint(provider) {
|
|
159
|
+
try {
|
|
160
|
+
const creds = await provider.read();
|
|
161
|
+
return creds?.endpoint ?? null;
|
|
162
|
+
} catch {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function normalizeEndpoint(input) {
|
|
167
|
+
return input.replace(/\/+$/, "");
|
|
168
|
+
}
|
|
169
|
+
function isHttpUrl(value) {
|
|
170
|
+
try {
|
|
171
|
+
const u = new URL(value);
|
|
172
|
+
return u.protocol === "http:" || u.protocol === "https:";
|
|
173
|
+
} catch {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export {
|
|
178
|
+
loginCommand
|
|
179
|
+
};
|