teleportation-cli 1.1.5 → 1.2.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 (42) hide show
  1. package/.claude/hooks/permission_request.mjs +326 -59
  2. package/.claude/hooks/post_tool_use.mjs +90 -0
  3. package/.claude/hooks/pre_tool_use.mjs +212 -293
  4. package/.claude/hooks/session-register.mjs +89 -104
  5. package/.claude/hooks/session_end.mjs +41 -42
  6. package/.claude/hooks/session_start.mjs +45 -60
  7. package/.claude/hooks/stop.mjs +752 -99
  8. package/.claude/hooks/user_prompt_submit.mjs +26 -3
  9. package/lib/cli/daemon-commands.js +1 -1
  10. package/lib/cli/teleport-commands.js +469 -0
  11. package/lib/daemon/daemon-v2.js +104 -0
  12. package/lib/daemon/lifecycle.js +56 -171
  13. package/lib/daemon/services/index.js +3 -0
  14. package/lib/daemon/services/polling-service.js +173 -0
  15. package/lib/daemon/services/queue-service.js +318 -0
  16. package/lib/daemon/services/session-service.js +115 -0
  17. package/lib/daemon/state.js +35 -0
  18. package/lib/daemon/task-executor-v2.js +413 -0
  19. package/lib/daemon/task-executor.js +270 -96
  20. package/lib/daemon/teleportation-daemon.js +709 -126
  21. package/lib/daemon/timeline-analyzer.js +215 -0
  22. package/lib/daemon/transcript-ingestion.js +696 -0
  23. package/lib/daemon/utils.js +91 -0
  24. package/lib/install/installer.js +184 -20
  25. package/lib/install/uhr-installer.js +136 -0
  26. package/lib/remote/providers/base-provider.js +46 -0
  27. package/lib/remote/providers/daytona-provider.js +58 -0
  28. package/lib/remote/providers/provider-factory.js +90 -19
  29. package/lib/remote/providers/sprites-provider.js +711 -0
  30. package/lib/teleport/exporters/claude-exporter.js +302 -0
  31. package/lib/teleport/exporters/gemini-exporter.js +307 -0
  32. package/lib/teleport/exporters/index.js +93 -0
  33. package/lib/teleport/exporters/interface.js +153 -0
  34. package/lib/teleport/fork-tracker.js +415 -0
  35. package/lib/teleport/git-committer.js +337 -0
  36. package/lib/teleport/index.js +48 -0
  37. package/lib/teleport/manager.js +620 -0
  38. package/lib/teleport/session-capture.js +282 -0
  39. package/package.json +6 -2
  40. package/teleportation-cli.cjs +488 -453
  41. package/.claude/hooks/heartbeat.mjs +0 -396
  42. package/lib/daemon/pid-manager.js +0 -183
@@ -1,15 +1,21 @@
1
1
  /**
2
2
  * Provider Factory for Intelligent Provider Selection
3
3
  *
4
- * Automatically selects the best cloud provider (Fly.io or Daytona) based on:
4
+ * Automatically selects the best cloud provider (Fly.io, Daytona, or Sprites.dev) based on:
5
5
  * - Task description analysis
6
6
  * - Estimated duration
7
7
  * - Keyword detection
8
8
  * - User preferences
9
+ *
10
+ * Provider characteristics:
11
+ * - **Daytona**: Quick, ephemeral tasks (PRs, bug fixes, prototypes)
12
+ * - **Fly.io**: Long-running persistent VMs (overnight, migrations)
13
+ * - **Sprites.dev**: Tasks requiring checkpoints/rollback (large refactors, experiments)
9
14
  */
10
15
 
11
16
  import { FlyProvider } from './fly-provider.js';
12
17
  import { DaytonaProvider } from './daytona-provider.js';
18
+ import { SpritesProvider } from './sprites-provider.js';
13
19
 
