@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
@@ -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 type { WorldConfig, WorldAddressEntry, WorldSupportedType } from './world.types.js';
6
+ /**
7
+ * A world instance node — hub for addresses of a given world.
8
+ * Registered as a child of the WorldManagerTool at o://world-manager/{world-name}.
9
+ *
10
+ * Uses the shared OS-level FilesystemTool for scoped filesystem access
11
+ * to the directories (addresses) registered with it.
12
+ */
13
+ export declare class WorldInstanceTool extends oLaneTool {
14
+ private worldConfig;
15
+ private addresses;
16
+ private persistPath;
17
+ private fsAddress;
18
+ constructor(nodeConfig: oNodeConfig, worldConfig: WorldConfig, persistPath?: string);
19
+ get world(): WorldConfig;
20
+ start(): Promise<void>;
21
+ _tool_register_address(request: oRequest): Promise<ToolResult>;
22
+ _tool_remove_address(request: oRequest): Promise<ToolResult>;
23
+ _tool_list_addresses(request: oRequest): Promise<ToolResult>;
24
+ _tool_get_world_info(_request: oRequest): Promise<ToolResult>;
25
+ _tool_ping_address(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,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;IACxC,OAAO,CAAC,SAAS,CAA0B;gBAGzC,UAAU,EAAE,WAAW,EACvB,WAAW,EAAE,WAAW,EACxB,WAAW,CAAC,EAAE,MAAM;IAmDtB,IAAI,KAAK,IAAI,WAAW,CAEvB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAgBtB,sBAAsB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAuC9D,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;IAU7D,kBAAkB,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC;IAgChE,YAAY,CAAC,IAAI,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,EAAE;YAO9C,aAAa;IAcrB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;CASxC"}
@@ -0,0 +1,214 @@
1
+ import { oLaneTool } from '@olane/o-lane';
2
+ import { oAddress } from '@olane/o-core';
3
+ import { readFile, writeFile, mkdir, access } from 'fs/promises';
4
+ import * as path from 'path';
5
+ async function pathExists(p) {
6
+ try {
7
+ await access(p);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ /**
15
+ * A world instance node — hub for addresses of a given world.
16
+ * Registered as a child of the WorldManagerTool at o://world-manager/{world-name}.
17
+ *
18
+ * Uses the shared OS-level FilesystemTool for scoped filesystem access
19
+ * to the directories (addresses) registered with it.
20
+ */
21
+ export class WorldInstanceTool extends oLaneTool {
22
+ constructor(nodeConfig, worldConfig, persistPath) {
23
+ super({
24
+ ...nodeConfig,
25
+ description: `World instance: ${worldConfig.name}`,
26
+ methods: {
27
+ register_address: {
28
+ name: 'register_address',
29
+ description: 'Register an address (directory path) with this world',
30
+ parameters: [
31
+ { name: 'address', type: 'string', required: true, description: 'The directory path to register' },
32
+ { name: 'type', type: 'string', required: true, description: 'Address type (e.g. filepath)' },
33
+ ],
34
+ dependencies: [],
35
+ },
36
+ remove_address: {
37
+ name: 'remove_address',
38
+ description: 'Remove an address from this world',
39
+ parameters: [
40
+ { name: 'address', type: 'string', required: true, description: 'The address to remove' },
41
+ ],
42
+ dependencies: [],
43
+ },
44
+ list_addresses: {
45
+ name: 'list_addresses',
46
+ description: 'List all addresses in this world',
47
+ parameters: [
48
+ { name: 'type', type: 'string', required: false, description: 'Filter by type' },
49
+ ],
50
+ dependencies: [],
51
+ },
52
+ get_world_info: {
53
+ name: 'get_world_info',
54
+ description: 'Get info about this world instance',
55
+ parameters: [],
56
+ dependencies: [],
57
+ },
58
+ ping_address: {
59
+ name: 'ping_address',
60
+ description: 'Ping a registered address to verify the underlying resource still exists',
61
+ parameters: [
62
+ { name: 'address', type: 'string', required: true, description: 'The registered address to ping' },
63
+ ],
64
+ dependencies: [],
65
+ },
66
+ },
67
+ });
68
+ this.addresses = [];
69
+ this.fsAddress = new oAddress('o://fs');
70
+ this.worldConfig = worldConfig;
71
+ this.persistPath = persistPath;
72
+ }
73
+ get world() {
74
+ return this.worldConfig;
75
+ }
76
+ async start() {
77
+ await super.start();
78
+ await this.loadAddresses();
79
+ // Sync existing filepath addresses to the shared OS-level FilesystemTool
80
+ const filepathAddresses = this.addresses
81
+ .filter((a) => a.type === 'filepath')
82
+ .map((a) => a.address);
83
+ for (const addr of filepathAddresses) {
84
+ await this.use(this.fsAddress, { method: 'add_path', params: { path: addr } });
85
+ }
86
+ }
87
+ // ── Tool methods ───────────────────────────────────────────
88
+ async _tool_register_address(request) {
89
+ const { address, type, metadata } = request.params;
90
+ if (!this.worldConfig.supportedTypes.includes(type)) {
91
+ return {
92
+ success: false,
93
+ error: `Unsupported type '${type}'. Supported: ${this.worldConfig.supportedTypes.join(', ')}`,
94
+ };
95
+ }
96
+ const existing = this.addresses.find((a) => a.address === address);
97
+ if (existing) {
98
+ return {
99
+ success: false,
100
+ error: `Address '${address}' is already registered in world '${this.worldConfig.name}'`,
101
+ };
102
+ }
103
+ // Validate and register with o://fs BEFORE storing
104
+ if (type === 'filepath') {
105
+ const fsResult = await this.use(this.fsAddress, { method: 'add_path', params: { path: address } });
106
+ if (!fsResult.result?.success) {
107
+ return {
108
+ success: false,
109
+ error: fsResult.result?.error || `Address '${address}' does not exist or is not a valid directory`,
110
+ };
111
+ }
112
+ }
113
+ const entry = {
114
+ address,
115
+ type,
116
+ registeredAt: new Date().toISOString(),
117
+ metadata,
118
+ };
119
+ this.addresses.push(entry);
120
+ await this.persistAddresses();
121
+ return { success: true };
122
+ }
123
+ async _tool_remove_address(request) {
124
+ const { address } = request.params;
125
+ const entry = this.addresses.find((a) => a.address === address);
126
+ const before = this.addresses.length;
127
+ this.addresses = this.addresses.filter((a) => a.address !== address);
128
+ const removed = this.addresses.length < before;
129
+ if (removed) {
130
+ // Unsync from FilesystemTool
131
+ if (entry?.type === 'filepath') {
132
+ await this.use(this.fsAddress, { method: 'remove_path', params: { path: address } });
133
+ }
134
+ await this.persistAddresses();
135
+ }
136
+ return { success: true, removed };
137
+ }
138
+ async _tool_list_addresses(request) {
139
+ const { type } = request.params;
140
+ const filtered = type
141
+ ? this.addresses.filter((a) => a.type === type)
142
+ : [...this.addresses];
143
+ return { success: true, addresses: filtered };
144
+ }
145
+ async _tool_get_world_info(_request) {
146
+ const fsResponse = await this.use(this.fsAddress, { method: 'list_paths' });
147
+ return {
148
+ success: true,
149
+ config: this.worldConfig,
150
+ addressCount: this.addresses.length,
151
+ filesystemPaths: fsResponse.result?.paths || [],
152
+ };
153
+ }
154
+ async _tool_ping_address(request) {
155
+ const { address } = request.params;
156
+ const entry = this.addresses.find((a) => a.address === address);
157
+ if (!entry) {
158
+ return { success: false, error: `Address '${address}' is not registered in this world` };
159
+ }
160
+ if (entry.type === 'filepath') {
161
+ const fsResult = await this.use(this.fsAddress, { method: 'stat_path', params: { path: entry.address } });
162
+ if (!fsResult.result?.success) {
163
+ return {
164
+ success: false,
165
+ address: entry.address,
166
+ type: entry.type,
167
+ error: fsResult.result?.error || 'Resource not reachable',
168
+ };
169
+ }
170
+ return {
171
+ success: true,
172
+ address: entry.address,
173
+ type: entry.type,
174
+ isDirectory: fsResult.result.isDirectory,
175
+ size: fsResult.result.size,
176
+ modified: fsResult.result.modified,
177
+ };
178
+ }
179
+ return { success: false, error: `Ping not supported for type '${entry.type}'` };
180
+ }
181
+ // ── Convenience accessors ─────────────────────────────────
182
+ getAddresses(type) {
183
+ if (type)
184
+ return this.addresses.filter((a) => a.type === type);
185
+ return [...this.addresses];
186
+ }
187
+ // ── Persistence ────────────────────────────────────────────
188
+ async loadAddresses() {
189
+ if (!this.persistPath)
190
+ return;
191
+ try {
192
+ if (await pathExists(this.persistPath)) {
193
+ const raw = await readFile(this.persistPath, 'utf8');
194
+ if (!raw.trim())
195
+ return;
196
+ const data = JSON.parse(raw);
197
+ this.addresses = data.addresses || [];
198
+ }
199
+ }
200
+ catch {
201
+ this.addresses = [];
202
+ }
203
+ }
204
+ async persistAddresses() {
205
+ if (!this.persistPath)
206
+ return;
207
+ await mkdir(path.dirname(this.persistPath), { recursive: true });
208
+ const data = {
209
+ config: this.worldConfig,
210
+ addresses: this.addresses,
211
+ };
212
+ await writeFile(this.persistPath, JSON.stringify(data, null, 2), 'utf8');
213
+ }
214
+ }
@@ -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"}