@onklave/agent-cli 0.1.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.
Files changed (2) hide show
  1. package/main.js +2644 -0
  2. package/package.json +33 -0
package/main.js ADDED
@@ -0,0 +1,2644 @@
1
+ #!/usr/bin/env node
2
+ /******/ (() => { // webpackBootstrap
3
+ /******/ "use strict";
4
+ /******/ var __webpack_modules__ = ([
5
+ /* 0 */,
6
+ /* 1 */
7
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
8
+
9
+
10
+ /**
11
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
12
+ *
13
+ * This software is proprietary and confidential.
14
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
15
+ */
16
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
17
+ exports.COMMANDS = void 0;
18
+ const login_command_1 = __webpack_require__(2);
19
+ const logout_command_1 = __webpack_require__(9);
20
+ const whoami_command_1 = __webpack_require__(10);
21
+ const run_command_1 = __webpack_require__(11);
22
+ const status_command_1 = __webpack_require__(22);
23
+ const stop_command_1 = __webpack_require__(23);
24
+ const approve_command_1 = __webpack_require__(24);
25
+ const deny_command_1 = __webpack_require__(25);
26
+ const doctor_command_1 = __webpack_require__(26);
27
+ const init_command_1 = __webpack_require__(27);
28
+ const config_command_1 = __webpack_require__(28);
29
+ const register_command_1 = __webpack_require__(29);
30
+ const logs_command_1 = __webpack_require__(30);
31
+ exports.COMMANDS = {
32
+ login: login_command_1.loginCommand,
33
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
34
+ logout: (_args) => (0, logout_command_1.logoutCommand)(),
35
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
36
+ whoami: (_args) => (0, whoami_command_1.whoamiCommand)(),
37
+ run: run_command_1.runCommand,
38
+ status: status_command_1.statusCommand,
39
+ stop: stop_command_1.stopCommand,
40
+ approve: approve_command_1.approveCommand,
41
+ deny: deny_command_1.denyCommand,
42
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
43
+ doctor: (_args) => (0, doctor_command_1.doctorCommand)(),
44
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
45
+ init: (_args) => (0, init_command_1.initCommand)(),
46
+ config: config_command_1.configCommand,
47
+ register: register_command_1.registerCommand,
48
+ logs: logs_command_1.logsCommand,
49
+ };
50
+
51
+
52
+ /***/ }),
53
+ /* 2 */
54
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
55
+
56
+
57
+ /**
58
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
59
+ *
60
+ * This software is proprietary and confidential.
61
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
62
+ */
63
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
64
+ exports.loginCommand = loginCommand;
65
+ const auth_service_1 = __webpack_require__(3);
66
+ const utils_1 = __webpack_require__(8);
67
+ async function loginCommand(args) {
68
+ const { flags } = (0, utils_1.parseArgs)(args);
69
+ const authService = new auth_service_1.AuthService();
70
+ const token = flags['token'];
71
+ const platformUrl = flags['platform-url'];
72
+ if (typeof token !== 'string' || !token) {
73
+ console.log('Onklave Agent CLI — Login\n');
74
+ console.log('Usage: onklave login --token <token> [--platform-url <url>]\n');
75
+ console.log('To obtain a token:');
76
+ console.log(' 1. Log in to the Onklave Portal at https://portal.onklave.app');
77
+ console.log(' 2. Navigate to Settings > API Tokens');
78
+ console.log(' 3. Generate a new CLI token');
79
+ console.log(' 4. Run: onklave login --token <your-token>\n');
80
+ console.log('Note: Browser-based OAuth login will be available in v2.');
81
+ process.exitCode = 1;
82
+ return;
83
+ }
84
+ const metadata = {};
85
+ if (typeof platformUrl === 'string') {
86
+ metadata.platformUrl = platformUrl;
87
+ }
88
+ try {
89
+ await authService.saveToken(token, metadata);
90
+ console.log('Successfully authenticated with Onklave platform.');
91
+ console.log(`Credentials saved to ~/.config/onklave/credentials.json`);
92
+ if (typeof platformUrl === 'string') {
93
+ console.log(`Platform URL: ${platformUrl}`);
94
+ }
95
+ }
96
+ catch (err) {
97
+ console.error(`Login failed: ${err.message}`);
98
+ process.exitCode = 1;
99
+ }
100
+ }
101
+
102
+
103
+ /***/ }),
104
+ /* 3 */
105
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
106
+
107
+
108
+ /**
109
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
110
+ *
111
+ * This software is proprietary and confidential.
112
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
113
+ */
114
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
115
+ exports.AuthService = void 0;
116
+ const tslib_1 = __webpack_require__(4);
117
+ const fs = tslib_1.__importStar(__webpack_require__(5));
118
+ const path = tslib_1.__importStar(__webpack_require__(6));
119
+ const os = tslib_1.__importStar(__webpack_require__(7));
120
+ const DEFAULT_PLATFORM_URL = 'https://api.onklave.app';
121
+ class AuthService {
122
+ constructor() {
123
+ this.configDir = path.join(os.homedir(), '.config', 'onklave');
124
+ this.credentialsPath = path.join(this.configDir, 'credentials.json');
125
+ }
126
+ /**
127
+ * Ensure the config directory exists with restricted permissions.
128
+ */
129
+ ensureConfigDir() {
130
+ if (!fs.existsSync(this.configDir)) {
131
+ fs.mkdirSync(this.configDir, { recursive: true, mode: 0o700 });
132
+ }
133
+ }
134
+ /**
135
+ * Read the stored auth token.
136
+ */
137
+ async getToken() {
138
+ const creds = await this.getCredentials();
139
+ return creds?.token ?? null;
140
+ }
141
+ /**
142
+ * Save an auth token with optional metadata.
143
+ */
144
+ async saveToken(token, metadata) {
145
+ this.ensureConfigDir();
146
+ const existing = await this.getCredentials();
147
+ const credentials = {
148
+ ...existing,
149
+ token,
150
+ platformUrl: metadata?.platformUrl ?? existing?.platformUrl ?? DEFAULT_PLATFORM_URL,
151
+ userId: metadata?.userId ?? existing?.userId,
152
+ orgId: metadata?.orgId ?? existing?.orgId,
153
+ expiresAt: metadata?.expiresAt ?? existing?.expiresAt,
154
+ };
155
+ fs.writeFileSync(this.credentialsPath, JSON.stringify(credentials, null, 2), {
156
+ encoding: 'utf-8',
157
+ mode: 0o600,
158
+ });
159
+ // Ensure permissions are set even if file already existed
160
+ fs.chmodSync(this.credentialsPath, 0o600);
161
+ }
162
+ /**
163
+ * Remove the stored credentials file.
164
+ */
165
+ async clearToken() {
166
+ if (fs.existsSync(this.credentialsPath)) {
167
+ fs.unlinkSync(this.credentialsPath);
168
+ }
169
+ }
170
+ /**
171
+ * Check if a valid (non-expired) token exists.
172
+ */
173
+ async isAuthenticated() {
174
+ const creds = await this.getCredentials();
175
+ if (!creds?.token) {
176
+ return false;
177
+ }
178
+ if (creds.expiresAt) {
179
+ const expiry = new Date(creds.expiresAt);
180
+ if (expiry.getTime() <= Date.now()) {
181
+ return false;
182
+ }
183
+ }
184
+ return true;
185
+ }
186
+ /**
187
+ * Read the full credentials object from disk.
188
+ */
189
+ async getCredentials() {
190
+ if (!fs.existsSync(this.credentialsPath)) {
191
+ return null;
192
+ }
193
+ try {
194
+ const raw = fs.readFileSync(this.credentialsPath, 'utf-8');
195
+ return JSON.parse(raw);
196
+ }
197
+ catch {
198
+ return null;
199
+ }
200
+ }
201
+ /**
202
+ * Save the device token received during machine registration.
203
+ */
204
+ async saveDeviceToken(deviceToken, machineId) {
205
+ this.ensureConfigDir();
206
+ const existing = await this.getCredentials();
207
+ if (!existing) {
208
+ throw new Error('No credentials found. Please log in first with: onklave login --token <token>');
209
+ }
210
+ const credentials = {
211
+ ...existing,
212
+ deviceToken,
213
+ machineId,
214
+ };
215
+ fs.writeFileSync(this.credentialsPath, JSON.stringify(credentials, null, 2), {
216
+ encoding: 'utf-8',
217
+ mode: 0o600,
218
+ });
219
+ fs.chmodSync(this.credentialsPath, 0o600);
220
+ }
221
+ /**
222
+ * Get the platform URL from credentials or fallback to default.
223
+ */
224
+ async getPlatformUrl() {
225
+ const creds = await this.getCredentials();
226
+ return creds?.platformUrl ?? DEFAULT_PLATFORM_URL;
227
+ }
228
+ }
229
+ exports.AuthService = AuthService;
230
+
231
+
232
+ /***/ }),
233
+ /* 4 */
234
+ /***/ ((module) => {
235
+
236
+ module.exports = require("tslib");
237
+
238
+ /***/ }),
239
+ /* 5 */
240
+ /***/ ((module) => {
241
+
242
+ module.exports = require("fs");
243
+
244
+ /***/ }),
245
+ /* 6 */
246
+ /***/ ((module) => {
247
+
248
+ module.exports = require("path");
249
+
250
+ /***/ }),
251
+ /* 7 */
252
+ /***/ ((module) => {
253
+
254
+ module.exports = require("os");
255
+
256
+ /***/ }),
257
+ /* 8 */
258
+ /***/ ((__unused_webpack_module, exports) => {
259
+
260
+
261
+ /**
262
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
263
+ *
264
+ * This software is proprietary and confidential.
265
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
266
+ */
267
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
268
+ exports.parseArgs = parseArgs;
269
+ /**
270
+ * Parse command-line arguments into flags and positional args.
271
+ *
272
+ * Handles:
273
+ * --flag value
274
+ * --flag=value
275
+ * --boolean-flag (no value, treated as true)
276
+ * positional arguments
277
+ */
278
+ function parseArgs(args) {
279
+ const flags = {};
280
+ const positional = [];
281
+ let i = 0;
282
+ while (i < args.length) {
283
+ const arg = args[i];
284
+ if (arg.startsWith('--')) {
285
+ // Check for --flag=value format
286
+ const eqIndex = arg.indexOf('=');
287
+ if (eqIndex !== -1) {
288
+ const key = arg.slice(2, eqIndex);
289
+ const value = arg.slice(eqIndex + 1);
290
+ flags[key] = value;
291
+ i++;
292
+ continue;
293
+ }
294
+ const key = arg.slice(2);
295
+ const nextArg = args[i + 1];
296
+ // If next arg doesn't exist or is another flag, treat as boolean
297
+ if (!nextArg || nextArg.startsWith('--')) {
298
+ flags[key] = true;
299
+ i++;
300
+ }
301
+ else {
302
+ flags[key] = nextArg;
303
+ i += 2;
304
+ }
305
+ }
306
+ else if (arg.startsWith('-') && arg.length === 2) {
307
+ // Short flags like -h, -v
308
+ const key = arg.slice(1);
309
+ const nextArg = args[i + 1];
310
+ if (!nextArg || nextArg.startsWith('-')) {
311
+ flags[key] = true;
312
+ i++;
313
+ }
314
+ else {
315
+ flags[key] = nextArg;
316
+ i += 2;
317
+ }
318
+ }
319
+ else {
320
+ positional.push(arg);
321
+ i++;
322
+ }
323
+ }
324
+ return { flags, positional };
325
+ }
326
+
327
+
328
+ /***/ }),
329
+ /* 9 */
330
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
331
+
332
+
333
+ /**
334
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
335
+ *
336
+ * This software is proprietary and confidential.
337
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
338
+ */
339
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
340
+ exports.logoutCommand = logoutCommand;
341
+ const auth_service_1 = __webpack_require__(3);
342
+ async function logoutCommand() {
343
+ const authService = new auth_service_1.AuthService();
344
+ const isAuth = await authService.isAuthenticated();
345
+ if (!isAuth) {
346
+ console.log('Not currently logged in.');
347
+ return;
348
+ }
349
+ try {
350
+ await authService.clearToken();
351
+ console.log('Successfully logged out. Credentials removed.');
352
+ }
353
+ catch (err) {
354
+ console.error(`Logout failed: ${err.message}`);
355
+ process.exitCode = 1;
356
+ }
357
+ }
358
+
359
+
360
+ /***/ }),
361
+ /* 10 */
362
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
363
+
364
+
365
+ /**
366
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
367
+ *
368
+ * This software is proprietary and confidential.
369
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
370
+ */
371
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
372
+ exports.whoamiCommand = whoamiCommand;
373
+ const auth_service_1 = __webpack_require__(3);
374
+ async function whoamiCommand() {
375
+ const authService = new auth_service_1.AuthService();
376
+ const creds = await authService.getCredentials();
377
+ if (!creds?.token) {
378
+ console.log('Not logged in. Run: onklave login --token <token>');
379
+ process.exitCode = 1;
380
+ return;
381
+ }
382
+ const isValid = await authService.isAuthenticated();
383
+ console.log('Onklave Agent CLI — Identity\n');
384
+ console.log(` Platform URL: ${creds.platformUrl}`);
385
+ console.log(` User ID: ${creds.userId ?? '(not set)'}`);
386
+ console.log(` Org ID: ${creds.orgId ?? '(not set)'}`);
387
+ console.log(` Machine ID: ${creds.machineId ?? '(not registered)'}`);
388
+ console.log(` Token status: ${isValid ? 'valid' : 'expired'}`);
389
+ if (creds.expiresAt) {
390
+ console.log(` Expires at: ${creds.expiresAt}`);
391
+ }
392
+ console.log(` Device token: ${creds.deviceToken ? 'present' : 'not set'}`);
393
+ }
394
+
395
+
396
+ /***/ }),
397
+ /* 11 */
398
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
399
+
400
+
401
+ /**
402
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
403
+ *
404
+ * This software is proprietary and confidential.
405
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
406
+ */
407
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
408
+ exports.runCommand = runCommand;
409
+ const auth_service_1 = __webpack_require__(3);
410
+ const config_resolver_1 = __webpack_require__(12);
411
+ const platform_client_1 = __webpack_require__(13);
412
+ const comms_client_1 = __webpack_require__(14);
413
+ const session_manager_1 = __webpack_require__(16);
414
+ const state_publisher_1 = __webpack_require__(18);
415
+ const audit_streamer_1 = __webpack_require__(20);
416
+ const guardrail_enforcer_1 = __webpack_require__(21);
417
+ const events_types_1 = __webpack_require__(19);
418
+ const utils_1 = __webpack_require__(8);
419
+ async function runCommand(args) {
420
+ const { flags } = (0, utils_1.parseArgs)(args);
421
+ // Validate required flags
422
+ const task = flags['task'];
423
+ if (typeof task !== 'string' || !task) {
424
+ console.error('Error: --task is required.\n');
425
+ console.log('Usage: onklave run --task "..." [options]\n');
426
+ console.log('Options:');
427
+ console.log(' --task <task> Task description (required)');
428
+ console.log(' --context <path> Working directory (default: .)');
429
+ console.log(' --persona <name> Persona to use');
430
+ console.log(' --workflow <name> Workflow to execute');
431
+ console.log(' --model <model> Model to use');
432
+ console.log(' --timeout <seconds> Timeout in seconds (default: 120)');
433
+ console.log(' --headless Run without terminal output');
434
+ console.log(' --api-endpoint <url> Override platform API endpoint');
435
+ console.log(' --dry-run Print resolved config and exit');
436
+ process.exitCode = 1;
437
+ return;
438
+ }
439
+ // Authenticate
440
+ const authService = new auth_service_1.AuthService();
441
+ const isAuth = await authService.isAuthenticated();
442
+ if (!isAuth) {
443
+ console.error('Error: Not authenticated. Run: onklave login --token <token>');
444
+ process.exitCode = 1;
445
+ return;
446
+ }
447
+ const creds = await authService.getCredentials();
448
+ if (!creds) {
449
+ console.error('Error: Failed to read credentials.');
450
+ process.exitCode = 1;
451
+ return;
452
+ }
453
+ // Resolve configuration
454
+ const configResolver = new config_resolver_1.ConfigResolver();
455
+ const resolvedConfig = await configResolver.resolve(flags, process.cwd());
456
+ resolvedConfig.task = task;
457
+ // Dry run — print config and exit
458
+ if (resolvedConfig.dryRun) {
459
+ console.log('Onklave Agent CLI — Dry Run\n');
460
+ console.log('Resolved configuration:');
461
+ console.log(JSON.stringify(resolvedConfig, null, 2));
462
+ return;
463
+ }
464
+ // Create platform client
465
+ const platformClient = new platform_client_1.PlatformClient(resolvedConfig.platformUrl, creds.token);
466
+ // Create session on platform
467
+ let sessionId;
468
+ try {
469
+ console.log('Creating agent session on Onklave platform...');
470
+ const result = await platformClient.spawnSession({
471
+ task: resolvedConfig.task,
472
+ context: resolvedConfig.context,
473
+ persona: resolvedConfig.persona,
474
+ workflow: resolvedConfig.workflow,
475
+ model: resolvedConfig.model,
476
+ timeout: resolvedConfig.timeout,
477
+ machineId: creds.machineId,
478
+ });
479
+ sessionId = result.sessionId;
480
+ console.log(`Session created: ${sessionId}`);
481
+ }
482
+ catch (err) {
483
+ console.error(`Failed to create session: ${err.message}`);
484
+ process.exitCode = 1;
485
+ return;
486
+ }
487
+ // Connect to comms service
488
+ const commsClient = new comms_client_1.CommsClient();
489
+ const statePublisher = new state_publisher_1.StatePublisher(commsClient);
490
+ const auditStreamer = new audit_streamer_1.AuditStreamer(commsClient);
491
+ try {
492
+ console.log('Connecting to Onklave comms service...');
493
+ await commsClient.connect(resolvedConfig.platformUrl, creds.token);
494
+ console.log('Connected.');
495
+ }
496
+ catch (err) {
497
+ console.warn(`Warning: Could not connect to comms service: ${err.message}`);
498
+ console.warn('Session will continue without real-time streaming.');
499
+ }
500
+ // Load persona config if specified
501
+ let personaSystemPrompt = null;
502
+ if (resolvedConfig.persona) {
503
+ try {
504
+ const persona = await platformClient.getPersona(resolvedConfig.persona);
505
+ personaSystemPrompt = persona.systemPrompt;
506
+ // Merge persona guardrails
507
+ if (persona.allowedTools?.length) {
508
+ resolvedConfig.allowedTools = [
509
+ ...new Set([...resolvedConfig.allowedTools, ...persona.allowedTools]),
510
+ ];
511
+ }
512
+ if (persona.deniedTools?.length) {
513
+ resolvedConfig.deniedTools = [
514
+ ...new Set([...resolvedConfig.deniedTools, ...persona.deniedTools]),
515
+ ];
516
+ }
517
+ }
518
+ catch (err) {
519
+ console.warn(`Warning: Could not load persona "${resolvedConfig.persona}": ${err.message}`);
520
+ }
521
+ }
522
+ // Set up guardrail enforcer (available for future tool-call interception)
523
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
524
+ const _guardrailEnforcer = new guardrail_enforcer_1.GuardrailEnforcer({
525
+ rules: resolvedConfig.guardrails,
526
+ allowedTools: resolvedConfig.allowedTools,
527
+ deniedTools: resolvedConfig.deniedTools,
528
+ readablePaths: resolvedConfig.readablePaths,
529
+ writablePaths: resolvedConfig.writablePaths,
530
+ });
531
+ // Build session config
532
+ const sessionConfig = {
533
+ task: resolvedConfig.task,
534
+ context: resolvedConfig.context,
535
+ persona: resolvedConfig.persona,
536
+ workflow: resolvedConfig.workflow,
537
+ model: resolvedConfig.model,
538
+ timeout: resolvedConfig.timeout,
539
+ guardrails: resolvedConfig.guardrails,
540
+ allowedTools: resolvedConfig.allowedTools,
541
+ deniedTools: resolvedConfig.deniedTools,
542
+ apiKey: resolvedConfig.apiKey,
543
+ headless: resolvedConfig.headless,
544
+ platformUrl: resolvedConfig.platformUrl,
545
+ orgId: resolvedConfig.orgId,
546
+ systemPromptAppend: personaSystemPrompt ?? resolvedConfig.systemPromptAppend,
547
+ };
548
+ // Publish session started
549
+ statePublisher.publishSessionStarted(sessionId, sessionConfig);
550
+ auditStreamer.record({
551
+ sessionId,
552
+ type: events_types_1.AuditEventType.STATE_CHANGE,
553
+ action: 'session_started',
554
+ details: { task: resolvedConfig.task, model: resolvedConfig.model },
555
+ outcome: 'success',
556
+ });
557
+ // Listen for cancel commands
558
+ commsClient.onCancel((cancelledId) => {
559
+ if (cancelledId === sessionId) {
560
+ console.log('\nSession cancelled by platform.');
561
+ sessionManager.stopSession(sessionId).catch(() => {
562
+ /* already exiting */
563
+ });
564
+ }
565
+ });
566
+ // Listen for approval responses
567
+ commsClient.onApprovalResponse((response) => {
568
+ if (response.sessionId === sessionId) {
569
+ console.log(`\nApproval response: ${response.decision}${response.message ? ` — ${response.message}` : ''}`);
570
+ }
571
+ });
572
+ // Spawn Claude Code subprocess
573
+ const sessionManager = new session_manager_1.SessionManager();
574
+ let output = '';
575
+ console.log(`\nRunning task: ${resolvedConfig.task}`);
576
+ console.log(`Model: ${resolvedConfig.model}`);
577
+ console.log(`Context: ${resolvedConfig.context}`);
578
+ console.log('---\n');
579
+ // Set up timeout
580
+ const timeoutMs = resolvedConfig.timeout * 1000;
581
+ const timeoutHandle = setTimeout(async () => {
582
+ console.error(`\nSession timed out after ${resolvedConfig.timeout} seconds.`);
583
+ statePublisher.publishSessionFailed(sessionId, 'Session timed out');
584
+ await sessionManager.stopSession(sessionId).catch(() => {
585
+ /* already exiting */
586
+ });
587
+ try {
588
+ await platformClient.cancelSession(sessionId);
589
+ }
590
+ catch {
591
+ // Best effort
592
+ }
593
+ process.exitCode = 1;
594
+ }, timeoutMs);
595
+ try {
596
+ await sessionManager.spawnSession(sessionId, sessionConfig, {
597
+ onStdout: (data) => {
598
+ output += data;
599
+ if (!resolvedConfig.headless) {
600
+ process.stdout.write(data);
601
+ }
602
+ statePublisher.publishActivityUpdate(sessionId, data.trim().slice(0, 200));
603
+ },
604
+ onStderr: (data) => {
605
+ if (!resolvedConfig.headless) {
606
+ process.stderr.write(data);
607
+ }
608
+ auditStreamer.record({
609
+ sessionId,
610
+ type: events_types_1.AuditEventType.COMMAND_EXECUTION,
611
+ action: 'stderr_output',
612
+ details: { data: data.trim().slice(0, 500) },
613
+ outcome: 'failure',
614
+ });
615
+ },
616
+ onExit: async (code) => {
617
+ clearTimeout(timeoutHandle);
618
+ if (code === 0) {
619
+ console.log('\n---');
620
+ console.log(`Session ${sessionId} completed successfully.`);
621
+ statePublisher.publishSessionCompleted(sessionId, output.trim().slice(-500));
622
+ auditStreamer.record({
623
+ sessionId,
624
+ type: events_types_1.AuditEventType.STATE_CHANGE,
625
+ action: 'session_completed',
626
+ details: { exitCode: code },
627
+ outcome: 'success',
628
+ });
629
+ }
630
+ else {
631
+ console.error(`\n---`);
632
+ console.error(`Session ${sessionId} exited with code ${code}.`);
633
+ statePublisher.publishSessionFailed(sessionId, `Exit code: ${code}`);
634
+ auditStreamer.record({
635
+ sessionId,
636
+ type: events_types_1.AuditEventType.STATE_CHANGE,
637
+ action: 'session_failed',
638
+ details: { exitCode: code },
639
+ outcome: 'failure',
640
+ });
641
+ process.exitCode = 1;
642
+ }
643
+ // Disconnect comms
644
+ commsClient.disconnect();
645
+ },
646
+ });
647
+ // Wait for the process to finish
648
+ await new Promise((resolve) => {
649
+ const checkInterval = setInterval(() => {
650
+ if (!sessionManager.isSessionActive(sessionId)) {
651
+ clearInterval(checkInterval);
652
+ resolve();
653
+ }
654
+ }, 500);
655
+ });
656
+ }
657
+ catch (err) {
658
+ clearTimeout(timeoutHandle);
659
+ console.error(`Session failed: ${err.message}`);
660
+ statePublisher.publishSessionFailed(sessionId, err.message);
661
+ commsClient.disconnect();
662
+ process.exitCode = 1;
663
+ }
664
+ }
665
+
666
+
667
+ /***/ }),
668
+ /* 12 */
669
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
670
+
671
+
672
+ /**
673
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
674
+ *
675
+ * This software is proprietary and confidential.
676
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
677
+ */
678
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
679
+ exports.ConfigResolver = void 0;
680
+ const tslib_1 = __webpack_require__(4);
681
+ const fs = tslib_1.__importStar(__webpack_require__(5));
682
+ const path = tslib_1.__importStar(__webpack_require__(6));
683
+ const os = tslib_1.__importStar(__webpack_require__(7));
684
+ const DEFAULT_MODEL = 'claude-sonnet-4-20250514';
685
+ const DEFAULT_TIMEOUT = 120;
686
+ const DEFAULT_PLATFORM_URL = 'https://api.onklave.app';
687
+ class ConfigResolver {
688
+ /**
689
+ * Resolve configuration by merging all sources.
690
+ * Priority: flags > env > .onklave.json > global config > platform defaults
691
+ */
692
+ async resolve(flags, cwd) {
693
+ const projectConfig = this.loadOnklaveJson(cwd);
694
+ const globalConfig = this.loadGlobalConfig();
695
+ // Build config layers from lowest to highest priority
696
+ const defaults = {
697
+ task: '',
698
+ context: cwd,
699
+ persona: null,
700
+ workflow: null,
701
+ model: DEFAULT_MODEL,
702
+ timeout: DEFAULT_TIMEOUT,
703
+ headless: false,
704
+ dryRun: false,
705
+ apiKey: null,
706
+ apiEndpoint: DEFAULT_PLATFORM_URL,
707
+ platformUrl: DEFAULT_PLATFORM_URL,
708
+ orgId: null,
709
+ allowedTools: [],
710
+ deniedTools: [],
711
+ readablePaths: [],
712
+ writablePaths: [],
713
+ guardrails: [],
714
+ systemPromptAppend: null,
715
+ contextIncludes: [],
716
+ };
717
+ const fromGlobal = {};
718
+ if (globalConfig) {
719
+ if (globalConfig.platformUrl)
720
+ fromGlobal.platformUrl = globalConfig.platformUrl;
721
+ if (globalConfig.platformUrl)
722
+ fromGlobal.apiEndpoint = globalConfig.platformUrl;
723
+ if (globalConfig.defaultModel)
724
+ fromGlobal.model = globalConfig.defaultModel;
725
+ if (globalConfig.defaultPersona)
726
+ fromGlobal.persona = globalConfig.defaultPersona;
727
+ if (globalConfig.defaultTimeout)
728
+ fromGlobal.timeout = globalConfig.defaultTimeout;
729
+ }
730
+ const fromProject = {};
731
+ if (projectConfig) {
732
+ if (projectConfig.org)
733
+ fromProject.orgId = projectConfig.org;
734
+ if (projectConfig.defaults?.persona)
735
+ fromProject.persona = projectConfig.defaults.persona;
736
+ if (projectConfig.defaults?.workflow)
737
+ fromProject.workflow = projectConfig.defaults.workflow;
738
+ if (projectConfig.defaults?.model)
739
+ fromProject.model = projectConfig.defaults.model;
740
+ if (projectConfig.defaults?.timeout)
741
+ fromProject.timeout = projectConfig.defaults.timeout;
742
+ if (projectConfig.permissions?.tools_allowed)
743
+ fromProject.allowedTools = projectConfig.permissions.tools_allowed;
744
+ if (projectConfig.permissions?.tools_denied)
745
+ fromProject.deniedTools = projectConfig.permissions.tools_denied;
746
+ if (projectConfig.permissions?.paths_readable)
747
+ fromProject.readablePaths = projectConfig.permissions.paths_readable;
748
+ if (projectConfig.permissions?.paths_writable)
749
+ fromProject.writablePaths = projectConfig.permissions.paths_writable;
750
+ if (projectConfig.guardrails)
751
+ fromProject.guardrails = projectConfig.guardrails;
752
+ if (projectConfig.context?.system_prompt_append)
753
+ fromProject.systemPromptAppend =
754
+ projectConfig.context.system_prompt_append;
755
+ if (projectConfig.context?.includes)
756
+ fromProject.contextIncludes = projectConfig.context.includes;
757
+ }
758
+ const fromEnv = {};
759
+ if (process.env['ONKLAVE_API_KEY'])
760
+ fromEnv.apiKey = process.env['ONKLAVE_API_KEY'];
761
+ if (process.env['ONKLAVE_PLATFORM_URL']) {
762
+ fromEnv.platformUrl = process.env['ONKLAVE_PLATFORM_URL'];
763
+ fromEnv.apiEndpoint = process.env['ONKLAVE_PLATFORM_URL'];
764
+ }
765
+ if (process.env['ONKLAVE_MODEL'])
766
+ fromEnv.model = process.env['ONKLAVE_MODEL'];
767
+ if (process.env['ONKLAVE_ORG_ID'])
768
+ fromEnv.orgId = process.env['ONKLAVE_ORG_ID'];
769
+ if (process.env['ANTHROPIC_API_KEY'])
770
+ fromEnv.apiKey = process.env['ANTHROPIC_API_KEY'];
771
+ const fromFlags = {};
772
+ if (typeof flags['task'] === 'string')
773
+ fromFlags.task = flags['task'];
774
+ if (typeof flags['context'] === 'string')
775
+ fromFlags.context = path.resolve(flags['context']);
776
+ if (typeof flags['persona'] === 'string')
777
+ fromFlags.persona = flags['persona'];
778
+ if (typeof flags['workflow'] === 'string')
779
+ fromFlags.workflow = flags['workflow'];
780
+ if (typeof flags['model'] === 'string')
781
+ fromFlags.model = flags['model'];
782
+ if (typeof flags['timeout'] === 'string')
783
+ fromFlags.timeout = parseInt(flags['timeout'], 10);
784
+ if (flags['headless'] === true)
785
+ fromFlags.headless = true;
786
+ if (flags['dry-run'] === true)
787
+ fromFlags.dryRun = true;
788
+ if (typeof flags['api-endpoint'] === 'string') {
789
+ fromFlags.apiEndpoint = flags['api-endpoint'];
790
+ fromFlags.platformUrl = flags['api-endpoint'];
791
+ }
792
+ return this.mergeConfigs(defaults, fromGlobal, fromProject, fromEnv, fromFlags);
793
+ }
794
+ /**
795
+ * Load .onklave.json from the given directory.
796
+ */
797
+ loadOnklaveJson(cwd) {
798
+ const filePath = path.join(cwd, '.onklave.json');
799
+ if (!fs.existsSync(filePath)) {
800
+ return null;
801
+ }
802
+ try {
803
+ const raw = fs.readFileSync(filePath, 'utf-8');
804
+ return JSON.parse(raw);
805
+ }
806
+ catch (err) {
807
+ console.error(`Warning: Failed to parse .onklave.json: ${err.message}`);
808
+ return null;
809
+ }
810
+ }
811
+ /**
812
+ * Load global config from ~/.config/onklave/config.json.
813
+ */
814
+ loadGlobalConfig() {
815
+ const filePath = path.join(os.homedir(), '.config', 'onklave', 'config.json');
816
+ if (!fs.existsSync(filePath)) {
817
+ return null;
818
+ }
819
+ try {
820
+ const raw = fs.readFileSync(filePath, 'utf-8');
821
+ return JSON.parse(raw);
822
+ }
823
+ catch {
824
+ return null;
825
+ }
826
+ }
827
+ /**
828
+ * Save a value to the global config file.
829
+ */
830
+ saveGlobalConfig(key, value) {
831
+ const configDir = path.join(os.homedir(), '.config', 'onklave');
832
+ const filePath = path.join(configDir, 'config.json');
833
+ if (!fs.existsSync(configDir)) {
834
+ fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
835
+ }
836
+ let config = {};
837
+ if (fs.existsSync(filePath)) {
838
+ try {
839
+ config = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
840
+ }
841
+ catch {
842
+ // Start fresh
843
+ }
844
+ }
845
+ // Support dot-notation keys
846
+ const keys = key.split('.');
847
+ let target = config;
848
+ for (let i = 0; i < keys.length - 1; i++) {
849
+ const k = keys[i];
850
+ if (!target[k] || typeof target[k] !== 'object') {
851
+ target[k] = {};
852
+ }
853
+ target = target[k];
854
+ }
855
+ target[keys[keys.length - 1]] = value;
856
+ fs.writeFileSync(filePath, JSON.stringify(config, null, 2), {
857
+ encoding: 'utf-8',
858
+ mode: 0o600,
859
+ });
860
+ }
861
+ /**
862
+ * Get a value from the global config by dot-notation key.
863
+ */
864
+ getGlobalConfigValue(key) {
865
+ const config = this.loadGlobalConfig();
866
+ if (!config)
867
+ return undefined;
868
+ const keys = key.split('.');
869
+ let target = config;
870
+ for (const k of keys) {
871
+ if (target && typeof target === 'object' && k in target) {
872
+ target = target[k];
873
+ }
874
+ else {
875
+ return undefined;
876
+ }
877
+ }
878
+ return target;
879
+ }
880
+ /**
881
+ * Merge multiple partial configs, later entries override earlier.
882
+ */
883
+ mergeConfigs(...configs) {
884
+ const result = {};
885
+ for (const config of configs) {
886
+ for (const [key, value] of Object.entries(config)) {
887
+ if (value !== undefined && value !== null && value !== '') {
888
+ result[key] = value;
889
+ }
890
+ }
891
+ }
892
+ return result;
893
+ }
894
+ }
895
+ exports.ConfigResolver = ConfigResolver;
896
+
897
+
898
+ /***/ }),
899
+ /* 13 */
900
+ /***/ ((__unused_webpack_module, exports) => {
901
+
902
+
903
+ /**
904
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
905
+ *
906
+ * This software is proprietary and confidential.
907
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
908
+ */
909
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
910
+ exports.PlatformClient = void 0;
911
+ class PlatformClient {
912
+ constructor(baseUrl, token) {
913
+ this.baseUrl = baseUrl;
914
+ this.token = token;
915
+ }
916
+ /**
917
+ * Create a new agent session on the platform.
918
+ */
919
+ async spawnSession(config) {
920
+ return this.request('POST', '/api/v1/agent/spawn', config);
921
+ }
922
+ /**
923
+ * Get details for a specific session.
924
+ */
925
+ async getSession(sessionId) {
926
+ return this.request('GET', `/api/v1/agent/sessions/${sessionId}`);
927
+ }
928
+ /**
929
+ * List all active sessions for the authenticated user/machine.
930
+ */
931
+ async listSessions() {
932
+ return this.request('GET', '/api/v1/agent/sessions');
933
+ }
934
+ /**
935
+ * Cancel a running session.
936
+ */
937
+ async cancelSession(sessionId) {
938
+ await this.request('POST', `/api/v1/agent/sessions/${sessionId}/cancel`);
939
+ }
940
+ /**
941
+ * Respond to an approval gate.
942
+ */
943
+ async respondToGate(sessionId, decision, value) {
944
+ await this.request('POST', `/api/v1/agent/sessions/${sessionId}/gate`, {
945
+ decision,
946
+ message: value,
947
+ });
948
+ }
949
+ /**
950
+ * Get session logs from the platform.
951
+ */
952
+ async getSessionLogs(sessionId) {
953
+ return this.request('GET', `/api/v1/agent/sessions/${sessionId}/logs`);
954
+ }
955
+ /**
956
+ * Get a persona configuration by name.
957
+ */
958
+ async getPersona(name) {
959
+ return this.request('GET', `/api/v1/agent/personas/${encodeURIComponent(name)}`);
960
+ }
961
+ /**
962
+ * List all available personas.
963
+ */
964
+ async listPersonas() {
965
+ return this.request('GET', '/api/v1/agent/personas');
966
+ }
967
+ /**
968
+ * Get a workflow configuration by name.
969
+ */
970
+ async getWorkflow(name) {
971
+ return this.request('GET', `/api/v1/agent/workflows/${encodeURIComponent(name)}`);
972
+ }
973
+ /**
974
+ * Register this machine as an agent runner.
975
+ */
976
+ async registerMachine(linkingToken, metadata) {
977
+ return this.request('POST', '/api/v1/runner/register', {
978
+ linkingToken,
979
+ metadata,
980
+ });
981
+ }
982
+ /**
983
+ * Unregister this machine.
984
+ */
985
+ async unregisterMachine() {
986
+ await this.request('POST', '/api/v1/runner/unregister');
987
+ }
988
+ /**
989
+ * List all registered machines.
990
+ */
991
+ async listMachines() {
992
+ return this.request('GET', '/api/v1/runner/machines');
993
+ }
994
+ /**
995
+ * Check platform health.
996
+ */
997
+ async healthCheck() {
998
+ try {
999
+ const response = await fetch(`${this.baseUrl}/health`, {
1000
+ method: 'GET',
1001
+ headers: { Accept: 'application/json' },
1002
+ signal: AbortSignal.timeout(5000),
1003
+ });
1004
+ return response.ok;
1005
+ }
1006
+ catch {
1007
+ return false;
1008
+ }
1009
+ }
1010
+ /**
1011
+ * Make an authenticated HTTP request to the platform.
1012
+ */
1013
+ async request(method, path, body) {
1014
+ const url = `${this.baseUrl}${path}`;
1015
+ const headers = {
1016
+ Authorization: `Bearer ${this.token}`,
1017
+ 'Content-Type': 'application/json',
1018
+ Accept: 'application/json',
1019
+ };
1020
+ const options = {
1021
+ method,
1022
+ headers,
1023
+ signal: AbortSignal.timeout(30000),
1024
+ };
1025
+ if (body && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {
1026
+ options.body = JSON.stringify(body);
1027
+ }
1028
+ const response = await fetch(url, options);
1029
+ if (!response.ok) {
1030
+ let errorMessage = `Platform API error: ${response.status} ${response.statusText}`;
1031
+ try {
1032
+ const errorBody = await response.json();
1033
+ if (errorBody &&
1034
+ typeof errorBody === 'object' &&
1035
+ 'message' in errorBody) {
1036
+ errorMessage = `Platform API error: ${errorBody.message}`;
1037
+ }
1038
+ }
1039
+ catch {
1040
+ // Ignore JSON parse errors for error body
1041
+ }
1042
+ throw new Error(errorMessage);
1043
+ }
1044
+ // Handle empty responses (204, etc.)
1045
+ const contentType = response.headers.get('content-type');
1046
+ if (!contentType || !contentType.includes('application/json')) {
1047
+ return undefined;
1048
+ }
1049
+ const text = await response.text();
1050
+ if (!text) {
1051
+ return undefined;
1052
+ }
1053
+ return JSON.parse(text);
1054
+ }
1055
+ }
1056
+ exports.PlatformClient = PlatformClient;
1057
+
1058
+
1059
+ /***/ }),
1060
+ /* 14 */
1061
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1062
+
1063
+
1064
+ /**
1065
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1066
+ *
1067
+ * This software is proprietary and confidential.
1068
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1069
+ */
1070
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1071
+ exports.CommsClient = void 0;
1072
+ const socket_io_client_1 = __webpack_require__(15);
1073
+ class CommsClient {
1074
+ constructor() {
1075
+ this.socket = null;
1076
+ this.reconnectAttempts = 0;
1077
+ this.maxReconnectAttempts = 10;
1078
+ }
1079
+ /**
1080
+ * Connect to the Onklave comms service via Socket.IO.
1081
+ */
1082
+ async connect(platformUrl, token) {
1083
+ return new Promise((resolve, reject) => {
1084
+ const commsUrl = platformUrl.replace(/\/+$/, '');
1085
+ this.socket = (0, socket_io_client_1.io)(`${commsUrl}/agent`, {
1086
+ auth: { token },
1087
+ transports: ['websocket', 'polling'],
1088
+ reconnection: true,
1089
+ reconnectionAttempts: this.maxReconnectAttempts,
1090
+ reconnectionDelay: 1000,
1091
+ reconnectionDelayMax: 30000,
1092
+ timeout: 10000,
1093
+ });
1094
+ const connectTimeout = setTimeout(() => {
1095
+ if (this.socket && !this.socket.connected) {
1096
+ this.socket.disconnect();
1097
+ reject(new Error('WebSocket connection timed out after 10 seconds'));
1098
+ }
1099
+ }, 10000);
1100
+ this.socket.on('connect', () => {
1101
+ clearTimeout(connectTimeout);
1102
+ this.reconnectAttempts = 0;
1103
+ resolve();
1104
+ });
1105
+ this.socket.on('connect_error', (error) => {
1106
+ this.reconnectAttempts++;
1107
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
1108
+ clearTimeout(connectTimeout);
1109
+ reject(new Error(`WebSocket connection failed after ${this.maxReconnectAttempts} attempts: ${error.message}`));
1110
+ }
1111
+ });
1112
+ this.socket.on('disconnect', (reason) => {
1113
+ if (reason === 'io server disconnect') {
1114
+ // Server disconnected us, don't reconnect automatically
1115
+ console.error('[comms] Disconnected by server');
1116
+ }
1117
+ });
1118
+ });
1119
+ }
1120
+ /**
1121
+ * Disconnect from the comms service.
1122
+ */
1123
+ disconnect() {
1124
+ if (this.socket) {
1125
+ this.socket.removeAllListeners();
1126
+ this.socket.disconnect();
1127
+ this.socket = null;
1128
+ }
1129
+ }
1130
+ /**
1131
+ * Check if currently connected.
1132
+ */
1133
+ isConnected() {
1134
+ return this.socket?.connected ?? false;
1135
+ }
1136
+ /**
1137
+ * Emit a state event to the platform.
1138
+ */
1139
+ emitState(event) {
1140
+ this.socket?.emit('agent:state', event);
1141
+ }
1142
+ /**
1143
+ * Emit an audit event to the platform.
1144
+ */
1145
+ emitAudit(event) {
1146
+ this.socket?.emit('agent:audit', event);
1147
+ }
1148
+ /**
1149
+ * Emit a heartbeat to the platform.
1150
+ */
1151
+ emitHeartbeat(data) {
1152
+ this.socket?.emit('agent:heartbeat', data);
1153
+ }
1154
+ /**
1155
+ * Listen for approval responses from the platform.
1156
+ */
1157
+ onApprovalResponse(handler) {
1158
+ this.socket?.on('agent:approval_response', handler);
1159
+ }
1160
+ /**
1161
+ * Listen for session cancel commands from the platform.
1162
+ */
1163
+ onCancel(handler) {
1164
+ this.socket?.on('agent:cancel', (data) => {
1165
+ handler(data.sessionId);
1166
+ });
1167
+ }
1168
+ /**
1169
+ * Listen for remote spawn requests from the platform.
1170
+ */
1171
+ onSpawnRequest(handler) {
1172
+ this.socket?.on('agent:spawn', handler);
1173
+ }
1174
+ }
1175
+ exports.CommsClient = CommsClient;
1176
+
1177
+
1178
+ /***/ }),
1179
+ /* 15 */
1180
+ /***/ ((module) => {
1181
+
1182
+ module.exports = require("socket.io-client");
1183
+
1184
+ /***/ }),
1185
+ /* 16 */
1186
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1187
+
1188
+
1189
+ /**
1190
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1191
+ *
1192
+ * This software is proprietary and confidential.
1193
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1194
+ */
1195
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1196
+ exports.SessionManager = void 0;
1197
+ const child_process_1 = __webpack_require__(17);
1198
+ class SessionManager {
1199
+ constructor() {
1200
+ this.activeSessions = new Map();
1201
+ }
1202
+ /**
1203
+ * Spawn a new Claude Code subprocess for an agent session.
1204
+ * Returns the session ID.
1205
+ */
1206
+ async spawnSession(sessionId, config, callbacks = {}) {
1207
+ const args = [];
1208
+ // Build Claude CLI arguments
1209
+ if (config.task) {
1210
+ args.push('--print');
1211
+ args.push(config.task);
1212
+ }
1213
+ if (config.model) {
1214
+ args.push('--model', config.model);
1215
+ }
1216
+ if (config.allowedTools && config.allowedTools.length > 0) {
1217
+ args.push('--allowedTools', config.allowedTools.join(','));
1218
+ }
1219
+ if (config.systemPromptAppend) {
1220
+ args.push('--append-system-prompt', config.systemPromptAppend);
1221
+ }
1222
+ // Build environment
1223
+ const env = { ...process.env };
1224
+ if (config.apiKey) {
1225
+ env['ANTHROPIC_API_KEY'] = config.apiKey;
1226
+ }
1227
+ const child = (0, child_process_1.spawn)('claude', args, {
1228
+ cwd: config.context,
1229
+ env,
1230
+ stdio: ['pipe', 'pipe', 'pipe'],
1231
+ });
1232
+ const managed = {
1233
+ sessionId,
1234
+ process: child,
1235
+ config,
1236
+ startedAt: new Date(),
1237
+ };
1238
+ this.activeSessions.set(sessionId, managed);
1239
+ // Wire up stdout
1240
+ child.stdout?.on('data', (data) => {
1241
+ const text = data.toString();
1242
+ if (callbacks.onStdout) {
1243
+ callbacks.onStdout(text);
1244
+ }
1245
+ });
1246
+ // Wire up stderr
1247
+ child.stderr?.on('data', (data) => {
1248
+ const text = data.toString();
1249
+ if (callbacks.onStderr) {
1250
+ callbacks.onStderr(text);
1251
+ }
1252
+ });
1253
+ // Handle process exit
1254
+ child.on('exit', (code, signal) => {
1255
+ this.activeSessions.delete(sessionId);
1256
+ if (callbacks.onExit) {
1257
+ callbacks.onExit(code, signal);
1258
+ }
1259
+ });
1260
+ // Handle spawn errors
1261
+ child.on('error', (err) => {
1262
+ this.activeSessions.delete(sessionId);
1263
+ if (callbacks.onStderr) {
1264
+ callbacks.onStderr(`Failed to spawn Claude Code: ${err.message}`);
1265
+ }
1266
+ if (callbacks.onExit) {
1267
+ callbacks.onExit(1, null);
1268
+ }
1269
+ });
1270
+ return sessionId;
1271
+ }
1272
+ /**
1273
+ * Stop a specific session by killing its subprocess.
1274
+ */
1275
+ async stopSession(sessionId) {
1276
+ const session = this.activeSessions.get(sessionId);
1277
+ if (!session) {
1278
+ throw new Error(`No active session found with ID: ${sessionId}`);
1279
+ }
1280
+ // Try graceful shutdown first (SIGTERM), then force after timeout
1281
+ session.process.kill('SIGTERM');
1282
+ await new Promise((resolve) => {
1283
+ const forceTimeout = setTimeout(() => {
1284
+ if (session.process.killed === false) {
1285
+ session.process.kill('SIGKILL');
1286
+ }
1287
+ resolve();
1288
+ }, 5000);
1289
+ session.process.on('exit', () => {
1290
+ clearTimeout(forceTimeout);
1291
+ resolve();
1292
+ });
1293
+ });
1294
+ this.activeSessions.delete(sessionId);
1295
+ }
1296
+ /**
1297
+ * Stop all active sessions.
1298
+ */
1299
+ async stopAll() {
1300
+ const sessionIds = [...this.activeSessions.keys()];
1301
+ const results = await Promise.allSettled(sessionIds.map((id) => this.stopSession(id)));
1302
+ for (let i = 0; i < results.length; i++) {
1303
+ const result = results[i];
1304
+ if (result.status === 'rejected') {
1305
+ console.error(`Failed to stop session ${sessionIds[i]}: ${result.reason}`);
1306
+ }
1307
+ }
1308
+ }
1309
+ /**
1310
+ * Get all active session IDs.
1311
+ */
1312
+ getActiveSessionIds() {
1313
+ return [...this.activeSessions.keys()];
1314
+ }
1315
+ /**
1316
+ * Check if a session is currently active.
1317
+ */
1318
+ isSessionActive(sessionId) {
1319
+ return this.activeSessions.has(sessionId);
1320
+ }
1321
+ /**
1322
+ * Get session details for an active session.
1323
+ */
1324
+ getSession(sessionId) {
1325
+ const session = this.activeSessions.get(sessionId);
1326
+ if (!session)
1327
+ return null;
1328
+ return { config: session.config, startedAt: session.startedAt };
1329
+ }
1330
+ }
1331
+ exports.SessionManager = SessionManager;
1332
+
1333
+
1334
+ /***/ }),
1335
+ /* 17 */
1336
+ /***/ ((module) => {
1337
+
1338
+ module.exports = require("child_process");
1339
+
1340
+ /***/ }),
1341
+ /* 18 */
1342
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1343
+
1344
+
1345
+ /**
1346
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1347
+ *
1348
+ * This software is proprietary and confidential.
1349
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1350
+ */
1351
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1352
+ exports.StatePublisher = void 0;
1353
+ const events_types_1 = __webpack_require__(19);
1354
+ class StatePublisher {
1355
+ constructor(commsClient) {
1356
+ this.commsClient = commsClient;
1357
+ }
1358
+ /**
1359
+ * Publish that a session has started.
1360
+ */
1361
+ publishSessionStarted(sessionId, config) {
1362
+ this.emit({
1363
+ sessionId,
1364
+ type: events_types_1.AgentStateEventType.SESSION_STARTED,
1365
+ timestamp: new Date().toISOString(),
1366
+ data: {
1367
+ task: config.task,
1368
+ persona: config.persona,
1369
+ workflow: config.workflow,
1370
+ model: config.model,
1371
+ context: config.context,
1372
+ timeout: config.timeout,
1373
+ },
1374
+ });
1375
+ }
1376
+ /**
1377
+ * Publish an activity update (e.g., "Reading file src/main.ts").
1378
+ */
1379
+ publishActivityUpdate(sessionId, activity) {
1380
+ this.emit({
1381
+ sessionId,
1382
+ type: events_types_1.AgentStateEventType.ACTIVITY_UPDATE,
1383
+ timestamp: new Date().toISOString(),
1384
+ data: { activity },
1385
+ });
1386
+ }
1387
+ /**
1388
+ * Publish a step transition in a workflow.
1389
+ */
1390
+ publishStepTransition(sessionId, step) {
1391
+ this.emit({
1392
+ sessionId,
1393
+ type: events_types_1.AgentStateEventType.STEP_TRANSITION,
1394
+ timestamp: new Date().toISOString(),
1395
+ data: { step },
1396
+ });
1397
+ }
1398
+ /**
1399
+ * Publish that the session is waiting for an approval gate.
1400
+ */
1401
+ publishWaitingApproval(sessionId, gate) {
1402
+ this.emit({
1403
+ sessionId,
1404
+ type: events_types_1.AgentStateEventType.WAITING_APPROVAL,
1405
+ timestamp: new Date().toISOString(),
1406
+ data: { gate },
1407
+ });
1408
+ }
1409
+ /**
1410
+ * Publish that a session completed successfully.
1411
+ */
1412
+ publishSessionCompleted(sessionId, summary) {
1413
+ this.emit({
1414
+ sessionId,
1415
+ type: events_types_1.AgentStateEventType.SESSION_COMPLETED,
1416
+ timestamp: new Date().toISOString(),
1417
+ data: { summary },
1418
+ });
1419
+ }
1420
+ /**
1421
+ * Publish that a session failed.
1422
+ */
1423
+ publishSessionFailed(sessionId, error) {
1424
+ this.emit({
1425
+ sessionId,
1426
+ type: events_types_1.AgentStateEventType.SESSION_FAILED,
1427
+ timestamp: new Date().toISOString(),
1428
+ data: { error },
1429
+ });
1430
+ }
1431
+ emit(event) {
1432
+ if (this.commsClient.isConnected()) {
1433
+ this.commsClient.emitState(event);
1434
+ }
1435
+ }
1436
+ }
1437
+ exports.StatePublisher = StatePublisher;
1438
+
1439
+
1440
+ /***/ }),
1441
+ /* 19 */
1442
+ /***/ ((__unused_webpack_module, exports) => {
1443
+
1444
+
1445
+ /**
1446
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1447
+ *
1448
+ * This software is proprietary and confidential.
1449
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1450
+ */
1451
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1452
+ exports.AuditEventType = exports.AgentStateEventType = void 0;
1453
+ var AgentStateEventType;
1454
+ (function (AgentStateEventType) {
1455
+ AgentStateEventType["SESSION_STARTED"] = "session_started";
1456
+ AgentStateEventType["SESSION_COMPLETED"] = "session_completed";
1457
+ AgentStateEventType["SESSION_FAILED"] = "session_failed";
1458
+ AgentStateEventType["SESSION_CANCELLED"] = "session_cancelled";
1459
+ AgentStateEventType["ACTIVITY_UPDATE"] = "activity_update";
1460
+ AgentStateEventType["STEP_TRANSITION"] = "step_transition";
1461
+ AgentStateEventType["WAITING_APPROVAL"] = "waiting_approval";
1462
+ AgentStateEventType["APPROVAL_RECEIVED"] = "approval_received";
1463
+ AgentStateEventType["HEARTBEAT"] = "heartbeat";
1464
+ })(AgentStateEventType || (exports.AgentStateEventType = AgentStateEventType = {}));
1465
+ var AuditEventType;
1466
+ (function (AuditEventType) {
1467
+ AuditEventType["TOOL_CALL"] = "tool_call";
1468
+ AuditEventType["FILE_ACCESS"] = "file_access";
1469
+ AuditEventType["COMMAND_EXECUTION"] = "command_execution";
1470
+ AuditEventType["GUARDRAIL_CHECK"] = "guardrail_check";
1471
+ AuditEventType["APPROVAL_GATE"] = "approval_gate";
1472
+ AuditEventType["STATE_CHANGE"] = "state_change";
1473
+ })(AuditEventType || (exports.AuditEventType = AuditEventType = {}));
1474
+
1475
+
1476
+ /***/ }),
1477
+ /* 20 */
1478
+ /***/ ((__unused_webpack_module, exports) => {
1479
+
1480
+
1481
+ /**
1482
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1483
+ *
1484
+ * This software is proprietary and confidential.
1485
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1486
+ */
1487
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1488
+ exports.AuditStreamer = void 0;
1489
+ class AuditStreamer {
1490
+ constructor(commsClient) {
1491
+ this.commsClient = commsClient;
1492
+ this.buffer = [];
1493
+ this.maxBufferSize = 1000;
1494
+ }
1495
+ /**
1496
+ * Record and stream an audit event.
1497
+ * If disconnected, events are buffered for later flushing.
1498
+ */
1499
+ record(event) {
1500
+ const fullEvent = {
1501
+ ...event,
1502
+ timestamp: new Date().toISOString(),
1503
+ };
1504
+ if (this.commsClient.isConnected()) {
1505
+ // Flush any buffered events first
1506
+ if (this.buffer.length > 0) {
1507
+ this.flush();
1508
+ }
1509
+ this.commsClient.emitAudit(fullEvent);
1510
+ }
1511
+ else {
1512
+ // Buffer if disconnected
1513
+ this.buffer.push(fullEvent);
1514
+ if (this.buffer.length > this.maxBufferSize) {
1515
+ // Drop oldest events if buffer is full
1516
+ this.buffer = this.buffer.slice(-this.maxBufferSize);
1517
+ }
1518
+ }
1519
+ }
1520
+ /**
1521
+ * Flush all buffered events to the platform.
1522
+ * Called on reconnect or when connection becomes available.
1523
+ */
1524
+ flush() {
1525
+ if (!this.commsClient.isConnected() || this.buffer.length === 0) {
1526
+ return;
1527
+ }
1528
+ const events = [...this.buffer];
1529
+ this.buffer = [];
1530
+ for (const event of events) {
1531
+ this.commsClient.emitAudit(event);
1532
+ }
1533
+ }
1534
+ /**
1535
+ * Get the number of buffered events.
1536
+ */
1537
+ getBufferSize() {
1538
+ return this.buffer.length;
1539
+ }
1540
+ }
1541
+ exports.AuditStreamer = AuditStreamer;
1542
+
1543
+
1544
+ /***/ }),
1545
+ /* 21 */
1546
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1547
+
1548
+
1549
+ /**
1550
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1551
+ *
1552
+ * This software is proprietary and confidential.
1553
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1554
+ */
1555
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1556
+ exports.GuardrailEnforcer = void 0;
1557
+ const tslib_1 = __webpack_require__(4);
1558
+ const path = tslib_1.__importStar(__webpack_require__(6));
1559
+ class GuardrailEnforcer {
1560
+ constructor(config) {
1561
+ this.config = config;
1562
+ }
1563
+ /**
1564
+ * Check if a tool call is permitted by the guardrail configuration.
1565
+ */
1566
+ checkToolCall(tool, params) {
1567
+ // Check explicit deny list first
1568
+ if (this.config.deniedTools.length > 0) {
1569
+ for (const denied of this.config.deniedTools) {
1570
+ if (this.matchPattern(tool, denied)) {
1571
+ return {
1572
+ allowed: false,
1573
+ reason: `Tool "${tool}" is explicitly denied`,
1574
+ };
1575
+ }
1576
+ }
1577
+ }
1578
+ // Check explicit allow list (if set, only listed tools are allowed)
1579
+ if (this.config.allowedTools.length > 0) {
1580
+ const isAllowed = this.config.allowedTools.some((allowed) => this.matchPattern(tool, allowed));
1581
+ if (!isAllowed) {
1582
+ return {
1583
+ allowed: false,
1584
+ reason: `Tool "${tool}" is not in the allowed tools list`,
1585
+ };
1586
+ }
1587
+ }
1588
+ // Check guardrail rules
1589
+ for (const rule of this.config.rules) {
1590
+ if (this.matchPattern(tool, rule.match)) {
1591
+ if (rule.action === 'deny') {
1592
+ return {
1593
+ allowed: false,
1594
+ reason: rule.reason ?? `Denied by guardrail rule: ${rule.name}`,
1595
+ };
1596
+ }
1597
+ if (rule.action === 'require_approval') {
1598
+ return {
1599
+ allowed: true,
1600
+ requiresApproval: true,
1601
+ reason: rule.reason ?? `Requires approval per rule: ${rule.name}`,
1602
+ };
1603
+ }
1604
+ }
1605
+ }
1606
+ // Check file paths in params if applicable
1607
+ if (params['path'] && typeof params['path'] === 'string') {
1608
+ const pathResult = this.checkPathAccess(params['path'], 'read');
1609
+ if (!pathResult.allowed) {
1610
+ return pathResult;
1611
+ }
1612
+ }
1613
+ return { allowed: true };
1614
+ }
1615
+ /**
1616
+ * Check if a file path is accessible for the given operation.
1617
+ */
1618
+ checkPathAccess(filePath, operation) {
1619
+ const normalizedPath = path.resolve(filePath);
1620
+ if (operation === 'write' || operation === 'delete') {
1621
+ // Check writable paths
1622
+ if (this.config.writablePaths.length > 0) {
1623
+ const isWritable = this.config.writablePaths.some((wp) => normalizedPath.startsWith(path.resolve(wp)));
1624
+ if (!isWritable) {
1625
+ return {
1626
+ allowed: false,
1627
+ reason: `Path "${filePath}" is not in the writable paths list`,
1628
+ };
1629
+ }
1630
+ }
1631
+ }
1632
+ if (operation === 'read') {
1633
+ // Check readable paths
1634
+ if (this.config.readablePaths.length > 0) {
1635
+ const isReadable = this.config.readablePaths.some((rp) => normalizedPath.startsWith(path.resolve(rp)));
1636
+ if (!isReadable) {
1637
+ return {
1638
+ allowed: false,
1639
+ reason: `Path "${filePath}" is not in the readable paths list`,
1640
+ };
1641
+ }
1642
+ }
1643
+ }
1644
+ // Block sensitive paths always
1645
+ const sensitivePatterns = [
1646
+ '.env',
1647
+ 'credentials.json',
1648
+ '.ssh',
1649
+ '.gnupg',
1650
+ '.aws/credentials',
1651
+ 'id_rsa',
1652
+ 'id_ed25519',
1653
+ ];
1654
+ const basename = path.basename(normalizedPath);
1655
+ for (const sensitive of sensitivePatterns) {
1656
+ if (basename === sensitive || normalizedPath.includes(`/${sensitive}`)) {
1657
+ return {
1658
+ allowed: false,
1659
+ reason: `Access to sensitive path "${filePath}" is blocked by default`,
1660
+ };
1661
+ }
1662
+ }
1663
+ return { allowed: true };
1664
+ }
1665
+ /**
1666
+ * Check if a shell command is permitted.
1667
+ */
1668
+ checkCommand(command) {
1669
+ // Check guardrail rules that apply to commands
1670
+ for (const rule of this.config.rules) {
1671
+ if (rule.match.startsWith('cmd:')) {
1672
+ const cmdPattern = rule.match.slice(4);
1673
+ if (this.matchPattern(command, cmdPattern)) {
1674
+ if (rule.action === 'deny') {
1675
+ return {
1676
+ allowed: false,
1677
+ reason: rule.reason ?? `Command denied by guardrail rule: ${rule.name}`,
1678
+ };
1679
+ }
1680
+ if (rule.action === 'require_approval') {
1681
+ return {
1682
+ allowed: true,
1683
+ requiresApproval: true,
1684
+ reason: rule.reason ??
1685
+ `Command requires approval per rule: ${rule.name}`,
1686
+ };
1687
+ }
1688
+ }
1689
+ }
1690
+ }
1691
+ // Block destructive commands by default
1692
+ const destructivePatterns = [
1693
+ 'rm -rf /',
1694
+ 'rm -rf ~',
1695
+ 'mkfs',
1696
+ 'dd if=',
1697
+ ':(){:|:&};:',
1698
+ 'chmod -R 777 /',
1699
+ ];
1700
+ for (const pattern of destructivePatterns) {
1701
+ if (command.includes(pattern)) {
1702
+ return {
1703
+ allowed: false,
1704
+ reason: `Destructive command pattern detected: "${pattern}"`,
1705
+ };
1706
+ }
1707
+ }
1708
+ return { allowed: true };
1709
+ }
1710
+ /**
1711
+ * Check if an approval gate should trigger for the given tool call.
1712
+ */
1713
+ shouldTriggerApproval(tool, params) {
1714
+ const result = this.checkToolCall(tool, params);
1715
+ return result.requiresApproval === true;
1716
+ }
1717
+ /**
1718
+ * Match a value against a pattern (supports simple glob with *).
1719
+ */
1720
+ matchPattern(value, pattern) {
1721
+ if (pattern === '*')
1722
+ return true;
1723
+ if (pattern === value)
1724
+ return true;
1725
+ // Simple glob matching: convert * to regex .*
1726
+ if (pattern.includes('*')) {
1727
+ const escaped = pattern
1728
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
1729
+ .replace(/\*/g, '.*');
1730
+ const regex = new RegExp(`^${escaped}$`);
1731
+ return regex.test(value);
1732
+ }
1733
+ return false;
1734
+ }
1735
+ }
1736
+ exports.GuardrailEnforcer = GuardrailEnforcer;
1737
+
1738
+
1739
+ /***/ }),
1740
+ /* 22 */
1741
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1742
+
1743
+
1744
+ /**
1745
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1746
+ *
1747
+ * This software is proprietary and confidential.
1748
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1749
+ */
1750
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1751
+ exports.statusCommand = statusCommand;
1752
+ const auth_service_1 = __webpack_require__(3);
1753
+ const platform_client_1 = __webpack_require__(13);
1754
+ const utils_1 = __webpack_require__(8);
1755
+ async function statusCommand(args) {
1756
+ const { positional } = (0, utils_1.parseArgs)(args);
1757
+ const sessionId = positional[0];
1758
+ const authService = new auth_service_1.AuthService();
1759
+ const creds = await authService.getCredentials();
1760
+ if (!creds?.token) {
1761
+ console.error('Not authenticated. Run: onklave login --token <token>');
1762
+ process.exitCode = 1;
1763
+ return;
1764
+ }
1765
+ const platformClient = new platform_client_1.PlatformClient(creds.platformUrl, creds.token);
1766
+ try {
1767
+ if (sessionId) {
1768
+ // Show details for a specific session
1769
+ const session = await platformClient.getSession(sessionId);
1770
+ printSessionDetails(session);
1771
+ }
1772
+ else {
1773
+ // List all active sessions
1774
+ const sessions = await platformClient.listSessions();
1775
+ if (sessions.length === 0) {
1776
+ console.log('No active sessions.');
1777
+ return;
1778
+ }
1779
+ printSessionTable(sessions);
1780
+ }
1781
+ }
1782
+ catch (err) {
1783
+ console.error(`Failed to get session status: ${err.message}`);
1784
+ process.exitCode = 1;
1785
+ }
1786
+ }
1787
+ function printSessionDetails(session) {
1788
+ console.log('Onklave Agent Session\n');
1789
+ console.log(` Session ID: ${session.sessionId}`);
1790
+ console.log(` Status: ${formatStatus(session.status)}`);
1791
+ console.log(` Task: ${session.task}`);
1792
+ console.log(` Model: ${session.model}`);
1793
+ console.log(` Persona: ${session.persona ?? '(none)'}`);
1794
+ console.log(` Workflow: ${session.workflow ?? '(none)'}`);
1795
+ console.log(` Machine: ${session.machineId ?? '(unknown)'}`);
1796
+ console.log(` Started: ${session.startedAt}`);
1797
+ if (session.completedAt) {
1798
+ console.log(` Completed: ${session.completedAt}`);
1799
+ }
1800
+ if (session.duration !== null && session.duration !== undefined) {
1801
+ console.log(` Duration: ${session.duration}s`);
1802
+ }
1803
+ if (session.error) {
1804
+ console.log(` Error: ${session.error}`);
1805
+ }
1806
+ if (session.summary) {
1807
+ console.log(`\n Summary:\n ${session.summary}`);
1808
+ }
1809
+ }
1810
+ function printSessionTable(sessions) {
1811
+ console.log('Active Agent Sessions\n');
1812
+ // Header
1813
+ const idWidth = 24;
1814
+ const statusWidth = 18;
1815
+ const taskWidth = 40;
1816
+ const modelWidth = 16;
1817
+ const header = [
1818
+ 'SESSION ID'.padEnd(idWidth),
1819
+ 'STATUS'.padEnd(statusWidth),
1820
+ 'TASK'.padEnd(taskWidth),
1821
+ 'MODEL'.padEnd(modelWidth),
1822
+ ].join(' ');
1823
+ console.log(header);
1824
+ console.log('-'.repeat(header.length));
1825
+ for (const session of sessions) {
1826
+ const row = [
1827
+ session.sessionId.slice(0, idWidth - 2).padEnd(idWidth),
1828
+ formatStatus(session.status).padEnd(statusWidth),
1829
+ truncate(session.task, taskWidth - 2).padEnd(taskWidth),
1830
+ session.model.padEnd(modelWidth),
1831
+ ].join(' ');
1832
+ console.log(row);
1833
+ }
1834
+ console.log(`\nTotal: ${sessions.length} session(s)`);
1835
+ }
1836
+ function formatStatus(status) {
1837
+ const statusMap = {
1838
+ pending: 'PENDING',
1839
+ initializing: 'INITIALIZING',
1840
+ running: 'RUNNING',
1841
+ waiting_approval: 'WAITING APPROVAL',
1842
+ paused: 'PAUSED',
1843
+ completed: 'COMPLETED',
1844
+ failed: 'FAILED',
1845
+ cancelled: 'CANCELLED',
1846
+ timed_out: 'TIMED OUT',
1847
+ };
1848
+ return statusMap[status] ?? status.toUpperCase();
1849
+ }
1850
+ function truncate(str, maxLen) {
1851
+ if (str.length <= maxLen)
1852
+ return str;
1853
+ return str.slice(0, maxLen - 3) + '...';
1854
+ }
1855
+
1856
+
1857
+ /***/ }),
1858
+ /* 23 */
1859
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1860
+
1861
+
1862
+ /**
1863
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1864
+ *
1865
+ * This software is proprietary and confidential.
1866
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1867
+ */
1868
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1869
+ exports.stopCommand = stopCommand;
1870
+ const auth_service_1 = __webpack_require__(3);
1871
+ const platform_client_1 = __webpack_require__(13);
1872
+ const utils_1 = __webpack_require__(8);
1873
+ async function stopCommand(args) {
1874
+ const { flags, positional } = (0, utils_1.parseArgs)(args);
1875
+ const sessionId = positional[0];
1876
+ const stopAll = flags['all'] === true;
1877
+ if (!sessionId && !stopAll) {
1878
+ console.error('Error: Provide a session ID or use --all.\n');
1879
+ console.log('Usage: onklave stop <session-id>');
1880
+ console.log(' onklave stop --all');
1881
+ process.exitCode = 1;
1882
+ return;
1883
+ }
1884
+ const authService = new auth_service_1.AuthService();
1885
+ const creds = await authService.getCredentials();
1886
+ if (!creds?.token) {
1887
+ console.error('Not authenticated. Run: onklave login --token <token>');
1888
+ process.exitCode = 1;
1889
+ return;
1890
+ }
1891
+ const platformClient = new platform_client_1.PlatformClient(creds.platformUrl, creds.token);
1892
+ try {
1893
+ if (stopAll) {
1894
+ const sessions = await platformClient.listSessions();
1895
+ if (sessions.length === 0) {
1896
+ console.log('No active sessions to stop.');
1897
+ return;
1898
+ }
1899
+ console.log(`Stopping ${sessions.length} session(s)...`);
1900
+ const results = await Promise.allSettled(sessions.map((s) => platformClient.cancelSession(s.sessionId)));
1901
+ let succeeded = 0;
1902
+ let failed = 0;
1903
+ for (const result of results) {
1904
+ if (result.status === 'fulfilled') {
1905
+ succeeded++;
1906
+ }
1907
+ else {
1908
+ failed++;
1909
+ }
1910
+ }
1911
+ console.log(`Stopped ${succeeded} session(s).`);
1912
+ if (failed > 0) {
1913
+ console.warn(`Failed to stop ${failed} session(s).`);
1914
+ }
1915
+ }
1916
+ else {
1917
+ console.log(`Stopping session ${sessionId}...`);
1918
+ await platformClient.cancelSession(sessionId);
1919
+ console.log(`Session ${sessionId} cancelled.`);
1920
+ }
1921
+ }
1922
+ catch (err) {
1923
+ console.error(`Failed to stop session: ${err.message}`);
1924
+ process.exitCode = 1;
1925
+ }
1926
+ }
1927
+
1928
+
1929
+ /***/ }),
1930
+ /* 24 */
1931
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1932
+
1933
+
1934
+ /**
1935
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1936
+ *
1937
+ * This software is proprietary and confidential.
1938
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1939
+ */
1940
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1941
+ exports.approveCommand = approveCommand;
1942
+ const auth_service_1 = __webpack_require__(3);
1943
+ const platform_client_1 = __webpack_require__(13);
1944
+ const utils_1 = __webpack_require__(8);
1945
+ async function approveCommand(args) {
1946
+ const { flags, positional } = (0, utils_1.parseArgs)(args);
1947
+ const sessionId = positional[0];
1948
+ if (!sessionId) {
1949
+ console.error('Error: Session ID is required.\n');
1950
+ console.log('Usage: onklave approve <session-id> [--message "..."]');
1951
+ process.exitCode = 1;
1952
+ return;
1953
+ }
1954
+ const authService = new auth_service_1.AuthService();
1955
+ const creds = await authService.getCredentials();
1956
+ if (!creds?.token) {
1957
+ console.error('Not authenticated. Run: onklave login --token <token>');
1958
+ process.exitCode = 1;
1959
+ return;
1960
+ }
1961
+ const platformClient = new platform_client_1.PlatformClient(creds.platformUrl, creds.token);
1962
+ const message = typeof flags['message'] === 'string' ? flags['message'] : undefined;
1963
+ try {
1964
+ await platformClient.respondToGate(sessionId, 'approve', message);
1965
+ console.log(`Session ${sessionId} approved.`);
1966
+ if (message) {
1967
+ console.log(`Message: ${message}`);
1968
+ }
1969
+ }
1970
+ catch (err) {
1971
+ console.error(`Failed to approve session: ${err.message}`);
1972
+ process.exitCode = 1;
1973
+ }
1974
+ }
1975
+
1976
+
1977
+ /***/ }),
1978
+ /* 25 */
1979
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
1980
+
1981
+
1982
+ /**
1983
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
1984
+ *
1985
+ * This software is proprietary and confidential.
1986
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
1987
+ */
1988
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
1989
+ exports.denyCommand = denyCommand;
1990
+ const auth_service_1 = __webpack_require__(3);
1991
+ const platform_client_1 = __webpack_require__(13);
1992
+ const utils_1 = __webpack_require__(8);
1993
+ async function denyCommand(args) {
1994
+ const { flags, positional } = (0, utils_1.parseArgs)(args);
1995
+ const sessionId = positional[0];
1996
+ if (!sessionId) {
1997
+ console.error('Error: Session ID is required.\n');
1998
+ console.log('Usage: onklave deny <session-id> [--reason "..."]');
1999
+ process.exitCode = 1;
2000
+ return;
2001
+ }
2002
+ const authService = new auth_service_1.AuthService();
2003
+ const creds = await authService.getCredentials();
2004
+ if (!creds?.token) {
2005
+ console.error('Not authenticated. Run: onklave login --token <token>');
2006
+ process.exitCode = 1;
2007
+ return;
2008
+ }
2009
+ const platformClient = new platform_client_1.PlatformClient(creds.platformUrl, creds.token);
2010
+ const reason = typeof flags['reason'] === 'string' ? flags['reason'] : undefined;
2011
+ try {
2012
+ await platformClient.respondToGate(sessionId, 'deny', reason);
2013
+ console.log(`Session ${sessionId} denied.`);
2014
+ if (reason) {
2015
+ console.log(`Reason: ${reason}`);
2016
+ }
2017
+ }
2018
+ catch (err) {
2019
+ console.error(`Failed to deny session: ${err.message}`);
2020
+ process.exitCode = 1;
2021
+ }
2022
+ }
2023
+
2024
+
2025
+ /***/ }),
2026
+ /* 26 */
2027
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
2028
+
2029
+
2030
+ /**
2031
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
2032
+ *
2033
+ * This software is proprietary and confidential.
2034
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
2035
+ */
2036
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2037
+ exports.doctorCommand = doctorCommand;
2038
+ const tslib_1 = __webpack_require__(4);
2039
+ const fs = tslib_1.__importStar(__webpack_require__(5));
2040
+ const path = tslib_1.__importStar(__webpack_require__(6));
2041
+ const child_process_1 = __webpack_require__(17);
2042
+ const auth_service_1 = __webpack_require__(3);
2043
+ const platform_client_1 = __webpack_require__(13);
2044
+ const comms_client_1 = __webpack_require__(14);
2045
+ async function doctorCommand() {
2046
+ console.log('Onklave Agent CLI — Doctor\n');
2047
+ console.log('Running diagnostics...\n');
2048
+ const results = [];
2049
+ // 1. Auth status
2050
+ results.push(await checkAuth());
2051
+ // 2. Platform URL reachability
2052
+ results.push(await checkPlatform());
2053
+ // 3. Claude Code CLI availability
2054
+ results.push(checkClaudeCli());
2055
+ // 4. Node.js version
2056
+ results.push(checkNodeVersion());
2057
+ // 5. .onklave.json in cwd
2058
+ results.push(checkProjectConfig());
2059
+ // 6. WebSocket connectivity
2060
+ results.push(await checkWebSocket());
2061
+ // Print results
2062
+ let hasFailure = false;
2063
+ for (const result of results) {
2064
+ const icon = result.status === 'ok'
2065
+ ? '[OK] '
2066
+ : result.status === 'warn'
2067
+ ? '[WARN]'
2068
+ : '[FAIL]';
2069
+ console.log(` ${icon} ${result.name}: ${result.detail}`);
2070
+ if (result.status === 'fail')
2071
+ hasFailure = true;
2072
+ }
2073
+ console.log('');
2074
+ if (hasFailure) {
2075
+ console.log('Some checks failed. Please resolve the issues above.');
2076
+ process.exitCode = 1;
2077
+ }
2078
+ else {
2079
+ console.log('All checks passed. Onklave Agent CLI is ready.');
2080
+ }
2081
+ }
2082
+ async function checkAuth() {
2083
+ const authService = new auth_service_1.AuthService();
2084
+ const isAuth = await authService.isAuthenticated();
2085
+ if (isAuth) {
2086
+ const creds = await authService.getCredentials();
2087
+ return {
2088
+ name: 'Authentication',
2089
+ status: 'ok',
2090
+ detail: `Authenticated (platform: ${creds?.platformUrl ?? 'default'})`,
2091
+ };
2092
+ }
2093
+ const creds = await authService.getCredentials();
2094
+ if (creds?.token) {
2095
+ return {
2096
+ name: 'Authentication',
2097
+ status: 'warn',
2098
+ detail: 'Token exists but may be expired',
2099
+ };
2100
+ }
2101
+ return {
2102
+ name: 'Authentication',
2103
+ status: 'fail',
2104
+ detail: 'Not authenticated. Run: onklave login --token <token>',
2105
+ };
2106
+ }
2107
+ async function checkPlatform() {
2108
+ const authService = new auth_service_1.AuthService();
2109
+ const platformUrl = await authService.getPlatformUrl();
2110
+ const platformClient = new platform_client_1.PlatformClient(platformUrl, '');
2111
+ const healthy = await platformClient.healthCheck();
2112
+ if (healthy) {
2113
+ return {
2114
+ name: 'Platform API',
2115
+ status: 'ok',
2116
+ detail: `Reachable at ${platformUrl}`,
2117
+ };
2118
+ }
2119
+ return {
2120
+ name: 'Platform API',
2121
+ status: 'warn',
2122
+ detail: `Not reachable at ${platformUrl}`,
2123
+ };
2124
+ }
2125
+ function checkClaudeCli() {
2126
+ try {
2127
+ const claudePath = (0, child_process_1.execSync)('which claude', {
2128
+ encoding: 'utf-8',
2129
+ timeout: 5000,
2130
+ }).trim();
2131
+ return {
2132
+ name: 'Claude Code CLI',
2133
+ status: 'ok',
2134
+ detail: `Found at ${claudePath}`,
2135
+ };
2136
+ }
2137
+ catch {
2138
+ return {
2139
+ name: 'Claude Code CLI',
2140
+ status: 'fail',
2141
+ detail: 'Not found. Install Claude Code CLI: https://docs.anthropic.com/claude-code',
2142
+ };
2143
+ }
2144
+ }
2145
+ function checkNodeVersion() {
2146
+ const version = process.version;
2147
+ const major = parseInt(version.slice(1).split('.')[0], 10);
2148
+ if (major >= 22) {
2149
+ return { name: 'Node.js', status: 'ok', detail: version };
2150
+ }
2151
+ if (major >= 18) {
2152
+ return {
2153
+ name: 'Node.js',
2154
+ status: 'warn',
2155
+ detail: `${version} (22+ recommended)`,
2156
+ };
2157
+ }
2158
+ return {
2159
+ name: 'Node.js',
2160
+ status: 'fail',
2161
+ detail: `${version} (22+ required)`,
2162
+ };
2163
+ }
2164
+ function checkProjectConfig() {
2165
+ const configPath = path.join(process.cwd(), '.onklave.json');
2166
+ if (fs.existsSync(configPath)) {
2167
+ try {
2168
+ const raw = fs.readFileSync(configPath, 'utf-8');
2169
+ JSON.parse(raw);
2170
+ return {
2171
+ name: 'Project config',
2172
+ status: 'ok',
2173
+ detail: `.onklave.json found and valid`,
2174
+ };
2175
+ }
2176
+ catch (err) {
2177
+ return {
2178
+ name: 'Project config',
2179
+ status: 'warn',
2180
+ detail: `.onklave.json found but invalid: ${err.message}`,
2181
+ };
2182
+ }
2183
+ }
2184
+ return {
2185
+ name: 'Project config',
2186
+ status: 'warn',
2187
+ detail: 'No .onklave.json in current directory. Run: onklave init',
2188
+ };
2189
+ }
2190
+ async function checkWebSocket() {
2191
+ const authService = new auth_service_1.AuthService();
2192
+ const creds = await authService.getCredentials();
2193
+ if (!creds?.token) {
2194
+ return {
2195
+ name: 'WebSocket',
2196
+ status: 'warn',
2197
+ detail: 'Skipped (not authenticated)',
2198
+ };
2199
+ }
2200
+ const commsClient = new comms_client_1.CommsClient();
2201
+ try {
2202
+ await commsClient.connect(creds.platformUrl, creds.token);
2203
+ commsClient.disconnect();
2204
+ return {
2205
+ name: 'WebSocket',
2206
+ status: 'ok',
2207
+ detail: 'Connected to comms service',
2208
+ };
2209
+ }
2210
+ catch {
2211
+ return {
2212
+ name: 'WebSocket',
2213
+ status: 'warn',
2214
+ detail: 'Could not connect to comms service',
2215
+ };
2216
+ }
2217
+ }
2218
+
2219
+
2220
+ /***/ }),
2221
+ /* 27 */
2222
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
2223
+
2224
+
2225
+ /**
2226
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
2227
+ *
2228
+ * This software is proprietary and confidential.
2229
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
2230
+ */
2231
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2232
+ exports.initCommand = initCommand;
2233
+ const tslib_1 = __webpack_require__(4);
2234
+ const fs = tslib_1.__importStar(__webpack_require__(5));
2235
+ const path = tslib_1.__importStar(__webpack_require__(6));
2236
+ async function initCommand() {
2237
+ const configPath = path.join(process.cwd(), '.onklave.json');
2238
+ if (fs.existsSync(configPath)) {
2239
+ console.error('Error: .onklave.json already exists in this directory.');
2240
+ console.log('To overwrite, delete the existing file first.');
2241
+ process.exitCode = 1;
2242
+ return;
2243
+ }
2244
+ const template = {
2245
+ project: path.basename(process.cwd()),
2246
+ org: '',
2247
+ description: '',
2248
+ defaults: {
2249
+ persona: '',
2250
+ workflow: '',
2251
+ model: 'claude-sonnet-4-20250514',
2252
+ timeout: 120,
2253
+ },
2254
+ guardrails: [
2255
+ {
2256
+ name: 'no-secrets-access',
2257
+ match: 'file_*',
2258
+ action: 'deny',
2259
+ reason: 'Prevent access to secret files',
2260
+ paths: ['.env*', '*.pem', '*.key'],
2261
+ },
2262
+ {
2263
+ name: 'approve-destructive-commands',
2264
+ match: 'cmd:rm*',
2265
+ action: 'require_approval',
2266
+ reason: 'Destructive commands require approval',
2267
+ },
2268
+ ],
2269
+ permissions: {
2270
+ tools_allowed: [],
2271
+ tools_denied: [],
2272
+ paths_readable: ['.'],
2273
+ paths_writable: ['src/', 'tests/', 'docs/'],
2274
+ },
2275
+ context: {
2276
+ includes: ['src/', 'package.json', 'tsconfig.json'],
2277
+ system_prompt_append: '',
2278
+ },
2279
+ };
2280
+ fs.writeFileSync(configPath, JSON.stringify(template, null, 2) + '\n', 'utf-8');
2281
+ console.log('Created .onklave.json in the current directory.\n');
2282
+ console.log('Edit the file to configure:');
2283
+ console.log(' - project: Your project name');
2284
+ console.log(' - org: Your Onklave organization ID');
2285
+ console.log(' - defaults: Default persona, workflow, model, and timeout');
2286
+ console.log(' - guardrails: Rules for tool/path restrictions');
2287
+ console.log(' - permissions: Allowed/denied tools and path access');
2288
+ console.log(' - context: Files to include and system prompt additions');
2289
+ }
2290
+
2291
+
2292
+ /***/ }),
2293
+ /* 28 */
2294
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
2295
+
2296
+
2297
+ /**
2298
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
2299
+ *
2300
+ * This software is proprietary and confidential.
2301
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
2302
+ */
2303
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2304
+ exports.configCommand = configCommand;
2305
+ const config_resolver_1 = __webpack_require__(12);
2306
+ const utils_1 = __webpack_require__(8);
2307
+ async function configCommand(args) {
2308
+ const { positional } = (0, utils_1.parseArgs)(args);
2309
+ const subcommand = positional[0];
2310
+ const key = positional[1];
2311
+ const value = positional[2];
2312
+ const configResolver = new config_resolver_1.ConfigResolver();
2313
+ if (!subcommand) {
2314
+ // Show effective config
2315
+ const resolved = await configResolver.resolve({}, process.cwd());
2316
+ console.log('Onklave Agent CLI — Effective Configuration\n');
2317
+ console.log('Sources (highest to lowest priority):');
2318
+ console.log(' 1. Command-line flags');
2319
+ console.log(' 2. Environment variables (ONKLAVE_*, ANTHROPIC_API_KEY)');
2320
+ console.log(' 3. Project config (.onklave.json)');
2321
+ console.log(' 4. Global config (~/.config/onklave/config.json)');
2322
+ console.log(' 5. Platform defaults\n');
2323
+ console.log('Resolved values:');
2324
+ console.log(JSON.stringify(resolved, null, 2));
2325
+ return;
2326
+ }
2327
+ if (subcommand === 'get') {
2328
+ if (!key) {
2329
+ console.error('Error: Key is required.\n');
2330
+ console.log('Usage: onklave config get <key>');
2331
+ console.log('Example: onklave config get defaultModel');
2332
+ process.exitCode = 1;
2333
+ return;
2334
+ }
2335
+ const configValue = configResolver.getGlobalConfigValue(key);
2336
+ if (configValue === undefined) {
2337
+ console.log(`(not set)`);
2338
+ }
2339
+ else if (typeof configValue === 'object') {
2340
+ console.log(JSON.stringify(configValue, null, 2));
2341
+ }
2342
+ else {
2343
+ console.log(String(configValue));
2344
+ }
2345
+ return;
2346
+ }
2347
+ if (subcommand === 'set') {
2348
+ if (!key) {
2349
+ console.error('Error: Key is required.\n');
2350
+ console.log('Usage: onklave config set <key> <value>');
2351
+ console.log('Example: onklave config set defaultModel claude-sonnet-4-20250514');
2352
+ process.exitCode = 1;
2353
+ return;
2354
+ }
2355
+ if (value === undefined) {
2356
+ console.error('Error: Value is required.\n');
2357
+ console.log('Usage: onklave config set <key> <value>');
2358
+ process.exitCode = 1;
2359
+ return;
2360
+ }
2361
+ // Try to parse as number or boolean
2362
+ let parsedValue = value;
2363
+ if (value === 'true')
2364
+ parsedValue = true;
2365
+ else if (value === 'false')
2366
+ parsedValue = false;
2367
+ else if (/^\d+$/.test(value))
2368
+ parsedValue = parseInt(value, 10);
2369
+ configResolver.saveGlobalConfig(key, parsedValue);
2370
+ console.log(`Set ${key} = ${JSON.stringify(parsedValue)}`);
2371
+ return;
2372
+ }
2373
+ console.error(`Unknown config subcommand: ${subcommand}\n`);
2374
+ console.log('Usage:');
2375
+ console.log(' onklave config Show effective configuration');
2376
+ console.log(' onklave config get <key> Get a specific config value');
2377
+ console.log(' onklave config set <k> <v> Set a global config value');
2378
+ process.exitCode = 1;
2379
+ }
2380
+
2381
+
2382
+ /***/ }),
2383
+ /* 29 */
2384
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
2385
+
2386
+
2387
+ /**
2388
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
2389
+ *
2390
+ * This software is proprietary and confidential.
2391
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
2392
+ */
2393
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2394
+ exports.registerCommand = registerCommand;
2395
+ const tslib_1 = __webpack_require__(4);
2396
+ const os = tslib_1.__importStar(__webpack_require__(7));
2397
+ const auth_service_1 = __webpack_require__(3);
2398
+ const platform_client_1 = __webpack_require__(13);
2399
+ const utils_1 = __webpack_require__(8);
2400
+ async function registerCommand(args) {
2401
+ const { flags } = (0, utils_1.parseArgs)(args);
2402
+ const linkingToken = flags['token'];
2403
+ if (typeof linkingToken !== 'string' || !linkingToken) {
2404
+ console.error('Error: --token is required.\n');
2405
+ console.log('Usage: onklave register --token <linking-token>\n');
2406
+ console.log('To obtain a linking token:');
2407
+ console.log(' 1. Log in to the Onklave Portal');
2408
+ console.log(' 2. Navigate to Settings > Machines');
2409
+ console.log(' 3. Click "Register Machine" to generate a linking token');
2410
+ process.exitCode = 1;
2411
+ return;
2412
+ }
2413
+ const authService = new auth_service_1.AuthService();
2414
+ const creds = await authService.getCredentials();
2415
+ if (!creds?.token) {
2416
+ console.error('Not authenticated. Run: onklave login --token <token>');
2417
+ process.exitCode = 1;
2418
+ return;
2419
+ }
2420
+ const metadata = {
2421
+ hostname: os.hostname(),
2422
+ os: `${os.platform()} ${os.release()}`,
2423
+ arch: os.arch(),
2424
+ nodeVersion: process.version,
2425
+ capabilities: detectCapabilities(),
2426
+ };
2427
+ const platformClient = new platform_client_1.PlatformClient(creds.platformUrl, creds.token);
2428
+ try {
2429
+ console.log('Registering machine with Onklave platform...');
2430
+ console.log(` Hostname: ${metadata.hostname}`);
2431
+ console.log(` OS: ${metadata.os}`);
2432
+ console.log(` Arch: ${metadata.arch}`);
2433
+ console.log(` Node: ${metadata.nodeVersion}`);
2434
+ const result = await platformClient.registerMachine(linkingToken, metadata);
2435
+ await authService.saveDeviceToken(result.deviceToken, result.machineId);
2436
+ console.log(`\nMachine registered successfully.`);
2437
+ console.log(` Machine ID: ${result.machineId}`);
2438
+ console.log(` Device token stored in ~/.config/onklave/credentials.json`);
2439
+ console.log(`\nThis machine can now receive remote agent session requests.`);
2440
+ }
2441
+ catch (err) {
2442
+ console.error(`Registration failed: ${err.message}`);
2443
+ process.exitCode = 1;
2444
+ }
2445
+ }
2446
+ function detectCapabilities() {
2447
+ const capabilities = ['agent-runner'];
2448
+ // Check if Claude Code is available
2449
+ try {
2450
+ const { execSync } = __webpack_require__(17);
2451
+ execSync('which claude', { timeout: 3000, stdio: 'pipe' });
2452
+ capabilities.push('claude-code');
2453
+ }
2454
+ catch {
2455
+ // Claude Code not available
2456
+ }
2457
+ // Check if Docker is available
2458
+ try {
2459
+ const { execSync } = __webpack_require__(17);
2460
+ execSync('which docker', { timeout: 3000, stdio: 'pipe' });
2461
+ capabilities.push('docker');
2462
+ }
2463
+ catch {
2464
+ // Docker not available
2465
+ }
2466
+ return capabilities;
2467
+ }
2468
+
2469
+
2470
+ /***/ }),
2471
+ /* 30 */
2472
+ /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
2473
+
2474
+
2475
+ /**
2476
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
2477
+ *
2478
+ * This software is proprietary and confidential.
2479
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
2480
+ */
2481
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2482
+ exports.logsCommand = logsCommand;
2483
+ const auth_service_1 = __webpack_require__(3);
2484
+ const platform_client_1 = __webpack_require__(13);
2485
+ const utils_1 = __webpack_require__(8);
2486
+ async function logsCommand(args) {
2487
+ const { positional, flags } = (0, utils_1.parseArgs)(args);
2488
+ const sessionId = positional[0];
2489
+ if (!sessionId) {
2490
+ console.error('Error: Session ID is required.\n');
2491
+ console.log('Usage: onklave logs <session-id> [--tail <n>]');
2492
+ process.exitCode = 1;
2493
+ return;
2494
+ }
2495
+ const authService = new auth_service_1.AuthService();
2496
+ const creds = await authService.getCredentials();
2497
+ if (!creds?.token) {
2498
+ console.error('Not authenticated. Run: onklave login --token <token>');
2499
+ process.exitCode = 1;
2500
+ return;
2501
+ }
2502
+ const platformClient = new platform_client_1.PlatformClient(creds.platformUrl, creds.token);
2503
+ try {
2504
+ const logs = await platformClient.getSessionLogs(sessionId);
2505
+ if (!logs || logs.length === 0) {
2506
+ console.log(`No logs available for session ${sessionId}.`);
2507
+ return;
2508
+ }
2509
+ // Apply tail if specified
2510
+ const tail = typeof flags['tail'] === 'string' ? parseInt(flags['tail'], 10) : 0;
2511
+ const displayLogs = tail > 0 ? logs.slice(-tail) : logs;
2512
+ console.log(`Logs for session ${sessionId}:\n`);
2513
+ for (const line of displayLogs) {
2514
+ console.log(line);
2515
+ }
2516
+ }
2517
+ catch (err) {
2518
+ console.error(`Failed to fetch logs: ${err.message}`);
2519
+ process.exitCode = 1;
2520
+ }
2521
+ }
2522
+
2523
+
2524
+ /***/ })
2525
+ /******/ ]);
2526
+ /************************************************************************/
2527
+ /******/ // The module cache
2528
+ /******/ var __webpack_module_cache__ = {};
2529
+ /******/
2530
+ /******/ // The require function
2531
+ /******/ function __webpack_require__(moduleId) {
2532
+ /******/ // Check if module is in cache
2533
+ /******/ var cachedModule = __webpack_module_cache__[moduleId];
2534
+ /******/ if (cachedModule !== undefined) {
2535
+ /******/ return cachedModule.exports;
2536
+ /******/ }
2537
+ /******/ // Create a new module (and put it into the cache)
2538
+ /******/ var module = __webpack_module_cache__[moduleId] = {
2539
+ /******/ // no module.id needed
2540
+ /******/ // no module.loaded needed
2541
+ /******/ exports: {}
2542
+ /******/ };
2543
+ /******/
2544
+ /******/ // Execute the module function
2545
+ /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
2546
+ /******/
2547
+ /******/ // Return the exports of the module
2548
+ /******/ return module.exports;
2549
+ /******/ }
2550
+ /******/
2551
+ /************************************************************************/
2552
+ var __webpack_exports__ = {};
2553
+ // This entry needs to be wrapped in an IIFE because it needs to be isolated against other modules in the chunk.
2554
+ (() => {
2555
+ var exports = __webpack_exports__;
2556
+ //#!/usr/bin/env node
2557
+
2558
+ /**
2559
+ * Copyright (c) 2025 Onklave (Pty) Ltd. All Rights Reserved.
2560
+ *
2561
+ * This software is proprietary and confidential.
2562
+ * Unauthorized copying, modification, or distribution is strictly prohibited.
2563
+ */
2564
+ Object.defineProperty(exports, "__esModule", ({ value: true }));
2565
+ const commands_1 = __webpack_require__(1);
2566
+ const VERSION = '0.1.0';
2567
+ function showHelp() {
2568
+ console.log(`
2569
+ Onklave Agent CLI v${VERSION}
2570
+
2571
+ Usage: onklave <command> [options]
2572
+
2573
+ Commands:
2574
+ login Log in to Onklave platform
2575
+ logout Log out and remove stored credentials
2576
+ whoami Show current identity and auth status
2577
+ run Run an agent task via Claude Code
2578
+ status [session-id] Show session status or list active sessions
2579
+ stop <session-id> Stop a running session
2580
+ approve <session-id> Approve a pending approval gate
2581
+ deny <session-id> Deny a pending approval gate
2582
+ doctor Run diagnostic checks
2583
+ init Create .onklave.json in the current directory
2584
+ config View or modify configuration
2585
+ register Register this machine as an agent runner
2586
+ logs <session-id> View logs for a session
2587
+
2588
+ Options:
2589
+ --help, -h Show this help message
2590
+ --version, -v Show version number
2591
+
2592
+ Examples:
2593
+ onklave login --token <token>
2594
+ onklave run --task "Fix the failing tests in src/"
2595
+ onklave run --task "Refactor auth module" --persona security-reviewer
2596
+ onklave status
2597
+ onklave stop abc123
2598
+ onklave doctor
2599
+ `.trim());
2600
+ }
2601
+ async function main() {
2602
+ const args = process.argv.slice(2);
2603
+ const command = args[0];
2604
+ // Handle top-level flags
2605
+ if (!command || command === '--help' || command === '-h') {
2606
+ showHelp();
2607
+ return;
2608
+ }
2609
+ if (command === '--version' || command === '-v') {
2610
+ console.log(`onklave v${VERSION}`);
2611
+ return;
2612
+ }
2613
+ // Look up command handler
2614
+ const handler = commands_1.COMMANDS[command];
2615
+ if (!handler) {
2616
+ console.error(`Unknown command: ${command}\n`);
2617
+ showHelp();
2618
+ process.exitCode = 1;
2619
+ return;
2620
+ }
2621
+ // Pass remaining args to command handler
2622
+ const commandArgs = args.slice(1);
2623
+ // Check for --help on subcommand
2624
+ if (commandArgs.includes('--help') || commandArgs.includes('-h')) {
2625
+ // Let the command handle its own help (it will show usage when missing required args)
2626
+ // But for commands that don't check, show generic help
2627
+ }
2628
+ try {
2629
+ await handler(commandArgs);
2630
+ }
2631
+ catch (err) {
2632
+ console.error(`Error: ${err.message}`);
2633
+ process.exitCode = 1;
2634
+ }
2635
+ }
2636
+ main();
2637
+
2638
+ })();
2639
+
2640
+ var __webpack_export_target__ = exports;
2641
+ for(var __webpack_i__ in __webpack_exports__) __webpack_export_target__[__webpack_i__] = __webpack_exports__[__webpack_i__];
2642
+ if(__webpack_exports__.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true });
2643
+ /******/ })()
2644
+ ;