@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.
- package/dist/src/address/address-factory.d.ts +23 -0
- package/dist/src/address/address-factory.d.ts.map +1 -0
- package/dist/src/address/address-factory.js +42 -0
- package/dist/src/address-book/address-book.d.ts +32 -0
- package/dist/src/address-book/address-book.d.ts.map +1 -0
- package/dist/src/address-book/address-book.js +65 -0
- package/dist/src/auth/os-auth-guard.d.ts +20 -0
- package/dist/src/auth/os-auth-guard.d.ts.map +1 -0
- package/dist/src/auth/os-auth-guard.js +39 -0
- package/dist/src/identity/copass-id.d.ts +23 -0
- package/dist/src/identity/copass-id.d.ts.map +1 -0
- package/dist/src/identity/copass-id.js +37 -0
- package/dist/src/index.d.ts +12 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +12 -0
- package/dist/src/lifecycle/os-lifecycle.d.ts +36 -0
- package/dist/src/lifecycle/os-lifecycle.d.ts.map +1 -0
- package/dist/src/lifecycle/os-lifecycle.js +99 -0
- package/dist/src/mcp/os-mcp-server.d.ts +29 -0
- package/dist/src/mcp/os-mcp-server.d.ts.map +1 -0
- package/dist/src/mcp/os-mcp-server.js +244 -0
- package/dist/src/memory/memory-harness.d.ts +38 -0
- package/dist/src/memory/memory-harness.d.ts.map +1 -0
- package/dist/src/memory/memory-harness.js +100 -0
- package/dist/src/nodes/relay-node.d.ts +31 -0
- package/dist/src/nodes/relay-node.d.ts.map +1 -0
- package/dist/src/nodes/relay-node.js +85 -0
- package/dist/src/o-olane-os/interfaces/o-os.config.d.ts +15 -1
- package/dist/src/o-olane-os/interfaces/o-os.config.d.ts.map +1 -1
- package/dist/src/o-olane-os/o-os.d.ts +22 -0
- package/dist/src/o-olane-os/o-os.d.ts.map +1 -1
- package/dist/src/o-olane-os/o-os.js +109 -9
- package/dist/src/tools/filesystem.tool.d.ts +24 -0
- package/dist/src/tools/filesystem.tool.d.ts.map +1 -0
- package/dist/src/tools/filesystem.tool.js +163 -0
- package/dist/src/utils/config.d.ts +7 -1
- package/dist/src/utils/config.d.ts.map +1 -1
- package/dist/src/utils/config.js +40 -19
- package/dist/src/vector-store/copass-vector-store.tool.d.ts +29 -0
- package/dist/src/vector-store/copass-vector-store.tool.d.ts.map +1 -0
- package/dist/src/vector-store/copass-vector-store.tool.js +152 -0
- package/dist/src/worlds/world-instance.tool.d.ts +30 -0
- package/dist/src/worlds/world-instance.tool.d.ts.map +1 -0
- package/dist/src/worlds/world-instance.tool.js +179 -0
- package/dist/src/worlds/world-manager.tool.d.ts +61 -0
- package/dist/src/worlds/world-manager.tool.d.ts.map +1 -0
- package/dist/src/worlds/world-manager.tool.js +270 -0
- package/dist/src/worlds/world.types.d.ts +23 -0
- package/dist/src/worlds/world.types.d.ts.map +1 -0
- package/dist/src/worlds/world.types.js +1 -0
- package/package.json +15 -14
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { oAddress } from '@olane/o-core';
|
|
2
|
+
import { oLaneTool } from '@olane/o-lane';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
const INGEST_CONCURRENCY = 5;
|
|
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 class CopassVectorStoreTool extends oLaneTool {
|
|
16
|
+
constructor(config) {
|
|
17
|
+
super({
|
|
18
|
+
...config,
|
|
19
|
+
address: new oAddress('o://vector-store'),
|
|
20
|
+
description: 'Vector store backed by the Copass knowledge graph',
|
|
21
|
+
methods: {
|
|
22
|
+
add_documents: {
|
|
23
|
+
name: 'add_documents',
|
|
24
|
+
description: 'Add documents to the store',
|
|
25
|
+
dependencies: [],
|
|
26
|
+
parameters: [
|
|
27
|
+
{
|
|
28
|
+
name: 'documents',
|
|
29
|
+
type: 'array',
|
|
30
|
+
description: 'The documents to add',
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
search_similar: {
|
|
35
|
+
name: 'search_similar',
|
|
36
|
+
description: 'Search for similar documents in the store',
|
|
37
|
+
dependencies: [],
|
|
38
|
+
parameters: [
|
|
39
|
+
{ name: 'query', type: 'string', description: 'The query to search for' },
|
|
40
|
+
{ name: 'limit', type: 'number', description: 'Max results' },
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
delete_documents: {
|
|
44
|
+
name: 'delete_documents',
|
|
45
|
+
description: 'Delete documents from the store (no-op)',
|
|
46
|
+
dependencies: [],
|
|
47
|
+
parameters: [],
|
|
48
|
+
},
|
|
49
|
+
update_documents: {
|
|
50
|
+
name: 'update_documents',
|
|
51
|
+
description: 'Update documents in the store (no-op)',
|
|
52
|
+
dependencies: [],
|
|
53
|
+
parameters: [],
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Ingest documents into the Copass backend via `olane ingest text`.
|
|
60
|
+
* Runs up to INGEST_CONCURRENCY CLI calls in parallel.
|
|
61
|
+
*/
|
|
62
|
+
async _tool_add_documents(request) {
|
|
63
|
+
const { documents } = request.params;
|
|
64
|
+
if (!Array.isArray(documents)) {
|
|
65
|
+
return { success: false, error: 'documents must be an array' };
|
|
66
|
+
}
|
|
67
|
+
// Build work items
|
|
68
|
+
const work = [];
|
|
69
|
+
for (const doc of documents) {
|
|
70
|
+
const content = doc.pageContent || doc.page_content || '';
|
|
71
|
+
if (!content)
|
|
72
|
+
continue;
|
|
73
|
+
work.push({ content, address: doc.metadata?.address || '' });
|
|
74
|
+
}
|
|
75
|
+
// Process in parallel batches
|
|
76
|
+
let ingested = 0;
|
|
77
|
+
for (let i = 0; i < work.length; i += INGEST_CONCURRENCY) {
|
|
78
|
+
const batch = work.slice(i, i + INGEST_CONCURRENCY);
|
|
79
|
+
const results = await Promise.allSettled(batch.map(({ content, address }) => {
|
|
80
|
+
const hints = address ? [address] : [];
|
|
81
|
+
return execCli([
|
|
82
|
+
'ingest', 'text',
|
|
83
|
+
'--source-type', 'vector-store',
|
|
84
|
+
...(hints.length ? ['--entity-hints', ...hints] : []),
|
|
85
|
+
...(address ? ['--additional-context', `Address: ${address}`] : []),
|
|
86
|
+
], content);
|
|
87
|
+
}));
|
|
88
|
+
ingested += results.filter((r) => r.status === 'fulfilled').length;
|
|
89
|
+
}
|
|
90
|
+
return { success: true, ingested, total: documents.length };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Search via `olane copass context` (fast path).
|
|
94
|
+
*/
|
|
95
|
+
async _tool_search_similar(request) {
|
|
96
|
+
const { query, limit } = request.params;
|
|
97
|
+
try {
|
|
98
|
+
const result = await execCli([
|
|
99
|
+
'copass', 'context', query,
|
|
100
|
+
'--detail-level', 'concise',
|
|
101
|
+
...(limit ? ['--max-tokens', String(Math.min(limit * 500, 8000))] : []),
|
|
102
|
+
'--json',
|
|
103
|
+
]);
|
|
104
|
+
try {
|
|
105
|
+
return JSON.parse(result);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return { success: true, results: result };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
this.logger.warn(`Vector search failed: ${err}`);
|
|
113
|
+
return { success: true, results: [] };
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async _tool_delete_documents(_request) {
|
|
117
|
+
return { success: true };
|
|
118
|
+
}
|
|
119
|
+
async _tool_update_documents(_request) {
|
|
120
|
+
return { success: true };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function execCli(args, stdin) {
|
|
124
|
+
return new Promise((resolve, reject) => {
|
|
125
|
+
const child = spawn('olane', args, {
|
|
126
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
127
|
+
env: {
|
|
128
|
+
...process.env,
|
|
129
|
+
FORCE_COLOR: '0',
|
|
130
|
+
NODE_OPTIONS: (process.env.NODE_OPTIONS || '')
|
|
131
|
+
.replace(/--inspect[^ ]*/g, '')
|
|
132
|
+
.trim(),
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
let stdout = '';
|
|
136
|
+
let stderr = '';
|
|
137
|
+
child.stdout.on('data', (d) => { stdout += d; });
|
|
138
|
+
child.stderr.on('data', (d) => { stderr += d; });
|
|
139
|
+
child.on('close', (code) => {
|
|
140
|
+
if (code !== 0) {
|
|
141
|
+
reject(new Error(stderr.trim() || `CLI exited with code ${code}`));
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
resolve(stdout.trim());
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
if (stdin !== undefined) {
|
|
148
|
+
child.stdin.write(stdin);
|
|
149
|
+
}
|
|
150
|
+
child.stdin.end();
|
|
151
|
+
});
|
|
152
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
import { FilesystemTool } from '../tools/filesystem.tool.js';
|
|
6
|
+
import type { WorldConfig, WorldAddressEntry, WorldSupportedType } from './world.types.js';
|
|
7
|
+
/**
|
|
8
|
+
* A world instance node — hub for addresses of a given world.
|
|
9
|
+
* Registered as a child of the WorldManagerTool at o://world-manager/{world-name}.
|
|
10
|
+
*
|
|
11
|
+
* Each world instance owns a FilesystemTool child that provides scoped
|
|
12
|
+
* filesystem access to the directories (addresses) registered with it.
|
|
13
|
+
*/
|
|
14
|
+
export declare class WorldInstanceTool extends oLaneTool {
|
|
15
|
+
private worldConfig;
|
|
16
|
+
private addresses;
|
|
17
|
+
private persistPath;
|
|
18
|
+
filesystemTool: FilesystemTool | null;
|
|
19
|
+
constructor(nodeConfig: oNodeConfig, worldConfig: WorldConfig, persistPath?: string);
|
|
20
|
+
get world(): WorldConfig;
|
|
21
|
+
start(): Promise<void>;
|
|
22
|
+
_tool_register_address(request: oRequest): Promise<ToolResult>;
|
|
23
|
+
_tool_remove_address(request: oRequest): Promise<ToolResult>;
|
|
24
|
+
_tool_list_addresses(request: oRequest): Promise<ToolResult>;
|
|
25
|
+
_tool_get_world_info(_request: oRequest): Promise<ToolResult>;
|
|
26
|
+
getAddresses(type?: WorldSupportedType): WorldAddressEntry[];
|
|
27
|
+
private loadAddresses;
|
|
28
|
+
persistAddresses(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=world-instance.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-instance.tool.d.ts","sourceRoot":"","sources":["../../../src/worlds/world-instance.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;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,kBAAkB,EAEnB,MAAM,kBAAkB,CAAC;AAQ1B;;;;;;GAMG;AACH,qBAAa,iBAAkB,SAAQ,SAAS;IAC9C,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,SAAS,CAA2B;IAC5C,OAAO,CAAC,WAAW,CAAqB;IACjC,cAAc,EAAE,cAAc,GAAG,IAAI,CAAQ;gBAGlD,UAAU,EAAE,WAAW,EACvB,WAAW,EAAE,WAAW,EACxB,WAAW,CAAC,EAAE,MAAM;IA2CtB,IAAI,KAAK,IAAI,WAAW,CAEvB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBtB,sBAAsB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAkC9D,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAkB5D,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAQ5D,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAWnE,YAAY,CAAC,IAAI,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,EAAE;YAO9C,aAAa;IAcrB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;CASxC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { oLaneTool } from '@olane/o-lane';
|
|
2
|
+
import { oAddress } from '@olane/o-core';
|
|
3
|
+
import { FilesystemTool } from '../tools/filesystem.tool.js';
|
|
4
|
+
import { readFile, writeFile, mkdir, access } from 'fs/promises';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
async function pathExists(p) {
|
|
7
|
+
try {
|
|
8
|
+
await access(p);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* A world instance node — hub for addresses of a given world.
|
|
17
|
+
* Registered as a child of the WorldManagerTool at o://world-manager/{world-name}.
|
|
18
|
+
*
|
|
19
|
+
* Each world instance owns a FilesystemTool child that provides scoped
|
|
20
|
+
* filesystem access to the directories (addresses) registered with it.
|
|
21
|
+
*/
|
|
22
|
+
export class WorldInstanceTool extends oLaneTool {
|
|
23
|
+
constructor(nodeConfig, worldConfig, persistPath) {
|
|
24
|
+
super({
|
|
25
|
+
...nodeConfig,
|
|
26
|
+
description: `World instance: ${worldConfig.name}`,
|
|
27
|
+
methods: {
|
|
28
|
+
register_address: {
|
|
29
|
+
name: 'register_address',
|
|
30
|
+
description: 'Register an address (directory path) with this world',
|
|
31
|
+
parameters: [
|
|
32
|
+
{ name: 'address', type: 'string', required: true, description: 'The directory path to register' },
|
|
33
|
+
{ name: 'type', type: 'string', required: true, description: 'Address type (e.g. filepath)' },
|
|
34
|
+
],
|
|
35
|
+
dependencies: [],
|
|
36
|
+
},
|
|
37
|
+
remove_address: {
|
|
38
|
+
name: 'remove_address',
|
|
39
|
+
description: 'Remove an address from this world',
|
|
40
|
+
parameters: [
|
|
41
|
+
{ name: 'address', type: 'string', required: true, description: 'The address to remove' },
|
|
42
|
+
],
|
|
43
|
+
dependencies: [],
|
|
44
|
+
},
|
|
45
|
+
list_addresses: {
|
|
46
|
+
name: 'list_addresses',
|
|
47
|
+
description: 'List all addresses in this world',
|
|
48
|
+
parameters: [
|
|
49
|
+
{ name: 'type', type: 'string', required: false, description: 'Filter by type' },
|
|
50
|
+
],
|
|
51
|
+
dependencies: [],
|
|
52
|
+
},
|
|
53
|
+
get_world_info: {
|
|
54
|
+
name: 'get_world_info',
|
|
55
|
+
description: 'Get info about this world instance',
|
|
56
|
+
parameters: [],
|
|
57
|
+
dependencies: [],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
this.addresses = [];
|
|
62
|
+
this.filesystemTool = null;
|
|
63
|
+
this.worldConfig = worldConfig;
|
|
64
|
+
this.persistPath = persistPath;
|
|
65
|
+
}
|
|
66
|
+
get world() {
|
|
67
|
+
return this.worldConfig;
|
|
68
|
+
}
|
|
69
|
+
async start() {
|
|
70
|
+
await super.start();
|
|
71
|
+
await this.loadAddresses();
|
|
72
|
+
// Create the FilesystemTool child node scoped to this world's filepath addresses
|
|
73
|
+
const filepathAddresses = this.addresses
|
|
74
|
+
.filter((a) => a.type === 'filepath')
|
|
75
|
+
.map((a) => a.address);
|
|
76
|
+
const slug = this.worldConfig.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
77
|
+
this.filesystemTool = new FilesystemTool({
|
|
78
|
+
address: new oAddress(`o://world-manager/${slug}/fs`),
|
|
79
|
+
leader: this.leader,
|
|
80
|
+
parent: this.address,
|
|
81
|
+
_allowNestedAddress: true,
|
|
82
|
+
}, filepathAddresses);
|
|
83
|
+
this.addChildNode(this.filesystemTool);
|
|
84
|
+
await this.filesystemTool.start();
|
|
85
|
+
}
|
|
86
|
+
// ── Tool methods ───────────────────────────────────────────
|
|
87
|
+
async _tool_register_address(request) {
|
|
88
|
+
const { address, type, metadata } = request.params;
|
|
89
|
+
if (!this.worldConfig.supportedTypes.includes(type)) {
|
|
90
|
+
return {
|
|
91
|
+
success: false,
|
|
92
|
+
error: `Unsupported type '${type}'. Supported: ${this.worldConfig.supportedTypes.join(', ')}`,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
const existing = this.addresses.find((a) => a.address === address);
|
|
96
|
+
if (existing) {
|
|
97
|
+
return {
|
|
98
|
+
success: false,
|
|
99
|
+
error: `Address '${address}' is already registered in world '${this.worldConfig.name}'`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const entry = {
|
|
103
|
+
address,
|
|
104
|
+
type,
|
|
105
|
+
registeredAt: new Date().toISOString(),
|
|
106
|
+
metadata,
|
|
107
|
+
};
|
|
108
|
+
this.addresses.push(entry);
|
|
109
|
+
// Sync filepath to the FilesystemTool
|
|
110
|
+
if (type === 'filepath' && this.filesystemTool) {
|
|
111
|
+
await this.filesystemTool._tool_add_path({ params: { path: address } });
|
|
112
|
+
}
|
|
113
|
+
await this.persistAddresses();
|
|
114
|
+
return { success: true };
|
|
115
|
+
}
|
|
116
|
+
async _tool_remove_address(request) {
|
|
117
|
+
const { address } = request.params;
|
|
118
|
+
const entry = this.addresses.find((a) => a.address === address);
|
|
119
|
+
const before = this.addresses.length;
|
|
120
|
+
this.addresses = this.addresses.filter((a) => a.address !== address);
|
|
121
|
+
const removed = this.addresses.length < before;
|
|
122
|
+
if (removed) {
|
|
123
|
+
// Unsync from FilesystemTool
|
|
124
|
+
if (entry?.type === 'filepath' && this.filesystemTool) {
|
|
125
|
+
await this.filesystemTool._tool_remove_path({ params: { path: address } });
|
|
126
|
+
}
|
|
127
|
+
await this.persistAddresses();
|
|
128
|
+
}
|
|
129
|
+
return { success: true, removed };
|
|
130
|
+
}
|
|
131
|
+
async _tool_list_addresses(request) {
|
|
132
|
+
const { type } = request.params;
|
|
133
|
+
const filtered = type
|
|
134
|
+
? this.addresses.filter((a) => a.type === type)
|
|
135
|
+
: [...this.addresses];
|
|
136
|
+
return { success: true, addresses: filtered };
|
|
137
|
+
}
|
|
138
|
+
async _tool_get_world_info(_request) {
|
|
139
|
+
return {
|
|
140
|
+
success: true,
|
|
141
|
+
config: this.worldConfig,
|
|
142
|
+
addressCount: this.addresses.length,
|
|
143
|
+
filesystemPaths: this.filesystemTool?.getAllowedPaths() || [],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// ── Convenience accessors ─────────────────────────────────
|
|
147
|
+
getAddresses(type) {
|
|
148
|
+
if (type)
|
|
149
|
+
return this.addresses.filter((a) => a.type === type);
|
|
150
|
+
return [...this.addresses];
|
|
151
|
+
}
|
|
152
|
+
// ── Persistence ────────────────────────────────────────────
|
|
153
|
+
async loadAddresses() {
|
|
154
|
+
if (!this.persistPath)
|
|
155
|
+
return;
|
|
156
|
+
try {
|
|
157
|
+
if (await pathExists(this.persistPath)) {
|
|
158
|
+
const raw = await readFile(this.persistPath, 'utf8');
|
|
159
|
+
if (!raw.trim())
|
|
160
|
+
return;
|
|
161
|
+
const data = JSON.parse(raw);
|
|
162
|
+
this.addresses = data.addresses || [];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
this.addresses = [];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
async persistAddresses() {
|
|
170
|
+
if (!this.persistPath)
|
|
171
|
+
return;
|
|
172
|
+
await mkdir(path.dirname(this.persistPath), { recursive: true });
|
|
173
|
+
const data = {
|
|
174
|
+
config: this.worldConfig,
|
|
175
|
+
addresses: this.addresses,
|
|
176
|
+
};
|
|
177
|
+
await writeFile(this.persistPath, JSON.stringify(data, null, 2), 'utf8');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
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
|
+
import { WorldInstanceTool } from './world-instance.tool.js';
|
|
6
|
+
import type { WorldConfig, WorldSupportedType } from './world.types.js';
|
|
7
|
+
export interface WorldManagerConfig extends oNodeConfig {
|
|
8
|
+
/** Base storage path for world data. Defaults to ~/.olane/storage/{systemName}/worlds/ */
|
|
9
|
+
storagePath?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* WorldManagerTool — dedicated oLaneTool node at o://world-manager.
|
|
13
|
+
* Child of the root leader. Manages the lifecycle of all world instance nodes.
|
|
14
|
+
*
|
|
15
|
+
* On startup: reads persisted world configs and starts a WorldInstanceTool child for each.
|
|
16
|
+
*/
|
|
17
|
+
export declare class WorldManagerTool extends oLaneTool {
|
|
18
|
+
private worlds;
|
|
19
|
+
private storagePath;
|
|
20
|
+
private fsWatcher;
|
|
21
|
+
private syncDebounce;
|
|
22
|
+
constructor(config: WorldManagerConfig);
|
|
23
|
+
start(): Promise<void>;
|
|
24
|
+
stop(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Watch the worlds directory for file changes.
|
|
27
|
+
* When the CLI writes a new address to a world JSON,
|
|
28
|
+
* the running instance picks it up and syncs to memory.
|
|
29
|
+
*/
|
|
30
|
+
private startWatching;
|
|
31
|
+
private stopWatching;
|
|
32
|
+
/**
|
|
33
|
+
* Sync a world from its JSON file on disk into the running instance.
|
|
34
|
+
* Handles both new worlds and updated addresses on existing worlds.
|
|
35
|
+
*/
|
|
36
|
+
private syncFromDisk;
|
|
37
|
+
_tool_create_world(request: oRequest): Promise<ToolResult>;
|
|
38
|
+
_tool_remove_world(request: oRequest): Promise<ToolResult>;
|
|
39
|
+
_tool_list_worlds(_request: oRequest): Promise<ToolResult>;
|
|
40
|
+
_tool_join_world(request: oRequest): Promise<ToolResult>;
|
|
41
|
+
listWorlds(): WorldConfig[];
|
|
42
|
+
getWorldInstance(id: string): WorldInstanceTool | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Create a world (public convenience, delegates to _tool_create_world).
|
|
45
|
+
*/
|
|
46
|
+
createWorld(params: {
|
|
47
|
+
name: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
icon?: string;
|
|
50
|
+
supportedTypes?: WorldSupportedType[];
|
|
51
|
+
createdBy?: string;
|
|
52
|
+
}): Promise<ToolResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Join a world (public convenience, delegates to _tool_join_world).
|
|
55
|
+
*/
|
|
56
|
+
joinWorld(id: string, copassId: string): Promise<ToolResult>;
|
|
57
|
+
private startWorldInstance;
|
|
58
|
+
private restoreWorlds;
|
|
59
|
+
private persistWorldConfig;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=world-manager.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-manager.tool.d.ts","sourceRoot":"","sources":["../../../src/worlds/world-manager.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAY,QAAQ,EAAyB,MAAM,eAAe,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAa,MAAM,kBAAkB,CAAC;AAKnF,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,0FAA0F;IAC1F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;GAKG;AACH,qBAAa,gBAAiB,SAAQ,SAAS;IAC7C,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,YAAY,CAA+B;gBAEvC,MAAM,EAAE,kBAAkB;IAsDhC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,YAAY;IAQpB;;;OAGG;YACW,YAAY;IAqCpB,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IA4B1D,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAkB1D,iBAAiB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAK1D,gBAAgB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAiB9D,UAAU,IAAI,WAAW,EAAE;IAI3B,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAI3D;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE;QACxB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,cAAc,CAAC,EAAE,kBAAkB,EAAE,CAAC;QACtC,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,UAAU,CAAC;IAIvB;;OAEG;IACG,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;YAMpD,kBAAkB;YAwBlB,aAAa;YAsBb,kBAAkB;CAkBjC"}
|