omniwire 3.2.1 → 3.3.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.
@@ -1 +1 @@
1
- {"session_id":"8ef02123-7368-447d-82e3-ee14a27328b0","transcript_path":"C:\\Users\\Admin\\.claude\\projects\\C--Users-Admin\\8ef02123-7368-447d-82e3-ee14a27328b0.jsonl","cwd":"C:\\Users\\Admin\\omniwire","model":{"id":"claude-opus-4-6[1m]","display_name":"Opus 4.6 (1M context)"},"workspace":{"current_dir":"C:\\Users\\Admin\\omniwire","project_dir":"C:\\Users\\Admin","added_dirs":["C:/Users/Admin"]},"version":"2.1.87","output_style":{"name":"default"},"cost":{"total_cost_usd":4.372866899999998,"total_duration_ms":1369723,"total_api_duration_ms":587779,"total_lines_added":38,"total_lines_removed":24},"context_window":{"total_input_tokens":786,"total_output_tokens":21423,"context_window_size":1000000,"current_usage":{"input_tokens":1,"output_tokens":95,"cache_creation_input_tokens":261,"cache_read_input_tokens":99806},"used_percentage":10,"remaining_percentage":90},"exceeds_200k_tokens":false,"rate_limits":{"five_hour":{"used_percentage":35,"resets_at":1774828800},"seven_day":{"used_percentage":41,"resets_at":1775206800}}}
1
+ {"session_id":"8ef02123-7368-447d-82e3-ee14a27328b0","transcript_path":"C:\\Users\\Admin\\.claude\\projects\\C--Users-Admin\\8ef02123-7368-447d-82e3-ee14a27328b0.jsonl","cwd":"C:\\Users\\Admin\\omniwire","model":{"id":"claude-opus-4-6[1m]","display_name":"Opus 4.6 (1M context)"},"workspace":{"current_dir":"C:\\Users\\Admin\\omniwire","project_dir":"C:\\Users\\Admin","added_dirs":["C:/Users/Admin"]},"version":"2.1.87","output_style":{"name":"default"},"cost":{"total_cost_usd":10.609117700000006,"total_duration_ms":2361015,"total_api_duration_ms":1488385,"total_lines_added":180,"total_lines_removed":39},"context_window":{"total_input_tokens":1132,"total_output_tokens":59608,"context_window_size":1000000,"current_usage":{"input_tokens":1,"output_tokens":293,"cache_creation_input_tokens":257,"cache_read_input_tokens":138910},"used_percentage":14,"remaining_percentage":86},"exceeds_200k_tokens":false,"rate_limits":{"five_hour":{"used_percentage":37,"resets_at":1774828800},"seven_day":{"used_percentage":41,"resets_at":1775206800}}}
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  <p align="center">
10
10
  <a href="https://www.npmjs.com/package/omniwire"><img src="https://img.shields.io/npm/v/omniwire?style=for-the-badge&logo=npm&color=CB3837&labelColor=0D1117" alt="npm" /></a>
11
- <img src="https://img.shields.io/badge/MCP_Tools-81-59C2FF?style=for-the-badge&labelColor=0D1117" alt="tools" />
11
+ <img src="https://img.shields.io/badge/MCP_Tools-86-59C2FF?style=for-the-badge&labelColor=0D1117" alt="tools" />
12
12
  <img src="https://img.shields.io/badge/A2A-Protocol-00C853?style=for-the-badge&labelColor=0D1117" alt="A2A" />
13
13
  <img src="https://img.shields.io/badge/Latency-~80ms-FF6D00?style=for-the-badge&labelColor=0D1117" alt="latency" />
14
14
  <img src="https://img.shields.io/badge/CyberBase-Sync-CC93E6?style=for-the-badge&labelColor=0D1117" alt="cyberbase" />
@@ -19,7 +19,7 @@
19
19
 
20
20
  **The infrastructure layer for AI agent swarms.**
21
21
 
22
- 82 MCP tools · A2A protocol · OmniMesh VPN · nftables firewall · CDP browser · cookie sync · 2FA TOTP · CyberBase persistence
22
+ 87 MCP tools · A2A protocol · OmniMesh VPN · nftables firewall · CDP browser · cookie sync · 2FA TOTP · bi-directional sync · CyberBase persistence
23
23
 
24
24
  </div>
25
25
 
@@ -214,7 +214,7 @@ graph TB
214
214
  direction TB
215
215
  MCP["MCP Protocol Layer<br/>stdio | SSE | REST"]
216
216
 
217
- subgraph tools["81 Tools"]
217
+ subgraph tools["86 Tools"]
218
218
  direction LR
