neotoma 0.9.0 → 0.10.0

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.
Files changed (199) hide show
  1. package/README.md +11 -7
  2. package/dist/actions.d.ts +10 -5
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +144 -15
  5. package/dist/actions.js.map +1 -1
  6. package/dist/cli/hooks.d.ts +4 -4
  7. package/dist/cli/hooks.js +4 -4
  8. package/dist/cli/hooks_detect.d.ts.map +1 -1
  9. package/dist/cli/hooks_detect.js +16 -9
  10. package/dist/cli/hooks_detect.js.map +1 -1
  11. package/dist/cli/index.d.ts.map +1 -1
  12. package/dist/cli/index.js +87 -15
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/cli/mcp_config_scan.d.ts +10 -0
  15. package/dist/cli/mcp_config_scan.d.ts.map +1 -1
  16. package/dist/cli/mcp_config_scan.js +85 -5
  17. package/dist/cli/mcp_config_scan.js.map +1 -1
  18. package/dist/cli/setup.d.ts +1 -0
  19. package/dist/cli/setup.d.ts.map +1 -1
  20. package/dist/cli/setup.js +71 -1
  21. package/dist/cli/setup.js.map +1 -1
  22. package/dist/core/operations.d.ts +9 -0
  23. package/dist/core/operations.d.ts.map +1 -1
  24. package/dist/core/operations.js +3 -0
  25. package/dist/core/operations.js.map +1 -1
  26. package/dist/inspector/assets/{Combination-CujEssa-.js → Combination-BP0-kPZX.js} +1 -1
  27. package/dist/inspector/assets/{agent_badge-Cy2xdM19.js → agent_badge-BZT-JO2h.js} +1 -1
  28. package/dist/inspector/assets/agent_detail-BGMLF8-n.js +1 -0
  29. package/dist/inspector/assets/{agent_filter-9Y5V9TSY.js → agent_filter-DMC4CzhM.js} +1 -1
  30. package/dist/inspector/assets/agent_grant_detail-Brqy5K7M.js +1 -0
  31. package/dist/inspector/assets/{agent_grant_form-DjoTByJj.js → agent_grant_form-BLDkUh1Y.js} +1 -1
  32. package/dist/inspector/assets/agent_grants-B2StunRb.js +1 -0
  33. package/dist/inspector/assets/agents-lYmKs-fG.js +1 -0
  34. package/dist/inspector/assets/{arrow-left-Bxer0ezV.js → arrow-left-D1s7DOns.js} +1 -1
  35. package/dist/inspector/assets/{attribution_card-C48p_bBB.js → attribution_card-D-bp008l.js} +1 -1
  36. package/dist/inspector/assets/attribution_summary-Cs9Ccvt3.js +1 -0
  37. package/dist/inspector/assets/card-Btqgzh6p.js +1 -0
  38. package/dist/inspector/assets/{check-DN6vjWJ7.js → check-DAyRtq63.js} +1 -1
  39. package/dist/inspector/assets/{checkbox-DuNHytV3.js → checkbox-BrpwHaRo.js} +1 -1
  40. package/dist/inspector/assets/{chevron-down-BGEwSYyI.js → chevron-down-CCk_jMPN.js} +1 -1
  41. package/dist/inspector/assets/{chevron-right-D5OasTAw.js → chevron-right-C9NbdZtC.js} +1 -1
  42. package/dist/inspector/assets/compliance-BHiHtgfg.js +1 -0
  43. package/dist/inspector/assets/{confirm-dialog-2InCKZky.js → confirm-dialog-BcxtVONz.js} +2 -2
  44. package/dist/inspector/assets/conversation_common-Dw5j3QuN.js +1 -0
  45. package/dist/inspector/assets/conversation_detail-BR_rBMFV.js +1 -0
  46. package/dist/inspector/assets/{copy_id_button-CoFHQieu.js → copy_id_button-CyjfY7dx.js} +1 -1
  47. package/dist/inspector/assets/{corrections-C-GqSum_.js → corrections-DFExbcsm.js} +1 -1
  48. package/dist/inspector/assets/{dashboard-CB0ynQ0H.js → dashboard-CxnNRphy.js} +34 -34
  49. package/dist/inspector/assets/{data-table-Nyryp-JO.js → data-table-CazqdSem.js} +1 -1
  50. package/dist/inspector/assets/{dialog-DS3fUAm1.js → dialog-X5X7rLah.js} +1 -1
  51. package/dist/inspector/assets/{dropdown-menu-Cypcul5-.js → dropdown-menu-CmZjxUWM.js} +1 -1
  52. package/dist/inspector/assets/entities-l6icu6fc.js +1 -0
  53. package/dist/inspector/assets/entity_detail-daoxB-h1.js +17 -0
  54. package/dist/inspector/assets/{entity_link-DujmD1Yr.js → entity_link-DtMv__WC.js} +1 -1
  55. package/dist/inspector/assets/{external-link-C4V3VgZf.js → external-link-BBoTnT-P.js} +1 -1
  56. package/dist/inspector/assets/feedback-DeFhdWId.js +35 -0
  57. package/dist/inspector/assets/graph_explorer-BvicLJEW.js +23 -0
  58. package/dist/inspector/assets/index-B2zHigxN.js +199 -0
  59. package/dist/inspector/assets/{index-Dqo226iA.js → index-Czej0Y93.js} +1 -1
  60. package/dist/inspector/assets/{index-ZmrnhI6W.js → index-D5i6AEXI.js} +1 -1
  61. package/dist/inspector/assets/{index-Bx2zn3Hd.js → index-DJuPlRtP.js} +1 -1
  62. package/dist/inspector/assets/index-Df569_c9.css +1 -0
  63. package/dist/inspector/assets/interpretations-D9gWqVhy.js +1 -0
  64. package/dist/inspector/assets/interpretations-E0sIBf-l.js +1 -0
  65. package/dist/inspector/assets/{json_viewer-BkvSv8xS.js → json_viewer-ojLDPDtf.js} +1 -1
  66. package/dist/inspector/assets/{label-CbDLvpxl.js → label-DWyQNl4E.js} +1 -1
  67. package/dist/inspector/assets/live_relative_time-DzLnsA9y.js +1 -0
  68. package/dist/inspector/assets/observations-Ds0kFmaM.js +1 -0
  69. package/dist/inspector/assets/{page_shell-_vozYBwF.js → page_shell-C-4AKr0Y.js} +1 -1
  70. package/dist/inspector/assets/{pagination-aHI1LrUp.js → pagination-lSg-a95h.js} +1 -1
  71. package/dist/inspector/assets/{plus-CPWsVXx9.js → plus-CQMoR71F.js} +1 -1
  72. package/dist/inspector/assets/query_loading-BFETHugg.js +1 -0
  73. package/dist/inspector/assets/query_refresh_indicator-Bewf0Dj1.js +1 -0
  74. package/dist/inspector/assets/{recent_activity-DOx6FPz3.js → recent_activity-Csh_YraY.js} +2 -2
  75. package/dist/inspector/assets/recent_conversations-CBengQjb.js +1 -0
  76. package/dist/inspector/assets/recent_conversations-MKmxYevd.js +1 -0
  77. package/dist/inspector/assets/recent_records_feed-CCrBRfkG.js +1 -0
  78. package/dist/inspector/assets/relationship_detail-CUz_GhPI.js +1 -0
  79. package/dist/inspector/assets/relationships-Ulajo16_.js +1 -0
  80. package/dist/inspector/assets/{relationships-DnfqeglP.js → relationships-Z9ALu9Oa.js} +1 -1
  81. package/dist/inspector/assets/{sandbox-CHH6I9Ww.js → sandbox-CfD5QvC5.js} +1 -1
  82. package/dist/inspector/assets/schema_detail-B1W8rbzV.js +11 -0
  83. package/dist/inspector/assets/schemas-DVlEFPuf.js +5 -0
  84. package/dist/inspector/assets/search-BccQXyTN.js +1 -0
  85. package/dist/inspector/assets/{select-MlFuilHt.js → select-Dv1QM6oO.js} +1 -1
  86. package/dist/inspector/assets/settings-B4U8tFYI.js +1 -0
  87. package/dist/inspector/assets/source_detail-B1JlZBBx.js +17 -0
  88. package/dist/inspector/assets/{source_link-B0ZU_1AG.js → source_link-p8KzI1os.js} +1 -1
  89. package/dist/inspector/assets/sources-B5ssCN-s.js +9 -0
  90. package/dist/inspector/assets/{switch-DXGlOHG4.js → switch-BPI_y_Z3.js} +1 -1
  91. package/dist/inspector/assets/{tabs-C0mWq9S1.js → tabs-HUG-sxc2.js} +1 -1
  92. package/dist/inspector/assets/{textarea-wLUG8kv6.js → textarea-DNz92WE1.js} +1 -1
  93. package/dist/inspector/assets/timeline-DRqxyQUF.js +1 -0
  94. package/dist/inspector/assets/{timeline-DXEE4O4U.js → timeline-HN2EoMGt.js} +1 -1
  95. package/dist/inspector/assets/timeline_event_detail-DbA5EpiN.js +1 -0
  96. package/dist/inspector/assets/{trash-2-DWBXKl-O.js → trash-2-BAfHKatZ.js} +1 -1
  97. package/dist/inspector/assets/turn_detail-BUHzIhWX.js +1 -0
  98. package/dist/inspector/assets/turns-ADRkuqKL.js +1 -0
  99. package/dist/inspector/assets/use_agents-CTZrpsvS.js +1 -0
  100. package/dist/inspector/assets/use_entities-BEhy6HWn.js +1 -0
  101. package/dist/inspector/assets/use_interpretations-CKN63UxX.js +1 -0
  102. package/dist/inspector/assets/{use_mutations-C-WJL341.js → use_mutations-B4y1qmV5.js} +1 -1
  103. package/dist/inspector/assets/use_recent_conversations-CIBgmz9B.js +1 -0
  104. package/dist/inspector/assets/use_relationships-Cl-o_7u6.js +1 -0
  105. package/dist/inspector/assets/use_schemas-Bl11WNgP.js +1 -0
  106. package/dist/inspector/assets/use_sources-DkJZZBDp.js +1 -0
  107. package/dist/inspector/assets/use_stats-Cn1a3yt-.js +1 -0
  108. package/dist/inspector/assets/use_timeline-DZkbwA-7.js +1 -0
  109. package/dist/inspector/assets/use_turns-BHfaal9v.js +1 -0
  110. package/dist/inspector/index.html +2 -2
  111. package/dist/mcp_dev_shim.d.ts +17 -0
  112. package/dist/mcp_dev_shim.d.ts.map +1 -0
  113. package/dist/mcp_dev_shim.js +324 -0
  114. package/dist/mcp_dev_shim.js.map +1 -0
  115. package/dist/mcp_server_card.js +1 -1
  116. package/dist/server.d.ts +1 -0
  117. package/dist/server.d.ts.map +1 -1
  118. package/dist/server.js +87 -16
  119. package/dist/server.js.map +1 -1
  120. package/dist/services/compliance/scorecard.d.ts +35 -73
  121. package/dist/services/compliance/scorecard.d.ts.map +1 -1
  122. package/dist/services/compliance/scorecard.js +234 -270
  123. package/dist/services/compliance/scorecard.js.map +1 -1
  124. package/dist/services/conversation_turn.d.ts +38 -0
  125. package/dist/services/conversation_turn.d.ts.map +1 -1
  126. package/dist/services/conversation_turn.js +128 -5
  127. package/dist/services/conversation_turn.js.map +1 -1
  128. package/dist/services/mcp_oauth.d.ts +9 -7
  129. package/dist/services/mcp_oauth.d.ts.map +1 -1
  130. package/dist/services/mcp_oauth.js +170 -13
  131. package/dist/services/mcp_oauth.js.map +1 -1
  132. package/dist/services/recent_conversations.d.ts +7 -0
  133. package/dist/services/recent_conversations.d.ts.map +1 -1
  134. package/dist/services/recent_conversations.js +89 -14
  135. package/dist/services/recent_conversations.js.map +1 -1
  136. package/dist/services/root_landing/site_nav.d.ts.map +1 -1
  137. package/dist/services/root_landing/site_nav.js +8 -3
  138. package/dist/services/root_landing/site_nav.js.map +1 -1
  139. package/dist/services/schema_definitions.d.ts.map +1 -1
  140. package/dist/services/schema_definitions.js +29 -4
  141. package/dist/services/schema_definitions.js.map +1 -1
  142. package/dist/services/schema_registry.d.ts.map +1 -1
  143. package/dist/services/schema_registry.js +28 -2
  144. package/dist/services/schema_registry.js.map +1 -1
  145. package/dist/shared/action_schemas.d.ts +163 -16
  146. package/dist/shared/action_schemas.d.ts.map +1 -1
  147. package/dist/shared/action_schemas.js +28 -10
  148. package/dist/shared/action_schemas.js.map +1 -1
  149. package/dist/shared/contract_mappings.d.ts.map +1 -1
  150. package/dist/shared/contract_mappings.js +23 -0
  151. package/dist/shared/contract_mappings.js.map +1 -1
  152. package/dist/shared/openapi_types.d.ts +242 -16
  153. package/dist/shared/openapi_types.d.ts.map +1 -1
  154. package/dist/tool_definitions.d.ts +1 -1
  155. package/dist/tool_definitions.d.ts.map +1 -1
  156. package/dist/tool_definitions.js +6 -0
  157. package/dist/tool_definitions.js.map +1 -1
  158. package/openapi.yaml +287 -28
  159. package/package.json +4 -1
  160. package/dist/inspector/assets/agent_detail-34_3u913.js +0 -1
  161. package/dist/inspector/assets/agent_grant_detail-fs0DKTd5.js +0 -1
  162. package/dist/inspector/assets/agent_grants-DUtqBZkK.js +0 -1
  163. package/dist/inspector/assets/agents-CIUBwgRT.js +0 -1
  164. package/dist/inspector/assets/attribution_summary-B7KAy0mn.js +0 -1
  165. package/dist/inspector/assets/card-Bz-JK2L1.js +0 -1
  166. package/dist/inspector/assets/compliance-B7gRLVKA.js +0 -1
  167. package/dist/inspector/assets/entities-B1ZBrker.js +0 -1
  168. package/dist/inspector/assets/entity_detail-DlsbmdeN.js +0 -17
  169. package/dist/inspector/assets/feedback-BQFBT-KP.js +0 -35
  170. package/dist/inspector/assets/graph_explorer-Ckir-IQl.js +0 -23
  171. package/dist/inspector/assets/index-ClljmJBP.js +0 -199
  172. package/dist/inspector/assets/index-NU89qCAK.css +0 -1
  173. package/dist/inspector/assets/interpretations-B7wb65mL.js +0 -1
  174. package/dist/inspector/assets/interpretations-CUaxEt1j.js +0 -1
  175. package/dist/inspector/assets/observations-lXPbAxMw.js +0 -1
  176. package/dist/inspector/assets/recent_conversations-CgG1tewt.js +0 -1
  177. package/dist/inspector/assets/recent_records_feed-CQN5zaI8.js +0 -1
  178. package/dist/inspector/assets/relationship_detail-LsEDdRi1.js +0 -1
  179. package/dist/inspector/assets/relationships-bLyNDRTv.js +0 -1
  180. package/dist/inspector/assets/schema_detail-DnkpfNNX.js +0 -11
  181. package/dist/inspector/assets/schemas-CvrYW_Oj.js +0 -5
  182. package/dist/inspector/assets/search-Bj5zl6Sn.js +0 -1
  183. package/dist/inspector/assets/settings-D5tFC9Ho.js +0 -1
  184. package/dist/inspector/assets/source_detail-C2OkmsHz.js +0 -17
  185. package/dist/inspector/assets/sources-BDnp2oAz.js +0 -9
  186. package/dist/inspector/assets/timeline-LjwviNGU.js +0 -1
  187. package/dist/inspector/assets/timeline_event_detail-C0M5GhTm.js +0 -1
  188. package/dist/inspector/assets/turn_detail-DXCnGJQ4.js +0 -1
  189. package/dist/inspector/assets/turns-C6blPs3y.js +0 -1
  190. package/dist/inspector/assets/use_agents-Cl-ZvBxZ.js +0 -1
  191. package/dist/inspector/assets/use_entities-DtfxOiM5.js +0 -1
  192. package/dist/inspector/assets/use_interpretations-usFKH4p9.js +0 -1
  193. package/dist/inspector/assets/use_recent_conversations-CcGV91zn.js +0 -1
  194. package/dist/inspector/assets/use_relationships-Ci7lTjAZ.js +0 -1
  195. package/dist/inspector/assets/use_schemas-D_uXgmEv.js +0 -1
  196. package/dist/inspector/assets/use_sources-CFY0i0dw.js +0 -1
  197. package/dist/inspector/assets/use_stats-DBERXcdx.js +0 -1
  198. package/dist/inspector/assets/use_timeline-BqlPwIlB.js +0 -1
  199. package/dist/inspector/assets/use_turns-vQjPAKeW.js +0 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Your agents forget. Neotoma makes them remember.
