opentology 0.2.7 → 0.2.8

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.
@@ -1,3 +1,11 @@
1
+ import type { OpenTologyConfig } from '../lib/config.js';
2
+ import type { StoreAdapter } from '../lib/store-adapter.js';
1
3
  export declare const MAX_TRIPLES_PER_PUSH = 100;
2
4
  export declare function assertTripleLimit(tripleCount: number): void;
5
+ /**
6
+ * Persist a named graph to a .ttl file in embedded mode.
7
+ * Exports the full graph, writes to .opentology/data/{slug}.ttl, and tracks
8
+ * the file in config — mirroring CLI push behavior.
9
+ */
10
+ export declare function persistGraph(adapter: StoreAdapter, config: OpenTologyConfig, graphUri: string): Promise<void>;
3
11
  export declare function startMcpServer(): Promise<void>;
@@ -1,7 +1,7 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
2
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
3
  import { ListToolsRequestSchema, CallToolRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
4
- import { loadConfig, saveConfig, configExists, resolveGraphUri } from '../lib/config.js';
4
+ import { loadConfig, saveConfig, configExists, resolveGraphUri, addTrackedFile } from '../lib/config.js';
5
5
  import { deepScan } from '../lib/deep-scanner.js';
6
6
  import { pushSymbolTriples } from '../lib/deep-scan-triples.js';
7
7
  import { createReadyAdapter } from '../lib/store-factory.js';
@@ -41,6 +41,26 @@ function resolveConfig(params) {
41
41
  throw new Error('No config found. Run opentology init first.');
42
42
  }
43
43
  }
44
+ /**
45
+ * Persist a named graph to a .ttl file in embedded mode.
46
+ * Exports the full graph, writes to .opentology/data/{slug}.ttl, and tracks
47
+ * the file in config — mirroring CLI push behavior.
48
+ */
49
+ export async function persistGraph(adapter, config, graphUri) {
50
+ if (config.mode !== 'embedded')
51
+ return;
52
+ const exported = await adapter.exportGraph(graphUri);
53
+ if (!exported.trim())
54
+ return;
55
+ // Derive a filename slug from the graph URI
56
+ const slug = graphUri.replace(/[^a-zA-Z0-9-]/g, '_').replace(/_+/g, '_');
57
+ const dataDir = join(process.cwd(), '.opentology', 'data');
58
+ const filePath = join(dataDir, `${slug}.ttl`);
59
+ mkdirSync(dataDir, { recursive: true });
60
+ writeFileSync(filePath, exported, 'utf-8');
61
+ addTrackedFile(config, graphUri, filePath);
62
+ saveConfig(config);
63
+ }
44
64
  async function handleInit(args) {
45
65
  const projectId = args.projectId;
46
66
  const mode = args.mode || 'http';
@@ -108,6 +128,7 @@ async function handlePush(args) {
108
128
  if (infer !== false) {
109
129
  inference = await materializeInferences(adapter, graphUri);
110
130
  }
131
+ await persistGraph(adapter, config, graphUri);
111
132
  return {
112
133
  success: true,
113
134
  tripleCount: validation.tripleCount,
@@ -200,6 +221,7 @@ async function handleDrop(args) {
200
221
  });
201
222
  const adapter = await createReadyAdapter(config);
202
223
  await adapter.dropGraph(graphUri);
224
+ await persistGraph(adapter, config, graphUri);
203
225
  return { success: true, graphUri };
204
226
  }
205
227
  async function handleDelete(args) {
@@ -214,6 +236,7 @@ async function handleDelete(args) {
214
236
  });
215
237
  const adapter = await createReadyAdapter(config);
216
238
  await adapter.deleteTriples(graphUri, { turtle: content, where });
239
+ await persistGraph(adapter, config, graphUri);
217
240
  return { success: true };
218
241
  }
219
242
  async function handleDiff(args) {
@@ -288,6 +311,7 @@ async function handleGraphDrop(args) {
288
311
  const graphUri = resolveGraphUri(config, name);
289
312
  const adapter = await createReadyAdapter(config);
290
313
  await adapter.dropGraph(graphUri);
314
+ await persistGraph(adapter, config, graphUri);
291
315
  const graphs = config.graphs ?? {};
292
316
  delete graphs[name];
293
317
  config.graphs = Object.keys(graphs).length > 0 ? graphs : undefined;
@@ -328,6 +352,7 @@ async function handleContextScan(args) {
328
352
  const contextUri = `${config.graphUri}/context`;
329
353
  const adapter = await createReadyAdapter(config);
330
354
  pushStats = await pushSymbolTriples(adapter, contextUri, scanResult);
355
+ await persistGraph(adapter, config, contextUri);
331
356
  }
332
357
  catch {
333
358
  // Non-fatal: push is best-effort
@@ -363,6 +388,7 @@ async function handleContextScan(args) {
363
388
  }
364
389
  await adapter.sparqlUpdate(`INSERT DATA { GRAPH <${contextUri}> {\n${sparqlTriples.join('\n')}\n} }`);
365
390
  moduleStats = { modules: dg.modules.length, edges: dg.edges.length };
391
+ await persistGraph(adapter, config, contextUri);
366
392
  }
367
393
  }
368
394
  catch {
@@ -515,6 +541,7 @@ async function handleContextInit(args) {
515
541
  }
516
542
  await adapter.sparqlUpdate(`INSERT DATA { GRAPH <${contextUri}> {\n${sparqlTriples.join('\n')}\n} }`);
517
543
  moduleStats = { modules: dg.modules.length, edges: dg.edges.length };
544
+ await persistGraph(adapter, config, contextUri);
518
545
  actions.push(`Pushed ${dg.modules.length} Module triples with ${dg.edges.length} dependsOn edges`);
519
546
  }
520
547
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opentology",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Ontology-powered project memory for AI coding assistants — your codebase as a knowledge graph",
5
5
  "type": "module",
6
6
  "bin": {