alaska-ai 0.1.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 (74) hide show
  1. package/README.md +56 -0
  2. package/dist/adapters/slack.d.ts +130 -0
  3. package/dist/adapters/slack.js +1484 -0
  4. package/dist/adapters/slack.js.map +1 -0
  5. package/dist/backends/claude.d.ts +78 -0
  6. package/dist/backends/claude.js +452 -0
  7. package/dist/backends/claude.js.map +1 -0
  8. package/dist/backends/codex.d.ts +53 -0
  9. package/dist/backends/codex.js +324 -0
  10. package/dist/backends/codex.js.map +1 -0
  11. package/dist/cli/init.d.ts +50 -0
  12. package/dist/cli/init.js +386 -0
  13. package/dist/cli/init.js.map +1 -0
  14. package/dist/cli/prompt.d.ts +31 -0
  15. package/dist/cli/prompt.js +145 -0
  16. package/dist/cli/prompt.js.map +1 -0
  17. package/dist/cli/start.d.ts +28 -0
  18. package/dist/cli/start.js +522 -0
  19. package/dist/cli/start.js.map +1 -0
  20. package/dist/cli.d.ts +2 -0
  21. package/dist/cli.js +65 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +8 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/mcp/callbacks.d.ts +32 -0
  27. package/dist/mcp/callbacks.js +181 -0
  28. package/dist/mcp/callbacks.js.map +1 -0
  29. package/dist/mcp/config.d.ts +15 -0
  30. package/dist/mcp/config.js +22 -0
  31. package/dist/mcp/config.js.map +1 -0
  32. package/dist/mcp/entry.d.ts +13 -0
  33. package/dist/mcp/entry.js +119 -0
  34. package/dist/mcp/entry.js.map +1 -0
  35. package/dist/mcp/file-browser.d.ts +15 -0
  36. package/dist/mcp/file-browser.js +135 -0
  37. package/dist/mcp/file-browser.js.map +1 -0
  38. package/dist/mcp/ipc-server.d.ts +64 -0
  39. package/dist/mcp/ipc-server.js +380 -0
  40. package/dist/mcp/ipc-server.js.map +1 -0
  41. package/dist/mcp/preview-server.d.ts +33 -0
  42. package/dist/mcp/preview-server.js +254 -0
  43. package/dist/mcp/preview-server.js.map +1 -0
  44. package/dist/mcp/server.d.ts +51 -0
  45. package/dist/mcp/server.js +257 -0
  46. package/dist/mcp/server.js.map +1 -0
  47. package/dist/mcp/tunnel.d.ts +17 -0
  48. package/dist/mcp/tunnel.js +154 -0
  49. package/dist/mcp/tunnel.js.map +1 -0
  50. package/dist/router.d.ts +113 -0
  51. package/dist/router.js +511 -0
  52. package/dist/router.js.map +1 -0
  53. package/dist/sandbox-policy.d.ts +6 -0
  54. package/dist/sandbox-policy.js +46 -0
  55. package/dist/sandbox-policy.js.map +1 -0
  56. package/dist/scheduler.d.ts +42 -0
  57. package/dist/scheduler.js +169 -0
  58. package/dist/scheduler.js.map +1 -0
  59. package/dist/store.d.ts +95 -0
  60. package/dist/store.js +353 -0
  61. package/dist/store.js.map +1 -0
  62. package/dist/types/adapter.d.ts +50 -0
  63. package/dist/types/adapter.js +9 -0
  64. package/dist/types/adapter.js.map +1 -0
  65. package/dist/types/backend.d.ts +73 -0
  66. package/dist/types/backend.js +8 -0
  67. package/dist/types/backend.js.map +1 -0
  68. package/dist/types/events.d.ts +47 -0
  69. package/dist/types/events.js +9 -0
  70. package/dist/types/events.js.map +1 -0
  71. package/dist/utils.d.ts +59 -0
  72. package/dist/utils.js +272 -0
  73. package/dist/utils.js.map +1 -0
  74. package/package.json +50 -0
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Tunnel manager — opens public tunnels via cloudflared or ngrok.
3
+ *
4
+ * Tunnels are only used for user-facing things (dev server previews,
5
+ * file browsers) — never for the bridge's own IPC server.
6
+ */
7
+ import { spawn } from 'node:child_process';
8
+ import { detectTunnelTools } from '../cli/init.js';
9
+ /** Tracks all active tunnels for cleanup. */
10
+ const activeTunnels = new Map();
11
+ /**
12
+ * Open a tunnel on the given port using cloudflared (preferred) or ngrok.
13
+ * Auto-closes after `ttl` seconds.
14
+ */
15
+ export async function openTunnel(port, ttl) {
16
+ const { hasCloudflared, hasNgrok } = detectTunnelTools();
17
+ if (hasCloudflared) {
18
+ return openCloudflaredTunnel(port, ttl);
19
+ }
20
+ if (hasNgrok) {
21
+ return openNgrokTunnel(port, ttl);
22
+ }
23
+ throw new Error('No tunnel tool available. Install cloudflared or ngrok:\n' +
24
+ ' brew install cloudflared\n' +
25
+ ' brew install ngrok');
26
+ }
27
+ /** Open a cloudflared tunnel. Parses the public URL from stderr. */
28
+ function openCloudflaredTunnel(port, ttl) {
29
+ return new Promise((resolve, reject) => {
30
+ const child = spawn('cloudflared', ['tunnel', '--url', `http://localhost:${port}`], {
31
+ stdio: ['ignore', 'pipe', 'pipe'],
32
+ });
33
+ const id = `cf-${port}-${Date.now()}`;
34
+ let resolved = false;
35
+ const timer = ttl > 0 ? setTimeout(() => {
36
+ closeTunnel(id);
37
+ }, ttl * 1000) : null;
38
+ activeTunnels.set(id, { process: child, timer });
39
+ // cloudflared prints the URL to stderr like:
40
+ // "... https://some-random.trycloudflare.com ..."
41
+ let stderrBuf = '';
42
+ child.stderr?.on('data', (chunk) => {
43
+ stderrBuf += chunk.toString();
44
+ const match = stderrBuf.match(/https:\/\/[a-z0-9-]+\.trycloudflare\.com/);
45
+ if (match && !resolved) {
46
+ resolved = true;
47
+ const url = match[0];
48
+ console.log(`[tunnel] cloudflared tunnel opened: ${url} (port ${port}, TTL ${ttl}s)`);
49
+ resolve({
50
+ url,
51
+ close: () => closeTunnel(id),
52
+ });
53
+ }
54
+ });
55
+ child.on('error', (err) => {
56
+ activeTunnels.delete(id);
57
+ if (timer)
58
+ clearTimeout(timer);
59
+ if (!resolved)
60
+ reject(new Error(`cloudflared failed: ${err.message}`));
61
+ });
62
+ child.on('exit', (code) => {
63
+ activeTunnels.delete(id);
64
+ if (timer)
65
+ clearTimeout(timer);
66
+ if (!resolved)
67
+ reject(new Error(`cloudflared exited with code ${code} before URL was available`));
68
+ });
69
+ // Timeout if URL not found within 30 seconds
70
+ setTimeout(() => {
71
+ if (!resolved) {
72
+ resolved = true;
73
+ closeTunnel(id);
74
+ reject(new Error('cloudflared timed out waiting for URL'));
75
+ }
76
+ }, 30000);
77
+ });
78
+ }
79
+ /** Open an ngrok tunnel. Queries the local API for the public URL. */
80
+ function openNgrokTunnel(port, ttl) {
81
+ return new Promise((resolve, reject) => {
82
+ const child = spawn('ngrok', ['http', String(port)], {
83
+ stdio: ['ignore', 'pipe', 'pipe'],
84
+ });
85
+ const id = `ngrok-${port}-${Date.now()}`;
86
+ let resolved = false;
87
+ const timer = ttl > 0 ? setTimeout(() => {
88
+ closeTunnel(id);
89
+ }, ttl * 1000) : null;
90
+ activeTunnels.set(id, { process: child, timer });
91
+ child.on('error', (err) => {
92
+ activeTunnels.delete(id);
93
+ if (timer)
94
+ clearTimeout(timer);
95
+ if (!resolved)
96
+ reject(new Error(`ngrok failed: ${err.message}`));
97
+ });
98
+ child.on('exit', (code) => {
99
+ activeTunnels.delete(id);
100
+ if (timer)
101
+ clearTimeout(timer);
102
+ if (!resolved)
103
+ reject(new Error(`ngrok exited with code ${code}`));
104
+ });
105
+ // Poll the ngrok local API for the tunnel URL
106
+ const pollInterval = setInterval(async () => {
107
+ try {
108
+ const res = await fetch('http://127.0.0.1:4040/api/tunnels');
109
+ const data = await res.json();
110
+ const tunnel = data.tunnels?.find(t => t.proto === 'https') ?? data.tunnels?.[0];
111
+ if (tunnel && !resolved) {
112
+ resolved = true;
113
+ clearInterval(pollInterval);
114
+ const url = tunnel.public_url;
115
+ console.log(`[tunnel] ngrok tunnel opened: ${url} (port ${port}, TTL ${ttl}s)`);
116
+ resolve({
117
+ url,
118
+ close: () => closeTunnel(id),
119
+ });
120
+ }
121
+ }
122
+ catch {
123
+ // ngrok API not ready yet — keep polling
124
+ }
125
+ }, 500);
126
+ // Timeout after 30 seconds
127
+ setTimeout(() => {
128
+ clearInterval(pollInterval);
129
+ if (!resolved) {
130
+ resolved = true;
131
+ closeTunnel(id);
132
+ reject(new Error('ngrok timed out waiting for tunnel URL'));
133
+ }
134
+ }, 30000);
135
+ });
136
+ }
137
+ /** Close a specific tunnel by its internal ID. */
138
+ function closeTunnel(id) {
139
+ const tunnel = activeTunnels.get(id);
140
+ if (tunnel) {
141
+ if (tunnel.timer)
142
+ clearTimeout(tunnel.timer);
143
+ tunnel.process.kill('SIGTERM');
144
+ activeTunnels.delete(id);
145
+ console.log(`[tunnel] closed tunnel ${id}`);
146
+ }
147
+ }
148
+ /** Close all active tunnels. Called during shutdown. */
149
+ export function closeAllTunnels() {
150
+ for (const [id] of activeTunnels) {
151
+ closeTunnel(id);
152
+ }
153
+ }
154
+ //# sourceMappingURL=tunnel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tunnel.js","sourceRoot":"","sources":["../../src/mcp/tunnel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Router for Alaska.
3
+ *
4
+ * Maps channel/thread pairs to projects and sessions, manages backend
5
+ * lifecycle, and enforces session state machine transitions.
6
+ */
7
+ import type { Backend, FileAttachment, McpServerEntry } from './types/backend.js';
8
+ import type { NormalizedEvent } from './types/events.js';
9
+ import type { Store, Project, Session } from './store.js';
10
+ /** Factory function that creates a Backend instance given a backend name. */
11
+ export type BackendFactory = (backendName: string) => Backend;
12
+ export interface ResolveResult {
13
+ project: Project;
14
+ session: Session;
15
+ }
16
+ export interface RouteResult {
17
+ events: NormalizedEvent[];
18
+ session: Session;
19
+ }
20
+ /** Context passed to mcpConfigFactory for generating per-session MCP config. */
21
+ export interface McpConfigContext {
22
+ channelId: string;
23
+ threadId: string;
24
+ projectDir: string;
25
+ platform: string;
26
+ }
27
+ /** Factory that creates MCP config for a backend session. */
28
+ export type McpConfigFactory = (ctx: McpConfigContext) => McpServerEntry;
29
+ export interface RouterOptions {
30
+ /** Timeout for backend.send() in milliseconds. Default: 300000 (5 minutes). */
31
+ timeoutMs?: number;
32
+ /** Factory to generate MCP config for each backend session. */
33
+ mcpConfigFactory?: McpConfigFactory;
34
+ /** IPC server info for permission hook scripts. */
35
+ ipc?: {
36
+ port: number;
37
+ secret: string;
38
+ };
39
+ /** Path to compiled hook scripts directory (dist/hooks/). */
40
+ hookScriptDir?: string;
41
+ }
42
+ export declare class Router {
43
+ private store;
44
+ private backendFactory;
45
+ private activeBackends;
46
+ private timeoutMs;
47
+ private mcpConfigFactory?;
48
+ private ipc?;
49
+ private hookScriptDir?;
50
+ /** Per-thread lock to serialize concurrent sends/responds to the same thread. */
51
+ private threadLocks;
52
+ /** Last activity timestamp per thread for idle timeout cleanup. */
53
+ private lastActivity;
54
+ /** Idle cleanup interval handle. */
55
+ private idleCleanupInterval;
56
+ constructor(store: Store, backendFactory: BackendFactory, options?: RouterOptions);
57
+ /**
58
+ * Clean up backends that have been idle for longer than the timeout.
59
+ */
60
+ private cleanupIdleBackends;
61
+ /**
62
+ * Get an existing alive backend for a thread, or create and start a new one.
63
+ * Returns the backend ready for send().
64
+ */
65
+ private getOrCreateBackend;
66
+ /**
67
+ * Acquire a per-thread lock. If another operation is in progress for this
68
+ * thread, the returned promise won't resolve until it finishes.
69
+ * Returns a release function to call when the operation completes.
70
+ */
71
+ private acquireThreadLock;
72
+ /** Send with timeout — races backend.send() against a timeout. */
73
+ private sendWithTimeout;
74
+ /**
75
+ * Resolve a channel + thread to a project and session.
76
+ * Returns null if the channel is not bound to a project.
77
+ * Creates a new session if the thread is unknown in a bound channel.
78
+ */
79
+ resolve(channelId: string, threadId: string): Promise<ResolveResult | null>;
80
+ /** Prepend context metadata (time, source platform) so the backend can reason about relative dates and message origin. */
81
+ private prependContext;
82
+ /** Augment prompt text with upload info for files that have staging metadata. */
83
+ private augmentTextWithUploadInfo;
84
+ /** Clean up staging files from file attachments. */
85
+ private cleanupFileStaging;
86
+ /**
87
+ * Send a message through the backend and return normalized events.
88
+ * Manages session state transitions and persists backend session ID.
89
+ */
90
+ send(channelId: string, threadId: string, text: string, files?: FileAttachment[]): Promise<RouteResult>;
91
+ private _send;
92
+ /**
93
+ * Handle a user response when a session is waiting_for_input.
94
+ * This resumes the backend with the user's response text.
95
+ * When allowedTools is provided, the backend will auto-approve those tools.
96
+ */
97
+ respond(channelId: string, threadId: string, text: string, allowedTools?: string[]): Promise<RouteResult>;
98
+ private _respond;
99
+ /**
100
+ * Reset a session — clear the backend session ID so next message starts fresh.
101
+ */
102
+ resetSession(channelId: string, threadId: string): Promise<Session>;
103
+ /**
104
+ * Cancel a running backend for a thread. Uses interrupt() for clean
105
+ * cancellation, then stop() to terminate. Transitions the session back to idle.
106
+ * Returns true if a backend was cancelled, false if nothing was running.
107
+ */
108
+ cancelBackend(channelId: string, threadId: string): Promise<boolean>;
109
+ /**
110
+ * Graceful shutdown — stop all active backend sessions and clean up.
111
+ */
112
+ shutdown(): Promise<void>;
113
+ }