teleportation-cli 1.1.4 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/.claude/hooks/config-loader.mjs +88 -34
  2. package/.claude/hooks/permission_request.mjs +392 -82
  3. package/.claude/hooks/post_tool_use.mjs +90 -0
  4. package/.claude/hooks/pre_tool_use.mjs +247 -305
  5. package/.claude/hooks/session-register.mjs +94 -105
  6. package/.claude/hooks/session_end.mjs +41 -42
  7. package/.claude/hooks/session_start.mjs +45 -60
  8. package/.claude/hooks/stop.mjs +752 -99
  9. package/.claude/hooks/user_prompt_submit.mjs +26 -3
  10. package/README.md +7 -0
  11. package/lib/auth/api-key.js +12 -0
  12. package/lib/auth/token-refresh.js +286 -0
  13. package/lib/cli/daemon-commands.js +1 -1
  14. package/lib/cli/teleport-commands.js +469 -0
  15. package/lib/daemon/daemon-v2.js +104 -0
  16. package/lib/daemon/lifecycle.js +56 -171
  17. package/lib/daemon/response-classifier.js +15 -1
  18. package/lib/daemon/services/index.js +3 -0
  19. package/lib/daemon/services/polling-service.js +173 -0
  20. package/lib/daemon/services/queue-service.js +318 -0
  21. package/lib/daemon/services/session-service.js +115 -0
  22. package/lib/daemon/state.js +35 -0
  23. package/lib/daemon/task-executor-v2.js +413 -0
  24. package/lib/daemon/task-executor.js +1235 -0
  25. package/lib/daemon/teleportation-daemon.js +770 -25
  26. package/lib/daemon/timeline-analyzer.js +215 -0
  27. package/lib/daemon/transcript-ingestion.js +696 -0
  28. package/lib/daemon/utils.js +91 -0
  29. package/lib/install/installer.js +184 -20
  30. package/lib/install/uhr-installer.js +136 -0
  31. package/lib/remote/providers/base-provider.js +46 -0
  32. package/lib/remote/providers/daytona-provider.js +58 -0
  33. package/lib/remote/providers/provider-factory.js +90 -19
  34. package/lib/remote/providers/sprites-provider.js +711 -0
  35. package/lib/teleport/exporters/claude-exporter.js +302 -0
  36. package/lib/teleport/exporters/gemini-exporter.js +307 -0
  37. package/lib/teleport/exporters/index.js +93 -0
  38. package/lib/teleport/exporters/interface.js +153 -0
  39. package/lib/teleport/fork-tracker.js +415 -0
  40. package/lib/teleport/git-committer.js +337 -0
  41. package/lib/teleport/index.js +48 -0
  42. package/lib/teleport/manager.js +620 -0
  43. package/lib/teleport/session-capture.js +282 -0
  44. package/package.json +11 -5
  45. package/teleportation-cli.cjs +632 -451
  46. package/.claude/hooks/heartbeat.mjs +0 -396
  47. package/lib/daemon/agentic-executor.js +0 -803
  48. package/lib/daemon/pid-manager.js +0 -160
@@ -15,6 +15,56 @@
15
15
 
16
16
  import { stdin, stdout, exit, env } from 'node:process';
17
17
  import { appendFileSync } from 'node:fs';
18
+ import { homedir } from 'node:os';
19
+ import { join, dirname } from 'node:path';
20
+ import { fileURLToPath } from 'node:url';
21
+
22
+ // Get __dirname equivalent for ES modules
23
+ const __filename = fileURLToPath(import.meta.url);
24
+ const __dirname = dirname(__filename);
25
+
26
+ /**
27
+ * Try to import transcript-ingestion from multiple possible paths
28
+ * This makes the hook work in both development and installed contexts
29
+ *
30
+ * IMPORTANT: Only catches module-not-found errors. Syntax errors, runtime
31
+ * errors, and other exceptions are re-thrown immediately for debugging.
32
+ */
33
+ async function tryImportTranscriptIngestion() {
34
+ const possiblePaths = [
35
+ // If installed globally to ~/.claude/hooks/, lib is in ~/.teleportation/lib/daemon/
36
+ () => join(homedir(), '.teleportation', 'lib', 'daemon', 'transcript-ingestion.js'),
37
+ // If hook is still in project directory
38
+ () => join(process.cwd(), 'lib', 'daemon', 'transcript-ingestion.js'),
39
+ // Try relative to hook location (development)
40
+ () => join(__dirname, '..', '..', 'lib', 'daemon', 'transcript-ingestion.js')
41
+ ];
42
+
43
+ let lastError;
44
+
45
+ for (const getPath of possiblePaths) {
46
+ const modulePath = getPath();
47
+ try {
48
+ const module = await import(modulePath);
49
+ return module;
50
+ } catch (e) {
51
+ lastError = e;
52
+
53
+ // Only skip module-not-found errors - try next path
54
+ // Re-throw syntax errors, runtime errors, reference errors immediately
55
+ if (e.code === 'ERR_MODULE_NOT_FOUND' || e.code === 'ENOENT') {
56
+ continue; // Module doesn't exist at this path, try next
57
+ }
58
+
59
+ // Syntax error, runtime error, etc. - throw immediately with context
60
+ console.error(`[post_tool_use] Failed to import transcript-ingestion from ${modulePath}:`, e.message);
61
+ throw e;
62
+ }
63
+ }
64
+
65
+ // If we get here, module wasn't found in any location
66
+ throw new Error(`Could not find transcript-ingestion module in any expected location. Last error: ${lastError?.message || 'unknown'}`);
67
+ }
18
68
 
