nuxs-capsule 0.1.28 → 0.1.30

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 (114) hide show
  1. package/bin/nuxs-capsule-statusline.js +2 -0
  2. package/dist/agent-compress 2.js +155 -0
  3. package/dist/agent-compress 3.js +155 -0
  4. package/dist/agent-compress.d 2.ts +17 -0
  5. package/dist/agent-compress.d 3.ts +17 -0
  6. package/dist/agent-compress.d.ts 2.map +1 -0
  7. package/dist/agent-compress.d.ts 3.map +1 -0
  8. package/dist/agent-compress.js 2.map +1 -0
  9. package/dist/agent-compress.js 3.map +1 -0
  10. package/dist/install 2.js +270 -0
  11. package/dist/install 3.js +2 -0
  12. package/dist/install.d 2.ts +17 -0
  13. package/dist/install.d 3.ts +1 -0
  14. package/dist/install.d.ts 2.map +1 -0
  15. package/dist/install.d.ts 3.map +1 -0
  16. package/dist/install.js 2.map +1 -0
  17. package/dist/install.js 3.map +1 -0
  18. package/dist/intercept 2.js +406 -0
  19. package/dist/intercept 3.js +406 -0
  20. package/dist/intercept.d 2.ts +19 -0
  21. package/dist/intercept.d 3.ts +19 -0
  22. package/dist/intercept.d.ts 2.map +1 -0
  23. package/dist/intercept.d.ts 3.map +1 -0
  24. package/dist/intercept.js 2.map +1 -0
  25. package/dist/intercept.js 3.map +1 -0
  26. package/dist/lib/stickies.d.ts.map +1 -1
  27. package/dist/lib/stickies.js +18 -11
  28. package/dist/lib/stickies.js.map +1 -1
  29. package/dist/read-compress 2.js +189 -0
  30. package/dist/read-compress 3.js +189 -0
  31. package/dist/read-compress.d 2.ts +24 -0
  32. package/dist/read-compress.d 3.ts +24 -0
  33. package/dist/read-compress.d.ts 2.map +1 -0
  34. package/dist/read-compress.d.ts 3.map +1 -0
  35. package/dist/read-compress.js 2.map +1 -0
  36. package/dist/read-compress.js 3.map +1 -0
  37. package/dist/scan 2.js +253 -0
  38. package/dist/scan 3.js +2 -0
  39. package/dist/scan.d 2.ts +42 -0
  40. package/dist/scan.d 3.ts +1 -0
  41. package/dist/scan.d.ts 2.map +1 -0
  42. package/dist/scan.d.ts 3.map +1 -0
  43. package/dist/scan.js 2.map +1 -0
  44. package/dist/scan.js 3.map +1 -0
  45. package/dist/server 2.js +466 -0
  46. package/dist/server 3.js +466 -0
  47. package/dist/server.d 2.ts +10 -0
  48. package/dist/server.d 3.ts +10 -0
  49. package/dist/server.d.ts 2.map +1 -0
  50. package/dist/server.d.ts 3.map +1 -0
  51. package/dist/server.js 2.map +1 -0
  52. package/dist/server.js 3.map +1 -0
  53. package/dist/session-end 2.js +88 -0
  54. package/dist/session-end 3.js +2 -0
  55. package/dist/session-end.d 2.ts +18 -0
  56. package/dist/session-end.d 3.ts +1 -0
  57. package/dist/session-end.d.ts 2.map +1 -0
  58. package/dist/session-end.d.ts 3.map +1 -0
  59. package/dist/session-end.js +92 -13
  60. package/dist/session-end.js 2.map +1 -0
  61. package/dist/session-end.js 3.map +1 -0
  62. package/dist/session-end.js.map +1 -1
  63. package/dist/session-start 2.js +129 -0
  64. package/dist/session-start 3.js +129 -0
  65. package/dist/session-start.d 2.ts +15 -0
  66. package/dist/session-start.d 3.ts +15 -0
  67. package/dist/session-start.d.ts 2.map +1 -0
  68. package/dist/session-start.d.ts 3.map +1 -0
  69. package/dist/session-start.js +83 -8
  70. package/dist/session-start.js 2.map +1 -0
  71. package/dist/session-start.js 3.map +1 -0
  72. package/dist/session-start.js.map +1 -1
  73. package/dist/setup 2.js +522 -0
  74. package/dist/setup 3.js +522 -0
  75. package/dist/setup.d 2.ts +14 -0
  76. package/dist/setup.d 3.ts +14 -0
  77. package/dist/setup.d.ts 2.map +1 -0
  78. package/dist/setup.d.ts 3.map +1 -0
  79. package/dist/setup.js +15 -3
  80. package/dist/setup.js 2.map +1 -0
  81. package/dist/setup.js 3.map +1 -0
  82. package/dist/setup.js.map +1 -1
  83. package/dist/statusline.d.ts +14 -0
  84. package/dist/statusline.d.ts.map +1 -0
  85. package/dist/statusline.js +61 -0
  86. package/dist/statusline.js.map +1 -0
  87. package/dist/sticky-inject 2.js +88 -0
  88. package/dist/sticky-inject 3.js +2 -0
  89. package/dist/sticky-inject.d 2.ts +20 -0
  90. package/dist/sticky-inject.d 3.ts +1 -0
  91. package/dist/sticky-inject.d.ts 2.map +1 -0
  92. package/dist/sticky-inject.d.ts 3.map +1 -0
  93. package/dist/sticky-inject.js 2.map +1 -0
  94. package/dist/sticky-inject.js 3.map +1 -0
  95. package/dist/telemetry/usage.d.ts.map +1 -1
  96. package/dist/telemetry/usage.js +0 -4
  97. package/dist/telemetry/usage.js.map +1 -1
  98. package/dist/types 2.js +9 -0
  99. package/dist/types 3.js +9 -0
  100. package/dist/types.d 2.ts +371 -0
  101. package/dist/types.d 3.ts +371 -0
  102. package/dist/types.d.ts 2.map +1 -0
  103. package/dist/types.d.ts 3.map +1 -0
  104. package/dist/types.js 2.map +1 -0
  105. package/dist/types.js 3.map +1 -0
  106. package/dist/wrap 2.js +185 -0
  107. package/dist/wrap 3.js +2 -0
  108. package/dist/wrap.d 2.ts +14 -0
  109. package/dist/wrap.d 3.ts +1 -0
  110. package/dist/wrap.d.ts 2.map +1 -0
  111. package/dist/wrap.d.ts 3.map +1 -0
  112. package/dist/wrap.js 2.map +1 -0
  113. package/dist/wrap.js 3.map +1 -0
  114. package/package.json +3 -2
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import('../dist/statusline.js');
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Hook PostToolUse — `nuxs-capsule-agent-compress`.
4
+ *
5
+ * Intercepta result do tool Task (Agent) ou WebFetch quando retorna
6
+ * payload grande (>10k bytes). Gera cápsula TL;DR + bullets com refs.
7
+ *
8
+ * Pra agent: já é um sumário gerado por outro Claude — comprimir o
9
+ * sumário em sumário curto é seguro (não perde primários, eles ja
10
+ * são derivados).
11
+ *
12
+ * Pra WebFetch: comprime HTML/MD em snippet limpo.
13
+ *
14
+ * Original arquivado em ~/.nuxs/archive/.
15
+ */
16
+ import { archiveOriginal } from './lib/archive.js';
17
+ import { trackUsage } from './telemetry/usage.js';
18
+ import { getMachineFingerprint } from './lib/fingerprint.js';
19
+ import { estimateTokensFromBytes, estimateCostUsd } from './lib/tokenCount.js';
20
+ const THRESHOLD_BYTES = 10_000;
21
+ async function readStdin() {
22
+ return new Promise((resolve) => {
23
+ let data = '';
24
+ process.stdin.setEncoding('utf8');
25
+ process.stdin.on('data', (c) => { data += c; });
26
+ process.stdin.on('end', () => resolve(data));
27
+ setTimeout(() => resolve(data), 4000);
28
+ });
29
+ }
30
+ function extractToolText(resp) {
31
+ if (typeof resp === 'string')
32
+ return resp;
33
+ if (!resp)
34
+ return '';
35
+ const c = resp.content;
36
+ if (typeof c === 'string')
37
+ return c;
38
+ if (Array.isArray(c))
39
+ return c.map((x) => (x && typeof x === 'object' && 'text' in x ? x.text : '')).join('\n');
40
+ return '';
41
+ }
42
+ /**
43
+ * Comprime sumário gerado por agent.
44
+ * Estratégia: manter primeiras N linhas (geralmente conclusão),
45
+ * extrair bullets e file:line refs, descartar prosa.
46
+ */
47
+ function compressAgentOutput(text) {
48
+ const lines = text.split('\n');
49
+ const head = lines.slice(0, 10);
50
+ // Coleta bullets (markdown - ou *)
51
+ const bullets = lines.filter((l) => /^\s*[-*•]\s/.test(l)).slice(0, 30);
52
+ // Coleta refs file:line (típico em sumários de Explore)
53
+ const refRegex = /([\w/.-]+\.(ts|tsx|js|jsx|py|md|json|sql|yml|yaml)):(\d+)/g;
54
+ const refs = new Set();
55
+ let m;
56
+ while ((m = refRegex.exec(text)) !== null) {
57
+ refs.add(`${m[1]}:${m[3]}`);
58
+ if (refs.size >= 50)
59
+ break;
60
+ }
61
+ const out = [];
62
+ out.push('[NUXS CAPSULE: agent output comprimido]');
63
+ out.push(`Original: ${lines.length} linhas, ${Buffer.byteLength(text, 'utf8')} bytes.`);
64
+ out.push('');
65
+ out.push('── TL;DR (primeiras 10 linhas) ──');
66
+ out.push(...head);
67
+ if (bullets.length > 0) {
68
+ out.push('');
69
+ out.push('── bullets ──');
70
+ out.push(...bullets);
71
+ }
72
+ if (refs.size > 0) {
73
+ out.push('');
74
+ out.push('── refs encontradas ──');
75
+ out.push(...Array.from(refs));
76
+ }
77
+ return out.join('\n');
78
+ }
79
+ async function main() {
80
+ const stdin = await readStdin();
81
+ if (!stdin) {
82
+ process.exit(0);
83
+ return;
84
+ }
85
+ let input;
86
+ try {
87
+ input = JSON.parse(stdin);
88
+ }
89
+ catch {
90
+ process.exit(0);
91
+ return;
92
+ }
93
+ const toolName = input.tool_name ?? '';
94
+ // Aplica em Task (subagents) e WebFetch
95
+ if (!/^(Task|WebFetch)$/.test(toolName)) {
96
+ process.exit(0);
97
+ return;
98
+ }
99
+ const text = extractToolText(input.tool_response);
100
+ const bytes = Buffer.byteLength(text, 'utf8');
101
+ if (bytes < THRESHOLD_BYTES) {
102
+ process.exit(0);
103
+ return;
104
+ }
105
+ const source = toolName === 'Task'
106
+ ? `agent:${input.tool_input?.subagent_type ?? 'unknown'}:${(input.tool_input?.description ?? '').slice(0, 40)}`
107
+ : `webfetch:${input.tool_input?.url ?? 'unknown'}`;
108
+ const compressed = compressAgentOutput(text);
109
+ const compressedBytes = Buffer.byteLength(compressed, 'utf8');
110
+ const tokensOriginal = estimateTokensFromBytes(bytes);
111
+ const tokensCompressed = estimateTokensFromBytes(compressedBytes);
112
+ const tokensSaved = tokensOriginal - tokensCompressed;
113
+ if (tokensSaved <= 0) {
114
+ process.exit(0);
115
+ return;
116
+ }
117
+ let archivePath;
118
+ try {
119
+ archivePath = archiveOriginal('agent', source, text, {
120
+ tokens_original: tokensOriginal,
121
+ tokens_compressed: tokensCompressed
122
+ });
123
+ }
124
+ catch { /* */ }
125
+ const fingerprint = getMachineFingerprint();
126
+ const record = {
127
+ timestamp: new Date().toISOString(),
128
+ capsule_type: 'api',
129
+ input_size_bytes: bytes,
130
+ output_size_bytes: compressedBytes,
131
+ input_tokens_estimated: tokensOriginal,
132
+ output_tokens_estimated: tokensCompressed,
133
+ tokens_saved: tokensSaved,
134
+ provider_used: 'algorithm',
135
+ cost_saved_usd: estimateCostUsd(tokensSaved, 0, 'sonnet-4-6'),
136
+ agent_detected: 'claude_code',
137
+ latency_ms: 0,
138
+ machine_fingerprint: fingerprint
139
+ };
140
+ try {
141
+ await trackUsage(record);
142
+ }
143
+ catch { /* */ }
144
+ const refLine = archivePath ? `\n📦 Original: ${archivePath}` : '';
145
+ const out = {
146
+ hookSpecificOutput: {
147
+ hookEventName: 'PostToolUse',
148
+ additionalContext: compressed + refLine
149
+ }
150
+ };
151
+ process.stdout.write(JSON.stringify(out));
152
+ process.exit(0);
153
+ }
154
+ main().catch(() => process.exit(0));
155
+ //# sourceMappingURL=agent-compress.js.map
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Hook PostToolUse — `nuxs-capsule-agent-compress`.
4
+ *
5
+ * Intercepta result do tool Task (Agent) ou WebFetch quando retorna
6
+ * payload grande (>10k bytes). Gera cápsula TL;DR + bullets com refs.
7
+ *
8
+ * Pra agent: já é um sumário gerado por outro Claude — comprimir o
9
+ * sumário em sumário curto é seguro (não perde primários, eles ja
10
+ * são derivados).
11
+ *
12
+ * Pra WebFetch: comprime HTML/MD em snippet limpo.
13
+ *
14
+ * Original arquivado em ~/.nuxs/archive/.
15
+ */
16
+ import { archiveOriginal } from './lib/archive.js';
17
+ import { trackUsage } from './telemetry/usage.js';
18
+ import { getMachineFingerprint } from './lib/fingerprint.js';
19
+ import { estimateTokensFromBytes, estimateCostUsd } from './lib/tokenCount.js';
20
+ const THRESHOLD_BYTES = 10_000;
21
+ async function readStdin() {
22
+ return new Promise((resolve) => {
23
+ let data = '';
24
+ process.stdin.setEncoding('utf8');
25
+ process.stdin.on('data', (c) => { data += c; });
26
+ process.stdin.on('end', () => resolve(data));
27
+ setTimeout(() => resolve(data), 4000);
28
+ });
29
+ }
30
+ function extractToolText(resp) {
31
+ if (typeof resp === 'string')
32
+ return resp;
33
+ if (!resp)
34
+ return '';
35
+ const c = resp.content;
36
+ if (typeof c === 'string')
37
+ return c;
38
+ if (Array.isArray(c))
39
+ return c.map((x) => (x && typeof x === 'object' && 'text' in x ? x.text : '')).join('\n');
40
+ return '';
41
+ }
42
+ /**
43
+ * Comprime sumário gerado por agent.
44
+ * Estratégia: manter primeiras N linhas (geralmente conclusão),
45
+ * extrair bullets e file:line refs, descartar prosa.
46
+ */
47
+ function compressAgentOutput(text) {
48
+ const lines = text.split('\n');
49
+ const head = lines.slice(0, 10);
50
+ // Coleta bullets (markdown - ou *)
51
+ const bullets = lines.filter((l) => /^\s*[-*•]\s/.test(l)).slice(0, 30);
52
+ // Coleta refs file:line (típico em sumários de Explore)
53
+ const refRegex = /([\w/.-]+\.(ts|tsx|js|jsx|py|md|json|sql|yml|yaml)):(\d+)/g;
54
+ const refs = new Set();
55
+ let m;
56
+ while ((m = refRegex.exec(text)) !== null) {
57
+ refs.add(`${m[1]}:${m[3]}`);
58
+ if (refs.size >= 50)
59
+ break;
60
+ }
61
+ const out = [];
62
+ out.push('[NUXS CAPSULE: agent output comprimido]');
63
+ out.push(`Original: ${lines.length} linhas, ${Buffer.byteLength(text, 'utf8')} bytes.`);
64
+ out.push('');
65
+ out.push('── TL;DR (primeiras 10 linhas) ──');
66
+ out.push(...head);
67
+ if (bullets.length > 0) {
68
+ out.push('');
69
+ out.push('── bullets ──');
70
+ out.push(...bullets);
71
+ }
72
+ if (refs.size > 0) {
73
+ out.push('');
74
+ out.push('── refs encontradas ──');
75
+ out.push(...Array.from(refs));
76
+ }
77
+ return out.join('\n');
78
+ }
79
+ async function main() {
80
+ const stdin = await readStdin();
81
+ if (!stdin) {
82
+ process.exit(0);
83
+ return;
84
+ }
85
+ let input;
86
+ try {
87
+ input = JSON.parse(stdin);
88
+ }
89
+ catch {
90
+ process.exit(0);
91
+ return;
92
+ }
93
+ const toolName = input.tool_name ?? '';
94
+ // Aplica em Task (subagents) e WebFetch
95
+ if (!/^(Task|WebFetch)$/.test(toolName)) {
96
+ process.exit(0);
97
+ return;
98
+ }
99
+ const text = extractToolText(input.tool_response);
100
+ const bytes = Buffer.byteLength(text, 'utf8');
101
+ if (bytes < THRESHOLD_BYTES) {
102
+ process.exit(0);
103
+ return;
104
+ }
105
+ const source = toolName === 'Task'
106
+ ? `agent:${input.tool_input?.subagent_type ?? 'unknown'}:${(input.tool_input?.description ?? '').slice(0, 40)}`
107
+ : `webfetch:${input.tool_input?.url ?? 'unknown'}`;
108
+ const compressed = compressAgentOutput(text);
109
+ const compressedBytes = Buffer.byteLength(compressed, 'utf8');
110
+ const tokensOriginal = estimateTokensFromBytes(bytes);
111
+ const tokensCompressed = estimateTokensFromBytes(compressedBytes);
112
+ const tokensSaved = tokensOriginal - tokensCompressed;
113
+ if (tokensSaved <= 0) {
114
+ process.exit(0);
115
+ return;
116
+ }
117
+ let archivePath;
118
+ try {
119
+ archivePath = archiveOriginal('agent', source, text, {
120
+ tokens_original: tokensOriginal,
121
+ tokens_compressed: tokensCompressed
122
+ });
123
+ }
124
+ catch { /* */ }
125
+ const fingerprint = getMachineFingerprint();
126
+ const record = {
127
+ timestamp: new Date().toISOString(),
128
+ capsule_type: 'api',
129
+ input_size_bytes: bytes,
130
+ output_size_bytes: compressedBytes,
131
+ input_tokens_estimated: tokensOriginal,
132
+ output_tokens_estimated: tokensCompressed,
133
+ tokens_saved: tokensSaved,
134
+ provider_used: 'algorithm',
135
+ cost_saved_usd: estimateCostUsd(tokensSaved, 0, 'sonnet-4-6'),
136
+ agent_detected: 'claude_code',
137
+ latency_ms: 0,
138
+ machine_fingerprint: fingerprint
139
+ };
140
+ try {
141
+ await trackUsage(record);
142
+ }
143
+ catch { /* */ }
144
+ const refLine = archivePath ? `\n📦 Original: ${archivePath}` : '';
145
+ const out = {
146
+ hookSpecificOutput: {
147
+ hookEventName: 'PostToolUse',
148
+ additionalContext: compressed + refLine
149
+ }
150
+ };
151
+ process.stdout.write(JSON.stringify(out));
152
+ process.exit(0);
153
+ }
154
+ main().catch(() => process.exit(0));
155
+ //# sourceMappingURL=agent-compress.js.map
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Hook PostToolUse — `nuxs-capsule-agent-compress`.
4
+ *
5
+ * Intercepta result do tool Task (Agent) ou WebFetch quando retorna
6
+ * payload grande (>10k bytes). Gera cápsula TL;DR + bullets com refs.
7
+ *
8
+ * Pra agent: já é um sumário gerado por outro Claude — comprimir o
9
+ * sumário em sumário curto é seguro (não perde primários, eles ja
10
+ * são derivados).
11
+ *
12
+ * Pra WebFetch: comprime HTML/MD em snippet limpo.
13
+ *
14
+ * Original arquivado em ~/.nuxs/archive/.
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=agent-compress.d.ts.map
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Hook PostToolUse — `nuxs-capsule-agent-compress`.
4
+ *
5
+ * Intercepta result do tool Task (Agent) ou WebFetch quando retorna
6
+ * payload grande (>10k bytes). Gera cápsula TL;DR + bullets com refs.
7
+ *
8
+ * Pra agent: já é um sumário gerado por outro Claude — comprimir o
9
+ * sumário em sumário curto é seguro (não perde primários, eles ja
10
+ * são derivados).
11
+ *
12
+ * Pra WebFetch: comprime HTML/MD em snippet limpo.
13
+ *
14
+ * Original arquivado em ~/.nuxs/archive/.
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=agent-compress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-compress.d.ts","sourceRoot":"","sources":["../src/agent-compress.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-compress.d.ts","sourceRoot":"","sources":["../src/agent-compress.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;GAaG"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-compress.js","sourceRoot":"","sources":["../src/agent-compress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-compress.js","sourceRoot":"","sources":["../src/agent-compress.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * CLI: `npx nuxs-capsule install`
3
+ *
4
+ * Instalador GUIADO interativo [Finn 26/Mai/2026]. Diferente do setup
5
+ * que só configura MCP local, este aqui:
6
+ *
7
+ * 1. Detecta tudo no PC [Claude Code, Cursor, OpenClaw CLI, Hermes API]
8
+ * 2. Configura local via setup.ts
9
+ * 3. Lê ~/.ssh/config + ~/.ssh/known_hosts pra achar servidores
10
+ * 4. Lista hosts e pergunta "instalar Capsule lá também?"
11
+ * 5. Se sim, faz SSH e roda install-linux.sh remoto via curl
12
+ * 6. License key entrada UMA vez, usada pra todos
13
+ *
14
+ * Modelo de UX: estilo `vercel` CLI [pergunta o mínimo, faz o resto].
15
+ */
16
+ import { execSync } from 'node:child_process';
17
+ import { existsSync, readFileSync } from 'node:fs';
18
+ import { homedir } from 'node:os';
19
+ import { dirname, join } from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+ import { createInterface } from 'node:readline/promises';
22
+ // __dirname não existe em ESM — derivar via import.meta.
23
+ const __filename = fileURLToPath(import.meta.url);
24
+ const __dirname = dirname(__filename);
25
+ const SSH_CONFIG = join(homedir(), '.ssh', 'config');
26
+ const SSH_KNOWN_HOSTS = join(homedir(), '.ssh', 'known_hosts');
27
+ const INSTALL_LINUX_URL = 'https://pixeldesk.dev/install-linux.sh';
28
+ // ─── Detect local ──────────────────────────────────────────────────
29
+ function detectLocalAgents() {
30
+ const out = [];
31
+ if (existsSync(join(homedir(), '.claude', 'settings.json'))) {
32
+ out.push({ kind: 'claude_code', source: 'local', detail: '~/.claude/settings.json' });
33
+ }
34
+ if (existsSync(join(homedir(), '.cursor', 'mcp.json'))) {
35
+ out.push({ kind: 'cursor', source: 'local', detail: '~/.cursor/mcp.json' });
36
+ }
37
+ // OpenClaw CLI no PATH
38
+ try {
39
+ const path = execSync('which openclaw', { stdio: ['ignore', 'pipe', 'ignore'] })
40
+ .toString().trim();
41
+ if (path) {
42
+ out.push({ kind: 'openclaw', source: 'local', detail: path });
43
+ }
44
+ }
45
+ catch { /* not installed */ }
46
+ // Hermes API rodando local
47
+ try {
48
+ const r = execSync('curl -s -m 1 http://127.0.0.1:8642/v1/models 2>/dev/null || echo NO', {
49
+ stdio: ['ignore', 'pipe', 'ignore']
50
+ }).toString().trim();
51
+ if (r && !r.includes('NO')) {
52
+ out.push({ kind: 'hermes', source: 'local', detail: 'http://127.0.0.1:8642' });
53
+ }
54
+ }
55
+ catch { /* not running */ }
56
+ return out;
57
+ }
58
+ // ─── Detect SSH hosts ──────────────────────────────────────────────
59
+ function parseSshConfig(text) {
60
+ const hosts = [];
61
+ let cur = null;
62
+ for (const raw of text.split('\n')) {
63
+ const line = raw.trim();
64
+ if (!line || line.startsWith('#'))
65
+ continue;
66
+ const m = line.match(/^(\w+)\s+(.+)$/);
67
+ if (!m)
68
+ continue;
69
+ const key = m[1].toLowerCase();
70
+ const val = m[2].trim();
71
+ if (key === 'host') {
72
+ // pode ser "Host alias" ou "Host *" (wildcard, ignora)
73
+ if (val === '*' || val.includes('*')) {
74
+ cur = null;
75
+ continue;
76
+ }
77
+ if (cur)
78
+ hosts.push(cur);
79
+ cur = { alias: val, hostname: val };
80
+ }
81
+ else if (cur) {
82
+ if (key === 'hostname')
83
+ cur.hostname = val;
84
+ else if (key === 'user')
85
+ cur.user = val;
86
+ else if (key === 'port')
87
+ cur.port = parseInt(val, 10);
88
+ else if (key === 'identityfile')
89
+ cur.identityFile = val;
90
+ }
91
+ }
92
+ if (cur)
93
+ hosts.push(cur);
94
+ return hosts;
95
+ }
96
+ function detectSshHosts() {
97
+ if (!existsSync(SSH_CONFIG))
98
+ return [];
99
+ try {
100
+ return parseSshConfig(readFileSync(SSH_CONFIG, 'utf8'));
101
+ }
102
+ catch {
103
+ return [];
104
+ }
105
+ }
106
+ // ─── Remote install via SSH ────────────────────────────────────────
107
+ async function probeRemoteAgents(host) {
108
+ const target = host.user ? `${host.user}@${host.hostname}` : host.alias;
109
+ const ssh = `ssh -o ConnectTimeout=5 -o BatchMode=yes ${target}`;
110
+ const out = [];
111
+ try {
112
+ const oc = execSync(`${ssh} 'which openclaw 2>/dev/null || echo NO'`, {
113
+ stdio: ['ignore', 'pipe', 'ignore'], timeout: 8000
114
+ }).toString().trim();
115
+ if (oc && !oc.includes('NO')) {
116
+ out.push({ kind: 'openclaw', source: 'remote', host: host.alias, detail: oc });
117
+ }
118
+ }
119
+ catch { /* timeout ou auth fail */ }
120
+ try {
121
+ const hr = execSync(`${ssh} 'curl -s -m 1 http://127.0.0.1:8642/v1/models >/dev/null 2>&1 && echo YES || echo NO'`, { stdio: ['ignore', 'pipe', 'ignore'], timeout: 8000 }).toString().trim();
122
+ if (hr === 'YES') {
123
+ out.push({ kind: 'hermes', source: 'remote', host: host.alias, detail: '127.0.0.1:8642' });
124
+ }
125
+ }
126
+ catch { /* idem */ }
127
+ return out;
128
+ }
129
+ function remoteInstall(host, kind, envVars) {
130
+ const envStr = Object.entries(envVars)
131
+ .map(([k, v]) => `${k}=${JSON.stringify(v)}`)
132
+ .join(' ');
133
+ const target = host.user ? `${host.user}@${host.hostname}` : host.alias;
134
+ const cmd = `ssh ${target} "curl -fsSL ${INSTALL_LINUX_URL} | ${envStr} AGENT_KIND=${kind} bash"`;
135
+ console.log(` → ssh ${target} curl ${INSTALL_LINUX_URL} | bash`);
136
+ try {
137
+ execSync(cmd, { stdio: 'inherit', timeout: 90_000 });
138
+ return true;
139
+ }
140
+ catch (err) {
141
+ console.error(` ✗ Falhou: ${err.message}`);
142
+ return false;
143
+ }
144
+ }
145
+ // ─── Main flow ─────────────────────────────────────────────────────
146
+ async function ask(rl, q) {
147
+ return (await rl.question(q)).trim();
148
+ }
149
+ async function confirm(rl, q) {
150
+ const ans = (await rl.question(`${q} [y/N] `)).trim().toLowerCase();
151
+ return ans === 'y' || ans === 'yes' || ans === 's' || ans === 'sim';
152
+ }
153
+ async function main() {
154
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
155
+ try {
156
+ console.log('\n🟢 Nuxs Capsule — Instalador guiado\n');
157
+ // 1. License key
158
+ console.log('Pra licenciar todas as instalações [PC + servidores] de uma vez:');
159
+ const licenseKey = await ask(rl, ' License key [nxs_…] ou Enter pra Free anônimo: ');
160
+ // 2. Token do PixelDesk pros bridges
161
+ const pdToken = await ask(rl, ' PixelDesk agent token [pdsk_…]: ');
162
+ const pdSlug = await ask(rl, ' PixelDesk office slug: ');
163
+ // 3. Detect local
164
+ console.log('\n🔍 Detectando agentes no PC…');
165
+ const localAgents = detectLocalAgents();
166
+ if (localAgents.length === 0) {
167
+ console.log(' [nenhum agente detectado]');
168
+ }
169
+ else {
170
+ for (const a of localAgents) {
171
+ console.log(` ✓ ${a.kind} [${a.detail}]`);
172
+ }
173
+ }
174
+ // 4. Configura local via setup.ts
175
+ if (localAgents.some((a) => a.kind === 'claude_code' || a.kind === 'cursor')) {
176
+ console.log('\n→ Configurando MCP em Claude Code / Cursor…');
177
+ try {
178
+ // Path absoluto do setup.js no mesmo dist/. ESM friendly.
179
+ const setupPath = join(__dirname, 'setup.js');
180
+ execSync(`node ${JSON.stringify(setupPath)}`, {
181
+ stdio: 'inherit',
182
+ env: { ...process.env, NUXS_LICENSE_KEY: licenseKey || '' }
183
+ });
184
+ }
185
+ catch (err) {
186
+ console.log(` ⚠ Falha no setup automático: ${err.message}`);
187
+ console.log(' Roda manualmente: npx nuxs-capsule setup');
188
+ }
189
+ }
190
+ // 5. SSH hosts — config + entrada manual
191
+ console.log('\n🔍 Lendo ~/.ssh/config…');
192
+ let hosts = detectSshHosts();
193
+ if (hosts.length === 0) {
194
+ console.log(' [nenhum servidor configurado no SSH config]');
195
+ const wantManual = await confirm(rl, 'Tem servidor remoto pra instalar Capsule [tipo Vultr/EC2]?');
196
+ if (wantManual) {
197
+ while (true) {
198
+ const userHost = await ask(rl, ' user@hostname [ou Enter pra parar]: ');
199
+ if (!userHost)
200
+ break;
201
+ const m = userHost.match(/^([^@]+)@(.+)$/);
202
+ if (!m) {
203
+ console.log(' ⚠ Formato inválido. Use: user@hostname');
204
+ continue;
205
+ }
206
+ hosts.push({
207
+ alias: m[2],
208
+ hostname: m[2],
209
+ user: m[1]
210
+ });
211
+ console.log(` ✓ Adicionado: ${userHost}`);
212
+ }
213
+ }
214
+ }
215
+ else {
216
+ console.log(` ${hosts.length} servidor[es] encontrado[s]:`);
217
+ for (const h of hosts) {
218
+ console.log(` • ${h.alias} [${h.user ? h.user + '@' : ''}${h.hostname}]`);
219
+ }
220
+ }
221
+ // 6. Probe cada host
222
+ if (hosts.length > 0) {
223
+ const toInstall = await confirm(rl, '\nVerificar quais servidores tem agentes [pode demorar]?');
224
+ if (toInstall) {
225
+ for (const host of hosts) {
226
+ console.log(`\n • ${host.alias}…`);
227
+ const remote = await probeRemoteAgents(host);
228
+ if (remote.length === 0) {
229
+ console.log(' [sem OpenClaw/Hermes detectado ou SSH falhou]');
230
+ continue;
231
+ }
232
+ for (const a of remote) {
233
+ console.log(` ✓ ${a.kind} em ${a.detail}`);
234
+ }
235
+ if (!pdToken || !pdSlug) {
236
+ console.log(' ⚠ Sem token/slug — pulo este server.');
237
+ continue;
238
+ }
239
+ const yes = await confirm(rl, ` Instalar Capsule nos ${remote.length} agente[s]?`);
240
+ if (!yes)
241
+ continue;
242
+ for (const a of remote) {
243
+ const env = {
244
+ AGENT_NAME: `${a.kind}-${host.alias}`,
245
+ PIXELDESK_TOKEN: pdToken,
246
+ PIXELDESK_SLUG: pdSlug
247
+ };
248
+ if (a.kind === 'hermes') {
249
+ const apiKey = await ask(rl, ` HERMES_API_KEY pra ${host.alias} [sk_…]: `);
250
+ if (apiKey)
251
+ env.HERMES_API_KEY = apiKey;
252
+ }
253
+ remoteInstall(host, a.kind, env);
254
+ }
255
+ }
256
+ }
257
+ }
258
+ console.log('\n✅ Instalação concluída.');
259
+ console.log(' Acompanha tudo em: https://pixeldesk.dev/mymind → aba Capsule');
260
+ console.log(' Painel admin [Josu]: https://pixeldesk.dev/admin/capsule\n');
261
+ }
262
+ finally {
263
+ rl.close();
264
+ }
265
+ }
266
+ main().catch((err) => {
267
+ console.error('\n❌ Erro:', err.message);
268
+ process.exit(1);
269
+ });
270
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * CLI: `npx nuxs-capsule install`
3
+ *
4
+ * Instalador GUIADO interativo [Finn 26/Mai/2026]. Diferente do setup
5
+ * que só configura MCP local, este aqui:
6
+ *
7
+ * 1. Detecta tudo no PC [Claude Code, Cursor, OpenClaw CLI, Hermes API]
8
+ * 2. Configura local via setup.ts
9
+ * 3. Lê ~/.ssh/config + ~/.ssh/known_hosts pra achar servidores
10
+ * 4. Lista hosts e pergunta "instalar Capsule lá também?"
11
+ * 5. Se sim, faz SSH e roda install-linux.sh remoto via curl
12
+ * 6. License key entrada UMA vez, usada pra todos
13
+ *
14
+ * Modelo de UX: estilo `vercel` CLI [pergunta o mínimo, faz o resto].
15
+ */
16
+ export {};
17
+ //# sourceMappingURL=install.d.ts.map
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=install.d.ts.map