14
20
  export class ProviderFactory {
15
21
  /**
@@ -19,7 +25,8 @@ export class ProviderFactory {
19
25
  * @param {LivePortClient} config.livePortClient - LivePort client (required)
20
26
  * @param {string} [config.flyApiToken] - Fly.io API token
21
27
  * @param {string} [config.daytonaApiKey] - Daytona API key
22
- * @param {string} [config.defaultProvider] - Default provider ('fly' or 'daytona')
28
+ * @param {string} [config.spritesToken] - Sprites.dev API token
29
+ * @param {string} [config.defaultProvider] - Default provider ('fly', 'daytona', or 'sprites')
23
30
  */
24
31
  constructor(config = {}) {
25
32
  if (!config.vaultClient) {
@@ -47,6 +54,14 @@ export class ProviderFactory {
47
54
  'feature', 'branch', 'bug fix', 'hotfix',
48
55
  'test', 'experiment', 'prototype', 'spike',
49
56
  ];
57
+
58
+ // Keywords that suggest checkpoint/rollback needs (prefer Sprites)
59
+ this.spritesKeywords = [
60
+ 'checkpoint', 'rollback', 'restore', 'snapshot',
61
+ 'risky', 'experimental', 'major refactor', 'large refactor',
62
+ 'database migration', 'data migration', 'breaking change',
63
+ 'incremental', 'save point', 'recovery',
64
+ ];
50
65
  }
51
66
 
52
67
  /**
@@ -54,14 +69,15 @@ export class ProviderFactory {
54
69
  *
55
70
  * Decision logic:
56
71
  * 1. If provider explicitly specified in options, use it
57
- * 2. Analyze task description for duration indicators
58
- * 3. Match keywords to provider preferences
59
- * 4. Default to Daytona for quick, ephemeral tasks
72
+ * 2. Check for Sprites keywords (checkpoint/rollback needs)
73
+ * 3. Analyze task description for duration indicators
74
+ * 4. Match keywords to provider preferences
75
+ * 5. Default to Daytona for quick, ephemeral tasks
60
76
  *
61
77
  * @param {string} taskDescription - Description of the task to perform
62
78
  * @param {Object} [options] - Selection options
63
- * @param {string} [options.provider] - Force specific provider ('fly' or 'daytona')
64
- * @returns {string} Selected provider type ('fly' or 'daytona')
79
+ * @param {string} [options.provider] - Force specific provider ('fly', 'daytona', or 'sprites')
80
+ * @returns {string} Selected provider type ('fly', 'daytona', or 'sprites')
65
81
  */
66
82
  selectProvider(taskDescription, options = {}) {
67
83
  // 1. Explicit override takes precedence
@@ -69,20 +85,28 @@ export class ProviderFactory {
69
85
  return options.provider;
70
86
  }
71
87
 
72
- // 2. Estimate task duration
73
- const duration = this._estimateDuration(taskDescription);
88
+ const lowerDesc = taskDescription.toLowerCase();
74
89
 
75
- // 3. Analyze keywords
76
- const keywords = this._analyzeKeywords(taskDescription);
90
+ // 2. Check for Sprites-specific keywords (checkpoint/rollback needs)
91
+ const hasSpritesKeyword = this.spritesKeywords.some(keyword =>
92
+ lowerDesc.includes(keyword)
93
+ );
94
+
95
+ if (hasSpritesKeyword) {
96
+ return 'sprites';
97
+ }
77
98
 
78
- // 4. Decision logic
99
+ // 3. Estimate task duration
100
+ const duration = this._estimateDuration(taskDescription);
101
+
102
+ // 4. Decision logic based on duration
79
103
  if (duration === 'long') {
80
104
  return 'fly';
81
105
  }
82
106
 
83
- // Check for Fly-specific keywords
107
+ // 5. Check for Fly-specific keywords
84
108
  const hasFlyKeyword = this.flyKeywords.some(keyword =>
85
- taskDescription.toLowerCase().includes(keyword)
109
+ lowerDesc.includes(keyword)
86
110
  );
87
111
 
88
112
  if (hasFlyKeyword) {
@@ -96,9 +120,9 @@ export class ProviderFactory {
96
120
  /**
97
121
  * Create a provider instance of the specified type
98
122
  *
99
- * @param {string} type - Provider type ('fly' or 'daytona')
123
+ * @param {string} type - Provider type ('fly', 'daytona', or 'sprites')
100
124
  * @param {Object} [providerConfig] - Provider-specific configuration
101
- * @returns {FlyProvider|DaytonaProvider} Provider instance
125
+ * @returns {FlyProvider|DaytonaProvider|SpritesProvider} Provider instance
102
126
  * @throws {Error} If provider type is unknown
103
127
  */
104
128
  createProvider(type, providerConfig = {}) {
@@ -122,6 +146,13 @@ export class ProviderFactory {
122
146
  ...providerConfig,
123
147
  });
124
148
 
149
+ case 'sprites':
150
+ return new SpritesProvider({
151
+ ...baseConfig,
152
+ spritesToken: this.config.spritesToken,
153
+ ...providerConfig,
154
+ });
155
+
125
156
  default:
126
157
  throw new Error(`Unknown provider type: ${type}`);
127
158
  }
@@ -134,8 +165,8 @@ export class ProviderFactory {
134
165
  *
135
166
  * @param {string} taskDescription - Description of the task to perform
136
167
  * @param {Object} [options] - Selection and provider options
137
- * @param {string} [options.provider] - Force specific provider ('fly' or 'daytona')
138
- * @returns {FlyProvider|DaytonaProvider} Configured provider instance
168
+ * @param {string} [options.provider] - Force specific provider ('fly', 'daytona', or 'sprites')
169
+ * @returns {FlyProvider|DaytonaProvider|SpritesProvider} Configured provider instance
139
170
  */
140
171
  selectAndCreate(taskDescription, options = {}) {
141
172
  const providerType = this.selectProvider(taskDescription, options);
@@ -204,7 +235,7 @@ export class ProviderFactory {
204
235
  /**
205
236
  * Get default configuration for a provider type
206
237
  *
207
- * @param {string} type - Provider type ('fly' or 'daytona')
238
+ * @param {string} type - Provider type ('fly', 'daytona', or 'sprites')
208
239
  * @returns {Object} Default configuration for the provider
209
240
  */
210
241
  getDefaultProviderConfig(type) {
@@ -221,8 +252,48 @@ export class ProviderFactory {
221
252
  autoStopMinutes: 60,
222
253
  };
223
254
 
255
+ case 'sprites':
256
+ return {
257
+ // Sprites uses auto-hibernate, no explicit stop timer needed
258
+ cpus: 1,
259
+ memory: 2048,
260
+ };
261
+
224
262
  default:
225
263
  return {};
226
264
  }
227
265
  }
266
+
267
+ /**
268
+ * Get list of available providers
269
+ *
270
+ * @returns {string[]} Array of available provider types
271
+ */
272
+ getAvailableProviders() {
273
+ const available = [];
274
+
275
+ if (this.config.flyApiToken || process.env.FLY_API_TOKEN) {
276
+ available.push('fly');
277
+ }
278
+
279
+ if (this.config.daytonaApiKey || process.env.DAYTONA_API_KEY) {
280
+ available.push('daytona');
281
+ }
282
+
283
+ if (this.config.spritesToken || process.env.SPRITES_TOKEN) {
284
+ available.push('sprites');
285
+ }
286
+
287
+ return available;
288
+ }
289
+
290
+ /**
291
+ * Check if a specific provider is available
292
+ *
293
+ * @param {string} type - Provider type
294
+ * @returns {boolean} True if provider credentials are configured
295
+ */
296
+ isProviderAvailable(type) {
297
+ return this.getAvailableProviders().includes(type);
298
+ }
228
299
  }