mindgraph 0.7.0 → 0.9.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Shuruheel Ahamed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -130,6 +130,27 @@ const { job_id } = await graph.runSynthesis(project.uid);
130
130
  const job = await graph.getJob(job_id);
131
131
  ```
132
132
 
133
+ ### Operational Ontology (Layer 7)
134
+
135
+ Define typed domain objects (Customer, Order, Contract…) as a semantic contract and either **bind them to a SQL database** or extract them from documents — fused onto one object. Connecting a database (credentials/sync) is done in the dashboard; the SDK proposes/reviews schemas, queries, and lists the generated agent read tools.
136
+
137
+ | Method | Description |
138
+ |--------|-------------|
139
+ | `proposeOntologySchema(req)` | Draft a schema from a description (+ optional sample docs); returns `{ schema_id, job_id }` |
140
+ | `activateOntologySchema(id)` / `getOntologySchema(id)` / `listOntologySchemas()` | Schema lifecycle |
141
+ | `listOntologyProposals(opts?)` / `approveOntologyProposal(id)` / `rejectOntologyProposal(id)` | Review extracted-object proposals |
142
+ | `queryOntology({ query, include_cognitive_context })` | Typed retrieval with the cognitive overlay fused in |
143
+ | `listOntologyTools()` | The generated read-tool manifest (`search_/get_/summarize_<obj>`) the MCP server renders |
144
+
145
+ ```typescript
146
+ const { schema_id } = await graph.proposeOntologySchema({ description: "Clients, orders, contracts." });
147
+ await graph.activateOntologySchema(schema_id);
148
+ const { tools } = await graph.listOntologyTools();
149
+ const ctx = await graph.queryOntology({ query: "Which customers are a churn risk?", include_cognitive_context: true });
150
+ ```
151
+
152
+ See the [Operational Ontology](https://mindgraph.cloud/docs/ontology) and [Connect a database](https://mindgraph.cloud/docs/connect) docs.
153
+
133
154
  ### CRUD
134
155
 
135
156
  | Method | Description |
package/dist/index.d.mts CHANGED
@@ -81,12 +81,20 @@ interface EnrichedSearchResponse {
81
81
  chunks: SearchChunk[];
82
82
  }
83
83
  interface PathStep {
84
- uid: string;
84
+ node_uid: string;
85
85
  label: string;
86
86
  node_type: string;
87
87
  edge_type: string | null;
88
88
  depth: number;
89
89
  parent_uid: string | null;
90
+ /** Min-plus cost of the returned BFS path from the start node
91
+ * (sum of -ln(weight), weights clamped to (1e-9, 1]); cost of the path
92
+ * the traversal returned, not the cheapest path. 0 at the start node. */
93
+ path_cost?: number;
94
+ /** Product of edge confidences along the returned BFS path (clamped to
95
+ * (1e-9, 1]); a ranking signal, not a calibrated probability. 1 at the
96
+ * start node. */
97
+ path_confidence?: number;
90
98
  }
91
99
  interface PersonProps {
92
100
  canonical_name: string;
@@ -357,7 +365,17 @@ interface RetrieveRequest {
357
365
  * Retrieval action. Note: `"semantic"` requires a configured embedding
358
366
  * provider on the server; for semantic search use `retrieveContext()` instead.
359
367
  */
360
- action: "text" | "semantic" | "hybrid" | "active_goals" | "open_questions" | "weak_claims" | "pending_approvals" | "unresolved_contradictions" | "layer" | "recent";
368
+ action: "text" | "semantic" | "hybrid" | "active_goals" | "open_questions" | "weak_claims" | "pending_approvals" | "unresolved_contradictions" | "preferences" | "layer" | "recent";
369
+ /**
370
+ * Required for `"text"`, `"semantic"`, `"hybrid"`. Optional for
371
+ * `"preferences"`: with a `query` you get topic-relevant preferences (the
372
+ * semantic leg bridges low lexical overlap — e.g. "suggest a hotel"
373
+ * surfaces a stored "loved the rooftop pool"); without one you get all
374
+ * preferences, most salient first. Either way the result is a
375
+ * `SearchResult[]` (score = relevance with a query, salience without).
376
+ * Use `"preferences"` for advice/recommendation requests so answers
377
+ * reflect what the user likes.
378
+ */
361
379
  query?: string;
362
380
  k?: number;
363
381
  threshold?: number;
@@ -373,6 +391,16 @@ interface RetrieveRequest {
373
391
  * servers ignore the field.
374
392
  */
375
393
  explain?: boolean;
394
+ /**
395
+ * `recent` action only: restrict to nodes created at/after this unix
396
+ * timestamp (seconds). Filters by INGESTION time, not event time.
397
+ */
398
+ created_after?: number;
399
+ /**
400
+ * `recent` action only: restrict to nodes created at/before this unix
401
+ * timestamp (seconds). Filters by INGESTION time, not event time.
402
+ */
403
+ created_before?: number;
376
404
  }
377
405
  interface TraverseRequest {
378
406
  action: "chain" | "neighborhood" | "path" | "subgraph";
@@ -399,6 +427,16 @@ interface EvolveRequest {
399
427
  version?: number;
400
428
  agent_id?: string;
401
429
  }
430
+ /**
431
+ * Maps a 1-based page number to the **UTF-8 byte offset** where that page begins
432
+ * in `content`. `char_start` is a byte offset, NOT a codepoint count — count
433
+ * UTF-8 bytes (`new TextEncoder().encode(s).length`), not `s.length`, or pages
434
+ * will be wrong for any non-ASCII document.
435
+ */
436
+ interface PageOffset {
437
+ page: number;
438
+ char_start: number;
439
+ }
402
440
  interface IngestChunkRequest {
403
441
  content: string;
404
442
  chunk_type?: string;
@@ -437,10 +475,20 @@ interface IngestDocumentRequest {
437
475
  citation_count?: number;
438
476
  arxiv_id?: string;
439
477
  language?: string;
478
+ /** Per-page character offsets into `content`, used to map extractions back to source pages. */
479
+ page_offsets?: PageOffset[];
480
+ /** Total number of pages in the source document. */
481
+ page_count?: number;
482
+ /** MIME type of the original source (e.g. "application/pdf"). */
483
+ mime_type?: string;
484
+ /** Re-ingest even if a document with the same content was already ingested. */
485
+ force_reingest?: boolean;
440
486
  }
441
487
  interface IngestDocumentResponse {
442
488
  job_id: string;
443
489
  document_uid: string;
490
+ /** True when the document was recognized as a duplicate and ingestion was skipped. */
491
+ deduplicated?: boolean;
444
492
  }
445
493
  interface IngestSessionRequest {
446
494
  content: string;
@@ -478,6 +526,47 @@ interface ListArticlesResponse {
478
526
  total: number;
479
527
  has_more: boolean;
480
528
  }
529
+ /**
530
+ * Citation provenance for a graph node: the source chunk span(s) the node was
531
+ * extracted from. Annotated onto retrieve-context graph nodes via `source_chunks`.
532
+ */
533
+ interface SourceChunk {
534
+ chunk_uid: string;
535
+ /** UTF-8 byte offset into the chunk where the source span starts. */
536
+ char_start: number | null;
537
+ /** UTF-8 byte offset into the chunk where the source span ends. */
538
+ char_end: number | null;
539
+ /** 1-based page number where the span starts (null if no page map). */
540
+ page_start: number | null;
541
+ /** 1-based page number where the span ends (null if no page map). */
542
+ page_end: number | null;
543
+ /** The verbatim source span (when matched), else null. */
544
+ quote: string | null;
545
+ /**
546
+ * Web-Annotation-style selector object pinning the node to its source span,
547
+ * or null when no confident match. `start`/`end` are chunk-relative UTF-8 byte
548
+ * offsets; `exact` is the durable quote; `prefix`/`suffix` give re-anchoring context.
549
+ */
550
+ anchor: TextSelector | null;
551
+ }
552
+ /** A Web-Annotation quote+position selector (see `SourceChunk.anchor`). */
553
+ interface TextSelector {
554
+ exact: string;
555
+ prefix: string;
556
+ suffix: string;
557
+ start: number;
558
+ end: number;
559
+ }
560
+ /**
561
+ * Per-agent stance on a Claim: which agent asserts it and with what certainty.
562
+ * Annotated onto retrieve-context graph nodes (Claim nodes) via `believed_by`.
563
+ */
564
+ interface BelievedBy {
565
+ agent_uid: string;
566
+ agent_label: string;
567
+ /** The asserting agent's certainty in the claim, or null if unspecified. */
568
+ confidence: number | null;
569
+ }
481
570
  interface RetrieveContextResponse {
482
571
  articles?: ArticleResult[];
483
572
  chunks?: {
@@ -494,6 +583,8 @@ interface RetrieveContextResponse {
494
583
  uid: string;
495
584
  title: string;
496
585
  }[];
586
+ source_chunks?: SourceChunk[];
587
+ believed_by?: BelievedBy[];
497
588
  })[];
498
589
  edges: Record<string, unknown>[];
499
590
  };
@@ -674,6 +765,63 @@ interface FieldDefinition {
674
765
  array_item_type?: string;
675
766
  extraction_hint?: string;
676
767
  }
768
+ /**
769
+ * Datasource binding for an object type — the "semantic contract" mapping it to
770
+ * an external system (SQL today). Null/absent = extracted or authored.
771
+ * See docs/plans/layer7-semantic-contract.md §2.
772
+ */
773
+ interface ObjectBacking {
774
+ kind: "sql";
775
+ /** MDO-ready list; exactly one source is supported today. */
776
+ sources: SqlBackingSource[];
777
+ /** Identity key, resolved via an indexed source_pk at sync time. */
778
+ primary_key: string;
779
+ title_field?: string;
780
+ sync?: BackingSync;
781
+ }
782
+ interface SqlBackingSource {
783
+ /** FK into external_connections — credentials live in secrets, never here. */
784
+ connection_ref: string;
785
+ table: string;
786
+ /** Join/identity key within this source. */
787
+ key: string;
788
+ filter?: BackingFilter;
789
+ /** object field name -> binding. Each field is owned by exactly one source. */
790
+ field_map: Record<string, FieldBinding>;
791
+ }
792
+ interface FieldBinding {
793
+ column: string;
794
+ /** indexed = projected/embedded/searchable; live = fetched on demand, never stored. */
795
+ mode?: "indexed" | "live";
796
+ }
797
+ /** Structured predicate (column op value) — never raw SQL. */
798
+ interface BackingFilter {
799
+ column: string;
800
+ op: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "like" | "is_null" | "not_null";
801
+ value?: unknown;
802
+ }
803
+ interface BackingSync {
804
+ mode?: "incremental" | "full";
805
+ cursor_column?: string;
806
+ deleted_at_column?: string;
807
+ /** null = manual "Sync now"; cron later. */
808
+ schedule?: string | null;
809
+ }
810
+ /** Datasource binding for a relation type (FK column or M:M join table). */
811
+ type RelationBacking = {
812
+ kind: "sql_fk";
813
+ connection_ref: string;
814
+ fk_table: string;
815
+ fk_column: string;
816
+ /** `table.column` the FK references (the other side's PK). */
817
+ references: string;
818
+ } | {
819
+ kind: "sql_join_table";
820
+ connection_ref: string;
821
+ table: string;
822
+ from_column: string;
823
+ to_column: string;
824
+ };
677
825
  interface OntologySchema {
678
826
  id: string;
679
827
  org_id: string;
@@ -706,6 +854,8 @@ interface OntologyObjectType {
706
854
  extraction_hints?: string | null;
707
855
  default_confidence: number;
708
856
  review_policy: "always" | "low_confidence" | "never";
857
+ /** Datasource binding (null = extracted/authored). */
858
+ backing?: ObjectBacking | null;
709
859
  status: "active" | "deprecated" | "archived";
710
860
  version: number;
711
861
  created_at: string;
@@ -727,6 +877,8 @@ interface OntologyRelationType {
727
877
  fields_json: FieldDefinition[];
728
878
  extraction_hints?: string | null;
729
879
  review_policy: "always" | "low_confidence" | "never";
880
+ /** Datasource binding (null = extracted/authored). */
881
+ backing?: RelationBacking | null;
730
882
  status: "active" | "deprecated" | "archived";
731
883
  version: number;
732
884
  created_at: string;
@@ -736,6 +888,16 @@ interface OntologySchemaDetail extends OntologySchema {
736
888
  object_types: OntologyObjectType[];
737
889
  relation_types: OntologyRelationType[];
738
890
  }
891
+ /** A generated read-only tool descriptor (from `listOntologyTools`). */
892
+ interface OntologyToolDescriptor {
893
+ name: string;
894
+ description: string;
895
+ schema_id: string;
896
+ object_type: string;
897
+ /** "search" | "object" | "object_context" */
898
+ maps_to: string;
899
+ input_schema: Record<string, unknown>;
900
+ }
739
901
  interface CreateOntologySchemaRequest {
740
902
  name: string;
741
903
  description?: string;
@@ -756,6 +918,8 @@ interface OntologyObjectTypeInput {
756
918
  extraction_hints?: string;
757
919
  default_confidence?: number;
758
920
  review_policy?: "always" | "low_confidence" | "never";
921
+ /** Bind this object type to an external source (SQL). Omit for extracted/authored. */
922
+ backing?: ObjectBacking | null;
759
923
  }
760
924
  interface OntologyRelationTypeInput {
761
925
  name: string;
@@ -770,6 +934,8 @@ interface OntologyRelationTypeInput {
770
934
  fields?: FieldDefinition[];
771
935
  extraction_hints?: string;
772
936
  review_policy?: "always" | "low_confidence" | "never";
937
+ /** Bind this relation to an FK column or M:M join table. Both endpoints must be sql-mapped. */
938
+ backing?: RelationBacking | null;
773
939
  }
774
940
  /** Status: pending | approved | approval_required | rejected | applied | apply_failed. */
775
941
  interface OntologyProposal {
@@ -1175,6 +1341,10 @@ declare class MindGraph {
1175
1341
  documents_processed: number;
1176
1342
  node_source_pairs_added: number;
1177
1343
  }>;
1344
+ /** Backfill citation anchors (source_chunks spans) for existing graphs. Returns a background job id. */
1345
+ backfillAnchors(): Promise<{
1346
+ job_id: string;
1347
+ }>;
1178
1348
  listJobs(): Promise<Job[]>;
1179
1349
  getJob(id: string): Promise<Job>;
1180
1350
  cancelJob(id: string): Promise<unknown>;
@@ -1305,6 +1475,15 @@ declare class MindGraph {
1305
1475
  }[];
1306
1476
  }>;
1307
1477
  queryOntology(req: OntologyQueryRequest): Promise<OntologyQueryResponse>;
1478
+ /**
1479
+ * Read-only agent tool descriptors generated from the active ontology
1480
+ * schema(s). Each maps to a generic `/ontology` read endpoint with
1481
+ * `object_type` bound. Used by the MCP server to expose typed per-object
1482
+ * tools (`search_customers`, `summarize_customer`, …).
1483
+ */
1484
+ listOntologyTools(): Promise<{
1485
+ tools: OntologyToolDescriptor[];
1486
+ }>;
1308
1487
  getDomainObject(uid: string): Promise<DomainObject>;
1309
1488
  getDomainObjectContext(uid: string, depth?: number): Promise<OntologyQueryResponse>;
1310
1489
  getDomainObjectHistory(uid: string): Promise<{
@@ -1346,4 +1525,4 @@ declare class MindGraph {
1346
1525
  }>;
1347
1526
  }
1348
1527
 
1349
- export { type AnalogyCandidate, type ArgumentRequest, type ArticleResult, type BatchRequest, type CaptureRequest, type ClaimHub, type ClearResponse, type ClusterClaimSample, type ClusteredClaimHub, type CommitmentRequest, type ConceptCluster, type DecayRequest, type DeliberationRequest, type DialecticalPair, type DistillRequest, type DocumentRef, type EnrichedSearchResponse, type EntityBridge, type EntityRequest, type EpistemicCounts, type EventProps, type EvolveRequest, type ExecutionRequest, type GovernanceRequest, type GraphEdge, type GraphNode, type IngestChunkRequest, type IngestChunkResponse, type IngestDocumentRequest, type IngestDocumentResponse, type IngestSessionRequest, type InquiryRequest, type Job, type ListArticlesResponse, type MemoryConfigRequest, MindGraph, type MindGraphConfig, MindGraphError, type NationProps, type OrganizationProps, type PathStep, type PersonProps, type PlaceProps, type PlanRequest, type ProcedureRequest, type PurgeRequest, type RankedClaimHub, type RetrieveContextRequest, type RetrieveContextResponse, type RetrieveRequest, type RiskRequest, type SearchChunk, type SearchResult, type SessionRequest, type SignalsQuery, type SignalsResponse, type StructureRequest, type SynthesisJobResponse, type TheorySupportGap, type TraverseRequest };
1528
+ export { type AnalogyCandidate, type ArgumentRequest, type ArticleResult, type BatchRequest, type BelievedBy, type CaptureRequest, type ClaimHub, type ClearResponse, type ClusterClaimSample, type ClusteredClaimHub, type CommitmentRequest, type ConceptCluster, type DecayRequest, type DeliberationRequest, type DialecticalPair, type DistillRequest, type DocumentRef, type EnrichedSearchResponse, type EntityBridge, type EntityRequest, type EpistemicCounts, type EventProps, type EvolveRequest, type ExecutionRequest, type GovernanceRequest, type GraphEdge, type GraphNode, type IngestChunkRequest, type IngestChunkResponse, type IngestDocumentRequest, type IngestDocumentResponse, type IngestSessionRequest, type InquiryRequest, type Job, type ListArticlesResponse, type MemoryConfigRequest, MindGraph, type MindGraphConfig, MindGraphError, type NationProps, type OrganizationProps, type PathStep, type PersonProps, type PlaceProps, type PlanRequest, type ProcedureRequest, type PurgeRequest, type RankedClaimHub, type RetrieveContextRequest, type RetrieveContextResponse, type RetrieveRequest, type RiskRequest, type SearchChunk, type SearchResult, type SessionRequest, type SignalsQuery, type SignalsResponse, type SourceChunk, type StructureRequest, type SynthesisJobResponse, type TextSelector, type TheorySupportGap, type TraverseRequest };
package/dist/index.d.ts CHANGED
@@ -81,12 +81,20 @@ interface EnrichedSearchResponse {
81
81
  chunks: SearchChunk[];
82
82
  }
83
83
  interface PathStep {
84
- uid: string;
84
+ node_uid: string;
85
85
  label: string;
86
86
  node_type: string;
87
87
  edge_type: string | null;
88
88
  depth: number;
89
89
  parent_uid: string | null;
90
+ /** Min-plus cost of the returned BFS path from the start node
91
+ * (sum of -ln(weight), weights clamped to (1e-9, 1]); cost of the path
92
+ * the traversal returned, not the cheapest path. 0 at the start node. */
93
+ path_cost?: number;
94
+ /** Product of edge confidences along the returned BFS path (clamped to
95
+ * (1e-9, 1]); a ranking signal, not a calibrated probability. 1 at the
96
+ * start node. */
97
+ path_confidence?: number;
90
98
  }
91
99
  interface PersonProps {
92
100
  canonical_name: string;
@@ -357,7 +365,17 @@ interface RetrieveRequest {
357
365
  * Retrieval action. Note: `"semantic"` requires a configured embedding
358
366
  * provider on the server; for semantic search use `retrieveContext()` instead.
359
367
  */
360
- action: "text" | "semantic" | "hybrid" | "active_goals" | "open_questions" | "weak_claims" | "pending_approvals" | "unresolved_contradictions" | "layer" | "recent";
368
+ action: "text" | "semantic" | "hybrid" | "active_goals" | "open_questions" | "weak_claims" | "pending_approvals" | "unresolved_contradictions" | "preferences" | "layer" | "recent";
369
+ /**
370
+ * Required for `"text"`, `"semantic"`, `"hybrid"`. Optional for
371
+ * `"preferences"`: with a `query` you get topic-relevant preferences (the
372
+ * semantic leg bridges low lexical overlap — e.g. "suggest a hotel"
373
+ * surfaces a stored "loved the rooftop pool"); without one you get all
374
+ * preferences, most salient first. Either way the result is a
375
+ * `SearchResult[]` (score = relevance with a query, salience without).
376
+ * Use `"preferences"` for advice/recommendation requests so answers
377
+ * reflect what the user likes.
378
+ */
361
379
  query?: string;
362
380
  k?: number;
363
381
  threshold?: number;
@@ -373,6 +391,16 @@ interface RetrieveRequest {
373
391
  * servers ignore the field.
374
392
  */
375
393
  explain?: boolean;
394
+ /**
395
+ * `recent` action only: restrict to nodes created at/after this unix
396
+ * timestamp (seconds). Filters by INGESTION time, not event time.
397
+ */
398
+ created_after?: number;
399
+ /**
400
+ * `recent` action only: restrict to nodes created at/before this unix
401
+ * timestamp (seconds). Filters by INGESTION time, not event time.
402
+ */
403
+ created_before?: number;
376
404
  }
377
405
  interface TraverseRequest {
378
406
  action: "chain" | "neighborhood" | "path" | "subgraph";
@@ -399,6 +427,16 @@ interface EvolveRequest {
399
427
  version?: number;
400
428
  agent_id?: string;
401
429
  }
430
+ /**
431
+ * Maps a 1-based page number to the **UTF-8 byte offset** where that page begins
432
+ * in `content`. `char_start` is a byte offset, NOT a codepoint count — count
433
+ * UTF-8 bytes (`new TextEncoder().encode(s).length`), not `s.length`, or pages
434
+ * will be wrong for any non-ASCII document.
435
+ */
436
+ interface PageOffset {
437
+ page: number;
438
+ char_start: number;
439
+ }
402
440
  interface IngestChunkRequest {
403
441
  content: string;
404
442
  chunk_type?: string;
@@ -437,10 +475,20 @@ interface IngestDocumentRequest {
437
475
  citation_count?: number;
438
476
  arxiv_id?: string;
439
477
  language?: string;
478
+ /** Per-page character offsets into `content`, used to map extractions back to source pages. */
479
+ page_offsets?: PageOffset[];
480
+ /** Total number of pages in the source document. */
481
+ page_count?: number;
482
+ /** MIME type of the original source (e.g. "application/pdf"). */
483
+ mime_type?: string;
484
+ /** Re-ingest even if a document with the same content was already ingested. */
485
+ force_reingest?: boolean;
440
486
  }
441
487
  interface IngestDocumentResponse {
442
488
  job_id: string;
443
489
  document_uid: string;
490
+ /** True when the document was recognized as a duplicate and ingestion was skipped. */
491
+ deduplicated?: boolean;
444
492
  }
445
493
  interface IngestSessionRequest {
446
494
  content: string;
@@ -478,6 +526,47 @@ interface ListArticlesResponse {
478
526
  total: number;
479
527
  has_more: boolean;
480
528
  }
529
+ /**
530
+ * Citation provenance for a graph node: the source chunk span(s) the node was
531
+ * extracted from. Annotated onto retrieve-context graph nodes via `source_chunks`.
532
+ */
533
+ interface SourceChunk {
534
+ chunk_uid: string;
535
+ /** UTF-8 byte offset into the chunk where the source span starts. */
536
+ char_start: number | null;
537
+ /** UTF-8 byte offset into the chunk where the source span ends. */
538
+ char_end: number | null;
539
+ /** 1-based page number where the span starts (null if no page map). */
540
+ page_start: number | null;
541
+ /** 1-based page number where the span ends (null if no page map). */
542
+ page_end: number | null;
543
+ /** The verbatim source span (when matched), else null. */
544
+ quote: string | null;
545
+ /**
546
+ * Web-Annotation-style selector object pinning the node to its source span,
547
+ * or null when no confident match. `start`/`end` are chunk-relative UTF-8 byte
548
+ * offsets; `exact` is the durable quote; `prefix`/`suffix` give re-anchoring context.
549
+ */
550
+ anchor: TextSelector | null;
551
+ }
552
+ /** A Web-Annotation quote+position selector (see `SourceChunk.anchor`). */
553
+ interface TextSelector {
554
+ exact: string;
555
+ prefix: string;
556
+ suffix: string;
557
+ start: number;
558
+ end: number;
559
+ }
560
+ /**
561
+ * Per-agent stance on a Claim: which agent asserts it and with what certainty.
562
+ * Annotated onto retrieve-context graph nodes (Claim nodes) via `believed_by`.
563
+ */
564
+ interface BelievedBy {
565
+ agent_uid: string;
566
+ agent_label: string;
567
+ /** The asserting agent's certainty in the claim, or null if unspecified. */
568
+ confidence: number | null;
569
+ }
481
570
  interface RetrieveContextResponse {
482
571
  articles?: ArticleResult[];
483
572
  chunks?: {
@@ -494,6 +583,8 @@ interface RetrieveContextResponse {
494
583
  uid: string;
495
584
  title: string;
496
585
  }[];
586
+ source_chunks?: SourceChunk[];
587
+ believed_by?: BelievedBy[];
497
588
  })[];
498
589
  edges: Record<string, unknown>[];
499
590
  };
@@ -674,6 +765,63 @@ interface FieldDefinition {
674
765
  array_item_type?: string;
675
766
  extraction_hint?: string;
676
767
  }
768
+ /**
769
+ * Datasource binding for an object type — the "semantic contract" mapping it to
770
+ * an external system (SQL today). Null/absent = extracted or authored.
771
+ * See docs/plans/layer7-semantic-contract.md §2.
772
+ */
773
+ interface ObjectBacking {
774
+ kind: "sql";
775
+ /** MDO-ready list; exactly one source is supported today. */
776
+ sources: SqlBackingSource[];
777
+ /** Identity key, resolved via an indexed source_pk at sync time. */
778
+ primary_key: string;
779
+ title_field?: string;
780
+ sync?: BackingSync;
781
+ }
782
+ interface SqlBackingSource {
783
+ /** FK into external_connections — credentials live in secrets, never here. */
784
+ connection_ref: string;
785
+ table: string;
786
+ /** Join/identity key within this source. */
787
+ key: string;
788
+ filter?: BackingFilter;
789
+ /** object field name -> binding. Each field is owned by exactly one source. */
790
+ field_map: Record<string, FieldBinding>;
791
+ }
792
+ interface FieldBinding {
793
+ column: string;
794
+ /** indexed = projected/embedded/searchable; live = fetched on demand, never stored. */
795
+ mode?: "indexed" | "live";
796
+ }
797
+ /** Structured predicate (column op value) — never raw SQL. */
798
+ interface BackingFilter {
799
+ column: string;
800
+ op: "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "like" | "is_null" | "not_null";
801
+ value?: unknown;
802
+ }
803
+ interface BackingSync {
804
+ mode?: "incremental" | "full";
805
+ cursor_column?: string;
806
+ deleted_at_column?: string;
807
+ /** null = manual "Sync now"; cron later. */
808
+ schedule?: string | null;
809
+ }
810
+ /** Datasource binding for a relation type (FK column or M:M join table). */
811
+ type RelationBacking = {
812
+ kind: "sql_fk";
813
+ connection_ref: string;
814
+ fk_table: string;
815
+ fk_column: string;
816
+ /** `table.column` the FK references (the other side's PK). */
817
+ references: string;
818
+ } | {
819
+ kind: "sql_join_table";
820
+ connection_ref: string;
821
+ table: string;
822
+ from_column: string;
823
+ to_column: string;
824
+ };
677
825
  interface OntologySchema {
678
826
  id: string;
679
827
  org_id: string;
@@ -706,6 +854,8 @@ interface OntologyObjectType {
706
854
  extraction_hints?: string | null;
707
855
  default_confidence: number;
708
856
  review_policy: "always" | "low_confidence" | "never";
857
+ /** Datasource binding (null = extracted/authored). */
858
+ backing?: ObjectBacking | null;
709
859
  status: "active" | "deprecated" | "archived";
710
860
  version: number;
711
861
  created_at: string;
@@ -727,6 +877,8 @@ interface OntologyRelationType {
727
877
  fields_json: FieldDefinition[];
728
878
  extraction_hints?: string | null;
729
879
  review_policy: "always" | "low_confidence" | "never";
880
+ /** Datasource binding (null = extracted/authored). */
881
+ backing?: RelationBacking | null;
730
882
  status: "active" | "deprecated" | "archived";
731
883
  version: number;
732
884
  created_at: string;
@@ -736,6 +888,16 @@ interface OntologySchemaDetail extends OntologySchema {
736
888
  object_types: OntologyObjectType[];
737
889
  relation_types: OntologyRelationType[];
738
890
  }
891
+ /** A generated read-only tool descriptor (from `listOntologyTools`). */
892
+ interface OntologyToolDescriptor {
893
+ name: string;
894
+ description: string;
895
+ schema_id: string;
896
+ object_type: string;
897
+ /** "search" | "object" | "object_context" */
898
+ maps_to: string;
899
+ input_schema: Record<string, unknown>;
900
+ }
739
901
  interface CreateOntologySchemaRequest {
740
902
  name: string;
741
903
  description?: string;
@@ -756,6 +918,8 @@ interface OntologyObjectTypeInput {
756
918
  extraction_hints?: string;
757
919
  default_confidence?: number;
758
920
  review_policy?: "always" | "low_confidence" | "never";
921
+ /** Bind this object type to an external source (SQL). Omit for extracted/authored. */
922
+ backing?: ObjectBacking | null;
759
923
  }
760
924
  interface OntologyRelationTypeInput {
761
925
  name: string;
@@ -770,6 +934,8 @@ interface OntologyRelationTypeInput {
770
934
  fields?: FieldDefinition[];
771
935
  extraction_hints?: string;
772
936
  review_policy?: "always" | "low_confidence" | "never";
937
+ /** Bind this relation to an FK column or M:M join table. Both endpoints must be sql-mapped. */
938
+ backing?: RelationBacking | null;
773
939
  }
774
940
  /** Status: pending | approved | approval_required | rejected | applied | apply_failed. */
775
941
  interface OntologyProposal {
@@ -1175,6 +1341,10 @@ declare class MindGraph {
1175
1341
  documents_processed: number;
1176
1342
  node_source_pairs_added: number;
1177
1343
  }>;
1344
+ /** Backfill citation anchors (source_chunks spans) for existing graphs. Returns a background job id. */
1345
+ backfillAnchors(): Promise<{
1346
+ job_id: string;
1347
+ }>;
1178
1348
  listJobs(): Promise<Job[]>;
1179
1349
  getJob(id: string): Promise<Job>;
1180
1350
  cancelJob(id: string): Promise<unknown>;
@@ -1305,6 +1475,15 @@ declare class MindGraph {
1305
1475
  }[];
1306
1476
  }>;
1307
1477
  queryOntology(req: OntologyQueryRequest): Promise<OntologyQueryResponse>;
1478
+ /**
1479
+ * Read-only agent tool descriptors generated from the active ontology
1480
+ * schema(s). Each maps to a generic `/ontology` read endpoint with
1481
+ * `object_type` bound. Used by the MCP server to expose typed per-object
1482
+ * tools (`search_customers`, `summarize_customer`, …).
1483
+ */
1484
+ listOntologyTools(): Promise<{
1485
+ tools: OntologyToolDescriptor[];
1486
+ }>;
1308
1487
  getDomainObject(uid: string): Promise<DomainObject>;
1309
1488
  getDomainObjectContext(uid: string, depth?: number): Promise<OntologyQueryResponse>;
1310
1489
  getDomainObjectHistory(uid: string): Promise<{
@@ -1346,4 +1525,4 @@ declare class MindGraph {
1346
1525
  }>;
1347
1526
  }
1348
1527
 
1349
- export { type AnalogyCandidate, type ArgumentRequest, type ArticleResult, type BatchRequest, type CaptureRequest, type ClaimHub, type ClearResponse, type ClusterClaimSample, type ClusteredClaimHub, type CommitmentRequest, type ConceptCluster, type DecayRequest, type DeliberationRequest, type DialecticalPair, type DistillRequest, type DocumentRef, type EnrichedSearchResponse, type EntityBridge, type EntityRequest, type EpistemicCounts, type EventProps, type EvolveRequest, type ExecutionRequest, type GovernanceRequest, type GraphEdge, type GraphNode, type IngestChunkRequest, type IngestChunkResponse, type IngestDocumentRequest, type IngestDocumentResponse, type IngestSessionRequest, type InquiryRequest, type Job, type ListArticlesResponse, type MemoryConfigRequest, MindGraph, type MindGraphConfig, MindGraphError, type NationProps, type OrganizationProps, type PathStep, type PersonProps, type PlaceProps, type PlanRequest, type ProcedureRequest, type PurgeRequest, type RankedClaimHub, type RetrieveContextRequest, type RetrieveContextResponse, type RetrieveRequest, type RiskRequest, type SearchChunk, type SearchResult, type SessionRequest, type SignalsQuery, type SignalsResponse, type StructureRequest, type SynthesisJobResponse, type TheorySupportGap, type TraverseRequest };
1528
+ export { type AnalogyCandidate, type ArgumentRequest, type ArticleResult, type BatchRequest, type BelievedBy, type CaptureRequest, type ClaimHub, type ClearResponse, type ClusterClaimSample, type ClusteredClaimHub, type CommitmentRequest, type ConceptCluster, type DecayRequest, type DeliberationRequest, type DialecticalPair, type DistillRequest, type DocumentRef, type EnrichedSearchResponse, type EntityBridge, type EntityRequest, type EpistemicCounts, type EventProps, type EvolveRequest, type ExecutionRequest, type GovernanceRequest, type GraphEdge, type GraphNode, type IngestChunkRequest, type IngestChunkResponse, type IngestDocumentRequest, type IngestDocumentResponse, type IngestSessionRequest, type InquiryRequest, type Job, type ListArticlesResponse, type MemoryConfigRequest, MindGraph, type MindGraphConfig, MindGraphError, type NationProps, type OrganizationProps, type PathStep, type PersonProps, type PlaceProps, type PlanRequest, type ProcedureRequest, type PurgeRequest, type RankedClaimHub, type RetrieveContextRequest, type RetrieveContextResponse, type RetrieveRequest, type RiskRequest, type SearchChunk, type SearchResult, type SessionRequest, type SignalsQuery, type SignalsResponse, type SourceChunk, type StructureRequest, type SynthesisJobResponse, type TextSelector, type TheorySupportGap, type TraverseRequest };
package/dist/index.js CHANGED
@@ -559,6 +559,10 @@ var MindGraph = class {
559
559
  async backfillNodeSources() {
560
560
  return this.post("/backfill/node-sources", {});
561
561
  }
562
+ /** Backfill citation anchors (source_chunks spans) for existing graphs. Returns a background job id. */
563
+ async backfillAnchors() {
564
+ return this.post("/backfill/anchors", {});
565
+ }
562
566
  async listJobs() {
563
567
  return this.get("/jobs");
564
568
  }
@@ -752,6 +756,15 @@ var MindGraph = class {
752
756
  async queryOntology(req) {
753
757
  return this.post("/ontology/query", req);
754
758
  }
759
+ /**
760
+ * Read-only agent tool descriptors generated from the active ontology
761
+ * schema(s). Each maps to a generic `/ontology` read endpoint with
762
+ * `object_type` bound. Used by the MCP server to expose typed per-object
763
+ * tools (`search_customers`, `summarize_customer`, …).
764
+ */
765
+ async listOntologyTools() {
766
+ return this.get("/v1/ontology/tools");
767
+ }
755
768
  async getDomainObject(uid) {
756
769
  return this.get(`/ontology/object/${uid}`);
757
770
  }
package/dist/index.mjs CHANGED
@@ -532,6 +532,10 @@ var MindGraph = class {
532
532
  async backfillNodeSources() {
533
533
  return this.post("/backfill/node-sources", {});
534
534
  }
535
+ /** Backfill citation anchors (source_chunks spans) for existing graphs. Returns a background job id. */
536
+ async backfillAnchors() {
537
+ return this.post("/backfill/anchors", {});
538
+ }
535
539
  async listJobs() {
536
540
  return this.get("/jobs");
537
541
  }
@@ -725,6 +729,15 @@ var MindGraph = class {
725
729
  async queryOntology(req) {
726
730
  return this.post("/ontology/query", req);
727
731
  }
732
+ /**
733
+ * Read-only agent tool descriptors generated from the active ontology
734
+ * schema(s). Each maps to a generic `/ontology` read endpoint with
735
+ * `object_type` bound. Used by the MCP server to expose typed per-object
736
+ * tools (`search_customers`, `summarize_customer`, …).
737
+ */
738
+ async listOntologyTools() {
739
+ return this.get("/v1/ontology/tools");
740
+ }
728
741
  async getDomainObject(uid) {
729
742
  return this.get(`/ontology/object/${uid}`);
730
743
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindgraph",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "TypeScript client for the MindGraph Cloud API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -9,7 +9,9 @@
9
9
  "scripts": {
10
10
  "build": "tsup src/index.ts --format cjs,esm --dts",
11
11
  "lint": "tsc --noEmit",
12
- "test": "vitest run"
12
+ "test": "vitest run",
13
+ "test:offline": "vitest run src/offline.test.ts",
14
+ "test:e2e": "vitest run src/integration.test.ts"
13
15
  },
14
16
  "keywords": ["mindgraph", "knowledge-graph", "cognitive", "ai", "agent"],
15
17
  "license": "MIT",