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,50 @@
1
+ /**
2
+ * Shared adapter interface for Alaska messaging platforms.
3
+ *
4
+ * Each messaging adapter (for example, Slack) implements this interface.
5
+ * The core bridge code calls these methods without knowing which platform
6
+ * is active.
7
+ */
8
+ export interface Adapter {
9
+ /** Connect to the messaging platform and start listening. */
10
+ start(): Promise<void>;
11
+ /** Disconnect from the messaging platform. */
12
+ stop(): Promise<void>;
13
+ /** Post a text message in a thread. Splits long messages as needed. */
14
+ postText(channelId: string, threadTs: string, text: string, client: any): Promise<void>;
15
+ /** Post an interactive permission prompt with Allow/Deny buttons.
16
+ * When requestId is provided (hook-based flow), buttons resolve the permission
17
+ * in-process via resolvePermission() instead of calling router.respond(). */
18
+ postPermissionPrompt(channelId: string, threadTs: string, event: {
19
+ toolName: string;
20
+ toolInput: Record<string, unknown>;
21
+ context?: string;
22
+ requestId?: string;
23
+ }, client: any): Promise<void>;
24
+ /** Post an interactive question with dynamic option buttons.
25
+ * Called when Claude Code uses AskUserQuestion — renders options as buttons. */
26
+ postUserQuestion(channelId: string, threadTs: string, questions: Array<{
27
+ question: string;
28
+ header: string;
29
+ options: Array<{
30
+ label: string;
31
+ description: string;
32
+ }>;
33
+ multiSelect: boolean;
34
+ }>, requestId: string, client: any): Promise<void>;
35
+ /** Post an error message. */
36
+ postError(channelId: string, threadTs: string, message: string, client: any): Promise<void>;
37
+ /** Upload a file as an attachment in a thread. Called by MCP callbacks. */
38
+ uploadFile(channelId: string, threadId: string, filePath: string): Promise<void>;
39
+ /** Post a plain text message to a thread. Called by MCP callbacks (no context object needed). */
40
+ sendMessage(channelId: string, threadId: string, text: string): Promise<void>;
41
+ /** Create a new thread/conversation in a channel. Returns the thread ID.
42
+ * Used by the scheduler to start bridge-initiated sessions. */
43
+ createThread(channelId: string, title: string): Promise<string>;
44
+ /** Render a todo checklist in a thread (post new or update existing). */
45
+ renderTodoList(channelId: string, threadId: string, todos: Array<{
46
+ content: string;
47
+ status: string;
48
+ activeForm: string;
49
+ }>): Promise<void>;
50
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shared adapter interface for Alaska messaging platforms.
3
+ *
4
+ * Each messaging adapter (for example, Slack) implements this interface.
5
+ * The core bridge code calls these methods without knowing which platform
6
+ * is active.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../src/types/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Backend interface for Alaska coding agent wrappers.
3
+ *
4
+ * Each backend (Claude Code, Codex CLI) implements this interface.
5
+ * The router calls these methods without knowing which backend is active.
6
+ */
7
+ import type { NormalizedEvent } from './events.js';
8
+ export interface SendResult {
9
+ events: NormalizedEvent[];
10
+ sessionId: string | null;
11
+ }
12
+ /** Discriminator for how a file attachment is passed to backends. */
13
+ export type FileKind = 'image' | 'pdf' | 'text' | 'binary';
14
+ /** A file attachment to include in a message to the backend. */
15
+ export interface FileAttachment {
16
+ /** Base64-encoded file data. */
17
+ base64: string;
18
+ /** MIME type (e.g., 'image/png', 'application/pdf', 'text/plain'). */
19
+ mediaType: string;
20
+ /** How this file should be handled by backends. */
21
+ kind: FileKind;
22
+ /** Upload ID for referencing this file in the save_uploaded_file MCP tool. */
23
+ uploadId?: string;
24
+ /** Original filename of the uploaded file. */
25
+ filename?: string;
26
+ /** Full path to the staging file in ~/.alaska-ai/uploads/. */
27
+ stagingPath?: string;
28
+ }
29
+ /** MCP server configuration for injection into backend CLI. */
30
+ export interface McpServerEntry {
31
+ command: string;
32
+ args: string[];
33
+ env?: Record<string, string>;
34
+ }
35
+ export interface BackendOptions {
36
+ projectDir: string;
37
+ /** Optional MCP server config to inject so the backend agent gets bridge tools. */
38
+ mcpConfig?: McpServerEntry;
39
+ /** IPC server connection info for hook scripts. */
40
+ ipc?: {
41
+ port: number;
42
+ secret: string;
43
+ };
44
+ /** Chat context for hook scripts to send permission prompts. */
45
+ channelId?: string;
46
+ threadId?: string;
47
+ platform?: string;
48
+ /** Path to compiled hook scripts directory (dist/hooks/). */
49
+ hookScriptDir?: string;
50
+ /** Permission mode for the project. */
51
+ permissionMode?: 'supervised';
52
+ /** Sandbox mode for Codex. */
53
+ sandboxMode?: 'workspace-write';
54
+ }
55
+ export interface Backend {
56
+ /** Prepare the backend (e.g., validate CLI is available). */
57
+ start(options: BackendOptions): Promise<void>;
58
+ /** Send a prompt and return normalized events + session ID.
59
+ * Optional file attachments are passed as content blocks (Claude stream-json, Codex --image). */
60
+ send(text: string, files?: FileAttachment[]): Promise<SendResult>;
61
+ /** Return the current session ID for resume, or null if none. */
62
+ getSessionId(): string | null;
63
+ /** Set the session ID for resume (used by the router to restore from DB). */
64
+ setSessionId(id: string | null): void;
65
+ /** Set tools to auto-approve on the next send (for permission Allow flow). */
66
+ setAllowedTools(tools: string[]): void;
67
+ /** Clean interruption — cancel the current operation but keep the backend alive. */
68
+ interrupt(): Promise<void>;
69
+ /** Check if the backend subprocess is still alive and can accept messages. */
70
+ isAlive(): boolean;
71
+ /** Clean shutdown — kill any running process. */
72
+ stop(): Promise<void>;
73
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Backend interface for Alaska coding agent wrappers.
3
+ *
4
+ * Each backend (Claude Code, Codex CLI) implements this interface.
5
+ * The router calls these methods without knowing which backend is active.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=backend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../../src/types/backend.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Normalized event types for Alaska.
3
+ *
4
+ * Both Claude Code and Codex CLI produce different output formats.
5
+ * These types represent the bridge's internal event model that all
6
+ * backend output is normalized into before being passed to adapters.
7
+ */
8
+ export interface AssistantText {
9
+ type: 'assistant_text';
10
+ text: string;
11
+ }
12
+ export interface ToolUse {
13
+ type: 'tool_use';
14
+ toolName: string;
15
+ toolInput: Record<string, unknown>;
16
+ toolUseId?: string;
17
+ }
18
+ export interface ToolResult {
19
+ type: 'tool_result';
20
+ toolUseId: string;
21
+ content: string;
22
+ isError: boolean;
23
+ }
24
+ export interface CommandExecution {
25
+ type: 'command_execution';
26
+ command: string;
27
+ exitCode: number;
28
+ output: string;
29
+ }
30
+ export interface PermissionDenied {
31
+ type: 'permission_denied';
32
+ toolName: string;
33
+ toolInput: Record<string, unknown>;
34
+ context?: string;
35
+ }
36
+ export interface SessionStarted {
37
+ type: 'session_started';
38
+ sessionId: string;
39
+ }
40
+ export interface TurnCompleted {
41
+ type: 'turn_completed';
42
+ }
43
+ export interface ErrorEvent {
44
+ type: 'error';
45
+ message: string;
46
+ }
47
+ export type NormalizedEvent = AssistantText | ToolUse | ToolResult | CommandExecution | PermissionDenied | SessionStarted | TurnCompleted | ErrorEvent;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Normalized event types for Alaska.
3
+ *
4
+ * Both Claude Code and Codex CLI produce different output formats.
5
+ * These types represent the bridge's internal event model that all
6
+ * backend output is normalized into before being passed to adapters.
7
+ */
8
+ export {};
9
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/types/events.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Shared utility functions for Alaska.
3
+ */
4
+ import type { FileAttachment, FileKind } from './types/backend.js';
5
+ /** Canonical config directory: ~/.alaska-ai/ */
6
+ export declare function getConfigDir(): string;
7
+ export declare function getDbPath(): string;
8
+ export declare function getEnvPath(): string;
9
+ /** Check if a MIME type is a supported image type. */
10
+ export declare function isImageMimeType(mimeType: string | undefined | null): boolean;
11
+ /**
12
+ * Download a URL to a base64 string. Throws on failure.
13
+ * Uses Node 18+ built-in fetch.
14
+ */
15
+ export declare function downloadToBase64(url: string, headers?: Record<string, string>): Promise<{
16
+ base64: string;
17
+ mediaType: string;
18
+ }>;
19
+ /** Uploads staging directory: ~/.alaska-ai/uploads/ */
20
+ export declare function getUploadsDir(): string;
21
+ /**
22
+ * Save image data to the staging directory for later retrieval by the
23
+ * save_uploaded_file MCP tool. Returns the upload ID, sanitized filename,
24
+ * and full staging path.
25
+ */
26
+ export declare function saveToStagingDir(base64: string, mediaType: string, originalFilename: string): {
27
+ uploadId: string;
28
+ filename: string;
29
+ stagingPath: string;
30
+ };
31
+ /** Clean up staging files. Best-effort, ignores errors. */
32
+ export declare function cleanupStagingFiles(stagingPaths: string[]): void;
33
+ /**
34
+ * Classify a MIME type (and optionally filename) into a FileKind.
35
+ * Used to determine how a file attachment is passed to backends.
36
+ */
37
+ export declare function classifyMimeType(mimeType: string | undefined | null, filename?: string): FileKind;
38
+ /**
39
+ * Download a file from a URL, classify it, and save to staging.
40
+ * Returns a complete FileAttachment or null on download failure.
41
+ * This is the shared DRY utility used by both adapters.
42
+ */
43
+ export declare function downloadAndStageFile(url: string, filename: string, mimeType: string | undefined, authHeaders?: Record<string, string>): Promise<FileAttachment | null>;
44
+ /** Split text into chunks at word boundaries, respecting a character limit. */
45
+ export declare function splitText(text: string, limit: number): string[];
46
+ /**
47
+ * Wrap markdown tables in code blocks so they render with monospace alignment.
48
+ *
49
+ * Detects tables by finding separator rows (|---|---|), expands one line up
50
+ * for the header and down as long as lines start with |. Skips tables that
51
+ * are already inside code blocks.
52
+ */
53
+ export declare function wrapTablesInCodeBlocks(text: string): string;
54
+ /**
55
+ * Convert standard Markdown to Slack mrkdwn format.
56
+ *
57
+ * Handles: bold, italic, strikethrough, links, headers, tables (wrapped in code blocks).
58
+ */
59
+ export declare function markdownToSlackMrkdwn(text: string): string;
package/dist/utils.js ADDED
@@ -0,0 +1,272 @@
1
+ /**
2
+ * Shared utility functions for Alaska.
3
+ */
4
+ import * as os from 'node:os';
5
+ import * as path from 'node:path';
6
+ import * as fs from 'node:fs';
7
+ import { randomUUID } from 'node:crypto';
8
+ /** Canonical config directory: ~/.alaska-ai/ */
9
+ export function getConfigDir() {
10
+ return path.join(os.homedir(), '.alaska-ai');
11
+ }
12
+ export function getDbPath() {
13
+ return path.join(getConfigDir(), 'bridge.db');
14
+ }
15
+ export function getEnvPath() {
16
+ return path.join(getConfigDir(), '.env');
17
+ }
18
+ /** MIME types we recognize as images for passthrough to backends. */
19
+ const IMAGE_MIME_TYPES = new Set([
20
+ 'image/png', 'image/jpeg', 'image/gif', 'image/webp',
21
+ ]);
22
+ /** Check if a MIME type is a supported image type. */
23
+ export function isImageMimeType(mimeType) {
24
+ if (!mimeType)
25
+ return false;
26
+ // Handle "image/png; charset=..." etc.
27
+ const base = mimeType.split(';')[0].trim().toLowerCase();
28
+ return IMAGE_MIME_TYPES.has(base);
29
+ }
30
+ /**
31
+ * Download a URL to a base64 string. Throws on failure.
32
+ * Uses Node 18+ built-in fetch.
33
+ */
34
+ export async function downloadToBase64(url, headers) {
35
+ const response = await fetch(url, { headers });
36
+ if (!response.ok) {
37
+ throw new Error(`Download failed: HTTP ${response.status} ${response.statusText} for ${url}`);
38
+ }
39
+ const buffer = Buffer.from(await response.arrayBuffer());
40
+ const mediaType = (response.headers.get('content-type') || 'application/octet-stream')
41
+ .split(';')[0].trim();
42
+ return { base64: buffer.toString('base64'), mediaType };
43
+ }
44
+ /** Uploads staging directory: ~/.alaska-ai/uploads/ */
45
+ export function getUploadsDir() {
46
+ return path.join(getConfigDir(), 'uploads');
47
+ }
48
+ /**
49
+ * Save image data to the staging directory for later retrieval by the
50
+ * save_uploaded_file MCP tool. Returns the upload ID, sanitized filename,
51
+ * and full staging path.
52
+ */
53
+ export function saveToStagingDir(base64, mediaType, originalFilename) {
54
+ const uploadsDir = getUploadsDir();
55
+ fs.mkdirSync(uploadsDir, { recursive: true });
56
+ const uploadId = `upload_${randomUUID().replace(/-/g, '').slice(0, 12)}`;
57
+ const safeName = path.basename(originalFilename) || 'file.dat';
58
+ const stagingPath = path.join(uploadsDir, `${uploadId}-${safeName}`);
59
+ fs.writeFileSync(stagingPath, Buffer.from(base64, 'base64'));
60
+ console.log(`[uploads] saved staging file: ${stagingPath}`);
61
+ return { uploadId, filename: safeName, stagingPath };
62
+ }
63
+ /** Clean up staging files. Best-effort, ignores errors. */
64
+ export function cleanupStagingFiles(stagingPaths) {
65
+ for (const p of stagingPaths) {
66
+ try {
67
+ fs.unlinkSync(p);
68
+ console.log(`[uploads] cleaned up staging file: ${p}`);
69
+ }
70
+ catch (err) {
71
+ if (err.code !== 'ENOENT') {
72
+ console.error(`[uploads] failed to clean up staging file ${p}: ${err.message}`);
73
+ }
74
+ }
75
+ }
76
+ }
77
+ /** MIME types treated as text when extension-based detection isn't enough. */
78
+ const TEXT_APP_MIME_TYPES = new Set([
79
+ 'application/json', 'application/xml', 'application/javascript',
80
+ 'application/typescript', 'application/x-yaml', 'application/toml',
81
+ ]);
82
+ /** File extensions we consider text, even with generic MIME types. */
83
+ const TEXT_EXTENSIONS = new Set([
84
+ '.json', '.csv', '.md', '.txt', '.ts', '.js', '.jsx', '.tsx',
85
+ '.py', '.rb', '.go', '.rs', '.java', '.c', '.cpp', '.h', '.hpp',
86
+ '.yaml', '.yml', '.toml', '.xml', '.html', '.css', '.scss',
87
+ '.sh', '.bash', '.zsh', '.sql', '.graphql', '.env', '.ini',
88
+ '.cfg', '.conf', '.log', '.svg',
89
+ ]);
90
+ /**
91
+ * Classify a MIME type (and optionally filename) into a FileKind.
92
+ * Used to determine how a file attachment is passed to backends.
93
+ */
94
+ export function classifyMimeType(mimeType, filename) {
95
+ if (!mimeType)
96
+ return 'binary';
97
+ const base = mimeType.split(';')[0].trim().toLowerCase();
98
+ if (IMAGE_MIME_TYPES.has(base))
99
+ return 'image';
100
+ if (base === 'application/pdf')
101
+ return 'pdf';
102
+ if (base.startsWith('text/'))
103
+ return 'text';
104
+ if (TEXT_APP_MIME_TYPES.has(base))
105
+ return 'text';
106
+ // Fallback: check extension for common text types with generic MIME
107
+ if (filename) {
108
+ const ext = path.extname(filename).toLowerCase();
109
+ if (TEXT_EXTENSIONS.has(ext))
110
+ return 'text';
111
+ }
112
+ return 'binary';
113
+ }
114
+ /**
115
+ * Download a file from a URL, classify it, and save to staging.
116
+ * Returns a complete FileAttachment or null on download failure.
117
+ * This is the shared DRY utility used by both adapters.
118
+ */
119
+ export async function downloadAndStageFile(url, filename, mimeType, authHeaders) {
120
+ let downloaded;
121
+ try {
122
+ downloaded = await downloadToBase64(url, authHeaders);
123
+ }
124
+ catch (err) {
125
+ console.error(`[uploads] failed to download file ${filename} from ${url}: ${err.message}`);
126
+ return null;
127
+ }
128
+ const kind = classifyMimeType(downloaded.mediaType, filename);
129
+ const staging = saveToStagingDir(downloaded.base64, downloaded.mediaType, filename);
130
+ return {
131
+ base64: downloaded.base64,
132
+ mediaType: downloaded.mediaType,
133
+ kind,
134
+ uploadId: staging.uploadId,
135
+ filename: staging.filename,
136
+ stagingPath: staging.stagingPath,
137
+ };
138
+ }
139
+ /** Split text into chunks at word boundaries, respecting a character limit. */
140
+ export function splitText(text, limit) {
141
+ const chunks = [];
142
+ let remaining = text;
143
+ while (remaining.length > limit) {
144
+ // Find the last space before the limit
145
+ let splitAt = remaining.lastIndexOf(' ', limit);
146
+ if (splitAt <= 0) {
147
+ // No space found 鈥?split at limit
148
+ splitAt = limit;
149
+ }
150
+ chunks.push(remaining.slice(0, splitAt));
151
+ remaining = remaining.slice(splitAt).trimStart();
152
+ }
153
+ if (remaining.length > 0) {
154
+ chunks.push(remaining);
155
+ }
156
+ return chunks;
157
+ }
158
+ /**
159
+ * Wrap markdown tables in code blocks so they render with monospace alignment.
160
+ *
161
+ * Detects tables by finding separator rows (|---|---|), expands one line up
162
+ * for the header and down as long as lines start with |. Skips tables that
163
+ * are already inside code blocks.
164
+ */
165
+ export function wrapTablesInCodeBlocks(text) {
166
+ const lines = text.split('\n');
167
+ const separatorPattern = /^\|[\s\-:]+(\|[\s\-:]+)+\|?\s*$/;
168
+ let inCodeBlock = false;
169
+ // First pass: identify which lines belong to tables
170
+ const tableLines = new Set();
171
+ for (let i = 0; i < lines.length; i++) {
172
+ if (lines[i].trimStart().startsWith('```')) {
173
+ inCodeBlock = !inCodeBlock;
174
+ continue;
175
+ }
176
+ if (inCodeBlock)
177
+ continue;
178
+ if (separatorPattern.test(lines[i])) {
179
+ // Mark the separator line
180
+ tableLines.add(i);
181
+ // Expand up: header row (one line before separator)
182
+ if (i > 0 && lines[i - 1].trimStart().startsWith('|')) {
183
+ tableLines.add(i - 1);
184
+ }
185
+ // Expand down: data rows after separator
186
+ for (let j = i + 1; j < lines.length; j++) {
187
+ if (lines[j].trimStart().startsWith('|')) {
188
+ tableLines.add(j);
189
+ }
190
+ else {
191
+ break;
192
+ }
193
+ }
194
+ }
195
+ }
196
+ if (tableLines.size === 0)
197
+ return text;
198
+ // Second pass: wrap contiguous table regions in code blocks
199
+ const result = [];
200
+ let inTable = false;
201
+ for (let i = 0; i < lines.length; i++) {
202
+ if (tableLines.has(i)) {
203
+ if (!inTable) {
204
+ result.push('```');
205
+ inTable = true;
206
+ }
207
+ result.push(lines[i]);
208
+ }
209
+ else {
210
+ if (inTable) {
211
+ result.push('```');
212
+ inTable = false;
213
+ }
214
+ result.push(lines[i]);
215
+ }
216
+ }
217
+ if (inTable) {
218
+ result.push('```');
219
+ }
220
+ return result.join('\n');
221
+ }
222
+ /**
223
+ * Convert standard Markdown to Slack mrkdwn format.
224
+ *
225
+ * Handles: bold, italic, strikethrough, links, headers, tables (wrapped in code blocks).
226
+ */
227
+ export function markdownToSlackMrkdwn(text) {
228
+ // Wrap tables in code blocks before converting
229
+ text = wrapTablesInCodeBlocks(text);
230
+ // Process line by line to handle headers and preserve code blocks
231
+ const lines = text.split('\n');
232
+ let inCodeBlock = false;
233
+ const result = [];
234
+ for (const line of lines) {
235
+ // Toggle code block state
236
+ if (line.trimStart().startsWith('```')) {
237
+ inCodeBlock = !inCodeBlock;
238
+ result.push(line);
239
+ continue;
240
+ }
241
+ // Don't transform inside code blocks
242
+ if (inCodeBlock) {
243
+ result.push(line);
244
+ continue;
245
+ }
246
+ let converted = line;
247
+ // Headers 鈫?bold (Slack has no header syntax)
248
+ converted = converted.replace(/^(#{1,6})\s+(.+)$/, (_m, _hashes, content) => `**${content}**`);
249
+ // Bold+italic: ***text*** 鈫?placeholder (must come before bold and italic)
250
+ // Bold: **text** 鈫?placeholder to protect from italic pass
251
+ const boldSlots = [];
252
+ converted = converted.replace(/\*\*\*(.+?)\*\*\*/g, (_m, content) => {
253
+ boldSlots.push(`_${content}_`);
254
+ return `\x01BOLD${boldSlots.length - 1}\x01`;
255
+ });
256
+ converted = converted.replace(/\*\*(.+?)\*\*/g, (_m, content) => {
257
+ boldSlots.push(content);
258
+ return `\x01BOLD${boldSlots.length - 1}\x01`;
259
+ });
260
+ // Italic: *text* 鈫?_text_ (now safe 鈥?bold markers are placeholders)
261
+ converted = converted.replace(/\*([^*]+?)\*/g, '_$1_');
262
+ // Restore bold placeholders as Slack bold *text*
263
+ converted = converted.replace(/\x01BOLD(\d+)\x01/g, (_m, idx) => `*${boldSlots[parseInt(idx, 10)]}*`);
264
+ // Strikethrough: ~~text~~ 鈫?~text~
265
+ converted = converted.replace(/~~(.+?)~~/g, '~$1~');
266
+ // Links: [text](url) 鈫?text (url) 鈥?Slack auto-links bare URLs
267
+ converted = converted.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1 ($2)');
268
+ result.push(converted);
269
+ }
270
+ return result.join('\n');
271
+ }
272
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "alaska-ai",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "AI bridge CLI for running coding agents from chat platforms",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "bin": {
15
+ "alaska-ai": "dist/cli.js"
16
+ },
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.cli.json",
19
+ "build:web": "tsc -b && vite build",
20
+ "dev:web": "vite",
21
+ "preview:web": "vite preview",
22
+ "start": "node dist/cli.js start",
23
+ "check:pack": "npm pack --dry-run --cache .npm-cache",
24
+ "prepublishOnly": "npm run build && npm run check:pack"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "engines": {
30
+ "node": ">=18"
31
+ },
32
+ "license": "UNLICENSED",
33
+ "dependencies": {
34
+ "@clack/prompts": "^1.0.1",
35
+ "@modelcontextprotocol/sdk": "^1.27.1",
36
+ "@slack/bolt": "^4.6.0",
37
+ "better-sqlite3": "^12.6.2",
38
+ "cron-parser": "^5.5.0",
39
+ "picocolors": "^1.1.1",
40
+ "solid-js": "^1.9.10",
41
+ "zod": "^4.3.6"
42
+ },
43
+ "devDependencies": {
44
+ "@types/better-sqlite3": "^7.6.13",
45
+ "@types/node": "^25.3.2",
46
+ "typescript": "~5.9.3",
47
+ "vite": "^7.3.1",
48
+ "vite-plugin-solid": "^2.11.10"
49
+ }
50
+ }