omniwire 2.0.0

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 (90) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +316 -0
  3. package/dist/claude/integration.d.ts +12 -0
  4. package/dist/claude/integration.js +157 -0
  5. package/dist/claude/integration.js.map +1 -0
  6. package/dist/commands/browser.d.ts +2 -0
  7. package/dist/commands/browser.js +23 -0
  8. package/dist/commands/browser.js.map +1 -0
  9. package/dist/commands/builtins.d.ts +4 -0
  10. package/dist/commands/builtins.js +309 -0
  11. package/dist/commands/builtins.js.map +1 -0
  12. package/dist/commands/router.d.ts +2 -0
  13. package/dist/commands/router.js +174 -0
  14. package/dist/commands/router.js.map +1 -0
  15. package/dist/index.d.ts +2 -0
  16. package/dist/index.js +198 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/mcp/index.d.ts +2 -0
  19. package/dist/mcp/index.js +71 -0
  20. package/dist/mcp/index.js.map +1 -0
  21. package/dist/mcp/rest.d.ts +3 -0
  22. package/dist/mcp/rest.js +98 -0
  23. package/dist/mcp/rest.js.map +1 -0
  24. package/dist/mcp/server.d.ts +4 -0
  25. package/dist/mcp/server.js +419 -0
  26. package/dist/mcp/server.js.map +1 -0
  27. package/dist/mcp/sse.d.ts +2 -0
  28. package/dist/mcp/sse.js +43 -0
  29. package/dist/mcp/sse.js.map +1 -0
  30. package/dist/mcp/sync-tools.d.ts +5 -0
  31. package/dist/mcp/sync-tools.js +124 -0
  32. package/dist/mcp/sync-tools.js.map +1 -0
  33. package/dist/nodes/manager.d.ts +28 -0
  34. package/dist/nodes/manager.js +341 -0
  35. package/dist/nodes/manager.js.map +1 -0
  36. package/dist/nodes/realtime.d.ts +13 -0
  37. package/dist/nodes/realtime.js +46 -0
  38. package/dist/nodes/realtime.js.map +1 -0
  39. package/dist/nodes/shell.d.ts +17 -0
  40. package/dist/nodes/shell.js +137 -0
  41. package/dist/nodes/shell.js.map +1 -0
  42. package/dist/nodes/transfer.d.ts +22 -0
  43. package/dist/nodes/transfer.js +244 -0
  44. package/dist/nodes/transfer.js.map +1 -0
  45. package/dist/nodes/tunnel.d.ts +12 -0
  46. package/dist/nodes/tunnel.js +49 -0
  47. package/dist/nodes/tunnel.js.map +1 -0
  48. package/dist/protocol/config.d.ts +9 -0
  49. package/dist/protocol/config.js +133 -0
  50. package/dist/protocol/config.js.map +1 -0
  51. package/dist/protocol/paths.d.ts +3 -0
  52. package/dist/protocol/paths.js +19 -0
  53. package/dist/protocol/paths.js.map +1 -0
  54. package/dist/protocol/types.d.ts +106 -0
  55. package/dist/protocol/types.js +3 -0
  56. package/dist/protocol/types.js.map +1 -0
  57. package/dist/sync/db.d.ts +53 -0
  58. package/dist/sync/db.js +212 -0
  59. package/dist/sync/db.js.map +1 -0
  60. package/dist/sync/engine.d.ts +23 -0
  61. package/dist/sync/engine.js +251 -0
  62. package/dist/sync/engine.js.map +1 -0
  63. package/dist/sync/hasher.d.ts +2 -0
  64. package/dist/sync/hasher.js +25 -0
  65. package/dist/sync/hasher.js.map +1 -0
  66. package/dist/sync/index.d.ts +6 -0
  67. package/dist/sync/index.js +155 -0
  68. package/dist/sync/index.js.map +1 -0
  69. package/dist/sync/manifest.d.ts +4 -0
  70. package/dist/sync/manifest.js +105 -0
  71. package/dist/sync/manifest.js.map +1 -0
  72. package/dist/sync/memory-bridge.d.ts +7 -0
  73. package/dist/sync/memory-bridge.js +84 -0
  74. package/dist/sync/memory-bridge.js.map +1 -0
  75. package/dist/sync/paths.d.ts +6 -0
  76. package/dist/sync/paths.js +53 -0
  77. package/dist/sync/paths.js.map +1 -0
  78. package/dist/sync/schema.d.ts +2 -0
  79. package/dist/sync/schema.js +72 -0
  80. package/dist/sync/schema.js.map +1 -0
  81. package/dist/sync/types.d.ts +83 -0
  82. package/dist/sync/types.js +11 -0
  83. package/dist/sync/types.js.map +1 -0
  84. package/dist/sync/watcher.d.ts +21 -0
  85. package/dist/sync/watcher.js +87 -0
  86. package/dist/sync/watcher.js.map +1 -0
  87. package/dist/ui/format.d.ts +24 -0
  88. package/dist/ui/format.js +108 -0
  89. package/dist/ui/format.js.map +1 -0
  90. package/package.json +72 -0
