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.
- package/.claude/hooks/config-loader.mjs +88 -34
- package/.claude/hooks/permission_request.mjs +392 -82
- package/.claude/hooks/post_tool_use.mjs +90 -0
- package/.claude/hooks/pre_tool_use.mjs +247 -305
- package/.claude/hooks/session-register.mjs +94 -105
- package/.claude/hooks/session_end.mjs +41 -42
- package/.claude/hooks/session_start.mjs +45 -60
- package/.claude/hooks/stop.mjs +752 -99
- package/.claude/hooks/user_prompt_submit.mjs +26 -3
- package/README.md +7 -0
- package/lib/auth/api-key.js +12 -0
- package/lib/auth/token-refresh.js +286 -0
- package/lib/cli/daemon-commands.js +1 -1
- package/lib/cli/teleport-commands.js +469 -0
- package/lib/daemon/daemon-v2.js +104 -0
- package/lib/daemon/lifecycle.js +56 -171
- package/lib/daemon/response-classifier.js +15 -1
- package/lib/daemon/services/index.js +3 -0
- package/lib/daemon/services/polling-service.js +173 -0
- package/lib/daemon/services/queue-service.js +318 -0
- package/lib/daemon/services/session-service.js +115 -0
- package/lib/daemon/state.js +35 -0
- package/lib/daemon/task-executor-v2.js +413 -0
- package/lib/daemon/task-executor.js +1235 -0
- package/lib/daemon/teleportation-daemon.js +770 -25
- package/lib/daemon/timeline-analyzer.js +215 -0
- package/lib/daemon/transcript-ingestion.js +696 -0
- package/lib/daemon/utils.js +91 -0
- package/lib/install/installer.js +184 -20
- package/lib/install/uhr-installer.js +136 -0
- package/lib/remote/providers/base-provider.js +46 -0
- package/lib/remote/providers/daytona-provider.js +58 -0
- package/lib/remote/providers/provider-factory.js +90 -19
- package/lib/remote/providers/sprites-provider.js +711 -0
- package/lib/teleport/exporters/claude-exporter.js +302 -0
- package/lib/teleport/exporters/gemini-exporter.js +307 -0
- package/lib/teleport/exporters/index.js +93 -0
- package/lib/teleport/exporters/interface.js +153 -0
- package/lib/teleport/fork-tracker.js +415 -0
- package/lib/teleport/git-committer.js +337 -0
- package/lib/teleport/index.js +48 -0
- package/lib/teleport/manager.js +620 -0
- package/lib/teleport/session-capture.js +282 -0
- package/package.json +11 -5
- package/teleportation-cli.cjs +632 -451
- package/.claude/hooks/heartbeat.mjs +0 -396
- package/lib/daemon/agentic-executor.js +0 -803
- package/lib/daemon/pid-manager.js +0 -160
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
// Shared config loader for all hooks
|
|
3
3
|
// Reads from encrypted credentials (~/.teleportation/credentials), then ~/.teleportation-config.json, then env vars
|
|
4
|
+
// PRD-0019: Supports JWT authentication with automatic token refresh
|
|
4
5
|
|
|
5
6
|
import { readFile } from 'node:fs/promises';
|
|
6
7
|
import { homedir } from 'node:os';
|
|
@@ -12,6 +13,33 @@ import { fileURLToPath } from 'node:url';
|
|
|
12
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
14
|
const __dirname = dirname(__filename);
|
|
14
15
|
|
|
16
|
+
// Path resolution helper for auth modules
|
|
17
|
+
const AUTH_MODULE_PATHS = [
|
|
18
|
+
// If hook is still in project directory
|
|
19
|
+
() => join(process.cwd(), 'lib', 'auth'),
|
|
20
|
+
// If installed globally, try common locations
|
|
21
|
+
() => join(homedir(), '.teleportation', 'lib', 'auth'),
|
|
22
|
+
// Try relative to hook location (if hooks are symlinked)
|
|
23
|
+
() => join(__dirname, '..', '..', 'lib', 'auth')
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Try to import a module from multiple possible paths
|
|
28
|
+
*/
|
|
29
|
+
async function tryImportModule(moduleName) {
|
|
30
|
+
for (const getPath of AUTH_MODULE_PATHS) {
|
|
31
|
+
const modulePath = join(getPath(), moduleName);
|
|
32
|
+
try {
|
|
33
|
+
const module = await import(modulePath);
|
|
34
|
+
return module;
|
|
35
|
+
} catch (e) {
|
|
36
|
+
// Try next path
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
15
43
|
export async function loadConfig() {
|
|
16
44
|
// Test override: allow forcing config to be loaded from environment variables only
|
|
17
45
|
// This is useful for unit tests that mock the relay API.
|
|
@@ -20,46 +48,70 @@ export async function loadConfig() {
|
|
|
20
48
|
relayApiUrl: env.RELAY_API_URL || '',
|
|
21
49
|
relayApiKey: env.RELAY_API_KEY || '',
|
|
22
50
|
userToken: env.DETACH_USER_TOKEN || '',
|
|
23
|
-
slackWebhookUrl: env.SLACK_WEBHOOK_URL || ''
|
|
51
|
+
slackWebhookUrl: env.SLACK_WEBHOOK_URL || '',
|
|
52
|
+
authMethod: 'env'
|
|
24
53
|
};
|
|
25
54
|
}
|
|
26
55
|
|
|
27
|
-
// Priority 1: Try
|
|
56
|
+
// Priority 1: Try JWT authentication (PRD-0019)
|
|
57
|
+
// This provides automatic token refresh for short-lived access tokens
|
|
28
58
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
59
|
+
const tokenRefreshModule = await tryImportModule('token-refresh.js');
|
|
60
|
+
if (tokenRefreshModule && tokenRefreshModule.getValidAccessToken) {
|
|
61
|
+
const { getValidAccessToken, getAuthMethod } = tokenRefreshModule;
|
|
62
|
+
|
|
63
|
+
// Check if JWT credentials are available
|
|
64
|
+
const authInfo = await getAuthMethod();
|
|
65
|
+
if (authInfo.method === 'jwt') {
|
|
66
|
+
// Get a valid access token (refreshes automatically if needed)
|
|
67
|
+
const accessToken = await getValidAccessToken();
|
|
68
|
+
|
|
69
|
+
// Load credentials for other config values
|
|
70
|
+
const credentialsModule = await tryImportModule('credentials.js');
|
|
71
|
+
let relayApiUrl = '';
|
|
72
|
+
let slackWebhookUrl = '';
|
|
73
|
+
|
|
74
|
+
if (credentialsModule && credentialsModule.CredentialManager) {
|
|
75
|
+
const manager = new credentialsModule.CredentialManager();
|
|
76
|
+
const credentials = await manager.load();
|
|
77
|
+
if (credentials) {
|
|
78
|
+
relayApiUrl = credentials.relayApiUrl || credentials.relay_api_url || '';
|
|
79
|
+
slackWebhookUrl = credentials.slackWebhookUrl || credentials.slack_webhook_url || '';
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
relayApiUrl,
|
|
85
|
+
relayApiKey: accessToken, // JWT access token used as Bearer token
|
|
86
|
+
userToken: '',
|
|
87
|
+
slackWebhookUrl,
|
|
88
|
+
authMethod: 'jwt'
|
|
89
|
+
};
|
|
50
90
|
}
|
|
51
91
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
92
|
+
} catch (e) {
|
|
93
|
+
// JWT auth failed (token refresh error, etc.) - fall back to legacy auth
|
|
94
|
+
// Common errors: session expired, network issues, etc.
|
|
95
|
+
if (env.DEBUG) {
|
|
96
|
+
console.error(`[ConfigLoader] JWT auth failed: ${e.message}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Priority 2: Try to load from encrypted credentials file (legacy API key)
|
|
101
|
+
try {
|
|
102
|
+
const credentialsModule = await tryImportModule('credentials.js');
|
|
103
|
+
|
|
104
|
+
if (credentialsModule && credentialsModule.CredentialManager) {
|
|
105
|
+
const manager = new credentialsModule.CredentialManager();
|
|
55
106
|
const credentials = await manager.load();
|
|
56
|
-
|
|
107
|
+
|
|
57
108
|
if (credentials) {
|
|
58
109
|
return {
|
|
59
110
|
relayApiUrl: credentials.relayApiUrl || credentials.relay_api_url || '',
|
|
60
111
|
relayApiKey: credentials.relayApiKey || credentials.apiKey || credentials.relay_api_key || '',
|
|
61
112
|
userToken: credentials.userToken || credentials.user_token || '',
|
|
62
|
-
slackWebhookUrl: credentials.slackWebhookUrl || credentials.slack_webhook_url || ''
|
|
113
|
+
slackWebhookUrl: credentials.slackWebhookUrl || credentials.slack_webhook_url || '',
|
|
114
|
+
authMethod: 'api-key'
|
|
63
115
|
};
|
|
64
116
|
}
|
|
65
117
|
}
|
|
@@ -67,9 +119,9 @@ export async function loadConfig() {
|
|
|
67
119
|
// Credential manager not available or credentials don't exist, continue to fallback
|
|
68
120
|
}
|
|
69
121
|
|
|
70
|
-
// Priority
|
|
122
|
+
// Priority 3: Try to load from legacy config file
|
|
71
123
|
const configPath = join(homedir(), '.teleportation-config.json');
|
|
72
|
-
|
|
124
|
+
|
|
73
125
|
try {
|
|
74
126
|
const content = await readFile(configPath, 'utf8');
|
|
75
127
|
const config = JSON.parse(content);
|
|
@@ -77,17 +129,19 @@ export async function loadConfig() {
|
|
|
77
129
|
relayApiUrl: config.relay_api_url || '',
|
|
78
130
|
relayApiKey: config.relay_api_key || '',
|
|
79
131
|
userToken: config.user_token || '',
|
|
80
|
-
slackWebhookUrl: config.slack_webhook_url || ''
|
|
132
|
+
slackWebhookUrl: config.slack_webhook_url || '',
|
|
133
|
+
authMethod: 'legacy-config'
|
|
81
134
|
};
|
|
82
135
|
} catch (e) {
|
|
83
136
|
// Config file doesn't exist, continue to fallback
|
|
84
137
|
}
|
|
85
|
-
|
|
86
|
-
// Priority
|
|
138
|
+
|
|
139
|
+
// Priority 4: Fall back to environment variables
|
|
87
140
|
return {
|
|
88
141
|
relayApiUrl: env.RELAY_API_URL || '',
|
|
89
142
|
relayApiKey: env.RELAY_API_KEY || '',
|
|
90
143
|
userToken: env.DETACH_USER_TOKEN || '',
|
|
91
|
-
slackWebhookUrl: env.SLACK_WEBHOOK_URL || ''
|
|
144
|
+
slackWebhookUrl: env.SLACK_WEBHOOK_URL || '',
|
|
145
|
+
authMethod: 'env'
|
|
92
146
|
};
|
|
93
147
|
}
|