219
219
  EXEC["Execution<br/>exec run batch<br/>broadcast pipeline bg"]
220
220
  AGENT["Agentic<br/>store watch task<br/>a2a events locks"]
@@ -687,6 +687,8 @@ omniwire/
687
687
 
688
688
  | Version | Date | Changes |
689
689
  |---------|------|---------|
690
+ | **v3.3.0** | 2026-03-30 | New: `omniwire_coc` tool — unified CyberBase + Obsidian + Canvas sync. Auto-creates vault + canvas. `mirror-db` exports entire DB as .md. Configurable vault via `OMNIWIRE_VAULT_ROOT` env. 87 tools. |
691
+ | **v3.2.2** | 2026-03-30 | Fix: sync GitHub/npm metadata — badge, description, mermaid diagram all reflect 86 tools |
690
692
  | **v3.2.1** | 2026-03-30 | New: 5 bi-directional sync tools (`omniwire_sync`, `omniwire_sync_rules`, `omniwire_sync_hooks`, `omniwire_sync_memory`, `omniwire_sync_agents`) — 86 tools total |
691
693
  | **v3.2.0** | 2026-03-29 | New: `omniwire_2fa` TOTP manager — add/generate/verify/import/export 2FA codes, CyberBase + 1Password persistence, otpauth:// URI import, bulk code generation |
692
694
  | **v3.1.5** | 2026-03-29 | Fix: skip auto-audit batch entries from Obsidian vault + Canvas sync to prevent junk files |
@@ -6,7 +6,7 @@
6
6
  // authenticated, encrypted SSH channels. The "exec" references below are SSH2 methods.
7
7
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
8
  import { z } from 'zod';
9
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
9
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from 'node:fs';
10
10
  import { join } from 'node:path';
11
11
  import { ShellManager, kernelExec } from '../nodes/shell.js';
12
12
  import { RealtimeChannel } from '../nodes/realtime.js';
@@ -248,10 +248,40 @@ async function drainCb() {
248
248
  }
249
249
  // -- Obsidian + Canvas auto-sync ------------------------------------------------
250
250
  // Mirrors CyberBase writes to local Obsidian vault + Canvas mindmap.
251
- // Vault path is resolved at startup; if it doesn't exist, sync is silently skipped.
252
- const VAULT_ROOT = join(process.env.USERPROFILE ?? process.env.HOME ?? '', 'Documents', 'BuisnessProjects', 'CyberBase');
253
- const CANVAS_PATH = join(VAULT_ROOT, 'CyberBase MindMap.canvas');
251
+ // Vault path resolved from env or default; if it doesn't exist, sync is silently skipped.
252
+ // Set OMNIWIRE_VAULT_ROOT to override, or OMNIWIRE_CANVAS_NAME for custom canvas filename.
253
+ const VAULT_ROOT = process.env.OMNIWIRE_VAULT_ROOT ?? join(process.env.USERPROFILE ?? process.env.HOME ?? '', 'Documents', 'OmniWire');
254
+ const CANVAS_NAME = process.env.OMNIWIRE_CANVAS_NAME ?? 'OmniWire MindMap.canvas';
255
+ const CANVAS_PATH = join(VAULT_ROOT, CANVAS_NAME);
254
256
  const vaultExists = existsSync(VAULT_ROOT);
257
+ /** Ensure the Obsidian vault root and canvas file exist, creating them if needed */
258
+ function ensureVault() {
259
+ try {
260
+ if (!existsSync(VAULT_ROOT))
261
+ mkdirSync(VAULT_ROOT, { recursive: true });
262
+ if (!existsSync(CANVAS_PATH)) {
263
+ // Create a default canvas with a central hub node
264
+ const defaultCanvas = {
265
+ nodes: [{
266
+ id: 'core',
267
+ type: 'text',
268
+ text: '## OmniWire\nCentral knowledge hub',
269
+ x: 0,
270
+ y: 0,
271
+ width: 300,
272
+ height: 120,
273
+ color: '4',
274
+ }],
275
+ edges: [],
276
+ };
277
+ writeFileSync(CANVAS_PATH, JSON.stringify(defaultCanvas, null, '\t'), 'utf-8');
278
+ }
279
+ return true;
280
+ }
281
+ catch {
282
+ return false;
283
+ }
284
+ }
255
285
  /** Map CyberBase category → Obsidian vault subfolder */