@@ -0,0 +1,84 @@
1
+ // CyberSync — SQLite (Claude memory.db) -> PostgreSQL ingestion
2
+ //
3
+ // Reads Claude Code's local memory.db and ingests entries into
4
+ // the shared PostgreSQL knowledge + claude_memory tables.
5
+ import Database from 'better-sqlite3';
6
+ import { existsSync } from 'node:fs';
7
+ export class MemoryBridge {
8
+ db;
9
+ nodeId;
10
+ constructor(db, nodeId) {
11
+ this.db = db;
12
+ this.nodeId = nodeId;
13
+ }
14
+ // Ingest all entries from a local memory.db into PostgreSQL
15
+ async ingest(dbPath) {
16
+ if (!existsSync(dbPath))
17
+ return 0;
18
+ let sqlite;
19
+ try {
20
+ sqlite = new Database(dbPath, { readonly: true });
21
+ }
22
+ catch {
23
+ return 0;
24
+ }
25
+ let ingested = 0;
26
+ try {
27
+ // Discover tables — Claude memory.db schema may vary
28
+ const tables = sqlite.prepare("SELECT name FROM sqlite_master WHERE type='table'").all();
29
+ for (const { name } of tables) {
30
+ if (name.startsWith('sqlite_') || name === '_migrations')
31
+ continue;
32
+ try {
33
+ const columns = sqlite.prepare(`PRAGMA table_info("${name}")`).all();
34
+ const colNames = columns.map((c) => c.name);
35
+ // Strategy 1: key-value tables
36
+ if (colNames.includes('key') && colNames.includes('value')) {
37
+ const rows = sqlite.prepare(`SELECT key, value FROM "${name}"`).all();
38
+ for (const row of rows) {
39
+ await this.db.upsertClaudeMemory(this.nodeId, `${name}:${row.key}`, row.value);
40
+ await this.db.upsertKnowledge('claude-code', `${name}:${row.key}`, {
41
+ source: 'memory.db',
42
+ table: name,
43
+ node: this.nodeId,
44
+ value: tryParseJson(row.value),
45
+ });
46
+ ingested++;
47
+ }
48
+ continue;
49
+ }
50
+ // Strategy 2: generic tables — ingest as JSON rows
51
+ if (colNames.length > 0) {
52
+ const rows = sqlite.prepare(`SELECT * FROM "${name}" LIMIT 1000`).all();
53
+ for (let i = 0; i < rows.length; i++) {
54
+ const key = `${name}:row_${i}`;
55
+ await this.db.upsertKnowledge('claude-code', key, {
56
+ source: 'memory.db',
57
+ table: name,
58
+ node: this.nodeId,
59
+ ...rows[i],
60
+ });
61
+ ingested++;
62
+ }
63
+ }
64
+ }
65
+ catch {
66
+ // Skip tables that fail to query
67
+ }
68
+ }
69
+ }
70
+ finally {
71
+ sqlite.close();
72
+ }
73
+ return ingested;
74
+ }
75
+ }
76
+ function tryParseJson(value) {
77
+ try {
78
+ return JSON.parse(value);
79
+ }
80
+ catch {
81
+ return value;
82
+ }
83
+ }
84
+ //# sourceMappingURL=memory-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-bridge.js","sourceRoot":"","sources":["../../src/sync/memory-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare function toLinuxPath(content: string): string;
2
+ export declare function toWindowsPath(content: string): string;
3
+ export declare function adaptPathsForNode(content: string, targetOs: 'windows' | 'linux'): string;
4
+ export declare function getToolBaseDir(tool: string, os: 'windows' | 'linux'): string;
5
+ export declare function isJsonFile(filePath: string): boolean;
6
+ export declare function normalizeRelPath(relPath: string): string;
@@ -0,0 +1,53 @@
1
+ // OmniWire Sync — Windows/Linux path adaptation for JSON content
2
+ import { homedir } from 'node:os';
3
+ const WIN_HOME = homedir().replaceAll('\\', '/');
4
+ const WIN_HOME_BACKSLASH = homedir();
5
+ const LINUX_HOME = process.env.OMNIWIRE_LINUX_HOME ?? '/root';
6
+ const PATH_MAPS = [
7
+ [WIN_HOME_BACKSLASH, LINUX_HOME],
8
+ [WIN_HOME, LINUX_HOME],
9
+ ];
10
+ export function toLinuxPath(content) {
11
+ let result = content;
12
+ for (const [win, linux] of PATH_MAPS) {
13
+ result = result.replaceAll(win, linux);
14
+ }
15
+ return result.replaceAll('\\\\', '/').replaceAll('\\', '/');
16
+ }
17
+ export function toWindowsPath(content) {
18
+ let result = content;
19
+ for (const [win, linux] of PATH_MAPS) {
20
+ result = result.replaceAll(linux, win);
21
+ }
22
+ return result;
23
+ }
24
+ export function adaptPathsForNode(content, targetOs) {
25
+ return targetOs === 'windows' ? toWindowsPath(content) : toLinuxPath(content);
26
+ }
27
+ export function getToolBaseDir(tool, os) {
28
+ const home = os === 'windows' ? WIN_HOME : LINUX_HOME;
29
+ switch (tool) {
30
+ case 'claude-code':
31
+ return `${home}/.claude`;
32
+ case 'opencode':
33
+ return `${home}/.config/opencode`;
34
+ case 'openclaw':
35
+ return `${home}/.openclaw`;
36
+ case 'codex':
37
+ return `${home}/.codex`;
38
+ case 'gemini':
39
+ return `${home}/.gemini`;
40
+ case 'paperclip':
41
+ return `${home}/.paperclip`;
42
+ default:
43
+ return `${home}/.${tool}`;
44
+ }
45
+ }
46
+ export function isJsonFile(filePath) {
47
+ const lower = filePath.toLowerCase();
48
+ return lower.endsWith('.json') || lower.endsWith('.jsonc');
49
+ }
50
+ export function normalizeRelPath(relPath) {
51
+ return relPath.replaceAll('\\', '/');
52
+ }
53
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/sync/paths.ts"],"names":[],"mappings":"AAAA,iEAAiE;AAEjE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,MAAM,QAAQ,GAAG,OAAO,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACjD,MAAM,kBAAkB,GAAG,OAAO,EAAE,CAAC;AACrC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC;AAE9D,MAAM,SAAS,GAA6C;IAC1D,CAAC,kBAAkB,EAAE,UAAU,CAAC;IAChC,CAAC,QAAQ,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,IAAI,MAAM,GAAG,OAAO,CAAC;IACrB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QACrC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,IAAI,MAAM,GAAG,OAAO,CAAC;IACrB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,SAAS,EAAE,CAAC;QACrC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,QAA6B;IAC9E,OAAO,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,EAAuB;IAClE,MAAM,IAAI,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;IAEtD,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,aAAa;YAChB,OAAO,GAAG,IAAI,UAAU,CAAC;QAC3B,KAAK,UAAU;YACb,OAAO,GAAG,IAAI,mBAAmB,CAAC;QACpC,KAAK,UAAU;YACb,OAAO,GAAG,IAAI,YAAY,CAAC;QAC7B,KAAK,OAAO;YACV,OAAO,GAAG,IAAI,SAAS,CAAC;QAC1B,KAAK,QAAQ;YACX,OAAO,GAAG,IAAI,UAAU,CAAC;QAC3B,KAAK,WAAW;YACd,OAAO,GAAG,IAAI,aAAa,CAAC;QAC9B;YACE,OAAO,GAAG,IAAI,KAAK,IAAI,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type pg from 'pg';
2
+ export declare function runMigrations(pool: pg.Pool): Promise<void>;
@@ -0,0 +1,72 @@
1
+ // CyberSync — PostgreSQL schema + migration runner
2
+ const STATEMENTS = [
3
+ `CREATE TABLE IF NOT EXISTS sync_items (
4
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
5
+ tool TEXT NOT NULL,
6
+ category TEXT NOT NULL,
7
+ rel_path TEXT NOT NULL,
8
+ content_hash TEXT NOT NULL,
9
+ content BYTEA,
10
+ content_size BIGINT NOT NULL DEFAULT 0,
11
+ metadata JSONB DEFAULT '{}',
12
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
13
+ updated_by_node TEXT NOT NULL,
14
+ is_deleted BOOLEAN DEFAULT false,
15
+ UNIQUE(tool, rel_path)
16
+ )`,
17
+ `CREATE TABLE IF NOT EXISTS node_sync_state (
18
+ node_id TEXT NOT NULL,
19
+ item_id UUID NOT NULL REFERENCES sync_items(id) ON DELETE CASCADE,
20
+ content_hash TEXT NOT NULL,
21
+ synced_at TIMESTAMPTZ NOT NULL DEFAULT now(),
22
+ PRIMARY KEY (node_id, item_id)
23
+ )`,
24
+ `CREATE TABLE IF NOT EXISTS sync_events (
25
+ id BIGSERIAL PRIMARY KEY,
26
+ item_id UUID REFERENCES sync_items(id) ON DELETE SET NULL,
27
+ node_id TEXT NOT NULL,
28
+ event_type TEXT NOT NULL,
29
+ detail TEXT,
30
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
31
+ )`,
32
+ `CREATE TABLE IF NOT EXISTS knowledge (
33
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
34
+ source_tool TEXT NOT NULL,
35
+ key TEXT NOT NULL,
36
+ value JSONB NOT NULL,
37
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
38
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
39
+ )`,
40
+ `CREATE TABLE IF NOT EXISTS claude_memory (
41
+ id BIGSERIAL PRIMARY KEY,
42
+ node_id TEXT NOT NULL,
43
+ key TEXT NOT NULL,
44
+ value TEXT NOT NULL,
45
+ ingested_at TIMESTAMPTZ NOT NULL DEFAULT now(),
46
+ UNIQUE(node_id, key)
47
+ )`,
48
+ `CREATE TABLE IF NOT EXISTS node_heartbeats (
49
+ node_id TEXT PRIMARY KEY,
50
+ last_seen TIMESTAMPTZ NOT NULL DEFAULT now(),
51
+ items_count INTEGER DEFAULT 0,
52
+ pending_sync INTEGER DEFAULT 0
53
+ )`,
54
+ 'CREATE INDEX IF NOT EXISTS idx_sync_items_tool ON sync_items(tool)',
55
+ 'CREATE INDEX IF NOT EXISTS idx_sync_items_updated ON sync_items(updated_at)',
56
+ 'CREATE INDEX IF NOT EXISTS idx_sync_events_node ON sync_events(node_id)',
57
+ 'CREATE INDEX IF NOT EXISTS idx_sync_events_created ON sync_events(created_at)',
58
+ 'CREATE INDEX IF NOT EXISTS idx_knowledge_key ON knowledge(key)',
59
+ 'CREATE INDEX IF NOT EXISTS idx_claude_memory_node ON claude_memory(node_id)',
60
+ // v2.1 migrations: unique constraint for upsert + FTS index
61
+ 'CREATE UNIQUE INDEX IF NOT EXISTS idx_knowledge_tool_key ON knowledge(source_tool, key)',
62
+ `CREATE INDEX IF NOT EXISTS idx_knowledge_fts ON knowledge USING GIN (
63
+ to_tsvector('english', key || ' ' || value::text)
64
+ )`,
65
+ 'CREATE INDEX IF NOT EXISTS idx_sync_events_created_desc ON sync_events(created_at DESC)',
66
+ ];
67
+ export async function runMigrations(pool) {
68
+ for (const sql of STATEMENTS) {
69
+ await pool.query(sql);
70
+ }
71
+ }
72
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/sync/schema.ts"],"names":[],"mappings":"AAAA,mDAAmD;AAInD,MAAM,UAAU,GAAsB;IACpC;;;;;;;;;;;;;IAaE;IACF;;;;;;IAME;IACF;;;;;;;IAOE;IACF;;;;;;;IAOE;IACF;;;;;;;IAOE;IACF;;;;;IAKE;IACF,oEAAoE;IACpE,6EAA6E;IAC7E,yEAAyE;IACzE,+EAA+E;IAC/E,gEAAgE;IAChE,6EAA6E;IAC7E,4DAA4D;IAC5D,yFAAyF;IACzF;;IAEE;IACF,yFAAyF;CAC1F,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAa;IAC/C,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,83 @@
1
+ export interface SyncItem {
2
+ readonly id: string;
3
+ readonly tool: ToolName;
4
+ readonly category: string;
5
+ readonly relPath: string;
6
+ readonly contentHash: string;
7
+ readonly content: Buffer | null;
8
+ readonly contentSize: number;
9
+ readonly metadata: Record<string, unknown>;
10
+ readonly updatedAt: Date;
11
+ readonly updatedByNode: string;
12
+ readonly isDeleted: boolean;
13
+ }
14
+ export interface NodeSyncState {
15
+ readonly nodeId: string;
16
+ readonly itemId: string;
17
+ readonly contentHash: string;
18
+ readonly syncedAt: Date;
19
+ }
20
+ export interface SyncEvent {
21
+ readonly id: number;
22
+ readonly itemId: string | null;
23
+ readonly nodeId: string;
24
+ readonly eventType: SyncEventType;
25
+ readonly detail: string | null;
26
+ readonly createdAt: Date;
27
+ }
28
+ export type SyncEventType = 'push' | 'pull' | 'conflict' | 'delete' | 'reconcile' | 'error';
29
+ export interface KnowledgeEntry {
30
+ readonly id: string;
31
+ readonly sourceTool: ToolName;
32
+ readonly key: string;
33
+ readonly value: Record<string, unknown>;
34
+ readonly createdAt: Date;
35
+ readonly updatedAt: Date;
36
+ }
37
+ export interface ClaudeMemoryEntry {
38
+ readonly id: number;
39
+ readonly nodeId: string;
40
+ readonly key: string;
41
+ readonly value: string;
42
+ readonly ingestedAt: Date;
43
+ }
44
+ export interface NodeHeartbeat {
45
+ readonly nodeId: string;
46
+ readonly lastSeen: Date;
47
+ readonly itemsCount: number;
48
+ readonly pendingSync: number;
49
+ }
50
+ export type ToolName = 'claude-code' | 'opencode' | 'openclaw' | 'codex' | 'gemini' | 'paperclip';
51
+ export interface ToolManifest {
52
+ readonly tool: ToolName;
53
+ readonly baseDir: string;
54
+ readonly syncGlobs: readonly string[];
55
+ readonly excludeGlobs: readonly string[];
56
+ readonly ingestDb?: string;
57
+ }
58
+ export interface SyncDiff {
59
+ readonly itemId: string;
60
+ readonly relPath: string;
61
+ readonly tool: ToolName;
62
+ readonly localHash: string | null;
63
+ readonly remoteHash: string;
64
+ readonly direction: 'push' | 'pull' | 'conflict';
65
+ }
66
+ export interface SyncStatus {
67
+ readonly nodeId: string;
68
+ readonly totalItems: number;
69
+ readonly pendingSync: number;
70
+ readonly lastSync: Date | null;
71
+ readonly online: boolean;
72
+ }
73
+ export interface SyncConfig {
74
+ readonly nodeId: string;
75
+ readonly pgHost: string;
76
+ readonly pgPort: number;
77
+ readonly pgDatabase: string;
78
+ readonly pgUser: string;
79
+ readonly pgPassword: string;
80
+ readonly watchDebounceMs: number;
81
+ readonly reconcileIntervalMs: number;
82
+ }
83
+ export declare const DEFAULT_SYNC_CONFIG: Omit<SyncConfig, 'nodeId'>;
@@ -0,0 +1,11 @@
1
+ // CyberSync — Type definitions for unified mesh sync
2
+ export const DEFAULT_SYNC_CONFIG = {
3
+ pgHost: process.env.CYBERSYNC_PG_HOST ?? 'localhost',
4
+ pgPort: parseInt(process.env.CYBERSYNC_PG_PORT ?? '5432'),
5
+ pgDatabase: process.env.CYBERSYNC_PG_DATABASE ?? 'cybersync',
6
+ pgUser: process.env.CYBERSYNC_PG_USER ?? 'cybersync',
7
+ pgPassword: process.env.CYBERSYNC_PG_PASSWORD ?? '',
8
+ watchDebounceMs: 300,
9
+ reconcileIntervalMs: 5 * 60 * 1000,
10
+ };
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA,qDAAqD;AAgGrD,MAAM,CAAC,MAAM,mBAAmB,GAA+B;IAC7D,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,WAAW;IACpD,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,MAAM,CAAC;IACzD,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,WAAW;IAC5D,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,WAAW;IACpD,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,EAAE;IACnD,eAAe,EAAE,GAAG;IACpB,mBAAmB,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;CACnC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { ToolManifest } from './types.js';
2
+ export type FileChangeEvent = {
3
+ readonly type: 'add' | 'change' | 'unlink';
4
+ readonly tool: string;
5
+ readonly relPath: string;
6
+ readonly absPath: string;
7
+ };
8
+ export type ChangeHandler = (event: FileChangeEvent) => void;
9
+ export declare class SyncWatcher {
10
+ private manifests;
11
+ private debounceMs;
12
+ private onChange;
13
+ private watcher;
14
+ private pendingChanges;
15
+ private flushTimer;
16
+ private baseDirMap;
17
+ constructor(manifests: readonly ToolManifest[], debounceMs: number, onChange: ChangeHandler);
18
+ start(): void;
19
+ private scheduleFlush;
20
+ stop(): Promise<void>;
21
+ }
@@ -0,0 +1,87 @@
1
+ // CyberSync — single consolidated chokidar watcher with batch debounce
2
+ import { watch } from 'chokidar';
3
+ import { existsSync } from 'node:fs';
4
+ import { relative } from 'node:path';
5
+ import { normalizeRelPath } from './paths.js';
6
+ export class SyncWatcher {
7
+ manifests;
8
+ debounceMs;
9
+ onChange;
10
+ watcher = null;
11
+ pendingChanges = new Map();
12
+ flushTimer = null;
13
+ baseDirMap = [];
14
+ constructor(manifests, debounceMs, onChange) {
15
+ this.manifests = manifests;
16
+ this.debounceMs = debounceMs;
17
+ this.onChange = onChange;
18
+ }
19
+ start() {
20
+ const allGlobs = [];
21
+ const allIgnored = [];
22
+ for (const manifest of this.manifests) {
23
+ if (!existsSync(manifest.baseDir))
24
+ continue;
25
+ const baseNormalized = manifest.baseDir.replaceAll('\\', '/');
26
+ this.baseDirMap.push({ baseDir: baseNormalized, tool: manifest.tool });
27
+ for (const g of manifest.syncGlobs) {
28
+ allGlobs.push(`${baseNormalized}/${g}`);
29
+ }
30
+ for (const g of manifest.excludeGlobs) {
31
+ allIgnored.push(`${baseNormalized}/${g}`);
32
+ }
33
+ }
34
+ if (allGlobs.length === 0)
35
+ return;
36
+ this.watcher = watch(allGlobs, {
37
+ ignored: allIgnored,
38
+ persistent: true,
39
+ ignoreInitial: true,
40
+ awaitWriteFinish: { stabilityThreshold: 200, pollInterval: 50 },
41
+ followSymlinks: false,
42
+ });
43
+ const emit = (type, absPath) => {
44
+ const normalized = absPath.replaceAll('\\', '/');
45
+ // Find which tool manifest owns this file
46
+ const match = this.baseDirMap.find((m) => normalized.startsWith(m.baseDir + '/'));
47
+ if (!match)
48
+ return;
49
+ const relPath = normalizeRelPath(relative(match.baseDir, normalized));
50
+ const key = `${match.tool}:${relPath}`;
51
+ this.pendingChanges.set(key, {
52
+ type,
53
+ tool: match.tool,
54
+ relPath,
55
+ absPath: normalized,
56
+ });
57
+ this.scheduleFlush();
58
+ };
59
+ this.watcher.on('add', (p) => emit('add', p));
60
+ this.watcher.on('change', (p) => emit('change', p));
61
+ this.watcher.on('unlink', (p) => emit('unlink', p));
62
+ }
63
+ scheduleFlush() {
64
+ if (this.flushTimer)
65
+ return;
66
+ this.flushTimer = setTimeout(() => {
67
+ this.flushTimer = null;
68
+ const batch = [...this.pendingChanges.values()];
69
+ this.pendingChanges.clear();
70
+ for (const event of batch) {
71
+ this.onChange(event);
72
+ }
73
+ }, this.debounceMs);
74
+ }
75
+ async stop() {
76
+ if (this.flushTimer) {
77
+ clearTimeout(this.flushTimer);
78
+ this.flushTimer = null;
79
+ }
80
+ this.pendingChanges.clear();
81
+ if (this.watcher) {
82
+ await this.watcher.close();
83
+ this.watcher = null;
84
+ }
85
+ }
86
+ }
87
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/sync/watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export declare const bold: import("chalk").ChalkInstance;
2
+ export declare const dim: import("chalk").ChalkInstance;
3
+ export declare const red: import("chalk").ChalkInstance;
4
+ export declare const green: import("chalk").ChalkInstance;
5
+ export declare const yellow: import("chalk").ChalkInstance;
6
+ export declare const cyan: import("chalk").ChalkInstance;
7
+ export declare const magenta: import("chalk").ChalkInstance;
8
+ export declare const blue: import("chalk").ChalkInstance;
9
+ export declare const gray: import("chalk").ChalkInstance;
10
+ export declare const white: import("chalk").ChalkInstance;
11
+ export declare function nodeColor(nodeId: string): string;
12
+ export declare function nodeTag(nodeId: string): string;
13
+ export declare function formatTable(headers: string[], rows: string[][]): string;
14
+ export declare class Spinner {
15
+ private frame;
16
+ private interval;
17
+ private message;
18
+ constructor(message: string);
19
+ start(): void;
20
+ stop(finalMessage?: string): void;
21
+ update(message: string): void;
22
+ }
23
+ export declare function banner(onlineCount: number, totalCount: number): string;
24
+ export declare function prompt(onlineNodes: string[]): string;
@@ -0,0 +1,108 @@
1
+ // OmniWire UI — terminal formatting utilities
2
+ import chalk from 'chalk';
3
+ // Re-export chalk helpers for consistent styling
4
+ export const bold = chalk.bold;
5
+ export const dim = chalk.dim;
6
+ export const red = chalk.red;
7
+ export const green = chalk.green;
8
+ export const yellow = chalk.yellow;
9
+ export const cyan = chalk.cyan;
10
+ export const magenta = chalk.magenta;
11
+ export const blue = chalk.blue;
12
+ export const gray = chalk.gray;
13
+ export const white = chalk.white;
14
+ // Node-specific colors — auto-assigned from palette on first use
15
+ const COLOR_PALETTE = [chalk.blue.bold, chalk.green.bold, chalk.magenta.bold, chalk.cyan.bold, chalk.yellow.bold, chalk.red.bold];
16
+ const NODE_COLORS = {};
17
+ let colorIndex = 0;
18
+ function getNodeColorFn(nodeId) {
19
+ if (!NODE_COLORS[nodeId]) {
20
+ NODE_COLORS[nodeId] = COLOR_PALETTE[colorIndex % COLOR_PALETTE.length];
21
+ colorIndex++;
22
+ }
23
+ return NODE_COLORS[nodeId];
24
+ }
25
+ export function nodeColor(nodeId) {
26
+ return getNodeColorFn(nodeId)(`[${nodeId}]`);
27
+ }
28
+ export function nodeTag(nodeId) {
29
+ return getNodeColorFn(nodeId)(nodeId);
30
+ }
31
+ // Simple ASCII table formatter
32
+ export function formatTable(headers, rows) {
33
+ const allRows = [headers, ...rows];
34
+ const colWidths = headers.map((_, colIdx) => {
35
+ // Strip ANSI codes for width calculation
36
+ return Math.max(...allRows.map((row) => stripAnsi(row[colIdx] ?? '').length));
37
+ });
38
+ const sep = colWidths.map((w) => '─'.repeat(w + 2)).join('┼');
39
+ const headerLine = headers
40
+ .map((h, i) => ` ${padRight(h, colWidths[i])} `)
41
+ .join('│');
42
+ const dataLines = rows.map((row) => row.map((cell, i) => {
43
+ const visible = stripAnsi(cell);
44
+ const padding = colWidths[i] - visible.length;
45
+ return ` ${cell}${' '.repeat(Math.max(0, padding))} `;
46
+ }).join('│'));
47
+ return [headerLine, `─${sep}─`, ...dataLines].join('\n');
48
+ }
49
+ function padRight(str, len) {
50
+ const visible = stripAnsi(str);
51
+ return str + ' '.repeat(Math.max(0, len - visible.length));
52
+ }
53
+ // Strip ANSI escape codes for width calculation
54
+ function stripAnsi(str) {
55
+ return str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
56
+ }
57
+ // Spinner frames for loading states
58
+ const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
59
+ export class Spinner {
60
+ frame = 0;
61
+ interval = null;
62
+ message;
63
+ constructor(message) {
64
+ this.message = message;
65
+ }
66
+ start() {
67
+ this.interval = setInterval(() => {
68
+ const frame = SPINNER_FRAMES[this.frame % SPINNER_FRAMES.length];
69
+ process.stdout.write(`\r${cyan(frame)} ${this.message}`);
70
+ this.frame++;
71
+ }, 80);
72
+ }
73
+ stop(finalMessage) {
74
+ if (this.interval) {
75
+ clearInterval(this.interval);
76
+ this.interval = null;
77
+ }
78
+ process.stdout.write(`\r${' '.repeat(this.message.length + 4)}\r`);
79
+ if (finalMessage) {
80
+ console.log(finalMessage);
81
+ }
82
+ }
83
+ update(message) {
84
+ this.message = message;
85
+ }
86
+ }
87
+ // Banner
88
+ export function banner(onlineCount, totalCount) {
89
+ const status = onlineCount === totalCount
90
+ ? green(`${onlineCount}/${totalCount} online`)
91
+ : yellow(`${onlineCount}/${totalCount} online`);
92
+ return `
93
+ ${bold(cyan('╔══════════════════════════════════════════════╗'))}
94
+ ${bold(cyan('║'))} ${bold(white('OmniWire Terminal'))} ${dim('v2.0')} ${bold(cyan('║'))}
95
+ ${bold(cyan('║'))} ${dim('Unified mesh • MCP • 22 tools')} ${bold(cyan('║'))}
96
+ ${bold(cyan('║'))} ${dim('Nodes:')} ${status} ${bold(cyan('║'))}
97
+ ${bold(cyan('╚══════════════════════════════════════════════╝'))}
98
+ ${dim('Type @help for commands • @status for mesh health')}
99
+ `;
100
+ }
101
+ // Prompt string with node indicators
102
+ export function prompt(onlineNodes) {
103
+ const indicators = onlineNodes
104
+ .map((id) => getNodeColorFn(id)('●'))
105
+ .join('');
106
+ return `${indicators} ${bold(cyan('omniwire'))}${dim('>')} `;
107
+ }
108
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/ui/format.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAE9C,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,iDAAiD;AACjD,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AAC/B,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;AAC7B,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;AACjC,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;AACnC,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AAC/B,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AACrC,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AAC/B,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;AAC/B,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;AAEjC,iEAAiE;AACjE,MAAM,aAAa,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAClI,MAAM,WAAW,GAA0C,EAAE,CAAC;AAC9D,IAAI,UAAU,GAAG,CAAC,CAAC;AAEnB,SAAS,cAAc,CAAC,MAAc;IACpC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,WAAW,CAAC,MAAM,CAAC,GAAG,aAAa,CAAC,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACvE,UAAU,EAAE,CAAC;IACf,CAAC;IACD,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,MAAc;IACpC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC;AACxC,CAAC;AAED,+BAA+B;AAC/B,MAAM,UAAU,WAAW,CAAC,OAAiB,EAAE,IAAgB;IAC7D,MAAM,OAAO,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC1C,yCAAyC;QACzC,OAAO,IAAI,CAAC,GAAG,CACb,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAC7D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,OAAO;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;SAC/C,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACjC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE;QAClB,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9C,OAAO,IAAI,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC;IACxD,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CACb,CAAC;IAEF,OAAO,CAAC,UAAU,EAAE,IAAI,GAAG,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,GAAW;IACxC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,gDAAgD;AAChD,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,GAAG,CAAC,OAAO,CAAC,wBAAwB,EAAE,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,oCAAoC;AACpC,MAAM,cAAc,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAE1E,MAAM,OAAO,OAAO;IACV,KAAK,GAAG,CAAC,CAAC;IACV,QAAQ,GAA0C,IAAI,CAAC;IACvD,OAAO,CAAS;IAExB,YAAY,OAAe;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE;YAC/B,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YACzD,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,EAAE,EAAE,CAAC,CAAC;IACT,CAAC;IAED,IAAI,CAAC,YAAqB;QACxB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC7B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACvB,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACnE,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,MAAM,CAAC,OAAe;QACpB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;AAED,SAAS;AACT,MAAM,UAAU,MAAM,CAAC,WAAmB,EAAE,UAAkB;IAC5D,MAAM,MAAM,GAAG,WAAW,KAAK,UAAU;QACvC,CAAC,CAAC,KAAK,CAAC,GAAG,WAAW,IAAI,UAAU,SAAS,CAAC;QAC9C,CAAC,CAAC,MAAM,CAAC,GAAG,WAAW,IAAI,UAAU,SAAS,CAAC,CAAC;IAElD,OAAO;EACP,IAAI,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;EAC9D,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,wBAAwB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;EAC1G,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,+BAA+B,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;EACxF,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,QAAQ,CAAC,IAAI,MAAM,0BAA0B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;EACpF,IAAI,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;IAC5D,GAAG,CAAC,mDAAmD,CAAC;CAC3D,CAAC;AACF,CAAC;AAED,qCAAqC;AACrC,MAAM,UAAU,MAAM,CAAC,WAAqB;IAC1C,MAAM,UAAU,GAAG,WAAW;SAC3B,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;SACpC,IAAI,CAAC,EAAE,CAAC,CAAC;IACZ,OAAO,GAAG,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;AAC/D,CAAC"}