@olane/os 0.8.16 → 0.8.17

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 +22 -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 +109 -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 +179 -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 +15 -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,10 @@ 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';
13
19
  export class OlaneOS extends oObject {
14
20
  constructor(config) {
15
21
  super();
@@ -17,6 +23,9 @@ export class OlaneOS extends oObject {
17
23
  this.nodes = []; // clones of node for scale
18
24
  this.rootLeader = null; // the root leader node
19
25
  this.roundRobinIndex = 0;
26
+ this.worldManager = null;
27
+ this.addressBook = null;
28
+ this.memory = null;
20
29
  this.config = config;
21
30
  }
22
31
  entryNode() {
@@ -50,14 +59,17 @@ export class OlaneOS extends oObject {
50
59
  // Then we'll migrate to using o://os-config for persistence
51
60
  if (this.config.configFilePath) {
52
61
  try {
62
+ // Ensure parent directory exists before touch
63
+ await mkdir(path.dirname(this.config.configFilePath), { recursive: true });
53
64
  await touch(this.config.configFilePath);
54
65
  this.logger.debug('Config file path: ' + this.config.configFilePath);
55
66
  // let's load the config
56
67
  const config = await readFile(this.config.configFilePath, 'utf8');
57
68
  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');
69
+ if (!config || config.trim().length === 0) {
70
+ // Empty file (fresh OS) use the in-memory config as-is
71
+ this.logger.debug('Empty config file, using constructor config');
72
+ return;
61
73
  }
62
74
  const json = JSON.parse(config);
63
75
  this.logger.debug('Config file parsed: ' + json);
@@ -246,6 +258,94 @@ export class OlaneOS extends oObject {
246
258
  // Don't throw - allow OS to continue even if replay fails
247
259
  }
248
260
  }
261
+ /**
262
+ * Initialize world manager, address book, and memory harness
263
+ * after the leader and nodes are started.
264
+ */
265
+ async initOSServices() {
266
+ const instanceName = (await this.getOSInstanceName()) ||
267
+ this.config.network?.name ||
268
+ 'default';
269
+ // Address book
270
+ this.addressBook = new AddressBook(instanceName);
271
+ await this.addressBook.load();
272
+ // OS service nodes (children of root leader)
273
+ if (this.rootLeader) {
274
+ // Memory harness — shells out to `olane ingest/copass` CLI
275
+ this.memory = new MemoryHarness();
276
+ this.logger.debug('Memory harness initialized');
277
+ // Vector store — routes to Copass backend so index_network
278
+ // and any o://vector-store calls go through the memory harness
279
+ const vectorStore = new CopassVectorStoreTool({
280
+ address: new oAddress('o://vector-store'),
281
+ leader: this.rootLeader.address,
282
+ parent: this.rootLeader.address,
283
+ _allowNestedAddress: true,
284
+ });
285
+ this.rootLeader.addChildNode(vectorStore);
286
+ await vectorStore.start();
287
+ this.logger.debug('Copass vector store started');
288
+ // World manager
289
+ this.worldManager = new WorldManagerTool({
290
+ leader: this.rootLeader.address,
291
+ parent: this.rootLeader.address,
292
+ systemName: instanceName,
293
+ _allowNestedAddress: true,
294
+ });
295
+ this.rootLeader.addChildNode(this.worldManager);
296
+ await this.worldManager.start();
297
+ this.logger.debug('World manager started');
298
+ }
299
+ }
300
+ /**
301
+ * Only index if `indexCompletedAt` is not set in the instance config.
302
+ * Records the timestamp after successful indexing.
303
+ */
304
+ async indexOnceInBackground() {
305
+ const osName = await this.getOSInstanceName();
306
+ if (osName) {
307
+ const existing = await ConfigManager.getOSConfig(osName);
308
+ if (existing?.indexCompletedAt) {
309
+ this.logger.debug('Network already indexed, skipping');
310
+ return;
311
+ }
312
+ }
313
+ await this.indexNetworkParallel();
314
+ // Record completion
315
+ if (osName) {
316
+ const config = await ConfigManager.getOSConfig(osName);
317
+ if (config) {
318
+ await ConfigManager.saveOSConfig({
319
+ ...config,
320
+ indexCompletedAt: new Date().toISOString(),
321
+ });
322
+ }
323
+ }
324
+ }
325
+ /**
326
+ * Index all nodes in the network in parallel.
327
+ * Each node indexes itself + its children concurrently,
328
+ * rather than the default sequential tree walk.
329
+ */
330
+ async indexNetworkParallel() {
331
+ const allNodes = [
332
+ ...this.leaders,
333
+ ...this.nodes,
334
+ ];
335
+ this.logger.debug(`Indexing ${allNodes.length} node(s) in parallel...`);
336
+ await Promise.allSettled(allNodes.map(async (node) => {
337
+ try {
338
+ await node.use(node.address, {
339
+ method: 'index_network',
340
+ params: {},
341
+ });
342
+ }
343
+ catch (err) {
344
+ this.logger.warn(`Failed to index ${node.address.toString()}: ${err}`);
345
+ }
346
+ }));
347
+ this.logger.debug('Parallel network indexing complete');
348
+ }
249
349
  async use(oAddress, params) {
250
350
  const entryNode = this.entryNode();
251
351
  if (!entryNode) {
@@ -265,6 +365,9 @@ export class OlaneOS extends oObject {
265
365
  this.logger.debug('Leaders started...');
266
366
  await this.startNodes(NodeType.NODE);
267
367
  this.logger.debug('Nodes started...');
368
+ // Initialize world manager, address book, and memory harness
369
+ await this.initOSServices();
370
+ this.logger.debug('OS services initialized...');
268
371
  // Load config from o://os-config storage backend (after tools are initialized)
269
372
  // This merges any saved lanes from persistent storage
270
373
  await this.loadConfigFromStorage();
@@ -273,14 +376,11 @@ export class OlaneOS extends oObject {
273
376
  await this.runSavedPlans();
274
377
  this.logger.debug('Saved plans run...');
275
378
  this.logger.debug('OS instance started...');
276
- // index the OS instance
379
+ this.status = OlaneOSSystemStatus.RUNNING;
380
+ // Index the network once (first boot only), in the background.
277
381
  if (!this.config.noIndexNetwork) {
278
- await this.use(oAddress.leader(), {
279
- method: 'index_network',
280
- params: {},
281
- });
382
+ this.indexOnceInBackground().catch((err) => this.logger.error('Background network indexing failed:', err));
282
383
  }
283
- this.status = OlaneOSSystemStatus.RUNNING;
284
384
  return {
285
385
  peerId: this.rootLeader?.peerId.toString() || '',
286
386
  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
+ * for a world. Each world gets its own FilesystemTool as a child node.
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
+ * for a world. Each world gets its own FilesystemTool as a child node.
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"}