4
4
 
5
- Versioned records — contacts, tasks, decisions, finances — that persist across Claude, Cursor, ChatGPT, OpenClaw, and every agent you run. Open-source. Local-first. Deterministic. MIT licensed.
5
+ Versioned records — contacts, tasks, decisions, finances — that persist across Claude, Cursor, ChatGPT, OpenClaw, IronClaw, and every agent you run. Open-source. Local-first. Deterministic. MIT licensed.
6
6
 
7
7
  **[neotoma.io](https://neotoma.io)** · **[Evaluate](https://neotoma.io/evaluate)** · **[Install](https://neotoma.io/install)** · **[Documentation](https://neotoma.io/docs)**
8
8
 
@@ -38,6 +38,7 @@ graph LR
38
38
  MCP --> ChatGPT
39
39
  MCP --> Cursor
40
40
  MCP --> OpenClaw
41
+ MCP --> IronClaw
41
42
  ```
42
43
 
43
44
  - **Deterministic.** Same observations always produce the same versioned entity snapshots. No ordering sensitivity.
@@ -51,7 +52,7 @@ graph LR
51
52
  | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
52
53
  | **Privacy-first** | Your data stays local. Never used for training. User-controlled storage, optional encryption at rest. Full export and deletion control. |
53
54
  | **Deterministic** | Same input always produces same output. Schema-first extraction, hash-based entity IDs, full provenance. No silent mutation. |
54
- | **Cross-platform** | One memory graph across Claude, ChatGPT, Cursor, OpenClaw, Codex, and CLI. MCP-based access. No platform lock-in. Works alongside native memory. |
55
+ | **Cross-platform** | One memory graph across Claude, ChatGPT, Cursor, OpenClaw, IronClaw, Codex, and CLI. MCP-based access. No platform lock-in. Works alongside native memory. |
55
56
 
56
57
  ## State guarantees
57
58
 
@@ -121,14 +122,14 @@ Three interfaces. One state invariant. Every interface provides the same determi
121
122
  | Interface | Description |
122
123
  | -------------- | ------------------------------------------------------------------------------------------------------------------------------ |
123
124
  | **REST API** | Full HTTP interface for application integration. Entities, relationships, observations, schema, timeline, and version history. |
124
- | **MCP Server** | Model Context Protocol for Claude, ChatGPT, Cursor, OpenClaw, Codex, and more. Agents store and retrieve state through structured tool calls. |
125
+ | **MCP Server** | Model Context Protocol for Claude, ChatGPT, Cursor, OpenClaw, IronClaw, Codex, and more. Agents store and retrieve state through structured tool calls. |
125
126
  | **CLI** | Command-line for scripting and direct access. Inspect entities, replay timelines, and manage state from the terminal. |
126
127
 
127
128
  All three map to the same OpenAPI-backed operations. MCP tool calls log the equivalent CLI invocation.
128
129
 
129
130
  ## Who this is for
130
131
 
131
- People building a personal operating system with AI agents across their life — wiring together tools like Claude, Cursor, ChatGPT, OpenClaw, and custom scripts to manage contacts, tasks, finances, code, content, and other domains. The same person operates their agents, builds new pipelines, and debugs state drift. These are three operational modes, not separate personas:
132
+ People building a personal operating system with AI agents across their life — wiring together tools like Claude, Cursor, ChatGPT, OpenClaw, IronClaw, and custom scripts to manage contacts, tasks, finances, code, content, and other domains. The same person operates their agents, builds new pipelines, and debugs state drift. These are three operational modes, not separate personas:
132
133
 
133
134
  | Mode | What you're doing | The tax you pay without Neotoma | What you get back |
134
135
  | ---- | ----------------- | ------------------------------- | ----------------- |
@@ -155,7 +156,7 @@ Schema is flexible — store any entity type with whatever fields the message im
155
156
 
156
157
  ## Current status
157
158
 
158
- **Version:** v0.4.2 · **Releases:** 13 · **License:** MIT
159
+ **Version:** v0.9.1 · **Releases:** 26 · **License:** MIT
159
160
 
160
161
  ### What is guaranteed (even in preview)
161
162
 
@@ -188,6 +189,7 @@ Neotoma stores user data and requires secure configuration.
188
189
 
189
190
  ```bash
190
191
  npm run dev # MCP server (stdio)
192
+ npm run dev:mcp:dev-shim # stable stdio shim for MCP source iteration
191
193
  npm run dev:ui # Frontend
192
194
  npm run dev:server # API only (MCP at /mcp)
193
195
  npm run dev:full # API + UI + build watch
@@ -216,9 +218,11 @@ npm test
216
218
 
217
219
  Neotoma exposes state via MCP. Local storage only in preview. Local built-in auth.
218
220
 
219
- **Setup guides:** [Cursor](https://neotoma.io/neotoma-with-cursor) · [Claude Code](https://neotoma.io/neotoma-with-claude-code) · [Claude](https://neotoma.io/neotoma-with-claude) · [ChatGPT](https://neotoma.io/neotoma-with-chatgpt) · [Codex](https://neotoma.io/neotoma-with-codex) · [OpenClaw](https://neotoma.io/neotoma-with-openclaw)
221
+ **Setup guides:** [Cursor](https://neotoma.io/neotoma-with-cursor) · [Claude Code](https://neotoma.io/neotoma-with-claude-code) · [Claude](https://neotoma.io/neotoma-with-claude) · [ChatGPT](https://neotoma.io/neotoma-with-chatgpt) · [Codex](https://neotoma.io/neotoma-with-codex) · [OpenCode](docs/integrations/hooks/opencode.md) · [OpenClaw](https://neotoma.io/neotoma-with-openclaw) · [IronClaw](https://neotoma.io/neotoma-with-ironclaw)
220
222
 
221
- **Agent behavior contract:** Store first, retrieve before storing, extract entities from user input, create tasks for commitments. Full instructions: [MCP instructions](docs/developer/mcp/instructions.md) and [CLI agent instructions](docs/developer/cli_agent_instructions.md).
223
+ For local source iteration, use the stable dev shim (`scripts/run_neotoma_mcp_stdio_dev_shim.sh` or `npm run dev:mcp:dev-shim`) instead of pointing installed MCP clients at a `tsx watch` stdio process. The shim keeps the client-facing JSON-RPC stream stable and asks clients to refresh or reconnect when the tool interface changes.
224
+
225
+ **Agent behavior contract:** Store first, retrieve before storing, extract entities from user input, create tasks for commitments, and attach bounded host context such as repository name/root scope when available. Full instructions: [MCP instructions](docs/developer/mcp/instructions.md) and [CLI agent instructions](docs/developer/cli_agent_instructions.md).
222
226
 
223
227
  **Representative actions:** `store`, `retrieve_entities`, `retrieve_entity_snapshot`, `merge_entities`, `list_observations`, `create_relationship`, `list_relationships`, `list_timeline_events`, `retrieve_graph_neighborhood`. Full list: [MCP spec](docs/specs/MCP_SPEC.md).
224
228
 
package/dist/actions.d.ts CHANGED
@@ -22,6 +22,14 @@ export declare function isLocalRequest(req: express.Request): boolean;
22
22
  * a different authority. See src/middleware/aauth_verify.ts.
23
23
  */
24
24
  export declare function canonicalAauthAuthority(): string;
25
+ type StoreRelationshipRef = {
26
+ relationship_type: string;
27
+ source_index?: number;
28
+ target_index?: number;
29
+ source_entity_id?: string;
30
+ target_entity_id?: string;
31
+ metadata?: Record<string, unknown>;
32
+ };
25
33
  export declare function storeStructuredForApi(params: {
26
34
  userId: string;
27
35
  entities: Record<string, unknown>[];
@@ -29,11 +37,7 @@ export declare function storeStructuredForApi(params: {
29
37
  observationSource?: import("./shared/action_schemas.js").ObservationSource;
30
38
  idempotencyKey: string;
31
39
  originalFilename?: string;
32
- relationships?: Array<{
33
- relationship_type: string;
34
- source_index: number;
35
- target_index: number;
36
- }>;
40
+ relationships?: StoreRelationshipRef[];
37
41
  commit?: boolean;
38
42
  strict?: boolean;
39
43
  }): Promise<{
@@ -92,4 +96,5 @@ export declare function startHTTPServer(): Promise<{
92
96
  server: import("http").Server<typeof import("http").IncomingMessage, typeof import("http").ServerResponse>;
93
97
  port: number;
94
98
  } | undefined>;
99
+ export {};
95
100
  //# sourceMappingURL=actions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAiK9B,eAAO,MAAM,GAAG,6CAAY,CAAC;AAif7B;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAU5D;AA4PD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAmBhD;AA6nHD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,4BAA4B,EAAE,iBAAiB,CAAC;IAC3E,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,KAAK,CAAC;QACpB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;;;;;;;;;;;;;cAkfS,MAAM;gBACJ,MAAM;2BACK,MAAM;qBACZ,MAAM;mBACR,MAAM;wBACD,MAAM;uBACP,MAAM;;;;;;;;;mBA9IV,MAAM;qBACJ,MAAM;wBACH,MAAM,GAAG,IAAI;2BACV,MAAM;;wBAET,MAAM;uBACP,MAAM,EAAE;wBACP,MAAM;uBACP,MAAM;;kBA9NX,MAAM;oBACJ,MAAM;yBACD,MAAM;4BACH,MAAM;2BACP,MAAM;;+BA4NF,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;;;2BAkFlC,MAAM;0BACP,MAAM;0BACN,MAAM;;GA8E3B;AA29DD,wBAAsB,eAAe;;;eA2FpC"}
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAmK9B,eAAO,MAAM,GAAG,6CAAY,CAAC;AAif7B;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,GAAG,OAAO,CAU5D;AA4PD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAmBhD;AA4sHD,KAAK,oBAAoB,GAAG;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,CAAC;AAEF,wBAAsB,qBAAqB,CAAC,MAAM,EAAE;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,4BAA4B,EAAE,iBAAiB,CAAC;IAC3E,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;;;;;;;;;;;;;cA+fS,MAAM;gBACJ,MAAM;2BACK,MAAM;qBACZ,MAAM;mBACR,MAAM;wBACD,MAAM;uBACP,MAAM;;;;;;;;;mBA3JV,MAAM;qBACJ,MAAM;wBACH,MAAM,GAAG,IAAI;2BACV,MAAM;;wBAET,MAAM;uBACP,MAAM,EAAE;wBACP,MAAM;uBACP,MAAM;;kBA9NX,MAAM;oBACJ,MAAM;yBACD,MAAM;4BACH,MAAM;2BACP,MAAM;;+BA4NF,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;;;2BAkFlC,MAAM;0BACP,MAAM;0BACN,MAAM;;GA2F3B;AAuhED,wBAAsB,eAAe;;;eA2FpC"}
package/dist/actions.js CHANGED
@@ -43,7 +43,7 @@ import { resolveSandboxReportTransport } from "./services/sandbox/transport.js";
43
43
  import { getSqliteDb } from "./repositories/sqlite/sqlite_client.js";
44
44
  import { getMcpAuthToken } from "./crypto/mcp_auth_token.js";
45
45
  import { isOauthKeyCredentialValid, normalizeOauthNextPath, OAuthKeySessionStore, } from "./services/oauth_key_gate.js";
46
- import { AnalyzeSchemaCandidatesRequestSchema, CorrectEntityRequestSchema, CreateRelationshipRequestSchema, DeleteEntityRequestSchema, DeleteRelationshipRequestSchema, EntitiesQueryRequestSchema, EntitySnapshotRequestSchema, FieldProvenanceRequestSchema, GetSchemaRecommendationsRequestSchema, ListObservationsRequestSchema, ListRelationshipsRequestSchema, MergeEntitiesRequestSchema, SplitEntityRequestSchema, ObservationsQueryRequestSchema, RegisterSchemaRequestSchema, RelationshipSnapshotRequestSchema, RestoreEntityRequestSchema, RestoreRelationshipRequestSchema, RetrieveEntityByIdentifierSchema, RetrieveGraphNeighborhoodSchema, RetrieveRelatedEntitiesSchema, StoreRequestSchema, StoreUnstructuredRequestSchema, UpdateSchemaIncrementalRequestSchema, } from "./shared/action_schemas.js";
46
+ import { AnalyzeSchemaCandidatesRequestSchema, CorrectEntityRequestSchema, CreateRelationshipsRequestSchema, CreateRelationshipRequestSchema, DeleteEntityRequestSchema, DeleteRelationshipRequestSchema, EntitiesQueryRequestSchema, EntitySnapshotRequestSchema, FieldProvenanceRequestSchema, GetSchemaRecommendationsRequestSchema, ListObservationsRequestSchema, ListRelationshipsRequestSchema, MergeEntitiesRequestSchema, SplitEntityRequestSchema, ObservationsQueryRequestSchema, RegisterSchemaRequestSchema, RelationshipSnapshotRequestSchema, RestoreEntityRequestSchema, RestoreRelationshipRequestSchema, RetrieveEntityByIdentifierSchema, RetrieveGraphNeighborhoodSchema, RetrieveRelatedEntitiesSchema, StoreRequestSchema, StoreUnstructuredRequestSchema, UpdateSchemaIncrementalRequestSchema, } from "./shared/action_schemas.js";
47
47
  import { getMimeTypeFromExtension } from "./services/file_text_extraction.js";
48
48
  import { queryEntitiesWithCount } from "./shared/action_handlers/entity_handlers.js";
49
49
  import { retrieveEntityByIdentifierWithFallback } from "./shared/action_handlers/entity_identifier_handler.js";
@@ -51,8 +51,9 @@ import { prepareEntitySnapshotWithEmbedding, upsertEntitySnapshotWithEmbedding,
51
51
  import { readOpenApiActionsFile, readOpenApiFile } from "./shared/openapi_file.js";
52
52
  import { buildSmitheryServerCard } from "./mcp_server_card.js";
53
53
  import { listRecentRecordActivity, parseRecordActivityTypesQuery, } from "./services/recent_record_activity.js";
54
- import { listRecentConversations } from "./services/recent_conversations.js";
54
+ import { getRecentConversationById, listRecentConversations } from "./services/recent_conversations.js";
55
55
  import { listConversationTurns, getConversationTurn, } from "./services/conversation_turn.js";
56
+ import { buildComplianceScorecard } from "./services/compliance/scorecard.js";
56
57
  import { getAgent, listAgentRecords, listAgents } from "./services/agents_directory.js";
57
58
  export const app = express();
58
59
  // Trust proxy headers (required for express-rate-limit when X-Forwarded-For is present)
@@ -1688,21 +1689,38 @@ app.post("/mcp/oauth/token", oauthTokenLimit, express.urlencoded({ extended: tru
1688
1689
  try {
1689
1690
  const grant_type = req.body?.grant_type;
1690
1691
  const code = req.body?.code;
1692
+ const refresh_token = req.body?.refresh_token;
1691
1693
  logger.info("[MCP OAuth] Token request received", {
1692
1694
  grant_type: grant_type ?? null,
1693
1695
  has_code: typeof code === "string" && code.length > 0,
1694
1696
  code_hint: typeof code === "string" ? code.slice(0, 8) : null,
1697
+ has_refresh_token: typeof refresh_token === "string" && refresh_token.length > 0,
1695
1698
  host: req.header("host") ?? null,
1696
1699
  });
1697
- if (grant_type !== "authorization_code") {
1700
+ if (grant_type !== "authorization_code" && grant_type !== "refresh_token") {
1698
1701
  logger.warn("[MCP OAuth] Token rejected: unsupported grant_type", {
1699
1702
  grant_type: grant_type ?? null,
1700
1703
  });
1701
1704
  return res.status(400).json({
1702
1705
  error: "unsupported_grant_type",
1703
- error_description: "Only authorization_code is supported",
1706
+ error_description: "Only authorization_code and refresh_token are supported",
1704
1707
  });
1705
1708
  }
1709
+ if (grant_type === "refresh_token") {
1710
+ if (!refresh_token || typeof refresh_token !== "string") {
1711
+ logger.warn("[MCP OAuth] Token refresh rejected: missing refresh_token");
1712
+ return res
1713
+ .status(400)
1714
+ .json({ error: "invalid_request", error_description: "refresh_token is required" });
1715
+ }
1716
+ const { refreshAccessToken } = await import("./services/mcp_oauth.js");
1717
+ const token = await refreshAccessToken(refresh_token);
1718
+ logger.info("[MCP OAuth] Token refreshed", {
1719
+ has_refresh_token: Boolean(token.refresh_token),
1720
+ });
1721
+ res.setHeader("Content-Type", "application/json");
1722
+ return res.json(token);
1723
+ }
1706
1724
  if (!code || typeof code !== "string") {
1707
1725
  logger.warn("[MCP OAuth] Token rejected: missing code");
1708
1726
  return res
@@ -3271,6 +3289,21 @@ app.get("/agents/:key/records", async (req, res) => {
3271
3289
  return handleApiError(req, res, error, "Failed to list agent records", "DB_QUERY_FAILED", "APIError:agents_records");
3272
3290
  }
3273
3291
  });
3292
+ // GET /recent_conversations/:conversation_id — Inspector: one conversation with nested messages
3293
+ app.get("/recent_conversations/:conversation_id", async (req, res) => {
3294
+ try {
3295
+ const userId = await getAuthenticatedUserId(req, req.query.user_id);
3296
+ const conversationId = String(req.params.conversation_id ?? "").trim();
3297
+ const item = getRecentConversationById(userId, conversationId);
3298
+ if (!item) {
3299
+ return sendError(res, 404, "RESOURCE_NOT_FOUND", "Conversation not found");
3300
+ }
3301
+ return res.json(item);
3302
+ }
3303
+ catch (error) {
3304
+ return handleApiError(req, res, error, "Failed to load conversation", "DB_QUERY_FAILED", "APIError:recent_conversation_detail");
3305
+ }
3306
+ });
3274
3307
  // GET /recent_conversations — Inspector: conversations with nested messages (SQLite)
3275
3308
  app.get("/recent_conversations", async (req, res) => {
3276
3309
  try {
@@ -3279,7 +3312,9 @@ app.get("/recent_conversations", async (req, res) => {
3279
3312
  const offset = parseInt(String(req.query.offset ?? "0"), 10) || 0;
3280
3313
  const activity_after = typeof req.query.activity_after === "string" ? req.query.activity_after.trim() || null : null;
3281
3314
  const activity_before = typeof req.query.activity_before === "string" ? req.query.activity_before.trim() || null : null;
3282
- const agent_key = typeof req.query.agent_key === "string" ? req.query.agent_key.trim() || null : null;
3315
+ const agentKeyRaw = typeof req.query.agent_key === "string" ? req.query.agent_key.trim() : "";
3316
+ // UI and bookmarks may send agent_key=all; never treat that as a real deriveAgentKey value.
3317
+ const agent_key = agentKeyRaw.length > 0 && agentKeyRaw.toLowerCase() !== "all" ? agentKeyRaw : null;
3283
3318
  const result = listRecentConversations(userId, limit, offset, {
3284
3319
  activity_after,
3285
3320
  activity_before,
@@ -3328,6 +3363,32 @@ app.get("/turns/:turn_key", async (req, res) => {
3328
3363
  return handleApiError(req, res, error, "Failed to get turn", "DB_QUERY_FAILED", "APIError:turn_detail");
3329
3364
  }
3330
3365
  });
3366
+ // GET /admin/compliance/scorecard — Inspector: aggregated hook compliance (SQLite)
3367
+ app.get("/admin/compliance/scorecard", async (req, res) => {
3368
+ try {
3369
+ const userId = await getAuthenticatedUserId(req, req.query.user_id);
3370
+ const since = typeof req.query.since === "string" ? req.query.since : undefined;
3371
+ const until = typeof req.query.until === "string" ? req.query.until : undefined;
3372
+ const group_by = typeof req.query.group_by === "string" ? req.query.group_by : undefined;
3373
+ const min_turns = parseInt(String(req.query.min_turns ?? ""), 10);
3374
+ const min_backfill_rate = parseFloat(String(req.query.min_backfill_rate ?? ""));
3375
+ const top_missed_steps = parseInt(String(req.query.top_missed_steps ?? ""), 10);
3376
+ const include_synthetic = req.query.include_synthetic === "1" || String(req.query.include_synthetic).toLowerCase() === "true";
3377
+ const result = buildComplianceScorecard(userId, {
3378
+ since,
3379
+ until,
3380
+ group_by,
3381
+ min_turns: Number.isFinite(min_turns) ? min_turns : undefined,
3382
+ min_backfill_rate: Number.isFinite(min_backfill_rate) ? min_backfill_rate : undefined,
3383
+ top_missed_steps: Number.isFinite(top_missed_steps) ? top_missed_steps : undefined,
3384
+ include_synthetic,
3385
+ });
3386
+ return res.json(result);
3387
+ }
3388
+ catch (error) {
3389
+ return handleApiError(req, res, error, "Failed to build compliance scorecard", "DB_QUERY_FAILED", "APIError:compliance_scorecard");
3390
+ }
3391
+ });
3331
3392
  // GET /api/sources - Get source list (FU-301)
3332
3393
  app.get("/sources", async (req, res) => {
3333
3394
  try {
@@ -4185,30 +4246,41 @@ export async function storeStructuredForApi(params) {
4185
4246
  if (commit && relationships && relationships.length > 0) {
4186
4247
  const { relationshipsService } = await import("./services/relationships.js");
4187
4248
  for (const rel of relationships) {
4188
- const source = resolved[rel.source_index];
4189
- const target = resolved[rel.target_index];
4190
- if (!source || !target) {
4191
- logger.warn(`[STORE] Skipping relationship: invalid source_index=${rel.source_index} ` +
4192
- `or target_index=${rel.target_index} (have ${resolved.length} entities).`);
4249
+ const sourceEntityId = typeof rel.source_entity_id === "string"
4250
+ ? rel.source_entity_id
4251
+ : typeof rel.source_index === "number"
4252
+ ? resolved[rel.source_index]?.entity_id
4253
+ : undefined;
4254
+ const targetEntityId = typeof rel.target_entity_id === "string"
4255
+ ? rel.target_entity_id
4256
+ : typeof rel.target_index === "number"
4257
+ ? resolved[rel.target_index]?.entity_id
4258
+ : undefined;
4259
+ if (!sourceEntityId || !targetEntityId) {
4260
+ logger.warn(`[STORE] Skipping relationship: invalid source reference ` +
4261
+ `(source_index=${rel.source_index}, source_entity_id=${rel.source_entity_id}) ` +
4262
+ `or target reference (target_index=${rel.target_index}, ` +
4263
+ `target_entity_id=${rel.target_entity_id}); have ${resolved.length} entities.`);
4193
4264
  continue;
4194
4265
  }
4195
4266
  try {
4196
4267
  await relationshipsService.createRelationship({
4197
- source_entity_id: source.entity_id,
4198
- target_entity_id: target.entity_id,
4268
+ source_entity_id: sourceEntityId,
4269
+ target_entity_id: targetEntityId,
4199
4270
  relationship_type: rel.relationship_type,
4200
4271
  source_id: storageResult.sourceId,
4272
+ metadata: rel.metadata ?? {},
4201
4273
  user_id: userId,
4202
4274
  });
4203
4275
  relationshipsCreated.push({
4204
4276
  relationship_type: rel.relationship_type,
4205
- source_entity_id: source.entity_id,
4206
- target_entity_id: target.entity_id,
4277
+ source_entity_id: sourceEntityId,
4278
+ target_entity_id: targetEntityId,
4207
4279
  });
4208
4280
  }
4209
4281
  catch (relErr) {
4210
4282
  logger.warn(`Failed to create relationship ${rel.relationship_type} ` +
4211
- `${source.entity_id} -> ${target.entity_id}: ${relErr instanceof Error ? relErr.message : String(relErr)}`);
4283
+ `${sourceEntityId} -> ${targetEntityId}: ${relErr instanceof Error ? relErr.message : String(relErr)}`);
4212
4284
  }
4213
4285
  }
4214
4286
  }
@@ -4776,6 +4848,63 @@ app.post("/create_relationship", async (req, res) => {
4776
4848
  return sendError(res, 500, "DB_QUERY_FAILED", error instanceof Error ? error.message : "Failed to create relationship");
4777
4849
  }
4778
4850
  });
4851
+ // Create relationships in batch
4852
+ app.post("/create_relationships", async (req, res) => {
4853
+ const parsed = CreateRelationshipsRequestSchema.safeParse(req.body);
4854
+ if (!parsed.success) {
4855
+ logWarn("ValidationError:create_relationships", req, {
4856
+ issues: parsed.error.issues,
4857
+ });
4858
+ return sendValidationError(res, parsed.error.issues);
4859
+ }
4860
+ const { relationships, source_id, user_id } = parsed.data;
4861
+ const { relationshipsService } = await import("./services/relationships.js");
4862
+ try {
4863
+ const userId = await getAuthenticatedUserId(req, user_id);
4864
+ const created = [];
4865
+ const errors = [];
4866
+ for (const [index, relationship] of relationships.entries()) {
4867
+ try {
4868
+ const snapshot = await relationshipsService.createRelationship({
4869
+ relationship_type: relationship.relationship_type,
4870
+ source_entity_id: relationship.source_entity_id,
4871
+ target_entity_id: relationship.target_entity_id,
4872
+ source_id: relationship.source_id || source_id || null,
4873
+ metadata: relationship.metadata || {},
4874
+ user_id: userId,
4875
+ });
4876
+ created.push({
4877
+ index,
4878
+ ...snapshot,
4879
+ });
4880
+ }
4881
+ catch (error) {
4882
+ errors.push({
4883
+ index,
4884
+ relationship,
4885
+ error: error instanceof Error ? error.message : String(error),
4886
+ });
4887
+ }
4888
+ }
4889
+ logDebug("Success:create_relationships", req, {
4890
+ requested: relationships.length,
4891
+ created: created.length,
4892
+ errors: errors.length,
4893
+ });
4894
+ return res.json({
4895
+ success: errors.length === 0,
4896
+ requested: relationships.length,
4897
+ created_count: created.length,
4898
+ error_count: errors.length,
4899
+ relationships: created,
4900
+ errors,
4901
+ });
4902
+ }
4903
+ catch (error) {
4904
+ logError("RelationshipCreationError:create_relationships", req, error);
4905
+ return sendError(res, 500, "DB_QUERY_FAILED", error instanceof Error ? error.message : "Failed to create relationships");
4906
+ }
4907
+ });
4779
4908
  // List relationships
4780
4909
  app.post("/list_relationships", async (req, res) => {
4781
4910
  const parsed = ListRelationshipsRequestSchema.safeParse(req.body);