@olane/os 0.8.16 → 0.8.18

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 (51) hide show
  1. package/dist/src/address/address-factory.d.ts +23 -0
  2. package/dist/src/address/address-factory.d.ts.map +1 -0
  3. package/dist/src/address/address-factory.js +42 -0
  4. package/dist/src/address-book/address-book.d.ts +32 -0
  5. package/dist/src/address-book/address-book.d.ts.map +1 -0
  6. package/dist/src/address-book/address-book.js +65 -0
  7. package/dist/src/auth/os-auth-guard.d.ts +20 -0
  8. package/dist/src/auth/os-auth-guard.d.ts.map +1 -0
  9. package/dist/src/auth/os-auth-guard.js +39 -0
  10. package/dist/src/identity/copass-id.d.ts +23 -0
  11. package/dist/src/identity/copass-id.d.ts.map +1 -0
  12. package/dist/src/identity/copass-id.js +37 -0
  13. package/dist/src/index.d.ts +12 -0
  14. package/dist/src/index.d.ts.map +1 -1
  15. package/dist/src/index.js +12 -0
  16. package/dist/src/lifecycle/os-lifecycle.d.ts +36 -0
  17. package/dist/src/lifecycle/os-lifecycle.d.ts.map +1 -0
  18. package/dist/src/lifecycle/os-lifecycle.js +99 -0
  19. package/dist/src/mcp/os-mcp-server.d.ts +29 -0
  20. package/dist/src/mcp/os-mcp-server.d.ts.map +1 -0
  21. package/dist/src/mcp/os-mcp-server.js +244 -0
  22. package/dist/src/memory/memory-harness.d.ts +38 -0
  23. package/dist/src/memory/memory-harness.d.ts.map +1 -0
  24. package/dist/src/memory/memory-harness.js +100 -0
  25. package/dist/src/nodes/relay-node.d.ts +31 -0
  26. package/dist/src/nodes/relay-node.d.ts.map +1 -0
  27. package/dist/src/nodes/relay-node.js +85 -0
  28. package/dist/src/o-olane-os/interfaces/o-os.config.d.ts +15 -1
  29. package/dist/src/o-olane-os/interfaces/o-os.config.d.ts.map +1 -1
  30. package/dist/src/o-olane-os/o-os.d.ts +24 -0
  31. package/dist/src/o-olane-os/o-os.d.ts.map +1 -1
  32. package/dist/src/o-olane-os/o-os.js +121 -9
  33. package/dist/src/tools/filesystem.tool.d.ts +24 -0
  34. package/dist/src/tools/filesystem.tool.d.ts.map +1 -0
  35. package/dist/src/tools/filesystem.tool.js +163 -0
  36. package/dist/src/utils/config.d.ts +7 -1
  37. package/dist/src/utils/config.d.ts.map +1 -1
  38. package/dist/src/utils/config.js +40 -19
  39. package/dist/src/vector-store/copass-vector-store.tool.d.ts +29 -0
  40. package/dist/src/vector-store/copass-vector-store.tool.d.ts.map +1 -0
  41. package/dist/src/vector-store/copass-vector-store.tool.js +152 -0
  42. package/dist/src/worlds/world-instance.tool.d.ts +30 -0
  43. package/dist/src/worlds/world-instance.tool.d.ts.map +1 -0
  44. package/dist/src/worlds/world-instance.tool.js +214 -0
  45. package/dist/src/worlds/world-manager.tool.d.ts +61 -0
  46. package/dist/src/worlds/world-manager.tool.d.ts.map +1 -0
  47. package/dist/src/worlds/world-manager.tool.js +270 -0
  48. package/dist/src/worlds/world.types.d.ts +23 -0
  49. package/dist/src/worlds/world.types.d.ts.map +1 -0
  50. package/dist/src/worlds/world.types.js +1 -0
  51. package/package.json +17 -14
