@hexidecibel/companion 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/task-parser.test.d.ts +2 -0
- package/dist/__tests__/task-parser.test.d.ts.map +1 -0
- package/dist/__tests__/task-parser.test.js +79 -0
- package/dist/__tests__/task-parser.test.js.map +1 -0
- package/dist/anthropic-usage.d.ts +5 -0
- package/dist/anthropic-usage.d.ts.map +1 -0
- package/dist/anthropic-usage.js +112 -0
- package/dist/anthropic-usage.js.map +1 -0
- package/dist/cert-generator.d.ts +15 -0
- package/dist/cert-generator.d.ts.map +1 -0
- package/dist/cert-generator.js +298 -0
- package/dist/cert-generator.js.map +1 -0
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +122 -0
- package/dist/config.js.map +1 -0
- package/dist/encryption.d.ts +28 -0
- package/dist/encryption.d.ts.map +1 -0
- package/dist/encryption.js +95 -0
- package/dist/encryption.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +211 -0
- package/dist/index.js.map +1 -0
- package/dist/input-injector.d.ts +21 -0
- package/dist/input-injector.d.ts.map +1 -0
- package/dist/input-injector.js +126 -0
- package/dist/input-injector.js.map +1 -0
- package/dist/mdns.d.ts +11 -0
- package/dist/mdns.d.ts.map +1 -0
- package/dist/mdns.js +93 -0
- package/dist/mdns.js.map +1 -0
- package/dist/parser.d.ts +43 -0
- package/dist/parser.d.ts.map +1 -0
- package/dist/parser.js +800 -0
- package/dist/parser.js.map +1 -0
- package/dist/push.d.ts +38 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/push.js +359 -0
- package/dist/push.js.map +1 -0
- package/dist/qr-server.d.ts +13 -0
- package/dist/qr-server.d.ts.map +1 -0
- package/dist/qr-server.js +421 -0
- package/dist/qr-server.js.map +1 -0
- package/dist/scaffold/generator.d.ts +11 -0
- package/dist/scaffold/generator.d.ts.map +1 -0
- package/dist/scaffold/generator.js +206 -0
- package/dist/scaffold/generator.js.map +1 -0
- package/dist/scaffold/templates/index.d.ts +5 -0
- package/dist/scaffold/templates/index.d.ts.map +1 -0
- package/dist/scaffold/templates/index.js +22 -0
- package/dist/scaffold/templates/index.js.map +1 -0
- package/dist/scaffold/templates/node-express.d.ts +3 -0
- package/dist/scaffold/templates/node-express.d.ts.map +1 -0
- package/dist/scaffold/templates/node-express.js +218 -0
- package/dist/scaffold/templates/node-express.js.map +1 -0
- package/dist/scaffold/templates/python-fastapi.d.ts +3 -0
- package/dist/scaffold/templates/python-fastapi.d.ts.map +1 -0
- package/dist/scaffold/templates/python-fastapi.js +302 -0
- package/dist/scaffold/templates/python-fastapi.js.map +1 -0
- package/dist/scaffold/templates/react-mui-website.d.ts +3 -0
- package/dist/scaffold/templates/react-mui-website.d.ts.map +1 -0
- package/dist/scaffold/templates/react-mui-website.js +405 -0
- package/dist/scaffold/templates/react-mui-website.js.map +1 -0
- package/dist/scaffold/templates/react-typescript.d.ts +3 -0
- package/dist/scaffold/templates/react-typescript.d.ts.map +1 -0
- package/dist/scaffold/templates/react-typescript.js +275 -0
- package/dist/scaffold/templates/react-typescript.js.map +1 -0
- package/dist/scaffold/types.d.ts +55 -0
- package/dist/scaffold/types.d.ts.map +1 -0
- package/dist/scaffold/types.js +3 -0
- package/dist/scaffold/types.js.map +1 -0
- package/dist/subagent-watcher.d.ts +24 -0
- package/dist/subagent-watcher.d.ts.map +1 -0
- package/dist/subagent-watcher.js +307 -0
- package/dist/subagent-watcher.js.map +1 -0
- package/dist/tls.d.ts +10 -0
- package/dist/tls.d.ts.map +1 -0
- package/dist/tls.js +77 -0
- package/dist/tls.js.map +1 -0
- package/dist/tmux-manager.d.ts +71 -0
- package/dist/tmux-manager.d.ts.map +1 -0
- package/dist/tmux-manager.js +243 -0
- package/dist/tmux-manager.js.map +1 -0
- package/dist/tool-config.d.ts +33 -0
- package/dist/tool-config.d.ts.map +1 -0
- package/dist/tool-config.js +211 -0
- package/dist/tool-config.js.map +1 -0
- package/dist/types.d.ts +218 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/watcher.d.ts +63 -0
- package/dist/watcher.d.ts.map +1 -0
- package/dist/watcher.js +596 -0
- package/dist/watcher.js.map +1 -0
- package/dist/watcher.test.d.ts +2 -0
- package/dist/watcher.test.d.ts.map +1 -0
- package/dist/watcher.test.js +110 -0
- package/dist/watcher.test.js.map +1 -0
- package/dist/websocket.d.ts +62 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +1695 -0
- package/dist/websocket.js.map +1 -0
- package/package.json +71 -0
- package/scripts/build.sh +23 -0
- package/scripts/install-remote.sh +18 -0
- package/scripts/install.sh +558 -0
- package/scripts/uninstall.sh +113 -0
package/dist/config.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.loadConfig = loadConfig;
|
|
37
|
+
exports.saveConfig = saveConfig;
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const HOME_DIR = process.env.HOME || '/root';
|
|
41
|
+
const CONFIG_DIR = path.join(HOME_DIR, '.companion');
|
|
42
|
+
// Safe tools that can be auto-approved without user confirmation
|
|
43
|
+
const DEFAULT_AUTO_APPROVE_TOOLS = [
|
|
44
|
+
'Read',
|
|
45
|
+
'Glob',
|
|
46
|
+
'Grep',
|
|
47
|
+
'WebFetch',
|
|
48
|
+
'WebSearch',
|
|
49
|
+
];
|
|
50
|
+
const DEFAULT_CONFIG = {
|
|
51
|
+
port: 9877,
|
|
52
|
+
token: '',
|
|
53
|
+
tls: false,
|
|
54
|
+
certPath: path.join(CONFIG_DIR, 'certs', 'cert.pem'),
|
|
55
|
+
keyPath: path.join(CONFIG_DIR, 'certs', 'key.pem'),
|
|
56
|
+
tmuxSession: 'main',
|
|
57
|
+
codeHome: path.join(HOME_DIR, '.claude'),
|
|
58
|
+
mdnsEnabled: true,
|
|
59
|
+
pushDelayMs: 60000, // 1 minute
|
|
60
|
+
autoApproveTools: DEFAULT_AUTO_APPROVE_TOOLS,
|
|
61
|
+
};
|
|
62
|
+
function loadConfig() {
|
|
63
|
+
const configPath = process.env.CONFIG_PATH || path.join(CONFIG_DIR, 'config.json');
|
|
64
|
+
let fileConfig = {};
|
|
65
|
+
if (fs.existsSync(configPath)) {
|
|
66
|
+
try {
|
|
67
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
68
|
+
const parsed = JSON.parse(content);
|
|
69
|
+
// Map snake_case from config file to camelCase
|
|
70
|
+
fileConfig = {
|
|
71
|
+
port: parsed.port,
|
|
72
|
+
token: parsed.token,
|
|
73
|
+
tls: parsed.tls,
|
|
74
|
+
certPath: parsed.cert_path,
|
|
75
|
+
keyPath: parsed.key_path,
|
|
76
|
+
tmuxSession: parsed.tmux_session,
|
|
77
|
+
codeHome: parsed.code_home || parsed.claude_home,
|
|
78
|
+
mdnsEnabled: parsed.mdns_enabled,
|
|
79
|
+
fcmCredentialsPath: parsed.fcm_credentials_path,
|
|
80
|
+
pushDelayMs: parsed.push_delay_ms,
|
|
81
|
+
autoApproveTools: parsed.auto_approve_tools,
|
|
82
|
+
anthropicAdminApiKey: parsed.anthropic_admin_api_key,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.error(`Error loading config from ${configPath}:`, err);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
console.warn(`Config file not found at ${configPath}, using defaults`);
|
|
91
|
+
}
|
|
92
|
+
// Merge with defaults
|
|
93
|
+
const config = {
|
|
94
|
+
...DEFAULT_CONFIG,
|
|
95
|
+
...Object.fromEntries(Object.entries(fileConfig).filter(([_, v]) => v !== undefined)),
|
|
96
|
+
};
|
|
97
|
+
// Validate required fields
|
|
98
|
+
if (!config.token) {
|
|
99
|
+
console.error('Error: No authentication token configured');
|
|
100
|
+
console.error('Please set a token in the config file');
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
return config;
|
|
104
|
+
}
|
|
105
|
+
function saveConfig(config) {
|
|
106
|
+
const configPath = process.env.CONFIG_PATH || path.join(CONFIG_DIR, 'config.json');
|
|
107
|
+
// Convert to snake_case for file
|
|
108
|
+
const fileConfig = {
|
|
109
|
+
port: config.port,
|
|
110
|
+
token: config.token,
|
|
111
|
+
tls: config.tls,
|
|
112
|
+
cert_path: config.certPath,
|
|
113
|
+
key_path: config.keyPath,
|
|
114
|
+
tmux_session: config.tmuxSession,
|
|
115
|
+
code_home: config.codeHome,
|
|
116
|
+
mdns_enabled: config.mdnsEnabled,
|
|
117
|
+
fcm_credentials_path: config.fcmCredentialsPath,
|
|
118
|
+
push_delay_ms: config.pushDelayMs,
|
|
119
|
+
};
|
|
120
|
+
fs.writeFileSync(configPath, JSON.stringify(fileConfig, null, 2));
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface KeyPair {
|
|
2
|
+
publicKey: string;
|
|
3
|
+
secretKey: string;
|
|
4
|
+
}
|
|
5
|
+
export interface EncryptedPayload {
|
|
6
|
+
encrypted: true;
|
|
7
|
+
ciphertext: string;
|
|
8
|
+
nonce: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DecryptedPayload {
|
|
11
|
+
encrypted: false;
|
|
12
|
+
data: unknown;
|
|
13
|
+
}
|
|
14
|
+
export type MessagePayload = EncryptedPayload | DecryptedPayload | unknown;
|
|
15
|
+
export declare class EncryptionService {
|
|
16
|
+
private keyPair;
|
|
17
|
+
private clientPublicKeys;
|
|
18
|
+
constructor();
|
|
19
|
+
getPublicKey(): string;
|
|
20
|
+
setClientPublicKey(clientId: string, publicKeyBase64: string): void;
|
|
21
|
+
removeClientPublicKey(clientId: string): void;
|
|
22
|
+
hasClientPublicKey(clientId: string): boolean;
|
|
23
|
+
encrypt(clientId: string, data: unknown): EncryptedPayload | null;
|
|
24
|
+
decrypt(clientId: string, payload: EncryptedPayload): unknown | null;
|
|
25
|
+
isEncryptedPayload(payload: unknown): payload is EncryptedPayload;
|
|
26
|
+
}
|
|
27
|
+
export declare const encryptionService: EncryptionService;
|
|
28
|
+
//# sourceMappingURL=encryption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../src/encryption.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,KAAK,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,MAAM,cAAc,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,OAAO,CAAC;AAE3E,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAkB;IACjC,OAAO,CAAC,gBAAgB,CAAsC;;IAQ9D,YAAY,IAAI,MAAM;IAItB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI;IAcnE,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAI7C,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI7C,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI;IAwBjE,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,GAAG,IAAI;IA0BpE,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,IAAI,gBAAgB;CAUlE;AAGD,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.encryptionService = exports.EncryptionService = void 0;
|
|
7
|
+
const tweetnacl_1 = __importDefault(require("tweetnacl"));
|
|
8
|
+
const tweetnacl_util_1 = require("tweetnacl-util");
|
|
9
|
+
class EncryptionService {
|
|
10
|
+
keyPair;
|
|
11
|
+
clientPublicKeys = new Map();
|
|
12
|
+
constructor() {
|
|
13
|
+
// Generate server key pair on startup
|
|
14
|
+
this.keyPair = tweetnacl_1.default.box.keyPair();
|
|
15
|
+
console.log('Encryption: Key pair generated');
|
|
16
|
+
}
|
|
17
|
+
getPublicKey() {
|
|
18
|
+
return (0, tweetnacl_util_1.encodeBase64)(this.keyPair.publicKey);
|
|
19
|
+
}
|
|
20
|
+
setClientPublicKey(clientId, publicKeyBase64) {
|
|
21
|
+
try {
|
|
22
|
+
const publicKey = (0, tweetnacl_util_1.decodeBase64)(publicKeyBase64);
|
|
23
|
+
if (publicKey.length !== tweetnacl_1.default.box.publicKeyLength) {
|
|
24
|
+
throw new Error('Invalid public key length');
|
|
25
|
+
}
|
|
26
|
+
this.clientPublicKeys.set(clientId, publicKey);
|
|
27
|
+
console.log(`Encryption: Stored public key for client ${clientId}`);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
console.error(`Encryption: Failed to store public key for ${clientId}:`, err);
|
|
31
|
+
throw err;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
removeClientPublicKey(clientId) {
|
|
35
|
+
this.clientPublicKeys.delete(clientId);
|
|
36
|
+
}
|
|
37
|
+
hasClientPublicKey(clientId) {
|
|
38
|
+
return this.clientPublicKeys.has(clientId);
|
|
39
|
+
}
|
|
40
|
+
encrypt(clientId, data) {
|
|
41
|
+
const clientPublicKey = this.clientPublicKeys.get(clientId);
|
|
42
|
+
if (!clientPublicKey) {
|
|
43
|
+
console.warn(`Encryption: No public key for client ${clientId}`);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const message = (0, tweetnacl_util_1.encodeUTF8)(JSON.stringify(data));
|
|
48
|
+
const nonce = tweetnacl_1.default.randomBytes(tweetnacl_1.default.box.nonceLength);
|
|
49
|
+
const ciphertext = tweetnacl_1.default.box(message, nonce, clientPublicKey, this.keyPair.secretKey);
|
|
50
|
+
return {
|
|
51
|
+
encrypted: true,
|
|
52
|
+
ciphertext: (0, tweetnacl_util_1.encodeBase64)(ciphertext),
|
|
53
|
+
nonce: (0, tweetnacl_util_1.encodeBase64)(nonce),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
console.error('Encryption: Failed to encrypt:', err);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
decrypt(clientId, payload) {
|
|
62
|
+
const clientPublicKey = this.clientPublicKeys.get(clientId);
|
|
63
|
+
if (!clientPublicKey) {
|
|
64
|
+
console.warn(`Encryption: No public key for client ${clientId}`);
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const ciphertext = (0, tweetnacl_util_1.decodeBase64)(payload.ciphertext);
|
|
69
|
+
const nonce = (0, tweetnacl_util_1.decodeBase64)(payload.nonce);
|
|
70
|
+
const decrypted = tweetnacl_1.default.box.open(ciphertext, nonce, clientPublicKey, this.keyPair.secretKey);
|
|
71
|
+
if (!decrypted) {
|
|
72
|
+
console.error('Encryption: Decryption failed (authentication failed)');
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
const json = (0, tweetnacl_util_1.decodeUTF8)(decrypted);
|
|
76
|
+
return JSON.parse(json);
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
console.error('Encryption: Failed to decrypt:', err);
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
isEncryptedPayload(payload) {
|
|
84
|
+
return (typeof payload === 'object' &&
|
|
85
|
+
payload !== null &&
|
|
86
|
+
'encrypted' in payload &&
|
|
87
|
+
payload.encrypted === true &&
|
|
88
|
+
'ciphertext' in payload &&
|
|
89
|
+
'nonce' in payload);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.EncryptionService = EncryptionService;
|
|
93
|
+
// Export singleton instance
|
|
94
|
+
exports.encryptionService = new EncryptionService();
|
|
95
|
+
//# sourceMappingURL=encryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.js","sourceRoot":"","sources":["../src/encryption.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const config_1 = require("./config");
|
|
5
|
+
const watcher_1 = require("./watcher");
|
|
6
|
+
const subagent_watcher_1 = require("./subagent-watcher");
|
|
7
|
+
const input_injector_1 = require("./input-injector");
|
|
8
|
+
const mdns_1 = require("./mdns");
|
|
9
|
+
const push_1 = require("./push");
|
|
10
|
+
const websocket_1 = require("./websocket");
|
|
11
|
+
const tmux_manager_1 = require("./tmux-manager");
|
|
12
|
+
const tls_1 = require("./tls");
|
|
13
|
+
const cert_generator_1 = require("./cert-generator");
|
|
14
|
+
const qr_server_1 = require("./qr-server");
|
|
15
|
+
async function main() {
|
|
16
|
+
console.log('Companion Daemon v0.0.1');
|
|
17
|
+
console.log('==============================');
|
|
18
|
+
// Load configuration
|
|
19
|
+
const config = (0, config_1.loadConfig)();
|
|
20
|
+
console.log(`Config: Port ${config.port}, TLS: ${config.tls}, mDNS: ${config.mdnsEnabled}`);
|
|
21
|
+
// Auto-generate TLS certificates if enabled and missing
|
|
22
|
+
if (config.tls) {
|
|
23
|
+
const certPath = config.certPath || (0, cert_generator_1.getDefaultCertPaths)().certPath;
|
|
24
|
+
const keyPath = config.keyPath || (0, cert_generator_1.getDefaultCertPaths)().keyPath;
|
|
25
|
+
if (!(0, cert_generator_1.certsExist)(certPath, keyPath)) {
|
|
26
|
+
console.log('TLS certificates not found, generating self-signed certificates...');
|
|
27
|
+
try {
|
|
28
|
+
const paths = (0, cert_generator_1.generateAndSaveCerts)(certPath, keyPath);
|
|
29
|
+
config.certPath = paths.certPath;
|
|
30
|
+
config.keyPath = paths.keyPath;
|
|
31
|
+
console.log('Self-signed certificates generated successfully');
|
|
32
|
+
console.log('Note: Clients may need to accept the self-signed certificate');
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
console.error('Failed to generate TLS certificates:', err);
|
|
36
|
+
console.error('Falling back to non-TLS mode');
|
|
37
|
+
config.tls = false;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Validate TLS config
|
|
41
|
+
if (config.tls) {
|
|
42
|
+
const tlsErrors = (0, tls_1.validateTlsConfig)({
|
|
43
|
+
enabled: config.tls,
|
|
44
|
+
certPath: config.certPath,
|
|
45
|
+
keyPath: config.keyPath,
|
|
46
|
+
});
|
|
47
|
+
if (tlsErrors.length > 0) {
|
|
48
|
+
console.error('TLS configuration errors:');
|
|
49
|
+
tlsErrors.forEach((e) => console.error(` - ${e}`));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Initialize components
|
|
55
|
+
const watcher = new watcher_1.SessionWatcher(config.codeHome);
|
|
56
|
+
const subAgentWatcher = new subagent_watcher_1.SubAgentWatcher(config.codeHome);
|
|
57
|
+
const injector = new input_injector_1.InputInjector(config.tmuxSession);
|
|
58
|
+
const push = new push_1.PushNotificationService(config.fcmCredentialsPath, config.pushDelayMs);
|
|
59
|
+
// Create HTTP/HTTPS server with QR code endpoint
|
|
60
|
+
const qrHandler = (0, qr_server_1.createQRRequestHandler)(config);
|
|
61
|
+
const server = (0, tls_1.createServer)({
|
|
62
|
+
enabled: config.tls,
|
|
63
|
+
certPath: config.certPath,
|
|
64
|
+
keyPath: config.keyPath,
|
|
65
|
+
}, qrHandler);
|
|
66
|
+
// Initialize WebSocket handler
|
|
67
|
+
const wsHandler = new websocket_1.WebSocketHandler(server, config, watcher, injector, push, undefined, subAgentWatcher);
|
|
68
|
+
// Start mDNS advertisement
|
|
69
|
+
let mdns = null;
|
|
70
|
+
if (config.mdnsEnabled) {
|
|
71
|
+
mdns = new mdns_1.MdnsAdvertiser(config.port, config.tls);
|
|
72
|
+
mdns.start();
|
|
73
|
+
}
|
|
74
|
+
// Start file watchers
|
|
75
|
+
watcher.start();
|
|
76
|
+
subAgentWatcher.start();
|
|
77
|
+
// Auto-approve safe tools (from config and/or client toggle)
|
|
78
|
+
{
|
|
79
|
+
console.log(`Auto-approve tools from config: ${config.autoApproveTools.length > 0 ? config.autoApproveTools.join(', ') : '(none - client toggle only)'}`);
|
|
80
|
+
const tmux = new tmux_manager_1.TmuxManager('companion');
|
|
81
|
+
// Track in-flight approvals using composite key (sessionId:tools) to prevent double-firing
|
|
82
|
+
const pendingAutoApprovals = new Map();
|
|
83
|
+
watcher.on('pending-approval', async ({ sessionId, projectPath, tools }) => {
|
|
84
|
+
// Skip if auto-approve is not enabled (neither config nor client toggle)
|
|
85
|
+
if (config.autoApproveTools.length === 0 && !wsHandler.autoApproveEnabled) {
|
|
86
|
+
console.log(`[AUTO-APPROVE] Skipped: auto-approve not enabled (config tools: ${config.autoApproveTools.length}, client toggle: ${wsHandler.autoApproveEnabled})`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Check if any pending tool should be auto-approved
|
|
90
|
+
const autoApprovable = tools.filter((tool) => {
|
|
91
|
+
if (config.autoApproveTools.includes(tool))
|
|
92
|
+
return true;
|
|
93
|
+
if (wsHandler.autoApproveEnabled)
|
|
94
|
+
return true;
|
|
95
|
+
return false;
|
|
96
|
+
});
|
|
97
|
+
if (autoApprovable.length === 0) {
|
|
98
|
+
console.log(`[AUTO-APPROVE] No auto-approvable tools in: [${tools.join(', ')}]`);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// Composite dedup key: session + sorted tool names
|
|
102
|
+
// The watcher already deduplicates emissions (only fires on change),
|
|
103
|
+
// but this provides a safety net against rapid re-fires.
|
|
104
|
+
const dedupKey = `${sessionId}:${autoApprovable.sort().join(',')}`;
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
const lastApproval = pendingAutoApprovals.get(dedupKey);
|
|
107
|
+
if (lastApproval && now - lastApproval < 15000) {
|
|
108
|
+
console.log(`[AUTO-APPROVE] Dedup: skipping (last approval ${now - lastApproval}ms ago for ${dedupKey})`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
pendingAutoApprovals.set(dedupKey, now);
|
|
112
|
+
// Clean up old entries
|
|
113
|
+
for (const [key, ts] of pendingAutoApprovals) {
|
|
114
|
+
if (now - ts > 30000)
|
|
115
|
+
pendingAutoApprovals.delete(key);
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
// Find the tmux session that matches this conversation's project path
|
|
119
|
+
let targetTmuxSession;
|
|
120
|
+
if (projectPath) {
|
|
121
|
+
const tmuxSessions = await tmux.listSessions();
|
|
122
|
+
// Try exact match first
|
|
123
|
+
const exactMatch = tmuxSessions.find(ts => ts.workingDir === projectPath);
|
|
124
|
+
if (exactMatch) {
|
|
125
|
+
targetTmuxSession = exactMatch.name;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// Try normalized path match (trailing slash differences, symlinks)
|
|
129
|
+
const normalizedPath = projectPath.replace(/\/+$/, '');
|
|
130
|
+
const fuzzyMatch = tmuxSessions.find(ts => ts.workingDir?.replace(/\/+$/, '') === normalizedPath);
|
|
131
|
+
if (fuzzyMatch) {
|
|
132
|
+
targetTmuxSession = fuzzyMatch.name;
|
|
133
|
+
console.log(`[AUTO-APPROVE] Fuzzy path match: "${fuzzyMatch.name}" for ${projectPath}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// Wait for terminal to settle before sending approval
|
|
138
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
139
|
+
const sendApproval = async (target) => {
|
|
140
|
+
try {
|
|
141
|
+
await injector.sendInput('yes', target);
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
console.log(`[AUTO-APPROVE] Send failed: ${err}`);
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
if (targetTmuxSession) {
|
|
150
|
+
console.log(`[AUTO-APPROVE] Sending to tmux="${targetTmuxSession}" for tools [${autoApprovable.join(', ')}] (session: ${sessionId})`);
|
|
151
|
+
const success = await sendApproval(targetTmuxSession);
|
|
152
|
+
if (!success) {
|
|
153
|
+
// Retry once after 500ms
|
|
154
|
+
console.log(`[AUTO-APPROVE] Retrying after 500ms...`);
|
|
155
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
156
|
+
await sendApproval(targetTmuxSession);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
console.log(`[AUTO-APPROVE] Sending to active session for tools [${autoApprovable.join(', ')}] (no tmux match for ${projectPath})`);
|
|
161
|
+
const success = await sendApproval();
|
|
162
|
+
if (!success) {
|
|
163
|
+
console.log(`[AUTO-APPROVE] Retrying after 500ms...`);
|
|
164
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
165
|
+
await sendApproval();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
console.error(`[AUTO-APPROVE] Error: ${err}`);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// Start HTTP server
|
|
175
|
+
server.listen(config.port, () => {
|
|
176
|
+
console.log(`Server listening on port ${config.port}`);
|
|
177
|
+
console.log(`WebSocket endpoint: ws${config.tls ? 's' : ''}://localhost:${config.port}`);
|
|
178
|
+
console.log(`QR code setup: http${config.tls ? 's' : ''}://localhost:${config.port}/qr`);
|
|
179
|
+
});
|
|
180
|
+
// Graceful shutdown
|
|
181
|
+
const shutdown = async () => {
|
|
182
|
+
console.log('\nShutting down...');
|
|
183
|
+
watcher.stop();
|
|
184
|
+
subAgentWatcher.stop();
|
|
185
|
+
if (mdns)
|
|
186
|
+
mdns.stop();
|
|
187
|
+
server.close(() => {
|
|
188
|
+
console.log('Server closed');
|
|
189
|
+
process.exit(0);
|
|
190
|
+
});
|
|
191
|
+
// Force exit after 5 seconds
|
|
192
|
+
setTimeout(() => {
|
|
193
|
+
console.error('Forced shutdown after timeout');
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}, 5000);
|
|
196
|
+
};
|
|
197
|
+
process.on('SIGINT', shutdown);
|
|
198
|
+
process.on('SIGTERM', shutdown);
|
|
199
|
+
// Log status periodically
|
|
200
|
+
setInterval(() => {
|
|
201
|
+
const status = watcher.getStatus();
|
|
202
|
+
console.log(`Status: ${wsHandler.getAuthenticatedClientCount()} clients, ` +
|
|
203
|
+
`waiting: ${status.isWaitingForInput}, ` +
|
|
204
|
+
`push devices: ${push.getRegisteredDeviceCount()}`);
|
|
205
|
+
}, 60000);
|
|
206
|
+
}
|
|
207
|
+
main().catch((err) => {
|
|
208
|
+
console.error('Fatal error:', err);
|
|
209
|
+
process.exit(1);
|
|
210
|
+
});
|
|
211
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare class InputInjector {
|
|
2
|
+
private defaultSession;
|
|
3
|
+
private activeSession;
|
|
4
|
+
private sendLock;
|
|
5
|
+
constructor(tmuxSession: string);
|
|
6
|
+
/**
|
|
7
|
+
* Send input to the active session (or a specific session if provided)
|
|
8
|
+
* Uses a lock to prevent concurrent sends from interleaving
|
|
9
|
+
*/
|
|
10
|
+
sendInput(input: string, targetSession?: string): Promise<boolean>;
|
|
11
|
+
private doSendInput;
|
|
12
|
+
private escapeTmuxInput;
|
|
13
|
+
checkSessionExists(sessionName?: string): Promise<boolean>;
|
|
14
|
+
listSessions(): Promise<string[]>;
|
|
15
|
+
setActiveSession(sessionName: string): void;
|
|
16
|
+
getActiveSession(): string;
|
|
17
|
+
getDefaultSession(): string;
|
|
18
|
+
setSession(sessionName: string): void;
|
|
19
|
+
getSession(): string;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=input-injector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input-injector.d.ts","sourceRoot":"","sources":["../src/input-injector.ts"],"names":[],"mappings":"AAEA,qBAAa,aAAa;IACxB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAoC;gBAExC,WAAW,EAAE,MAAM;IAK/B;;;OAGG;IACG,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YA4B1D,WAAW;IAoCzB,OAAO,CAAC,eAAe;IAWjB,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS1D,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAqBvC,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAI3C,gBAAgB,IAAI,MAAM;IAI1B,iBAAiB,IAAI,MAAM;IAK3B,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAKrC,UAAU,IAAI,MAAM;CAGrB"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InputInjector = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
class InputInjector {
|
|
6
|
+
defaultSession;
|
|
7
|
+
activeSession;
|
|
8
|
+
sendLock = Promise.resolve();
|
|
9
|
+
constructor(tmuxSession) {
|
|
10
|
+
this.defaultSession = tmuxSession;
|
|
11
|
+
this.activeSession = tmuxSession;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Send input to the active session (or a specific session if provided)
|
|
15
|
+
* Uses a lock to prevent concurrent sends from interleaving
|
|
16
|
+
*/
|
|
17
|
+
async sendInput(input, targetSession) {
|
|
18
|
+
// Wait for any pending send to complete before starting this one
|
|
19
|
+
const previousLock = this.sendLock;
|
|
20
|
+
let releaseLock;
|
|
21
|
+
this.sendLock = new Promise(resolve => {
|
|
22
|
+
releaseLock = resolve;
|
|
23
|
+
});
|
|
24
|
+
try {
|
|
25
|
+
await previousLock;
|
|
26
|
+
const session = targetSession || this.activeSession;
|
|
27
|
+
const { spawnSync } = require('child_process');
|
|
28
|
+
// First, check if the tmux session exists
|
|
29
|
+
const checkResult = spawnSync('tmux', ['has-session', '-t', session], { timeout: 5000 });
|
|
30
|
+
if (checkResult.status !== 0) {
|
|
31
|
+
console.error(`Tmux session '${session}' not found`);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
// Session exists, send the input
|
|
35
|
+
return await this.doSendInput(input, session);
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
releaseLock();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async doSendInput(input, session) {
|
|
42
|
+
try {
|
|
43
|
+
console.log(`Sending input to tmux session '${session}': ${input.substring(0, 80)}...`);
|
|
44
|
+
const { spawnSync } = require('child_process');
|
|
45
|
+
// Send the text using spawnSync (avoids shell interpretation)
|
|
46
|
+
const textResult = spawnSync('tmux', ['send-keys', '-t', session, '-l', '--', input], { timeout: 5000 });
|
|
47
|
+
if (textResult.status !== 0) {
|
|
48
|
+
console.error('Failed to send text:', textResult.stderr?.toString());
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
console.log('Text sent to tmux');
|
|
52
|
+
// Wait for tmux to process the text before sending Enter
|
|
53
|
+
await new Promise(resolve => setTimeout(resolve, 150));
|
|
54
|
+
// Send Enter
|
|
55
|
+
const enterResult = spawnSync('tmux', ['send-keys', '-t', session, 'Enter'], { timeout: 5000 });
|
|
56
|
+
if (enterResult.status !== 0) {
|
|
57
|
+
console.error('Failed to send Enter:', enterResult.stderr?.toString());
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
console.log('Enter sent to tmux');
|
|
61
|
+
// Small delay after Enter to ensure tmux processes it before next message
|
|
62
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
63
|
+
console.log(`Input sent successfully to tmux session '${session}'`);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.error('Error sending input to tmux:', err);
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
escapeTmuxInput(input) {
|
|
72
|
+
// Escape special characters that tmux interprets
|
|
73
|
+
// Replace backslashes first, then other special chars
|
|
74
|
+
return input
|
|
75
|
+
.replace(/\\/g, '\\\\')
|
|
76
|
+
.replace(/"/g, '\\"')
|
|
77
|
+
.replace(/'/g, "\\'")
|
|
78
|
+
.replace(/\$/g, '\\$')
|
|
79
|
+
.replace(/`/g, '\\`');
|
|
80
|
+
}
|
|
81
|
+
async checkSessionExists(sessionName) {
|
|
82
|
+
const session = sessionName || this.activeSession;
|
|
83
|
+
return new Promise((resolve) => {
|
|
84
|
+
const check = (0, child_process_1.spawn)('tmux', ['has-session', '-t', session]);
|
|
85
|
+
check.on('close', (code) => resolve(code === 0));
|
|
86
|
+
check.on('error', () => resolve(false));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
async listSessions() {
|
|
90
|
+
return new Promise((resolve) => {
|
|
91
|
+
const list = (0, child_process_1.spawn)('tmux', ['list-sessions', '-F', '#{session_name}']);
|
|
92
|
+
let output = '';
|
|
93
|
+
list.stdout.on('data', (data) => {
|
|
94
|
+
output += data.toString();
|
|
95
|
+
});
|
|
96
|
+
list.on('close', (code) => {
|
|
97
|
+
if (code === 0) {
|
|
98
|
+
resolve(output.trim().split('\n').filter(Boolean));
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
resolve([]);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
list.on('error', () => resolve([]));
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
setActiveSession(sessionName) {
|
|
108
|
+
this.activeSession = sessionName;
|
|
109
|
+
}
|
|
110
|
+
getActiveSession() {
|
|
111
|
+
return this.activeSession;
|
|
112
|
+
}
|
|
113
|
+
getDefaultSession() {
|
|
114
|
+
return this.defaultSession;
|
|
115
|
+
}
|
|
116
|
+
// Deprecated - use setActiveSession
|
|
117
|
+
setSession(sessionName) {
|
|
118
|
+
this.activeSession = sessionName;
|
|
119
|
+
}
|
|
120
|
+
// Deprecated - use getActiveSession
|
|
121
|
+
getSession() {
|
|
122
|
+
return this.activeSession;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.InputInjector = InputInjector;
|
|
126
|
+
//# sourceMappingURL=input-injector.js.map
|