256
286
  function vaultFolder(category) {
257
287
  const cat = category.toLowerCase();
@@ -279,8 +309,8 @@ function sanitizeFilename(key) {
279
309
  }
280
310
  /** Auto-sync a knowledge entry to Obsidian vault as a .md file */
281
311
  function syncObsidian(category, key, value) {
282
- if (!vaultExists)
283
- return;
312
+ if (!existsSync(VAULT_ROOT))
313
+ ensureVault();
284
314
  try {
285
315
  const folder = join(VAULT_ROOT, vaultFolder(category));
286
316
  if (!existsSync(folder))
@@ -359,7 +389,9 @@ function canvasColor(category) {
359
389
  }
360
390
  /** Auto-sync a knowledge entry to the Canvas mindmap — adds or updates a node */
361
391
  function syncCanvas(category, key, value) {
362
- if (!vaultExists || !existsSync(CANVAS_PATH))
392
+ if (!existsSync(CANVAS_PATH))
393
+ ensureVault();
394
+ if (!existsSync(CANVAS_PATH))
363
395
  return;
364
396
  try {
365
397
  const raw = readFileSync(CANVAS_PATH, 'utf-8');
@@ -3993,8 +4025,7 @@ echo "port-knock configured: ${ports.join(' -> ')} -> port ${target}"`;
3993
4025
  if (action === 'sync-obsidian') {
3994
4026
  if (!key || !value)
3995
4027
  return fail('key and value required');
3996
- if (!vaultExists)
3997
- return fail(`Obsidian vault not found at ${VAULT_ROOT}`);
4028
+ ensureVault();
3998
4029
  const cat = category ?? 'general';
3999
4030
  syncObsidian(cat, key, value);
4000
4031
  const folder = vaultFolder(cat);
@@ -4003,14 +4034,117 @@ echo "port-knock configured: ${ports.join(' -> ')} -> port ${target}"`;
4003
4034
  if (action === 'sync-canvas') {
4004
4035
  if (!key || !value)
4005
4036
  return fail('key and value required');
4006
- if (!vaultExists || !existsSync(CANVAS_PATH))
4007
- return fail(`Canvas not found at ${CANVAS_PATH}`);
4037
+ ensureVault();
4008
4038
  const cat = category ?? 'general';
4009
4039
  syncCanvas(cat, key, value);
4010
4040
  return okBrief(`synced to Canvas: node auto_${sanitizeFilename(cat)}_${sanitizeFilename(key)} added/updated`);
4011
4041
  }
4012
4042
  return fail('invalid action');
4013
4043
  });
4044
+ // --- Tool: omniwire_coc ---
4045
+ // COC = CyberBase + Obsidian + Canvas — the default sync mode.
4046
+ // Single tool call writes to all three destinations simultaneously.
4047
+ // Also supports 'mirror-db' to export the entire DB as Obsidian .md files.
4048
+ server.tool('omniwire_coc', 'COC (CyberBase + Obsidian + Canvas) — unified sync. Default: writes to PostgreSQL, Obsidian vault (.md), and Canvas mindmap in one call. Use "mirror-db" to export the entire knowledge DB as Obsidian-formatted markdown files. Use "init" to set up the vault + canvas from scratch.', {
4049
+ action: z.enum(['save', 'mirror-db', 'init', 'status']).describe('save: write to all 3 destinations. mirror-db: export entire DB as .md files. init: create vault + canvas. status: show sync state.'),
4050
+ category: z.string().optional().describe('Knowledge category (e.g., tools, vulns, infra, notes)'),
4051
+ key: z.string().optional().describe('Entry key'),
4052
+ value: z.string().optional().describe('Entry value'),
4053
+ entries: z.array(z.object({ category: z.string(), key: z.string(), value: z.string() })).optional().describe('Bulk save: array of {category, key, value}'),
4054
+ }, async ({ action, category, key, value, entries }) => {
4055
+ if (action === 'init') {
4056
+ const created = ensureVault();
4057
+ if (!created)
4058
+ return fail('Failed to create vault directory');
4059
+ // Create standard subdirectories
4060
+ const dirs = ['projects', 'infrastructure', 'knowledge', 'knowledge/security-kb', 'system', 'logs', 'sync', 'memory'];
4061
+ for (const dir of dirs) {
4062
+ const p = join(VAULT_ROOT, dir);
4063
+ if (!existsSync(p))
4064
+ mkdirSync(p, { recursive: true });
4065
+ }
4066
+ return okBrief(`COC vault initialized at ${VAULT_ROOT}\n Canvas: ${CANVAS_NAME}\n Directories: ${dirs.join(', ')}`);
4067
+ }
4068
+ if (action === 'status') {
4069
+ const vaultOk = existsSync(VAULT_ROOT);
4070
+ const canvasOk = existsSync(CANVAS_PATH);
4071
+ const h = getCbHealth();
4072
+ let canvasNodes = 0;
4073
+ if (canvasOk) {
4074
+ try {
4075
+ const raw = JSON.parse(readFileSync(CANVAS_PATH, 'utf-8'));
4076
+ canvasNodes = raw.nodes?.length ?? 0;
4077
+ }
4078
+ catch { /* ignore */ }
4079
+ }
4080
+ // Count .md files in vault
4081
+ let mdCount = 0;
4082
+ const countMd = (dir) => {
4083
+ try {
4084
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
4085
+ if (entry.isDirectory())
4086
+ countMd(join(dir, entry.name));
4087
+ else if (entry.name.endsWith('.md'))
4088
+ mdCount++;
4089
+ }
4090
+ }
4091
+ catch { /* ignore */ }
4092
+ };
4093
+ if (vaultOk)
4094
+ countMd(VAULT_ROOT);
4095
+ return okBrief(`COC Status:\n Vault: ${vaultOk ? 'OK' : 'MISSING'} (${VAULT_ROOT})\n Canvas: ${canvasOk ? `OK (${canvasNodes} nodes)` : 'MISSING'}\n CyberBase: ${h.healthy ? 'OK' : 'UNHEALTHY'} (queue: ${h.queueSize})\n Obsidian files: ${mdCount} .md files`);
4096
+ }
4097
+ if (action === 'save') {
4098
+ // Bulk save
4099
+ if (entries?.length) {
4100
+ for (const e of entries) {
4101
+ cb(e.category, e.key, e.value);
4102
+ }
4103
+ return okBrief(`COC: saved ${entries.length} entries → CyberBase + Obsidian + Canvas`);
4104
+ }
4105
+ // Single save
4106
+ if (!key || !value)
4107
+ return fail('key and value required (or use entries[] for bulk)');
4108
+ const cat = category ?? 'general';
4109
+ cb(cat, key, value);
4110
+ return okBrief(`COC: saved ${cat}:${key} (${value.length} chars) → CyberBase + Obsidian + Canvas`);
4111
+ }
4112
+ if (action === 'mirror-db') {
4113
+ if (!cbManager)
4114
+ return fail('no CyberBase connection');
4115
+ ensureVault();
4116
+ // Export all knowledge entries from PostgreSQL and write as .md files
4117
+ const r = await cbManager.exec('contabo', `psql -h 127.0.0.1 -U cyberbase -d cyberbase -t -A -F '|' -c "SET statement_timeout='30s'; SELECT key, value->>'data', updated_at FROM knowledge WHERE source_tool='omniwire' ORDER BY key;" 2>/dev/null`);
4118
+ if (!r.stdout.trim())
4119
+ return okBrief('mirror-db: no entries found in CyberBase');
4120
+ const lines = r.stdout.trim().split('\n').filter((l) => l.includes('|'));
4121
+ let synced = 0;
4122
+ let skipped = 0;
4123
+ for (const line of lines) {
4124
+ const parts = line.split('|');
4125
+ if (parts.length < 2) {
4126
+ skipped++;
4127
+ continue;
4128
+ }
4129
+ const fullKey = parts[0].trim();
4130
+ const val = parts.slice(1, -1).join('|').trim(); // rejoin in case value has pipes
4131
+ if (!fullKey || !val) {
4132
+ skipped++;
4133
+ continue;
4134
+ }
4135
+ // Parse category:key format
4136
+ const colonIdx = fullKey.indexOf(':');
4137
+ const cat = colonIdx > 0 ? fullKey.slice(0, colonIdx) : 'general';
4138
+ const entryKey = colonIdx > 0 ? fullKey.slice(colonIdx + 1) : fullKey;
4139
+ syncObsidian(cat, entryKey, val);
4140
+ if (val.length > 50)
4141
+ syncCanvas(cat, entryKey, val);
4142
+ synced++;
4143
+ }
4144
+ return okBrief(`COC mirror-db: ${synced} entries synced to Obsidian + Canvas, ${skipped} skipped\n Vault: ${VAULT_ROOT}`);
4145
+ }
4146
+ return fail('invalid action');
4147
+ });
4014
4148
  // --- Tool 54: omniwire_omnimesh ---
4015
4149
  server.tool('omniwire_omnimesh', 'OmniMesh — built-in WireGuard mesh network manager. Create, manage, and monitor a full-mesh or hub-spoke WireGuard VPN across all nodes and any OS (Linux/Windows/macOS). Actions: status, init, add-peer, remove-peer, genkeys, deploy-config, up, down, install, health, rotate-keys, discover-endpoint, topology, sync-peers.', {
4016
4150
  action: z.enum([