@@ -1,6 +1,8 @@
1
1
  import { OlaneOSSystemStatus } from './enum/o-os.status-enum.js';
2
2
  import touch from 'touch';
3
3
  import { readFile } from 'fs/promises';
4
+ import { mkdir } from 'fs/promises';
5
+ import * as path from 'path';
4
6
  import { oLeaderNode } from '@olane/o-leader';
5
7
  import { oAddress, oObject } from '@olane/o-core';
6
8
  import { NodeType } from '@olane/o-core';
@@ -10,6 +12,11 @@ import { ConfigManager } from '../utils/config.js';
10
12
  import { oLaneTool } from '@olane/o-lane';
11
13
  import { oLaneStorage } from '@olane/o-storage';
12
14
  import { oNodeAddress } from '@olane/o-node';
15
+ import { WorldManagerTool } from '../worlds/world-manager.tool.js';
16
+ import { AddressBook } from '../address-book/address-book.js';
17
+ import { MemoryHarness } from '../memory/memory-harness.js';
18
+ import { CopassVectorStoreTool } from '../vector-store/copass-vector-store.tool.js';
19
+ import { FilesystemTool } from '../tools/filesystem.tool.js';
13
20
  export class OlaneOS extends oObject {
14
21
  constructor(config) {
15
22
  super();
@@ -17,6 +24,10 @@ export class OlaneOS extends oObject {
17
24
  this.nodes = []; // clones of node for scale
18
25
  this.rootLeader = null; // the root leader node
19
26
  this.roundRobinIndex = 0;
27
+ this.worldManager = null;
28
+ this.addressBook = null;
29
+ this.memory = null;
30
+ this.filesystemTool = null;
20
31
  this.config = config;
21
32
  }
22
33
  entryNode() {
@@ -50,14 +61,17 @@ export class OlaneOS extends oObject {
50
61
  // Then we'll migrate to using o://os-config for persistence
51
62
  if (this.config.configFilePath) {
52
63
  try {
64
+ // Ensure parent directory exists before touch
65
+ await mkdir(path.dirname(this.config.configFilePath), { recursive: true });
53
66
  await touch(this.config.configFilePath);
54
67
  this.logger.debug('Config file path: ' + this.config.configFilePath);
55
68
  // let's load the config
56
69
  const config = await readFile(this.config.configFilePath, 'utf8');
57
70
  this.logger.debug('Config file contents: ' + config);
58
- if (config?.length === 0) {
59
- // no contents, let's create a new config
60
- throw new Error('No config file found, cannot start OS instance');
71
+ if (!config || config.trim().length === 0) {
72
+ // Empty file (fresh OS) use the in-memory config as-is
73
+ this.logger.debug('Empty config file, using constructor config');
74
+ return;
61
75
  }
62
76
  const json = JSON.parse(config);
63
77
  this.logger.debug('Config file parsed: ' + json);
@@ -246,6 +260,104 @@ export class OlaneOS extends oObject {
246
260
  // Don't throw - allow OS to continue even if replay fails
247
261
  }
248
262
  }
263
+ /**
264
+ * Initialize world manager, address book, and memory harness
265
+ * after the leader and nodes are started.
266
+ */
267
+ async initOSServices() {
268
+ const instanceName = (await this.getOSInstanceName()) ||
269
+ this.config.network?.name ||
270
+ 'default';
271
+ // Address book
272
+ this.addressBook = new AddressBook(instanceName);
273
+ await this.addressBook.load();
274
+ // OS service nodes (children of root leader)
275
+ if (this.rootLeader) {
276
+ // Memory harness — shells out to `olane ingest/copass` CLI
277
+ this.memory = new MemoryHarness();
278
+ this.logger.debug('Memory harness initialized');
279
+ // Vector store — routes to Copass backend so index_network
280
+ // and any o://vector-store calls go through the memory harness
281
+ const vectorStore = new CopassVectorStoreTool({
282
+ address: new oAddress('o://vector-store'),
283
+ leader: this.rootLeader.address,
284
+ parent: this.rootLeader.address,
285
+ _allowNestedAddress: true,
286
+ });
287
+ this.rootLeader.addChildNode(vectorStore);
288
+ await vectorStore.start();
289
+ this.logger.debug('Copass vector store started');
290
+ // Filesystem tool — single instance for the entire OS
291
+ this.filesystemTool = new FilesystemTool({
292
+ address: new oAddress('o://fs'),
293
+ leader: this.rootLeader.address,
294
+ parent: this.rootLeader.address,
295
+ _allowNestedAddress: true,
296
+ });
297
+ this.rootLeader.addChildNode(this.filesystemTool);
298
+ await this.filesystemTool.start();
299
+ this.logger.debug('Filesystem tool started');
300
+ // World manager
301
+ this.worldManager = new WorldManagerTool({
302
+ leader: this.rootLeader.address,
303
+ parent: this.rootLeader.address,
304
+ systemName: instanceName,
305
+ _allowNestedAddress: true,
306
+ });
307
+ this.rootLeader.addChildNode(this.worldManager);
308
+ await this.worldManager.start();
309
+ this.logger.debug('World manager started');
310
+ }
311
+ }
312
+ /**
313
+ * Only index if `indexCompletedAt` is not set in the instance config.
314
+ * Records the timestamp after successful indexing.
315
+ */
316
+ async indexOnceInBackground() {
317
+ const osName = await this.getOSInstanceName();
318
+ if (osName) {
319
+ const existing = await ConfigManager.getOSConfig(osName);
320
+ if (existing?.indexCompletedAt) {
321
+ this.logger.debug('Network already indexed, skipping');
322
+ return;
323
+ }
324
+ }
325
+ await this.indexNetworkParallel();
326
+ // Record completion
327
+ if (osName) {
328
+ const config = await ConfigManager.getOSConfig(osName);
329
+ if (config) {
330
+ await ConfigManager.saveOSConfig({
331
+ ...config,
332
+ indexCompletedAt: new Date().toISOString(),
333
+ });
334
+ }
335
+ }
336
+ }
337
+ /**
338
+ * Index all nodes in the network in parallel.
339
+ * Each node indexes itself + its children concurrently,
340
+ * rather than the default sequential tree walk.
341
+ */
342
+ async indexNetworkParallel() {
343
+ const allNodes = [
344
+ ...this.leaders,
345
+ ...this.nodes,
346
+ ];
347
+ this.logger.debug(`Indexing ${allNodes.length} node(s) in parallel...`);
348
+ await Promise.allSettled(allNodes.map(async (node) => {
349
+ try {
350
+ await node.use(node.address, {
351
+ method: 'index_network',
352
+ params: {},
353
+ });
354
+ }
355
+ catch (err) {
356
+ this.logger.warn(`Failed to index ${node.address.toString()}: ${err}`);
357
+ }
358
+ }));
359
+ this.logger.debug('Parallel network indexing complete');
360
+ }
249
361
  async use(oAddress, params) {
250
362
  const entryNode = this.entryNode();
251
363
  if (!entryNode) {
@@ -265,6 +377,9 @@ export class OlaneOS extends oObject {
265
377
  this.logger.debug('Leaders started...');
266
378
  await this.startNodes(NodeType.NODE);
267
379
  this.logger.debug('Nodes started...');
380
+ // Initialize world manager, address book, and memory harness
381
+ await this.initOSServices();
382
+ this.logger.debug('OS services initialized...');
268
383
  // Load config from o://os-config storage backend (after tools are initialized)
269
384
  // This merges any saved lanes from persistent storage
270
385
  await this.loadConfigFromStorage();
@@ -273,14 +388,11 @@ export class OlaneOS extends oObject {
273
388
  await this.runSavedPlans();
274
389
  this.logger.debug('Saved plans run...');
275
390
  this.logger.debug('OS instance started...');
276
- // index the OS instance
391
+ this.status = OlaneOSSystemStatus.RUNNING;
392
+ // Index the network once (first boot only), in the background.
277
393
  if (!this.config.noIndexNetwork) {
278
- await this.use(oAddress.leader(), {
279
- method: 'index_network',
280
- params: {},
281
- });
394
+ this.indexOnceInBackground().catch((err) => this.logger.error('Background network indexing failed:', err));
282
395
  }
283
- this.status = OlaneOSSystemStatus.RUNNING;
284
396
  return {
285
397
  peerId: this.rootLeader?.peerId.toString() || '',
286
398
  transports: this.rootLeader?.transports || [],
@@ -0,0 +1,24 @@
1
+ import { oNodeConfig } from '@olane/o-node';
2
+ import { oLaneTool } from '@olane/o-lane';
3
+ import { oRequest } from '@olane/o-core';
4
+ import type { ToolResult } from '@olane/o-tool';
5
+ /**
6
+ * FilesystemTool — an oLaneTool that provides scoped filesystem access.
7
+ * A single instance exists per OS at o://fs, shared across all worlds.
8
+ *
9
+ * The tool maintains a list of allowed directory paths (addresses).
10
+ * All file operations are restricted to these directories.
11
+ */
12
+ export declare class FilesystemTool extends oLaneTool {
13
+ private allowedPaths;
14
+ constructor(config: oNodeConfig, allowedPaths?: string[]);
15
+ getAllowedPaths(): string[];
16
+ _tool_add_path(request: oRequest): Promise<ToolResult>;
17
+ _tool_remove_path(request: oRequest): Promise<ToolResult>;
18
+ _tool_list_paths(_request: oRequest): Promise<ToolResult>;
19
+ _tool_read_file(request: oRequest): Promise<ToolResult>;
20
+ _tool_list_files(request: oRequest): Promise<ToolResult>;
21
+ _tool_stat_path(request: oRequest): Promise<ToolResult>;
22
+ private isWithinAllowedPath;
23
+ }
24
+ //# sourceMappingURL=filesystem.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.tool.d.ts","sourceRoot":"","sources":["../../../src/tools/filesystem.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAY,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAIhD;;;;;;GAMG;AACH,qBAAa,cAAe,SAAQ,SAAS;IAC3C,OAAO,CAAC,YAAY,CAAgB;gBAExB,MAAM,EAAE,WAAW,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE;IAyDxD,eAAe,IAAI,MAAM,EAAE;IAMrB,cAAc,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAqBtD,iBAAiB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAQzD,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAMzD,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAgBvD,gBAAgB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAwBxD,eAAe,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAyB7D,OAAO,CAAC,mBAAmB;CAK5B"}
@@ -0,0 +1,163 @@
1
+ import { oLaneTool } from '@olane/o-lane';
2
+ import { readFile, readdir, stat, access } from 'fs/promises';
3
+ import * as path from 'path';
4
+ /**
5
+ * FilesystemTool — an oLaneTool that provides scoped filesystem access.
6
+ * A single instance exists per OS at o://fs, shared across all worlds.
7
+ *
8
+ * The tool maintains a list of allowed directory paths (addresses).
9
+ * All file operations are restricted to these directories.
10
+ */
11
+ export class FilesystemTool extends oLaneTool {
12
+ constructor(config, allowedPaths) {
13
+ super({
14
+ ...config,
15
+ description: 'Scoped filesystem access for a world',
16
+ methods: {
17
+ add_path: {
18
+ name: 'add_path',
19
+ description: 'Add a directory path to the allowed list',
20
+ parameters: [
21
+ { name: 'path', type: 'string', required: true, description: 'Absolute directory path' },
22
+ ],
23
+ dependencies: [],
24
+ },
25
+ remove_path: {
26
+ name: 'remove_path',
27
+ description: 'Remove a directory path from the allowed list',
28
+ parameters: [
29
+ { name: 'path', type: 'string', required: true, description: 'Path to remove' },
30
+ ],
31
+ dependencies: [],
32
+ },
33
+ list_paths: {
34
+ name: 'list_paths',
35
+ description: 'List all allowed directory paths',
36
+ parameters: [],
37
+ dependencies: [],
38
+ },
39
+ read_file: {
40
+ name: 'read_file',
41
+ description: 'Read a file within an allowed path',
42
+ parameters: [
43
+ { name: 'path', type: 'string', required: true, description: 'File path to read' },
44
+ ],
45
+ dependencies: [],
46
+ },
47
+ list_files: {
48
+ name: 'list_files',
49
+ description: 'List files in a directory within an allowed path',
50
+ parameters: [
51
+ { name: 'path', type: 'string', required: true, description: 'Directory path' },
52
+ { name: 'recursive', type: 'boolean', required: false, description: 'List recursively' },
53
+ ],
54
+ dependencies: [],
55
+ },
56
+ stat_path: {
57
+ name: 'stat_path',
58
+ description: 'Get file/directory info within an allowed path',
59
+ parameters: [
60
+ { name: 'path', type: 'string', required: true, description: 'Path to stat' },
61
+ ],
62
+ dependencies: [],
63
+ },
64
+ },
65
+ });
66
+ this.allowedPaths = [];
67
+ this.allowedPaths = allowedPaths || [];
68
+ }
69
+ getAllowedPaths() {
70
+ return [...this.allowedPaths];
71
+ }
72
+ // ── Path management ────────────────────────────────────────
73
+ async _tool_add_path(request) {
74
+ const { path: dirPath } = request.params;
75
+ const resolved = path.resolve(dirPath);
76
+ try {
77
+ await access(resolved);
78
+ const stats = await stat(resolved);
79
+ if (!stats.isDirectory()) {
80
+ return { success: false, error: `'${resolved}' is not a directory` };
81
+ }
82
+ }
83
+ catch {
84
+ return { success: false, error: `'${resolved}' does not exist or is not accessible` };
85
+ }
86
+ if (!this.allowedPaths.includes(resolved)) {
87
+ this.allowedPaths.push(resolved);
88
+ }
89
+ return { success: true, path: resolved };
90
+ }
91
+ async _tool_remove_path(request) {
92
+ const { path: dirPath } = request.params;
93
+ const resolved = path.resolve(dirPath);
94
+ const before = this.allowedPaths.length;
95
+ this.allowedPaths = this.allowedPaths.filter((p) => p !== resolved);
96
+ return { success: true, removed: this.allowedPaths.length < before };
97
+ }
98
+ async _tool_list_paths(_request) {
99
+ return { success: true, paths: [...this.allowedPaths] };
100
+ }
101
+ // ── File operations (scoped to allowed paths) ──────────────
102
+ async _tool_read_file(request) {
103
+ const { path: filePath } = request.params;
104
+ const resolved = path.resolve(filePath);
105
+ if (!this.isWithinAllowedPath(resolved)) {
106
+ return { success: false, error: `'${resolved}' is outside allowed paths` };
107
+ }
108
+ try {
109
+ const content = await readFile(resolved, 'utf8');
110
+ return { success: true, content, path: resolved };
111
+ }
112
+ catch (err) {
113
+ return { success: false, error: `Failed to read: ${err}` };
114
+ }
115
+ }
116
+ async _tool_list_files(request) {
117
+ const { path: dirPath, recursive } = request.params;
118
+ const resolved = path.resolve(dirPath);
119
+ if (!this.isWithinAllowedPath(resolved)) {
120
+ return { success: false, error: `'${resolved}' is outside allowed paths` };
121
+ }
122
+ try {
123
+ const entries = await readdir(resolved, {
124
+ withFileTypes: true,
125
+ recursive: !!recursive,
126
+ });
127
+ const files = entries.map((e) => ({
128
+ name: e.name,
129
+ isDirectory: e.isDirectory(),
130
+ path: path.join(e.parentPath || resolved, e.name),
131
+ }));
132
+ return { success: true, files };
133
+ }
134
+ catch (err) {
135
+ return { success: false, error: `Failed to list: ${err}` };
136
+ }
137
+ }
138
+ async _tool_stat_path(request) {
139
+ const { path: targetPath } = request.params;
140
+ const resolved = path.resolve(targetPath);
141
+ if (!this.isWithinAllowedPath(resolved)) {
142
+ return { success: false, error: `'${resolved}' is outside allowed paths` };
143
+ }
144
+ try {
145
+ const stats = await stat(resolved);
146
+ return {
147
+ success: true,
148
+ path: resolved,
149
+ isFile: stats.isFile(),
150
+ isDirectory: stats.isDirectory(),
151
+ size: stats.size,
152
+ modified: stats.mtime.toISOString(),
153
+ };
154
+ }
155
+ catch (err) {
156
+ return { success: false, error: `Failed to stat: ${err}` };
157
+ }
158
+ }
159
+ // ── Helpers ────────────────────────────────────────────────
160
+ isWithinAllowedPath(filePath) {
161
+ return this.allowedPaths.some((allowed) => filePath === allowed || filePath.startsWith(allowed + path.sep));
162
+ }
163
+ }
@@ -14,6 +14,12 @@ export interface OlaneOSInstanceConfig {
14
14
  transports?: string[];
15
15
  oNetworkConfig?: OlaneOSConfig;
16
16
  remoteLeaderAddress?: oNodeAddress;
17
+ /** Copass ID linked to this OS instance. */
18
+ copassId?: string;
19
+ /** World ID if this instance represents a world. */
20
+ worldId?: string;
21
+ /** Timestamp of first completed network index. */
22
+ indexCompletedAt?: string;
17
23
  }
18
24
  export interface CLIConfig {
19
25
  instancesPath: string;
@@ -29,7 +35,7 @@ export declare class ConfigManager {
29
35
  static getConfig(): Promise<CLIConfig>;
30
36
  static saveConfig(config: Partial<CLIConfig>): Promise<void>;
31
37
  static writeConfig(config: Partial<CLIConfig>): Promise<void>;
32
- static getOSConfigFromPath(path: string): Promise<OlaneOSInstanceConfig | null>;
38
+ static getOSConfigFromPath(p: string): Promise<OlaneOSInstanceConfig | null>;
33
39
  static getOSConfig(name: string): Promise<OlaneOSInstanceConfig | null>;
34
40
  static updateOSConfig(config: OlaneOSInstanceConfig): Promise<OlaneOSInstanceConfig | null>;
35
41
  static saveOSConfig(config: OlaneOSInstanceConfig): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/utils/config.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,mBAAmB,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,mBAAmB,CAAC,EAAE,YAAY,CAAC;CACpC;AAED,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC5C;AAED,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAE9C,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAuB;IAChD,OAAO,CAAC,MAAM,CAAC,aAAa,CAAyB;IACrD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAuB;WAEnC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IASxC,MAAM,CAAC,gBAAgB,IAAI,SAAS;WAOvB,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC;WAM/B,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;WAOrD,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;WAItD,mBAAmB,CAC9B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;WAO3B,WAAW,CACtB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;WAY3B,cAAc,CACzB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;WAQ3B,YAAY,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;WAS1D,eAAe,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;WAuBnD,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM3D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/utils/config.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,mBAAmB,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,aAAa,CAAC;IAC/B,mBAAmB,CAAC,EAAE,YAAY,CAAC;IACnC,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,SAAS;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;CAC5C;AAED,eAAO,MAAM,gBAAgB,gBAAgB,CAAC;AAoB9C,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAuB;IAChD,OAAO,CAAC,MAAM,CAAC,aAAa,CAAyB;IACrD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAuB;WAEnC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IASxC,MAAM,CAAC,gBAAgB,IAAI,SAAS;WAOvB,SAAS,IAAI,OAAO,CAAC,SAAS,CAAC;WAM/B,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;WAOrD,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;WAItD,mBAAmB,CAC9B,CAAC,EAAE,MAAM,GACR,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;WAW3B,WAAW,CACtB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;WAY3B,cAAc,CACzB,MAAM,EAAE,qBAAqB,GAC5B,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;WAQ3B,YAAY,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;WAQ1D,eAAe,IAAI,OAAO,CAAC,qBAAqB,EAAE,CAAC;WAsBnD,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAM3D"}
@@ -1,12 +1,28 @@
1
- import * as fs from 'fs-extra';
1
+ import { readFile, writeFile, mkdir, readdir, rm, access } from 'fs/promises';
2
2
  import * as path from 'path';
3
3
  import { DEFAULT_CONFIG_PATH, DEFAULT_INSTANCE_PATH, DEFAULT_CONFIG_FILE, } from '@olane/o-core';
4
4
  export const CONFIG_FILE_NAME = 'config.json';
5
+ async function pathExists(p) {
6
+ try {
7
+ await access(p);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ async function readJson(p) {
15
+ const data = await readFile(p, 'utf8');
16
+ return JSON.parse(data);
17
+ }
18
+ async function writeJson(p, data, opts) {
19
+ await writeFile(p, JSON.stringify(data, null, opts?.spaces), 'utf8');
20
+ }
5
21
  export class ConfigManager {
6
22
  static async initialize() {
7
- await fs.ensureDir(ConfigManager.configPath);
8
- await fs.ensureDir(ConfigManager.instancesPath);
9
- if (!(await fs.pathExists(ConfigManager.configFile))) {
23
+ await mkdir(ConfigManager.configPath, { recursive: true });
24
+ await mkdir(ConfigManager.instancesPath, { recursive: true });
25
+ if (!(await pathExists(ConfigManager.configFile))) {
10
26
  await this.writeConfig(this.getDefaultConfig());
11
27
  }
12
28
  }
@@ -18,7 +34,7 @@ export class ConfigManager {
18
34
  }
19
35
  static async getConfig() {
20
36
  await this.initialize();
21
- const config = await fs.readJson(ConfigManager.configFile);
37
+ const config = await readJson(ConfigManager.configFile);
22
38
  return { ...this.getDefaultConfig(), ...config };
23
39
  }
24
40
  static async saveConfig(config) {
@@ -28,18 +44,25 @@ export class ConfigManager {
28
44
  await this.writeConfig(newConfig);
29
45
  }
30
46
  static async writeConfig(config) {
31
- await fs.writeJson(ConfigManager.configFile, config, { spaces: 2 });
47
+ await writeJson(ConfigManager.configFile, config, { spaces: 2 });
32
48
  }
33
- static async getOSConfigFromPath(path) {
34
- if (await fs.pathExists(path)) {
35
- return await fs.readJson(path);
49
+ static async getOSConfigFromPath(p) {
50
+ try {
51
+ if (!(await pathExists(p)))
52
+ return null;
53
+ const raw = await readFile(p, 'utf8');
54
+ if (!raw || !raw.trim())
55
+ return null;
56
+ return JSON.parse(raw);
57
+ }
58
+ catch {
59
+ return null;
36
60
  }
37
- return null;
38
61
  }
39
62
  static async getOSConfig(name) {
40
63
  const configPath = path.join(ConfigManager.instancesPath, name, CONFIG_FILE_NAME);
41
- if (await fs.pathExists(configPath)) {
42
- return await fs.readJson(configPath);
64
+ if (await pathExists(configPath)) {
65
+ return await readJson(configPath);
43
66
  }
44
67
  return null;
45
68
  }
@@ -51,10 +74,9 @@ export class ConfigManager {
51
74
  return c;
52
75
  }
53
76
  static async saveOSConfig(config) {
54
- // Use direct filesystem operations for OS config persistence
55
77
  const osPath = path.join(ConfigManager.instancesPath, config.name);
56
- await fs.ensureDir(osPath);
57
- await fs.writeJson(path.join(osPath, CONFIG_FILE_NAME), config, {
78
+ await mkdir(osPath, { recursive: true });
79
+ await writeJson(path.join(osPath, CONFIG_FILE_NAME), config, {
58
80
  spaces: 2,
59
81
  });
60
82
  }
@@ -62,7 +84,7 @@ export class ConfigManager {
62
84
  try {
63
85
  await this.initialize();
64
86
  const osInstances = [];
65
- const osInstanceNames = await fs.readdir(ConfigManager.instancesPath);
87
+ const osInstanceNames = await readdir(ConfigManager.instancesPath);
66
88
  for (const osInstanceName of osInstanceNames) {
67
89
  const config = await this.getOSConfig(osInstanceName);
68
90
  if (config) {
@@ -72,7 +94,6 @@ export class ConfigManager {
72
94
  return osInstances;
73
95
  }
74
96
  catch (error) {
75
- // if the default path for config does not exist, return an empty array
76
97
  if (error instanceof Error && error.message.includes('ENOENT')) {
77
98
  return [];
78
99
  }
@@ -81,8 +102,8 @@ export class ConfigManager {
81
102
  }
82
103
  static async deleteOSInstance(name) {
83
104
  const osInstancePath = path.join(ConfigManager.instancesPath, name);
84
- if (await fs.pathExists(osInstancePath)) {
85
- await fs.remove(osInstancePath);
105
+ if (await pathExists(osInstancePath)) {
106
+ await rm(osInstancePath, { recursive: true });
86
107
  }
87
108
  }
88
109
  }
@@ -0,0 +1,29 @@
1
+ import { oRequest } from '@olane/o-core';
2
+ import { oLaneTool } from '@olane/o-lane';
3
+ import { oNodeConfig } from '@olane/o-node';
4
+ import type { ToolResult } from '@olane/o-tool';
5
+ /**
6
+ * Vector store implementation backed by the Copass backend via the CLI.
7
+ *
8
+ * Sits at o://vector-store so that `index_network` and any tool that
9
+ * calls `use(oAddress('o://vector-store'), ...)` routes through here.
10
+ *
11
+ * - add_documents → `olane ingest text` for each document (parallelized)
12
+ * - search_similar → `olane copass context` (fast path search)
13
+ * - delete/update → no-ops (Copass is append-only)
14
+ */
15
+ export declare class CopassVectorStoreTool extends oLaneTool {
16
+ constructor(config: oNodeConfig);
17
+ /**
18
+ * Ingest documents into the Copass backend via `olane ingest text`.
19
+ * Runs up to INGEST_CONCURRENCY CLI calls in parallel.
20
+ */
21
+ _tool_add_documents(request: oRequest): Promise<ToolResult>;
22
+ /**
23
+ * Search via `olane copass context` (fast path).
24
+ */
25
+ _tool_search_similar(request: oRequest): Promise<ToolResult>;
26
+ _tool_delete_documents(_request: oRequest): Promise<ToolResult>;
27
+ _tool_update_documents(_request: oRequest): Promise<ToolResult>;
28
+ }
29
+ //# sourceMappingURL=copass-vector-store.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copass-vector-store.tool.d.ts","sourceRoot":"","sources":["../../../src/vector-store/copass-vector-store.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,QAAQ,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKhD;;;;;;;;;GASG;AACH,qBAAa,qBAAsB,SAAQ,SAAS;gBACtC,MAAM,EAAE,WAAW;IA2C/B;;;OAGG;IACG,mBAAmB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAsCjE;;OAEG;IACG,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAsB5D,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAI/D,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;CAGtE"}