19
69
  const readStdin = () => new Promise((resolve, reject) => {
20
70
  let data = '';
@@ -207,6 +257,10 @@ function buildErrorMessage(tool_output) {
207
257
  const { session_id, tool_name, tool_input, tool_output, tool_use_id } = input || {};
208
258
  log(`Session: ${session_id}, Tool: ${tool_name}, tool_use_id: ${tool_use_id || 'none'}`);
209
259
 
260
+ // Detect message source
261
+ const isAutonomousTask = env.TELEPORTATION_TASK_MODE === 'true' || !!env.TELEPORTATION_PARENT_SESSION_ID;
262
+ const source = isAutonomousTask ? 'autonomous_task' : 'cli_interactive';
263
+
210
264
  // Validate session_id
211
265
  if (!isValidSessionId(session_id)) {
212
266
  log(`ERROR: Invalid session_id format: ${session_id}`);
@@ -339,6 +393,7 @@ function buildErrorMessage(tool_output) {
339
393
  body: JSON.stringify({
340
394
  session_id,
341
395
  type: completionEventType,
396
+ source,
342
397
  data: completionEventData
343
398
  })
344
399
  });
@@ -362,6 +417,7 @@ function buildErrorMessage(tool_output) {
362
417
  body: JSON.stringify({
363
418
  session_id,
364
419
  type: 'tool_error',
420
+ source,
365
421
  data: {
366
422
  tool_name,
367
423
  tool_input,
@@ -387,6 +443,7 @@ function buildErrorMessage(tool_output) {
387
443
  body: JSON.stringify({
388
444
  session_id,
389
445
  type: 'tool_executed',
446
+ source,
390
447
  data: {
391
448
  tool_name,
392
449
  tool_input,
@@ -401,6 +458,39 @@ function buildErrorMessage(tool_output) {
401
458
  log(`Failed to record legacy tool_executed: ${e.message}`);
402
459
  }
403
460
 
461
+ // =========================================================================
462
+ // Real-time transcript ingestion after each tool execution
463
+ // Ensures timeline stays in sync with assistant responses
464
+ // =========================================================================
465
+
466
+ try {
467
+ // Import transcript ingestion from multiple possible locations (works in dev + installed contexts)
468
+ const transcriptModule = await tryImportTranscriptIngestion();
469
+ const { ingestTranscriptToTimeline } = transcriptModule;
470
+
471
+ const claude_session_id = env.CLAUDE_SESSION_ID || session_id;
472
+ const cwd = env.TELEPORTATION_CWD || process.cwd();
473
+
474
+ // Use real-time mode flag to only process recent events (max 10)
475
+ await ingestTranscriptToTimeline({
476
+ claude_session_id,
477
+ parent_session_id: session_id,
478
+ task_id: null,
479
+ cwd,
480
+ config: {
481
+ relayApiUrl: RELAY_API_URL,
482
+ apiKey: RELAY_API_KEY
483
+ },
484
+ realTimeMode: true, // Fast mode - only recent events
485
+ maxEvents: 10 // Limit to 10 most recent events (prevents blocking hook)
486
+ });
487
+
488
+ log(`Real-time transcript ingestion completed`);
489
+ } catch (e) {
490
+ log(`Real-time transcript ingestion failed (non-fatal): ${e.message}`);
491
+ // Don't fail the hook if ingestion fails - this is a best-effort feature
492
+ }
493
+
404
494
  // PostToolUse hooks don't need to output anything
405
495
  return exit(0);
406
496
  })();