neotoma 0.22.2 → 0.23.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/README.md +2 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +58 -54
- package/dist/actions.js.map +1 -1
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +79 -3
- package/dist/config.js.map +1 -1
- package/dist/docs/developer/mcp/compact_instructions.md +2 -0
- package/dist/docs/developer/mcp/instructions.md +30 -3
- package/dist/docs/developer/mcp/proxy.md +6 -4
- package/dist/docs/foundation/core_identity.md +45 -4
- package/dist/docs/foundation/developer_release_principles.md +4 -1
- package/dist/docs/foundation/layered_architecture.md +10 -0
- package/dist/docs/foundation/mmry_comparison.md +4 -4
- package/dist/docs/foundation/problem_statement.md +3 -1
- package/dist/docs/foundation/product_positioning.md +21 -17
- package/dist/docs/foundation/redlines.md +21 -2
- package/dist/docs/foundation/scope_decisions.md +32 -10
- package/dist/docs/getting_started/what_is_neotoma.md +1 -1
- package/dist/docs/icp/icp_from_functionality.md +4 -2
- package/dist/docs/icp/icp_reconciliation.md +12 -1
- package/dist/docs/operations/configuration.md +54 -42
- package/dist/docs/reference/error_codes.md +27 -0
- package/dist/docs/specs/MCP_SPEC.md +1 -1
- package/dist/docs/subsystems/conflict_resolution.md +11 -6
- package/dist/docs/subsystems/observation_architecture.md +2 -2
- package/dist/docs/subsystems/reducer.md +29 -3
- package/dist/docs/subsystems/schema_registry.md +11 -0
- package/dist/docs/testing/automated_test_catalog.md +20 -9
- package/dist/mcp_http_session.d.ts +51 -0
- package/dist/mcp_http_session.d.ts.map +1 -0
- package/dist/mcp_http_session.js +173 -0
- package/dist/mcp_http_session.js.map +1 -0
- package/dist/reducers/observation_reducer.d.ts.map +1 -1
- package/dist/reducers/observation_reducer.js +24 -6
- package/dist/reducers/observation_reducer.js.map +1 -1
- package/dist/server.d.ts +31 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +189 -16
- package/dist/server.js.map +1 -1
- package/dist/services/field_canonicalization.d.ts +1 -0
- package/dist/services/field_canonicalization.d.ts.map +1 -1
- package/dist/services/field_canonicalization.js +15 -9
- package/dist/services/field_canonicalization.js.map +1 -1
- package/dist/services/interpretation.d.ts +2 -0
- package/dist/services/interpretation.d.ts.map +1 -1
- package/dist/services/interpretation.js +2 -1
- package/dist/services/interpretation.js.map +1 -1
- package/dist/services/schema_definitions.d.ts.map +1 -1
- package/dist/services/schema_definitions.js +108 -0
- package/dist/services/schema_definitions.js.map +1 -1
- package/dist/services/schema_registry.d.ts +16 -1
- package/dist/services/schema_registry.d.ts.map +1 -1
- package/dist/services/schema_registry.js.map +1 -1
- package/dist/services/skills/instance_skills.d.ts +137 -0
- package/dist/services/skills/instance_skills.d.ts.map +1 -0
- package/dist/services/skills/instance_skills.js +381 -0
- package/dist/services/skills/instance_skills.js.map +1 -0
- package/dist/services/store_warning_rule.d.ts +97 -0
- package/dist/services/store_warning_rule.d.ts.map +1 -0
- package/dist/services/store_warning_rule.js +175 -0
- package/dist/services/store_warning_rule.js.map +1 -0
- package/dist/tool_definitions.js +1 -1
- package/dist/tool_definitions.js.map +1 -1
- package/docs/developer/mcp/instructions.md +30 -3
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -197,9 +197,9 @@ Neotoma is primarily for developers building and operating AI agents who need a
|
|
|
197
197
|
|
|
198
198
|
Two further audiences follow from the same code: individuals running a personal cross-assistant memory (the built-in types are personal-information shaped, and the single-user SQLite plus Inspector path serves one person across assistants), and operators of a shared or hosted instance (OAuth, hardware-attested agent identity, per-agent grants, guest submission, peer federation, and Docker or Fly deploy targets).
|
|
199
199
|
|
|
200
|
-
It is not aimed at casual note-taking, PKM/Obsidian-style human-driven knowledge bases, or users who need a
|
|
200
|
+
It is not aimed at casual note-taking, PKM/Obsidian-style human-driven knowledge bases, or users who need a fully hosted product with nothing running on their own machine — Neotoma is local-first by design, and that part is not a temporary state. Installation is: today it is npm and the CLI, and a guided installation is intended but not yet available. If today's install path is what stands between you and trying it, that is our problem to fix, not a sign you are the wrong user.
|
|
201
201
|
|
|
202
|
-
Full profile: [ICP from functionality](docs/icp/icp_from_functionality.md).
|
|
202
|
+
Full profile: [ICP from functionality](docs/icp/icp_from_functionality.md) — the canonical public ICP statement. For how it relates to the other ICP documents and which is canonical for which surface, see [ICP reconciliation](docs/icp/icp_reconciliation.md).
|
|
203
203
|
|
|
204
204
|
## Status
|
|
205
205
|
|
package/dist/actions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
|
package/dist/actions.js
CHANGED
|
@@ -21,6 +21,7 @@ import { attributionContext } from "./middleware/attribution_context.js";
|
|
|
21
21
|
import { dbAbortContext } from "./middleware/db_abort_context.js";
|
|
22
22
|
import { aauthAdmission, getAAuthAdmissionFromRequest } from "./middleware/aauth_admission.js";
|
|
23
23
|
import { buildSessionInfo, normalizeSessionOrigin } from "./services/session_info.js";
|
|
24
|
+
import { evaluateStoreWarningRule } from "./services/store_warning_rule.js";
|
|
24
25
|
import { probeReadiness } from "./services/readiness.js";
|
|
25
26
|
import { AttributionPolicyError, enforceAttributionPolicy } from "./services/attribution_policy.js";
|
|
26
27
|
import { OverridePolicyViolationError } from "./services/override_validation.js";
|
|
@@ -38,9 +39,8 @@ import { initServerKeys } from "./services/encryption_service.js";
|
|
|
38
39
|
import { storeRawContent, downloadRawContent, resolveLocalSourceFilePath, SourceFileNotFoundError, } from "./services/raw_storage.js";
|
|
39
40
|
import { attachSourceLabelsToObservations } from "./services/observation_source_label.js";
|
|
40
41
|
import { isFilesystemLocalToCaller, buildFilePathServerLocalError, decodeFileContent, FileInputError, } from "./services/file_input_diagnostics.js";
|
|
41
|
-
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
42
42
|
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
43
|
-
import {
|
|
43
|
+
import { adoptRecoveredSessionId, completeSyntheticMcpHandshake, mintMcpHttpSession, unknownSessionJsonRpcBody, } from "./mcp_http_session.js";
|
|
44
44
|
import { logger } from "./utils/logger.js";
|
|
45
45
|
import { formatRequestLogLine } from "./utils/safe_request_log_format.js";
|
|
46
46
|
import { emitEntitySnapshotChange, emitObservationCreated, shallowFieldsChanged, } from "./events/substrate_store_emit.js";
|
|
@@ -1703,59 +1703,59 @@ app.all("/mcp", async (req, res) => {
|
|
|
1703
1703
|
let serverInstance = sessionId
|
|
1704
1704
|
? mcpServerInstances.get(sessionId)
|
|
1705
1705
|
: undefined;
|
|
1706
|
+
const mcpSessionMaps = {
|
|
1707
|
+
transports: mcpTransports,
|
|
1708
|
+
servers: mcpServerInstances,
|
|
1709
|
+
};
|
|
1710
|
+
const rpcIdForUnknownSession = req.body &&
|
|
1711
|
+
typeof req.body === "object" &&
|
|
1712
|
+
!Array.isArray(req.body) &&
|
|
1713
|
+
"id" in req.body &&
|
|
1714
|
+
(typeof req.body.id === "string" ||
|
|
1715
|
+
typeof req.body.id === "number")
|
|
1716
|
+
? req.body.id
|
|
1717
|
+
: null;
|
|
1706
1718
|
if (!transport && req.method === "POST" && isInitializeRequest(req.body)) {
|
|
1707
|
-
//
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
if (transport?.sessionId) {
|
|
1731
|
-
mcpTransports.delete(transport.sessionId);
|
|
1732
|
-
mcpServerInstances.delete(transport.sessionId);
|
|
1733
|
-
logger.error(`[MCP HTTP] Session closed: ${transport.sessionId}`);
|
|
1719
|
+
// Client-driven initialize: mint a fresh session (ignores any stale session id).
|
|
1720
|
+
const minted = await mintMcpHttpSession(req, mcpSessionMaps, resolvePublicAppOriginFromRequest);
|
|
1721
|
+
transport = minted.transport;
|
|
1722
|
+
serverInstance = minted.serverInstance;
|
|
1723
|
+
}
|
|
1724
|
+
else if (!transport &&
|
|
1725
|
+
req.method === "POST" &&
|
|
1726
|
+
typeof sessionId === "string" &&
|
|
1727
|
+
sessionId.length > 0 &&
|
|
1728
|
+
req.body &&
|
|
1729
|
+
typeof req.body === "object" &&
|
|
1730
|
+
!isInitializeRequest(req.body)) {
|
|
1731
|
+
// Recover-in-place (neotoma#2100): authenticated POST with an unknown session
|
|
1732
|
+
// id and a non-initialize body mints a new transport, completes a server-side
|
|
1733
|
+
// initialize handshake, then serves the original call under the new session id.
|
|
1734
|
+
// Auth already passed above — do not mint on 401 paths.
|
|
1735
|
+
try {
|
|
1736
|
+
const minted = await mintMcpHttpSession(req, mcpSessionMaps, resolvePublicAppOriginFromRequest);
|
|
1737
|
+
const handshakeOk = await completeSyntheticMcpHandshake(minted.transport);
|
|
1738
|
+
const recoveredSessionId = minted.transport.sessionId;
|
|
1739
|
+
if (!handshakeOk || !recoveredSessionId) {
|
|
1740
|
+
logger.warn(`[MCP HTTP] Recover-in-place handshake failed for stale Mcp-Session-Id (first 8 chars): ${sessionId.slice(0, 8)}...`);
|
|
1741
|
+
return res.status(404).json(unknownSessionJsonRpcBody(rpcIdForUnknownSession));
|
|
1734
1742
|
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1743
|
+
transport = minted.transport;
|
|
1744
|
+
serverInstance = minted.serverInstance;
|
|
1745
|
+
adoptRecoveredSessionId(req, recoveredSessionId);
|
|
1746
|
+
logger.info(`[MCP HTTP] Recovered unknown/expired session (stale first 8: ${sessionId.slice(0, 8)}...) → new session ${recoveredSessionId.slice(0, 8)}...`);
|
|
1747
|
+
}
|
|
1748
|
+
catch (recoverError) {
|
|
1749
|
+
logger.warn(`[MCP HTTP] Recover-in-place failed for stale Mcp-Session-Id (first 8 chars): ${sessionId.slice(0, 8)}...`, recoverError);
|
|
1750
|
+
return res.status(404).json(unknownSessionJsonRpcBody(rpcIdForUnknownSession));
|
|
1751
|
+
}
|
|
1738
1752
|
}
|
|
1739
1753
|
else if (!transport) {
|
|
1740
|
-
const rpcId = req.body &&
|
|
1741
|
-
typeof req.body === "object" &&
|
|
1742
|
-
!Array.isArray(req.body) &&
|
|
1743
|
-
"id" in req.body &&
|
|
1744
|
-
(typeof req.body.id === "string" ||
|
|
1745
|
-
typeof req.body.id === "number")
|
|
1746
|
-
? req.body.id
|
|
1747
|
-
: null;
|
|
1748
1754
|
const hadSessionHeader = typeof sessionId === "string" && sessionId.length > 0;
|
|
1749
1755
|
if (hadSessionHeader) {
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
error: {
|
|
1754
|
-
code: -32001,
|
|
1755
|
-
message: "Not Found: MCP session is unknown or expired on this API instance. The client should re-initialize by sending a new InitializeRequest without a session ID. If you run multiple replicas, enable sticky sessions for POST /mcp (or route /mcp to a single instance).",
|
|
1756
|
-
},
|
|
1757
|
-
id: rpcId,
|
|
1758
|
-
});
|
|
1756
|
+
// GET/DELETE unknown session, or POST only after mint/handshake failure above.
|
|
1757
|
+
logger.warn(`[MCP HTTP] Unknown or expired Mcp-Session-Id (first 8 chars): ${sessionId.slice(0, 8)}... server restart or stale client state`);
|
|
1758
|
+
return res.status(404).json(unknownSessionJsonRpcBody(rpcIdForUnknownSession));
|
|
1759
1759
|
}
|
|
1760
1760
|
return res.status(400).json({
|
|
1761
1761
|
jsonrpc: "2.0",
|
|
@@ -1763,7 +1763,7 @@ app.all("/mcp", async (req, res) => {
|
|
|
1763
1763
|
code: -32000,
|
|
1764
1764
|
message: "Bad Request: No MCP session on this request. Send an initialize JSON-RPC message first, then include the mcp-session-id response header on every subsequent POST.",
|
|
1765
1765
|
},
|
|
1766
|
-
id:
|
|
1766
|
+
id: rpcIdForUnknownSession,
|
|
1767
1767
|
});
|
|
1768
1768
|
}
|
|
1769
1769
|
// Thread AAuth / clientInfo fallback attribution into the server for
|
|
@@ -6658,11 +6658,15 @@ export async function storeStructuredForApi(params) {
|
|
|
6658
6658
|
const storeWarningRules = schemaDef?.store_warnings;
|
|
6659
6659
|
if (storeWarningRules?.length) {
|
|
6660
6660
|
for (const rule of storeWarningRules) {
|
|
6661
|
-
|
|
6662
|
-
|
|
6661
|
+
// Never inline the condition check here: a rule shape the evaluator
|
|
6662
|
+
// does not understand must yield a warning, never a throw. A thrown
|
|
6663
|
+
// TypeError from an advisory rule surfaced as DB_QUERY_FAILED and
|
|
6664
|
+
// made whole entity types unwritable (#2165, #2170).
|
|
6665
|
+
const evaluation = evaluateStoreWarningRule(rule, r.fields);
|
|
6666
|
+
if (evaluation.fired) {
|
|
6663
6667
|
schemaStoreWarnings.push({
|
|
6664
|
-
code:
|
|
6665
|
-
message:
|
|
6668
|
+
code: evaluation.code,
|
|
6669
|
+
message: evaluation.message,
|
|
6666
6670
|
observation_index: r.observation_index,
|
|
6667
6671
|
entity_type: r.entity_type,
|
|
6668
6672
|
entity_id: r.entity_id,
|