dmux 5.9.0 → 5.11.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/README.ja.md +1 -1
- package/README.md +5 -2
- package/dist/DmuxApp.d.ts.map +1 -1
- package/dist/DmuxApp.js +32 -6
- package/dist/DmuxApp.js.map +1 -1
- package/dist/actions/implementations/renameAction.d.ts.map +1 -1
- package/dist/actions/implementations/renameAction.js +11 -2
- package/dist/actions/implementations/renameAction.js.map +1 -1
- package/dist/components/panes/MergePane.d.ts.map +1 -1
- package/dist/components/panes/MergePane.js +3 -22
- package/dist/components/panes/MergePane.js.map +1 -1
- package/dist/components/panes/PaneCard.d.ts.map +1 -1
- package/dist/components/panes/PaneCard.js +13 -5
- package/dist/components/panes/PaneCard.js.map +1 -1
- package/dist/components/popups/inferenceSetupPopup.d.ts +21 -0
- package/dist/components/popups/inferenceSetupPopup.d.ts.map +1 -0
- package/dist/components/popups/inferenceSetupPopup.js +939 -0
- package/dist/components/popups/inferenceSetupPopup.js.map +1 -0
- package/dist/components/popups/kebabMenuPopup.d.ts +7 -0
- package/dist/components/popups/kebabMenuPopup.d.ts.map +1 -1
- package/dist/components/popups/kebabMenuPopup.js +48 -4
- package/dist/components/popups/kebabMenuPopup.js.map +1 -1
- package/dist/components/popups/settingsPopup.js +4 -0
- package/dist/components/popups/settingsPopup.js.map +1 -1
- package/dist/dashboard.js +2 -2
- package/dist/hooks/useAgentStatus.d.ts.map +1 -1
- package/dist/hooks/useAgentStatus.js +9 -2
- package/dist/hooks/useAgentStatus.js.map +1 -1
- package/dist/hooks/useInputHandling.d.ts +3 -1
- package/dist/hooks/useInputHandling.d.ts.map +1 -1
- package/dist/hooks/useInputHandling.js +30 -0
- package/dist/hooks/useInputHandling.js.map +1 -1
- package/dist/hooks/usePaneLoading.d.ts +8 -5
- package/dist/hooks/usePaneLoading.d.ts.map +1 -1
- package/dist/hooks/usePaneLoading.js +115 -68
- package/dist/hooks/usePaneLoading.js.map +1 -1
- package/dist/hooks/usePaneSync.d.ts +4 -7
- package/dist/hooks/usePaneSync.d.ts.map +1 -1
- package/dist/hooks/usePaneSync.js +12 -30
- package/dist/hooks/usePaneSync.js.map +1 -1
- package/dist/hooks/usePanes.d.ts.map +1 -1
- package/dist/hooks/usePanes.js +69 -30
- package/dist/hooks/usePanes.js.map +1 -1
- package/dist/hooks/useSidebarMouse.d.ts +24 -0
- package/dist/hooks/useSidebarMouse.d.ts.map +1 -0
- package/dist/hooks/useSidebarMouse.js +50 -0
- package/dist/hooks/useSidebarMouse.js.map +1 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +2 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +2 -0
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/index.js +25 -2
- package/dist/index.js.map +1 -1
- package/dist/services/CodexAppServerClient.d.ts +58 -0
- package/dist/services/CodexAppServerClient.d.ts.map +1 -0
- package/dist/services/CodexAppServerClient.js +263 -0
- package/dist/services/CodexAppServerClient.js.map +1 -0
- package/dist/services/GrokBuildClient.d.ts +17 -0
- package/dist/services/GrokBuildClient.d.ts.map +1 -0
- package/dist/services/GrokBuildClient.js +150 -0
- package/dist/services/GrokBuildClient.js.map +1 -0
- package/dist/services/InferenceService.d.ts +22 -0
- package/dist/services/InferenceService.d.ts.map +1 -0
- package/dist/services/InferenceService.js +342 -0
- package/dist/services/InferenceService.js.map +1 -0
- package/dist/services/PaneAnalyzer.d.ts +1 -16
- package/dist/services/PaneAnalyzer.d.ts.map +1 -1
- package/dist/services/PaneAnalyzer.js +17 -101
- package/dist/services/PaneAnalyzer.js.map +1 -1
- package/dist/services/PaneWorkerManager.d.ts +1 -1
- package/dist/services/PaneWorkerManager.d.ts.map +1 -1
- package/dist/services/PaneWorkerManager.js +9 -5
- package/dist/services/PaneWorkerManager.js.map +1 -1
- package/dist/services/PopupManager.d.ts +6 -1
- package/dist/services/PopupManager.d.ts.map +1 -1
- package/dist/services/PopupManager.js +30 -0
- package/dist/services/PopupManager.js.map +1 -1
- package/dist/services/StatusDetector.d.ts.map +1 -1
- package/dist/services/StatusDetector.js +15 -8
- package/dist/services/StatusDetector.js.map +1 -1
- package/dist/services/TerminalPaneNamingService.d.ts +44 -0
- package/dist/services/TerminalPaneNamingService.d.ts.map +1 -0
- package/dist/services/TerminalPaneNamingService.js +273 -0
- package/dist/services/TerminalPaneNamingService.js.map +1 -0
- package/dist/services/TmuxService.d.ts +5 -0
- package/dist/services/TmuxService.d.ts.map +1 -1
- package/dist/services/TmuxService.js +10 -3
- package/dist/services/TmuxService.js.map +1 -1
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/agentLaunch.d.ts +3 -2
- package/dist/utils/agentLaunch.d.ts.map +1 -1
- package/dist/utils/agentLaunch.js +9 -4
- package/dist/utils/agentLaunch.js.map +1 -1
- package/dist/utils/aiMerge.d.ts +4 -2
- package/dist/utils/aiMerge.d.ts.map +1 -1
- package/dist/utils/aiMerge.js +14 -59
- package/dist/utils/aiMerge.js.map +1 -1
- package/dist/utils/envKeySetup.d.ts +10 -0
- package/dist/utils/envKeySetup.d.ts.map +1 -0
- package/dist/utils/envKeySetup.js +58 -0
- package/dist/utils/envKeySetup.js.map +1 -0
- package/dist/utils/generated-agents-doc.d.ts +1 -1
- package/dist/utils/generated-agents-doc.js +1 -1
- package/dist/utils/inferenceProviders.d.ts +34 -0
- package/dist/utils/inferenceProviders.d.ts.map +1 -0
- package/dist/utils/inferenceProviders.js +265 -0
- package/dist/utils/inferenceProviders.js.map +1 -0
- package/dist/utils/inferenceSetup.d.ts +19 -0
- package/dist/utils/inferenceSetup.d.ts.map +1 -0
- package/dist/utils/inferenceSetup.js +37 -0
- package/dist/utils/inferenceSetup.js.map +1 -0
- package/dist/utils/inferenceWizard.d.ts +61 -0
- package/dist/utils/inferenceWizard.d.ts.map +1 -0
- package/dist/utils/inferenceWizard.js +175 -0
- package/dist/utils/inferenceWizard.js.map +1 -0
- package/dist/utils/onboarding.d.ts +4 -2
- package/dist/utils/onboarding.d.ts.map +1 -1
- package/dist/utils/onboarding.js +26 -53
- package/dist/utils/onboarding.js.map +1 -1
- package/dist/utils/openRouterApiKeySetup.d.ts +7 -0
- package/dist/utils/openRouterApiKeySetup.d.ts.map +1 -1
- package/dist/utils/openRouterApiKeySetup.js +21 -0
- package/dist/utils/openRouterApiKeySetup.js.map +1 -1
- package/dist/utils/paneAgentTracking.d.ts +31 -0
- package/dist/utils/paneAgentTracking.d.ts.map +1 -0
- package/dist/utils/paneAgentTracking.js +261 -0
- package/dist/utils/paneAgentTracking.js.map +1 -0
- package/dist/utils/popup.d.ts.map +1 -1
- package/dist/utils/popup.js +17 -5
- package/dist/utils/popup.js.map +1 -1
- package/dist/utils/prSummary.d.ts +1 -1
- package/dist/utils/prSummary.js +3 -3
- package/dist/utils/prSummary.js.map +1 -1
- package/dist/utils/settingsManager.d.ts.map +1 -1
- package/dist/utils/settingsManager.js +43 -0
- package/dist/utils/settingsManager.js.map +1 -1
- package/dist/utils/shellPaneDetection.d.ts.map +1 -1
- package/dist/utils/shellPaneDetection.js +2 -0
- package/dist/utils/shellPaneDetection.js.map +1 -1
- package/dist/utils/sidebarClickMap.d.ts +28 -0
- package/dist/utils/sidebarClickMap.d.ts.map +1 -0
- package/dist/utils/sidebarClickMap.js +91 -0
- package/dist/utils/sidebarClickMap.js.map +1 -0
- package/dist/utils/sidebarMouse.d.ts +55 -0
- package/dist/utils/sidebarMouse.d.ts.map +1 -0
- package/dist/utils/sidebarMouse.js +101 -0
- package/dist/utils/sidebarMouse.js.map +1 -0
- package/dist/utils/sidebarScrollOffset.d.ts +9 -0
- package/dist/utils/sidebarScrollOffset.d.ts.map +1 -0
- package/dist/utils/sidebarScrollOffset.js +23 -0
- package/dist/utils/sidebarScrollOffset.js.map +1 -0
- package/dist/utils/slug.d.ts.map +1 -1
- package/dist/utils/slug.js +9 -41
- package/dist/utils/slug.js.map +1 -1
- package/native/macos/prebuilt/dmux-helper.app/Contents/MacOS/dmux-helper +0 -0
- package/package.json +3 -3
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { resolveShellConfigPath } from './openRouterApiKeySetup.js';
|
|
5
|
+
function quoteForPosix(value) {
|
|
6
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
7
|
+
}
|
|
8
|
+
function quoteForFish(value) {
|
|
9
|
+
return `"${value
|
|
10
|
+
.replace(/\\/g, '\\\\')
|
|
11
|
+
.replace(/"/g, '\\"')
|
|
12
|
+
.replace(/\$/g, '\\$')
|
|
13
|
+
.replace(/`/g, '\\`')}"`;
|
|
14
|
+
}
|
|
15
|
+
function escapeRegex(value) {
|
|
16
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
17
|
+
}
|
|
18
|
+
export function buildEnvironmentExportLine(envKey, value, shellPath) {
|
|
19
|
+
if (path.basename(shellPath || '').toLowerCase().includes('fish')) {
|
|
20
|
+
return `set -gx ${envKey} ${quoteForFish(value.trim())}`;
|
|
21
|
+
}
|
|
22
|
+
return `export ${envKey}=${quoteForPosix(value.trim())}`;
|
|
23
|
+
}
|
|
24
|
+
export function upsertEnvironmentKeyBlock(existingContent, envKey, exportLine) {
|
|
25
|
+
const normalized = existingContent.replace(/\r\n/g, '\n');
|
|
26
|
+
const start = `# >>> dmux inference ${envKey} >>>`;
|
|
27
|
+
const end = `# <<< dmux inference ${envKey} <<<`;
|
|
28
|
+
const block = `${start}\n${exportLine}\n${end}`;
|
|
29
|
+
const pattern = new RegExp(`${escapeRegex(start)}[\\s\\S]*?${escapeRegex(end)}\\n?`, 'm');
|
|
30
|
+
if (pattern.test(normalized)) {
|
|
31
|
+
const replaced = normalized.replace(pattern, `${block}\n`);
|
|
32
|
+
return replaced.endsWith('\n') ? replaced : `${replaced}\n`;
|
|
33
|
+
}
|
|
34
|
+
const prefix = normalized
|
|
35
|
+
? `${normalized.endsWith('\n') ? normalized : `${normalized}\n`}\n`
|
|
36
|
+
: '';
|
|
37
|
+
return `${prefix}${block}\n`;
|
|
38
|
+
}
|
|
39
|
+
export async function persistEnvironmentKeyToShell(envKey, value, options) {
|
|
40
|
+
const homeDir = options?.homeDir || process.env.HOME || os.homedir();
|
|
41
|
+
if (!homeDir)
|
|
42
|
+
throw new Error('Unable to determine HOME directory');
|
|
43
|
+
const shellPath = options?.shellPath || process.env.SHELL;
|
|
44
|
+
const shellConfigPath = await resolveShellConfigPath(shellPath, homeDir);
|
|
45
|
+
let existingContent = '';
|
|
46
|
+
try {
|
|
47
|
+
existingContent = await fs.readFile(shellConfigPath, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// The selected shell startup file does not exist yet.
|
|
51
|
+
}
|
|
52
|
+
const exportLine = buildEnvironmentExportLine(envKey, value, shellPath);
|
|
53
|
+
const updated = upsertEnvironmentKeyBlock(existingContent, envKey, exportLine);
|
|
54
|
+
await fs.mkdir(path.dirname(shellConfigPath), { recursive: true });
|
|
55
|
+
await fs.writeFile(shellConfigPath, updated, 'utf-8');
|
|
56
|
+
return { shellConfigPath, exportLine };
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=envKeySetup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envKeySetup.js","sourceRoot":"","sources":["../../src/utils/envKeySetup.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
* Auto-generated AGENTS.md content
|
|
3
3
|
* DO NOT EDIT MANUALLY - run 'pnpm generate:hooks-docs' to regenerate
|
|
4
4
|
*/
|
|
5
|
-
export declare const AGENTS_MD = "# dmux Hooks System - Agent Reference\n\n**Auto-generated documentation for AI agents**\n\nThis document contains everything an AI agent needs to create, modify, and understand dmux hooks. It is automatically generated from the dmux source code and embedded in the binary.\n\n## What You're Working On\n\nYou are editing hooks for **dmux**, a tmux pane manager that creates AI-powered development workflows. Each pane runs in its own git worktree with an AI agent.\n\n## Your Goal\n\nCreate executable bash scripts in `.dmux-hooks/` that run automatically at key lifecycle events.\n\n## Quick Start\n\n1. **Create a hook file**: `touch .dmux-hooks/worktree_created`\n2. **Make it executable**: `chmod +x .dmux-hooks/worktree_created`\n3. **Add shebang**: Start with `#!/bin/bash`\n4. **Use environment variables**: Access `$DMUX_ROOT`, `$DMUX_WORKTREE_PATH`, etc.\n5. **Test it**: Set env vars manually and run the script\n\n## Hook Execution Model\n\n- **Mostly non-blocking**: Most hooks run in background (detached processes)\n- **Bootstrap-gated**: `worktree_created` blocks agent launch so setup can finish first, with no fixed timeout\n- **Live bootstrap output**: During `worktree_created`, stdout/stderr is streamed into the new pane's setup UI\n- **Failure behavior**: Background hook errors are logged; gated hooks can abort the operation\n- **Environment-based**: All context passed via environment variables\n- **Version controlled**: Hooks in `.dmux-hooks/` are shared with team\n- **Priority resolution**: `.dmux-hooks/` \u2192 `.dmux/hooks/` \u2192 `~/.dmux/hooks/`\n\n## Available Hooks\n\n### Pane Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `before_pane_create` | Before pane creation | Validation, notifications, pre-flight checks |\n| `pane_created` | After pane, before worktree | Configure tmux settings, prepare environment |\n| `worktree_created` | After worktree creation, before agent launch | Install deps, copy configs, setup git |\n| `before_pane_close` | Before closing | Save state, backup uncommitted work |\n| `pane_closed` | After closed | Cleanup resources, analytics, notifications |\n\n### Worktree Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `before_worktree_remove` | Before worktree removal | Archive worktree, save artifacts |\n| `worktree_removed` | After worktree removed | Cleanup external references |\n\n### Merge Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `pre_merge` | Before merge operation | Run final tests, create backups |\n| `post_merge` | After successful merge | Deploy, close issues, notify team |\n\n### Interactive Hooks (with HTTP callbacks)\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `run_test` | When tests triggered | Run test suite, report status via HTTP |\n| `run_dev` | When dev server triggered | Start dev server, create tunnel, report URL |\n\n\n## Environment Variables\n\n### Always Available\n```bash\nDMUX_ROOT=\"/path/to/project\" # Project root directory\nDMUX_SERVER_PORT=\"3142\" # HTTP server port\n```\n\n### Pane Context (most hooks)\n```bash\nDMUX_PANE_ID=\"dmux-1234567890\" # dmux pane identifier\nDMUX_SLUG=\"fix-auth-bug\" # Branch/worktree name\nDMUX_PROMPT=\"Fix authentication bug\" # User's prompt\nDMUX_AGENT=\"claude\" # Agent type (registry id, e.g. claude, codex, opencode)\nDMUX_TMUX_PANE_ID=\"%38\" # tmux pane ID\n```\n\n### Worktree Context\n```bash\nDMUX_WORKTREE_PATH=\"/path/.dmux/worktrees/fix-auth-bug\"\nDMUX_BRANCH=\"fix-auth-bug\" # Same as slug\n```\n\n### Bootstrap Progress Context\n```bash\nDMUX_PROGRESS=\"1\" # Set when output is shown in the new pane setup UI\nDMUX_STATUS_PREFIX=\"DMUX_STATUS:\" # Prefix for clean status messages\n```\n\n`worktree_created` can emit progress while it runs. Any stdout/stderr line is shown in the setup UI; lines prefixed with `$DMUX_STATUS_PREFIX` are displayed without the prefix.\n\n```bash\nstatus() {\n if [ \"${DMUX_PROGRESS:-0}\" = \"1\" ]; then\n echo \"${DMUX_STATUS_PREFIX:-DMUX_STATUS:} $*\"\n else\n echo \"[Hook] $*\"\n fi\n}\n```\n\n### Merge Context\n```bash\nDMUX_TARGET_BRANCH=\"main\" # Branch being merged into\n```\n\n## HTTP Callback API\n\nInteractive hooks (`run_test` and `run_dev`) can update dmux UI via HTTP.\n\n### Update Test Status\n```bash\ncurl -X PUT \"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\", \"output\": \"optional test output\"}'\n\n# Status values: \"running\" | \"passed\" | \"failed\"\n```\n\n### Update Dev Server\n```bash\ncurl -X PUT \"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\", \"url\": \"http://localhost:3000\"}'\n\n# Status values: \"running\" | \"stopped\"\n# url: Can be localhost or tunnel URL (ngrok, cloudflared, etc.)\n```\n\n## Common Patterns\n\n### Pattern 1: Install Dependencies\n```bash\n#!/bin/bash\n# .dmux-hooks/worktree_created\n\ncd \"$DMUX_WORKTREE_PATH\"\n\nstatus() {\n if [ \"${DMUX_PROGRESS:-0}\" = \"1\" ]; then\n echo \"${DMUX_STATUS_PREFIX:-DMUX_STATUS:} $*\"\n else\n echo \"[Hook] $*\"\n fi\n}\n\nif [ -f \"pnpm-lock.yaml\" ]; then\n status \"Installing dependencies with pnpm\"\n pnpm install --prefer-offline\nelif [ -f \"package-lock.json\" ]; then\n status \"Installing dependencies with npm\"\n npm install\nelif [ -f \"yarn.lock\" ]; then\n status \"Installing dependencies with yarn\"\n yarn install\nelif [ -f \"Gemfile\" ]; then\n status \"Installing gems\"\n bundle install\nelif [ -f \"requirements.txt\" ]; then\n status \"Installing Python dependencies\"\n pip install -r requirements.txt\nelif [ -f \"Cargo.toml\" ]; then\n status \"Building Rust project\"\n cargo build\nfi\n```\n\n### Pattern 2: Copy Configuration\n```bash\n#!/bin/bash\n# .dmux-hooks/worktree_created\n\n# Copy environment file\nif [ -f \"$DMUX_ROOT/.env.local\" ]; then\n cp \"$DMUX_ROOT/.env.local\" \"$DMUX_WORKTREE_PATH/.env.local\"\nfi\n\n# Copy other config files\nfor file in .env.development .npmrc .yarnrc; do\n if [ -f \"$DMUX_ROOT/$file\" ]; then\n cp \"$DMUX_ROOT/$file\" \"$DMUX_WORKTREE_PATH/$file\"\n fi\ndone\n```\n\n### Pattern 3: Run Tests with Status Updates\n```bash\n#!/bin/bash\n# .dmux-hooks/run_test\n\nset -e\ncd \"$DMUX_WORKTREE_PATH\"\nAPI=\"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test\"\n\n# Update: starting\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\"}' > /dev/null\n\n# Run tests and capture output\nOUTPUT_FILE=\"/tmp/dmux-test-$DMUX_PANE_ID.txt\"\nif pnpm test > \"$OUTPUT_FILE\" 2>&1; then\n STATUS=\"passed\"\nelse\n STATUS=\"failed\"\nfi\n\n# Get output (truncate if too long)\nOUTPUT=$(head -c 5000 \"$OUTPUT_FILE\")\n\n# Update: complete\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d \"$(jq -n --arg status \"$STATUS\" --arg output \"$OUTPUT\" '{status: $status, output: $output}')\" > /dev/null\n\nrm -f \"$OUTPUT_FILE\"\n```\n\n### Pattern 4: Dev Server with Tunnel\n```bash\n#!/bin/bash\n# .dmux-hooks/run_dev\n\nset -e\ncd \"$DMUX_WORKTREE_PATH\"\nAPI=\"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev\"\n\n# Start dev server in background\nLOG_FILE=\"/tmp/dmux-dev-$DMUX_PANE_ID.log\"\npnpm dev > \"$LOG_FILE\" 2>&1 &\nDEV_PID=$!\n\n# Wait for server to start\nsleep 5\n\n# Detect port from logs\nPORT=$(grep -oP 'localhost:Kd+' \"$LOG_FILE\" | head -1)\n[ -z \"$PORT\" ] && PORT=3000\n\n# Optional: Create tunnel with cloudflared\nif command -v cloudflared &> /dev/null; then\n TUNNEL=$(cloudflared tunnel --url \"http://localhost:$PORT\" 2>&1 | grep -oP 'https://[a-z0-9-]+.trycloudflare.com' | head -1)\n URL=\"${TUNNEL:-http://localhost:$PORT}\"\nelse\n URL=\"http://localhost:$PORT\"\nfi\n\n# Report status\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d \"{\"status\": \"running\", \"url\": \"$URL\"}\" > /dev/null\n\necho \"[Hook] Dev server running at $URL (PID: $DEV_PID)\"\n```\n\n### Pattern 5: Post-Merge Deployment\n```bash\n#!/bin/bash\n# .dmux-hooks/post_merge\n\nset -e\ncd \"$DMUX_ROOT\"\n\n# Only deploy from main/master\nif [ \"$DMUX_TARGET_BRANCH\" != \"main\" ] && [ \"$DMUX_TARGET_BRANCH\" != \"master\" ]; then\n exit 0\nfi\n\n# Push to remote\ngit push origin \"$DMUX_TARGET_BRANCH\"\n\n# Trigger deployment (example: Vercel)\nif [ -n \"$VERCEL_TOKEN\" ]; then\n curl -s -X POST \"https://api.vercel.com/v1/deployments\" -H \"Authorization: Bearer $VERCEL_TOKEN\" -H \"Content-Type: application/json\" -d '{\"name\": \"my-project\"}' > /dev/null\nfi\n\n# Close GitHub issue if prompt contains #123\nISSUE=$(echo \"$DMUX_PROMPT\" | grep -oP '#Kd+' | head -1)\nif [ -n \"$ISSUE\" ] && command -v gh &> /dev/null; then\n gh issue close \"$ISSUE\" -c \"Resolved in $DMUX_SLUG, merged to $DMUX_TARGET_BRANCH\" 2>/dev/null || true\nfi\n```\n\n## Best Practices\n\n1. **Always start with shebang**: `#!/bin/bash`\n2. **Set error handling**: `set -e` (exit on error)\n3. **Make executable**: `chmod +x .dmux-hooks/hook_name`\n4. **Background long operations**: Append `&` to avoid blocking\n5. **Check for required tools**: `command -v tool &> /dev/null`\n6. **Log for debugging**: `echo \"[Hook] message\" >> \"$DMUX_ROOT/.dmux/hooks.log\"`\n7. **Handle missing vars gracefully**: `[ -z \"$VAR\" ] && exit 0`\n8. **Use silent curl**: `curl -s` to avoid noise in logs\n9. **Clean up temp files**: Remove files in `/tmp/`\n10. **Test before committing**: Run hooks manually with mock env vars\n\n## Testing Hooks\n\n### Manual Testing\n```bash\n# 1. Set environment variables\nexport DMUX_ROOT=\"$(pwd)\"\nexport DMUX_PANE_ID=\"test-pane\"\nexport DMUX_SLUG=\"test-branch\"\nexport DMUX_WORKTREE_PATH=\"$(pwd)\"\nexport DMUX_SERVER_PORT=\"3142\"\nexport DMUX_AGENT=\"claude\"\nexport DMUX_PROMPT=\"Test prompt\"\n\n# 2. Run hook directly\n./.dmux-hooks/worktree_created\n\n# 3. Check exit code\necho $? # Should be 0 for success\n```\n\n### Syntax Check\n```bash\n# Check for syntax errors without running\nbash -n ./.dmux-hooks/worktree_created\n```\n\n### Shellcheck (if available)\n```bash\nshellcheck ./.dmux-hooks/worktree_created\n```\n\n## Project Context Analysis\n\nBefore creating hooks, analyze these files in the project:\n\n### Package Manager Detection\n```bash\n# Check which package manager is used\nif [ -f \"pnpm-lock.yaml\" ]; then\n # Use: pnpm install, pnpm test, pnpm dev\nelif [ -f \"package-lock.json\" ]; then\n # Use: npm install, npm test, npm run dev\nelif [ -f \"yarn.lock\" ]; then\n # Use: yarn install, yarn test, yarn dev\nfi\n```\n\n### Test Command Discovery\n```bash\n# Read package.json to find test command\ncat package.json | grep '\"test\"'\n# Or with jq:\njq -r '.scripts.test' package.json\n```\n\n### Dev Command Discovery\n```bash\n# Read package.json to find dev command\ncat package.json | grep '\"dev\"'\n# Or with jq:\njq -r '.scripts.dev' package.json\n```\n\n### Environment Variables\n```bash\n# Check for .env files to copy\nls -la | grep '.env'\n```\n\n### Build System\n```bash\n# Detect build system\nif [ -f \"vite.config.ts\" ]; then\n # Vite project\nelif [ -f \"next.config.js\" ]; then\n # Next.js project\nelif [ -f \"nuxt.config.ts\" ]; then\n # Nuxt project\nfi\n```\n\n## Common Mistakes to Avoid\n\n\u274C **Blocking operations**: `sleep 60` (blocks dmux)\n\u2705 **Background long tasks**: `slow_operation &`\n\n\u274C **Hardcoded paths**: `/Users/me/project`\n\u2705 **Use variables**: `\"$DMUX_ROOT\"`\n\n\u274C **Assuming tools exist**: `pnpm install`\n\u2705 **Check first**: `command -v pnpm && pnpm install`\n\n\u274C **No error handling**: Script fails silently\n\u2705 **Set error mode**: `set -e` or check exit codes\n\n\u274C **Forgetting executable bit**: Hook won't run\n\u2705 **Make executable**: `chmod +x`\n\n\u274C **Noisy output**: Clutters dmux logs\n\u2705 **Silent operations**: `curl -s`, `> /dev/null 2>&1`\n\n\u274C **Not testing**: Deploy and hope\n\u2705 **Test manually**: Run with mock env vars first\n\n## Debugging\n\nIf a hook isn't working:\n\n1. **Check if file exists**: `ls -la .dmux-hooks/`\n2. **Check permissions**: Should show `x` in `rwxr-xr-x`\n3. **Check syntax**: `bash -n .dmux-hooks/hook_name`\n4. **Test manually**: Set env vars and run\n5. **Check logs**: dmux logs to stderr with `[Hooks]` prefix\n6. **Simplify**: Remove complex parts, test basic version\n7. **Check tool availability**: `command -v required_tool`\n\n### Debug Mode\n```bash\n#!/bin/bash\n# Add to top of hook for debugging\nset -x # Print each command before executing\nset -e # Exit on error\n\n# Your hook logic here\n```\n\n## Summary Checklist\n\nWhen creating a new hook:\n\n- [ ] Create file in `.dmux-hooks/`\n- [ ] Add shebang: `#!/bin/bash`\n- [ ] Make executable: `chmod +x`\n- [ ] Add `set -e` for error handling\n- [ ] Use environment variables (never hardcode paths)\n- [ ] Keep blocking hooks chatty with status output\n- [ ] Background long operations with `&` only when the hook does not gate the operation\n- [ ] Check for required tools before using\n- [ ] Test manually with mock env vars\n- [ ] Add comments explaining what it does\n- [ ] Commit to version control\n\n## Getting Help\n\n- **Full documentation**: See `HOOKS.md` in project root\n- **Claude-specific tips**: See `CLAUDE.md` in `.dmux-hooks/`\n- **Examples**: Check `.dmux-hooks/examples/` directory\n- **dmux API**: See `API.md` for REST endpoints\n\n---\n\n*This documentation was auto-generated from dmux source code.*\n*Version: 2026-05-25*\n";
|
|
5
|
+
export declare const AGENTS_MD = "# dmux Hooks System - Agent Reference\n\n**Auto-generated documentation for AI agents**\n\nThis document contains everything an AI agent needs to create, modify, and understand dmux hooks. It is automatically generated from the dmux source code and embedded in the binary.\n\n## What You're Working On\n\nYou are editing hooks for **dmux**, a tmux pane manager that creates AI-powered development workflows. Each pane runs in its own git worktree with an AI agent.\n\n## Your Goal\n\nCreate executable bash scripts in `.dmux-hooks/` that run automatically at key lifecycle events.\n\n## Quick Start\n\n1. **Create a hook file**: `touch .dmux-hooks/worktree_created`\n2. **Make it executable**: `chmod +x .dmux-hooks/worktree_created`\n3. **Add shebang**: Start with `#!/bin/bash`\n4. **Use environment variables**: Access `$DMUX_ROOT`, `$DMUX_WORKTREE_PATH`, etc.\n5. **Test it**: Set env vars manually and run the script\n\n## Hook Execution Model\n\n- **Mostly non-blocking**: Most hooks run in background (detached processes)\n- **Bootstrap-gated**: `worktree_created` blocks agent launch so setup can finish first, with no fixed timeout\n- **Live bootstrap output**: During `worktree_created`, stdout/stderr is streamed into the new pane's setup UI\n- **Failure behavior**: Background hook errors are logged; gated hooks can abort the operation\n- **Environment-based**: All context passed via environment variables\n- **Version controlled**: Hooks in `.dmux-hooks/` are shared with team\n- **Priority resolution**: `.dmux-hooks/` \u2192 `.dmux/hooks/` \u2192 `~/.dmux/hooks/`\n\n## Available Hooks\n\n### Pane Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `before_pane_create` | Before pane creation | Validation, notifications, pre-flight checks |\n| `pane_created` | After pane, before worktree | Configure tmux settings, prepare environment |\n| `worktree_created` | After worktree creation, before agent launch | Install deps, copy configs, setup git |\n| `before_pane_close` | Before closing | Save state, backup uncommitted work |\n| `pane_closed` | After closed | Cleanup resources, analytics, notifications |\n\n### Worktree Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `before_worktree_remove` | Before worktree removal | Archive worktree, save artifacts |\n| `worktree_removed` | After worktree removed | Cleanup external references |\n\n### Merge Lifecycle Hooks\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `pre_merge` | Before merge operation | Run final tests, create backups |\n| `post_merge` | After successful merge | Deploy, close issues, notify team |\n\n### Interactive Hooks (with HTTP callbacks)\n\n| Hook | When | Common Use Cases |\n|------|------|------------------|\n| `run_test` | When tests triggered | Run test suite, report status via HTTP |\n| `run_dev` | When dev server triggered | Start dev server, create tunnel, report URL |\n\n\n## Environment Variables\n\n### Always Available\n```bash\nDMUX_ROOT=\"/path/to/project\" # Project root directory\nDMUX_SERVER_PORT=\"3142\" # HTTP server port\n```\n\n### Pane Context (most hooks)\n```bash\nDMUX_PANE_ID=\"dmux-1234567890\" # dmux pane identifier\nDMUX_SLUG=\"fix-auth-bug\" # Branch/worktree name\nDMUX_PROMPT=\"Fix authentication bug\" # User's prompt\nDMUX_AGENT=\"claude\" # Agent type (registry id, e.g. claude, codex, opencode)\nDMUX_TMUX_PANE_ID=\"%38\" # tmux pane ID\n```\n\n### Worktree Context\n```bash\nDMUX_WORKTREE_PATH=\"/path/.dmux/worktrees/fix-auth-bug\"\nDMUX_BRANCH=\"fix-auth-bug\" # Same as slug\n```\n\n### Bootstrap Progress Context\n```bash\nDMUX_PROGRESS=\"1\" # Set when output is shown in the new pane setup UI\nDMUX_STATUS_PREFIX=\"DMUX_STATUS:\" # Prefix for clean status messages\n```\n\n`worktree_created` can emit progress while it runs. Any stdout/stderr line is shown in the setup UI; lines prefixed with `$DMUX_STATUS_PREFIX` are displayed without the prefix.\n\n```bash\nstatus() {\n if [ \"${DMUX_PROGRESS:-0}\" = \"1\" ]; then\n echo \"${DMUX_STATUS_PREFIX:-DMUX_STATUS:} $*\"\n else\n echo \"[Hook] $*\"\n fi\n}\n```\n\n### Merge Context\n```bash\nDMUX_TARGET_BRANCH=\"main\" # Branch being merged into\n```\n\n## HTTP Callback API\n\nInteractive hooks (`run_test` and `run_dev`) can update dmux UI via HTTP.\n\n### Update Test Status\n```bash\ncurl -X PUT \"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\", \"output\": \"optional test output\"}'\n\n# Status values: \"running\" | \"passed\" | \"failed\"\n```\n\n### Update Dev Server\n```bash\ncurl -X PUT \"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\", \"url\": \"http://localhost:3000\"}'\n\n# Status values: \"running\" | \"stopped\"\n# url: Can be localhost or tunnel URL (ngrok, cloudflared, etc.)\n```\n\n## Common Patterns\n\n### Pattern 1: Install Dependencies\n```bash\n#!/bin/bash\n# .dmux-hooks/worktree_created\n\ncd \"$DMUX_WORKTREE_PATH\"\n\nstatus() {\n if [ \"${DMUX_PROGRESS:-0}\" = \"1\" ]; then\n echo \"${DMUX_STATUS_PREFIX:-DMUX_STATUS:} $*\"\n else\n echo \"[Hook] $*\"\n fi\n}\n\nif [ -f \"pnpm-lock.yaml\" ]; then\n status \"Installing dependencies with pnpm\"\n pnpm install --prefer-offline\nelif [ -f \"package-lock.json\" ]; then\n status \"Installing dependencies with npm\"\n npm install\nelif [ -f \"yarn.lock\" ]; then\n status \"Installing dependencies with yarn\"\n yarn install\nelif [ -f \"Gemfile\" ]; then\n status \"Installing gems\"\n bundle install\nelif [ -f \"requirements.txt\" ]; then\n status \"Installing Python dependencies\"\n pip install -r requirements.txt\nelif [ -f \"Cargo.toml\" ]; then\n status \"Building Rust project\"\n cargo build\nfi\n```\n\n### Pattern 2: Copy Configuration\n```bash\n#!/bin/bash\n# .dmux-hooks/worktree_created\n\n# Copy environment file\nif [ -f \"$DMUX_ROOT/.env.local\" ]; then\n cp \"$DMUX_ROOT/.env.local\" \"$DMUX_WORKTREE_PATH/.env.local\"\nfi\n\n# Copy other config files\nfor file in .env.development .npmrc .yarnrc; do\n if [ -f \"$DMUX_ROOT/$file\" ]; then\n cp \"$DMUX_ROOT/$file\" \"$DMUX_WORKTREE_PATH/$file\"\n fi\ndone\n```\n\n### Pattern 3: Run Tests with Status Updates\n```bash\n#!/bin/bash\n# .dmux-hooks/run_test\n\nset -e\ncd \"$DMUX_WORKTREE_PATH\"\nAPI=\"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/test\"\n\n# Update: starting\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d '{\"status\": \"running\"}' > /dev/null\n\n# Run tests and capture output\nOUTPUT_FILE=\"/tmp/dmux-test-$DMUX_PANE_ID.txt\"\nif pnpm test > \"$OUTPUT_FILE\" 2>&1; then\n STATUS=\"passed\"\nelse\n STATUS=\"failed\"\nfi\n\n# Get output (truncate if too long)\nOUTPUT=$(head -c 5000 \"$OUTPUT_FILE\")\n\n# Update: complete\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d \"$(jq -n --arg status \"$STATUS\" --arg output \"$OUTPUT\" '{status: $status, output: $output}')\" > /dev/null\n\nrm -f \"$OUTPUT_FILE\"\n```\n\n### Pattern 4: Dev Server with Tunnel\n```bash\n#!/bin/bash\n# .dmux-hooks/run_dev\n\nset -e\ncd \"$DMUX_WORKTREE_PATH\"\nAPI=\"http://localhost:$DMUX_SERVER_PORT/api/panes/$DMUX_PANE_ID/dev\"\n\n# Start dev server in background\nLOG_FILE=\"/tmp/dmux-dev-$DMUX_PANE_ID.log\"\npnpm dev > \"$LOG_FILE\" 2>&1 &\nDEV_PID=$!\n\n# Wait for server to start\nsleep 5\n\n# Detect port from logs\nPORT=$(grep -oP 'localhost:Kd+' \"$LOG_FILE\" | head -1)\n[ -z \"$PORT\" ] && PORT=3000\n\n# Optional: Create tunnel with cloudflared\nif command -v cloudflared &> /dev/null; then\n TUNNEL=$(cloudflared tunnel --url \"http://localhost:$PORT\" 2>&1 | grep -oP 'https://[a-z0-9-]+.trycloudflare.com' | head -1)\n URL=\"${TUNNEL:-http://localhost:$PORT}\"\nelse\n URL=\"http://localhost:$PORT\"\nfi\n\n# Report status\ncurl -s -X PUT \"$API\" -H \"Content-Type: application/json\" -d \"{\"status\": \"running\", \"url\": \"$URL\"}\" > /dev/null\n\necho \"[Hook] Dev server running at $URL (PID: $DEV_PID)\"\n```\n\n### Pattern 5: Post-Merge Deployment\n```bash\n#!/bin/bash\n# .dmux-hooks/post_merge\n\nset -e\ncd \"$DMUX_ROOT\"\n\n# Only deploy from main/master\nif [ \"$DMUX_TARGET_BRANCH\" != \"main\" ] && [ \"$DMUX_TARGET_BRANCH\" != \"master\" ]; then\n exit 0\nfi\n\n# Push to remote\ngit push origin \"$DMUX_TARGET_BRANCH\"\n\n# Trigger deployment (example: Vercel)\nif [ -n \"$VERCEL_TOKEN\" ]; then\n curl -s -X POST \"https://api.vercel.com/v1/deployments\" -H \"Authorization: Bearer $VERCEL_TOKEN\" -H \"Content-Type: application/json\" -d '{\"name\": \"my-project\"}' > /dev/null\nfi\n\n# Close GitHub issue if prompt contains #123\nISSUE=$(echo \"$DMUX_PROMPT\" | grep -oP '#Kd+' | head -1)\nif [ -n \"$ISSUE\" ] && command -v gh &> /dev/null; then\n gh issue close \"$ISSUE\" -c \"Resolved in $DMUX_SLUG, merged to $DMUX_TARGET_BRANCH\" 2>/dev/null || true\nfi\n```\n\n## Best Practices\n\n1. **Always start with shebang**: `#!/bin/bash`\n2. **Set error handling**: `set -e` (exit on error)\n3. **Make executable**: `chmod +x .dmux-hooks/hook_name`\n4. **Background long operations**: Append `&` to avoid blocking\n5. **Check for required tools**: `command -v tool &> /dev/null`\n6. **Log for debugging**: `echo \"[Hook] message\" >> \"$DMUX_ROOT/.dmux/hooks.log\"`\n7. **Handle missing vars gracefully**: `[ -z \"$VAR\" ] && exit 0`\n8. **Use silent curl**: `curl -s` to avoid noise in logs\n9. **Clean up temp files**: Remove files in `/tmp/`\n10. **Test before committing**: Run hooks manually with mock env vars\n\n## Testing Hooks\n\n### Manual Testing\n```bash\n# 1. Set environment variables\nexport DMUX_ROOT=\"$(pwd)\"\nexport DMUX_PANE_ID=\"test-pane\"\nexport DMUX_SLUG=\"test-branch\"\nexport DMUX_WORKTREE_PATH=\"$(pwd)\"\nexport DMUX_SERVER_PORT=\"3142\"\nexport DMUX_AGENT=\"claude\"\nexport DMUX_PROMPT=\"Test prompt\"\n\n# 2. Run hook directly\n./.dmux-hooks/worktree_created\n\n# 3. Check exit code\necho $? # Should be 0 for success\n```\n\n### Syntax Check\n```bash\n# Check for syntax errors without running\nbash -n ./.dmux-hooks/worktree_created\n```\n\n### Shellcheck (if available)\n```bash\nshellcheck ./.dmux-hooks/worktree_created\n```\n\n## Project Context Analysis\n\nBefore creating hooks, analyze these files in the project:\n\n### Package Manager Detection\n```bash\n# Check which package manager is used\nif [ -f \"pnpm-lock.yaml\" ]; then\n # Use: pnpm install, pnpm test, pnpm dev\nelif [ -f \"package-lock.json\" ]; then\n # Use: npm install, npm test, npm run dev\nelif [ -f \"yarn.lock\" ]; then\n # Use: yarn install, yarn test, yarn dev\nfi\n```\n\n### Test Command Discovery\n```bash\n# Read package.json to find test command\ncat package.json | grep '\"test\"'\n# Or with jq:\njq -r '.scripts.test' package.json\n```\n\n### Dev Command Discovery\n```bash\n# Read package.json to find dev command\ncat package.json | grep '\"dev\"'\n# Or with jq:\njq -r '.scripts.dev' package.json\n```\n\n### Environment Variables\n```bash\n# Check for .env files to copy\nls -la | grep '.env'\n```\n\n### Build System\n```bash\n# Detect build system\nif [ -f \"vite.config.ts\" ]; then\n # Vite project\nelif [ -f \"next.config.js\" ]; then\n # Next.js project\nelif [ -f \"nuxt.config.ts\" ]; then\n # Nuxt project\nfi\n```\n\n## Common Mistakes to Avoid\n\n\u274C **Blocking operations**: `sleep 60` (blocks dmux)\n\u2705 **Background long tasks**: `slow_operation &`\n\n\u274C **Hardcoded paths**: `/Users/me/project`\n\u2705 **Use variables**: `\"$DMUX_ROOT\"`\n\n\u274C **Assuming tools exist**: `pnpm install`\n\u2705 **Check first**: `command -v pnpm && pnpm install`\n\n\u274C **No error handling**: Script fails silently\n\u2705 **Set error mode**: `set -e` or check exit codes\n\n\u274C **Forgetting executable bit**: Hook won't run\n\u2705 **Make executable**: `chmod +x`\n\n\u274C **Noisy output**: Clutters dmux logs\n\u2705 **Silent operations**: `curl -s`, `> /dev/null 2>&1`\n\n\u274C **Not testing**: Deploy and hope\n\u2705 **Test manually**: Run with mock env vars first\n\n## Debugging\n\nIf a hook isn't working:\n\n1. **Check if file exists**: `ls -la .dmux-hooks/`\n2. **Check permissions**: Should show `x` in `rwxr-xr-x`\n3. **Check syntax**: `bash -n .dmux-hooks/hook_name`\n4. **Test manually**: Set env vars and run\n5. **Check logs**: dmux logs to stderr with `[Hooks]` prefix\n6. **Simplify**: Remove complex parts, test basic version\n7. **Check tool availability**: `command -v required_tool`\n\n### Debug Mode\n```bash\n#!/bin/bash\n# Add to top of hook for debugging\nset -x # Print each command before executing\nset -e # Exit on error\n\n# Your hook logic here\n```\n\n## Summary Checklist\n\nWhen creating a new hook:\n\n- [ ] Create file in `.dmux-hooks/`\n- [ ] Add shebang: `#!/bin/bash`\n- [ ] Make executable: `chmod +x`\n- [ ] Add `set -e` for error handling\n- [ ] Use environment variables (never hardcode paths)\n- [ ] Keep blocking hooks chatty with status output\n- [ ] Background long operations with `&` only when the hook does not gate the operation\n- [ ] Check for required tools before using\n- [ ] Test manually with mock env vars\n- [ ] Add comments explaining what it does\n- [ ] Commit to version control\n\n## Getting Help\n\n- **Full documentation**: See `HOOKS.md` in project root\n- **Claude-specific tips**: See `CLAUDE.md` in `.dmux-hooks/`\n- **Examples**: Check `.dmux-hooks/examples/` directory\n- **dmux API**: See `API.md` for REST endpoints\n\n---\n\n*This documentation was auto-generated from dmux source code.*\n*Version: 2026-08-15*\n";
|
|
6
6
|
//# sourceMappingURL=generated-agents-doc.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { InferenceTarget } from '../types.js';
|
|
2
|
+
export type InferenceProtocol = 'openai-compatible' | 'openai-responses' | 'anthropic' | 'cohere' | 'chatgpt' | 'grok-build';
|
|
3
|
+
export interface InferenceProviderDefinition {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
envKeys: string[];
|
|
8
|
+
baseUrl?: string;
|
|
9
|
+
protocol: InferenceProtocol;
|
|
10
|
+
modelDiscovery?: 'openai' | 'google' | 'cohere' | 'chatgpt' | 'grok-build';
|
|
11
|
+
maxTokensParam?: 'max_tokens' | 'max_completion_tokens';
|
|
12
|
+
custom?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface InferenceModel {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Providers with a stable text-generation API. Model ids intentionally do not
|
|
21
|
+
* live here: the setup flow asks each provider for its current catalog.
|
|
22
|
+
*/
|
|
23
|
+
export declare const INFERENCE_PROVIDERS: readonly InferenceProviderDefinition[];
|
|
24
|
+
export declare function getInferenceProvider(id: string): InferenceProviderDefinition | undefined;
|
|
25
|
+
export declare function resolveInferenceProvider(target: InferenceTarget): InferenceProviderDefinition | undefined;
|
|
26
|
+
export declare function getInferenceApiKey(provider: InferenceProviderDefinition): Promise<{
|
|
27
|
+
envKey: string;
|
|
28
|
+
apiKey: string;
|
|
29
|
+
} | null>;
|
|
30
|
+
export declare function hasInferenceApiKeySync(provider: InferenceProviderDefinition): boolean;
|
|
31
|
+
export declare function storeInferenceCredential(envKey: string, apiKey: string): Promise<void>;
|
|
32
|
+
export declare function isValidInferenceTarget(value: unknown): value is InferenceTarget;
|
|
33
|
+
export declare function describeInferenceTarget(target: InferenceTarget | null | undefined): string;
|
|
34
|
+
//# sourceMappingURL=inferenceProviders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inferenceProviders.d.ts","sourceRoot":"","sources":["../../src/utils/inferenceProviders.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,MAAM,iBAAiB,GACzB,mBAAmB,GACnB,kBAAkB,GAClB,WAAW,GACX,QAAQ,GACR,SAAS,GACT,YAAY,CAAC;AAEjB,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,cAAc,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,YAAY,CAAC;IAC3E,cAAc,CAAC,EAAE,YAAY,GAAG,uBAAuB,CAAC;IACxD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,2BAA2B,EAkK5D,CAAC;AAIX,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,2BAA2B,GAAG,SAAS,CAExF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,eAAe,GAAG,2BAA2B,GAAG,SAAS,CAwBzG;AAeD,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,2BAA2B,GACpC,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAapD;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,2BAA2B,GAAG,OAAO,CAErF;AAED,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB5F;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,eAAe,CAuB/E;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAI1F"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import os from 'os';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
/**
|
|
5
|
+
* Providers with a stable text-generation API. Model ids intentionally do not
|
|
6
|
+
* live here: the setup flow asks each provider for its current catalog.
|
|
7
|
+
*/
|
|
8
|
+
export const INFERENCE_PROVIDERS = [
|
|
9
|
+
{
|
|
10
|
+
id: 'chatgpt',
|
|
11
|
+
name: 'ChatGPT subscription',
|
|
12
|
+
description: 'Use a Codex/ChatGPT login and included plan usage',
|
|
13
|
+
envKeys: [],
|
|
14
|
+
protocol: 'chatgpt',
|
|
15
|
+
modelDiscovery: 'chatgpt',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'grok-build',
|
|
19
|
+
name: 'Grok Build subscription',
|
|
20
|
+
description: 'Use a SpaceXAI Grok Build login and included plan usage',
|
|
21
|
+
envKeys: [],
|
|
22
|
+
protocol: 'grok-build',
|
|
23
|
+
modelDiscovery: 'grok-build',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: 'openrouter',
|
|
27
|
+
name: 'OpenRouter',
|
|
28
|
+
description: 'One API key for models from many providers',
|
|
29
|
+
envKeys: ['OPENROUTER_API_KEY'],
|
|
30
|
+
baseUrl: 'https://openrouter.ai/api/v1',
|
|
31
|
+
protocol: 'openai-compatible',
|
|
32
|
+
modelDiscovery: 'openai',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'openai',
|
|
36
|
+
name: 'OpenAI API',
|
|
37
|
+
description: 'Usage-based OpenAI Platform access',
|
|
38
|
+
envKeys: ['OPENAI_API_KEY'],
|
|
39
|
+
baseUrl: 'https://api.openai.com/v1',
|
|
40
|
+
protocol: 'openai-responses',
|
|
41
|
+
modelDiscovery: 'openai',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'anthropic',
|
|
45
|
+
name: 'Anthropic',
|
|
46
|
+
description: 'Claude models through the Anthropic API',
|
|
47
|
+
envKeys: ['ANTHROPIC_API_KEY'],
|
|
48
|
+
baseUrl: 'https://api.anthropic.com/v1',
|
|
49
|
+
protocol: 'anthropic',
|
|
50
|
+
modelDiscovery: 'openai',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'google',
|
|
54
|
+
name: 'Google Gemini',
|
|
55
|
+
description: 'Gemini models through Google AI Studio',
|
|
56
|
+
envKeys: ['GOOGLE_GENERATIVE_AI_API_KEY', 'GOOGLE_API_KEY', 'GEMINI_API_KEY'],
|
|
57
|
+
baseUrl: 'https://generativelanguage.googleapis.com/v1beta/openai',
|
|
58
|
+
protocol: 'openai-compatible',
|
|
59
|
+
modelDiscovery: 'google',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'xai',
|
|
63
|
+
name: 'xAI',
|
|
64
|
+
description: 'Grok models through the xAI API',
|
|
65
|
+
envKeys: ['XAI_API_KEY'],
|
|
66
|
+
baseUrl: 'https://api.x.ai/v1',
|
|
67
|
+
protocol: 'openai-compatible',
|
|
68
|
+
modelDiscovery: 'openai',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'groq',
|
|
72
|
+
name: 'Groq',
|
|
73
|
+
description: 'Low-latency inference on Groq',
|
|
74
|
+
envKeys: ['GROQ_API_KEY'],
|
|
75
|
+
baseUrl: 'https://api.groq.com/openai/v1',
|
|
76
|
+
protocol: 'openai-compatible',
|
|
77
|
+
modelDiscovery: 'openai',
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'cerebras',
|
|
81
|
+
name: 'Cerebras',
|
|
82
|
+
description: 'Fast inference through Cerebras Inference',
|
|
83
|
+
envKeys: ['CEREBRAS_API_KEY'],
|
|
84
|
+
baseUrl: 'https://api.cerebras.ai/v1',
|
|
85
|
+
protocol: 'openai-compatible',
|
|
86
|
+
modelDiscovery: 'openai',
|
|
87
|
+
maxTokensParam: 'max_completion_tokens',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: 'deepseek',
|
|
91
|
+
name: 'DeepSeek',
|
|
92
|
+
description: 'DeepSeek chat and reasoning models',
|
|
93
|
+
envKeys: ['DEEPSEEK_API_KEY'],
|
|
94
|
+
baseUrl: 'https://api.deepseek.com',
|
|
95
|
+
protocol: 'openai-compatible',
|
|
96
|
+
modelDiscovery: 'openai',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 'mistral',
|
|
100
|
+
name: 'Mistral AI',
|
|
101
|
+
description: 'Mistral models through La Plateforme',
|
|
102
|
+
envKeys: ['MISTRAL_API_KEY'],
|
|
103
|
+
baseUrl: 'https://api.mistral.ai/v1',
|
|
104
|
+
protocol: 'openai-compatible',
|
|
105
|
+
modelDiscovery: 'openai',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: 'together',
|
|
109
|
+
name: 'Together AI',
|
|
110
|
+
description: 'Open and proprietary models on Together',
|
|
111
|
+
envKeys: ['TOGETHER_API_KEY', 'TOGETHER_AI_API_KEY'],
|
|
112
|
+
baseUrl: 'https://api.together.xyz/v1',
|
|
113
|
+
protocol: 'openai-compatible',
|
|
114
|
+
modelDiscovery: 'openai',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: 'fireworks',
|
|
118
|
+
name: 'Fireworks AI',
|
|
119
|
+
description: 'Serverless inference through Fireworks',
|
|
120
|
+
envKeys: ['FIREWORKS_API_KEY'],
|
|
121
|
+
baseUrl: 'https://api.fireworks.ai/inference/v1',
|
|
122
|
+
protocol: 'openai-compatible',
|
|
123
|
+
modelDiscovery: 'openai',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'perplexity',
|
|
127
|
+
name: 'Perplexity',
|
|
128
|
+
description: 'Agent API models and search-oriented Sonar presets',
|
|
129
|
+
envKeys: ['PERPLEXITY_API_KEY'],
|
|
130
|
+
baseUrl: 'https://api.perplexity.ai/v1',
|
|
131
|
+
protocol: 'openai-responses',
|
|
132
|
+
modelDiscovery: 'openai',
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'cohere',
|
|
136
|
+
name: 'Cohere',
|
|
137
|
+
description: 'Command models through the Cohere API',
|
|
138
|
+
envKeys: ['COHERE_API_KEY'],
|
|
139
|
+
baseUrl: 'https://api.cohere.com',
|
|
140
|
+
protocol: 'cohere',
|
|
141
|
+
modelDiscovery: 'cohere',
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: 'vercel',
|
|
145
|
+
name: 'Vercel AI Gateway',
|
|
146
|
+
description: 'Models routed through Vercel AI Gateway',
|
|
147
|
+
envKeys: ['AI_GATEWAY_API_KEY'],
|
|
148
|
+
baseUrl: 'https://ai-gateway.vercel.sh/v1',
|
|
149
|
+
protocol: 'openai-compatible',
|
|
150
|
+
modelDiscovery: 'openai',
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: 'huggingface',
|
|
154
|
+
name: 'Hugging Face',
|
|
155
|
+
description: 'Models available through the HF inference router',
|
|
156
|
+
envKeys: ['HF_TOKEN', 'HUGGING_FACE_HUB_TOKEN'],
|
|
157
|
+
baseUrl: 'https://router.huggingface.co/v1',
|
|
158
|
+
protocol: 'openai-compatible',
|
|
159
|
+
modelDiscovery: 'openai',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'custom',
|
|
163
|
+
name: 'Custom OpenAI-compatible',
|
|
164
|
+
description: 'Any service exposing /models and /chat/completions',
|
|
165
|
+
envKeys: [],
|
|
166
|
+
protocol: 'openai-compatible',
|
|
167
|
+
modelDiscovery: 'openai',
|
|
168
|
+
custom: true,
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
const CREDENTIALS_PATH = path.join(os.homedir(), '.dmux', 'inference-credentials.json');
|
|
172
|
+
export function getInferenceProvider(id) {
|
|
173
|
+
return INFERENCE_PROVIDERS.find((provider) => provider.id === id);
|
|
174
|
+
}
|
|
175
|
+
export function resolveInferenceProvider(target) {
|
|
176
|
+
const registered = getInferenceProvider(target.providerId);
|
|
177
|
+
if (registered && !registered.custom) {
|
|
178
|
+
return registered;
|
|
179
|
+
}
|
|
180
|
+
if (target.providerId === 'custom'
|
|
181
|
+
&& target.baseUrl
|
|
182
|
+
&& target.envKey) {
|
|
183
|
+
return {
|
|
184
|
+
id: 'custom',
|
|
185
|
+
name: target.providerName || 'Custom provider',
|
|
186
|
+
description: 'Custom OpenAI-compatible inference provider',
|
|
187
|
+
envKeys: [target.envKey],
|
|
188
|
+
baseUrl: target.baseUrl.replace(/\/+$/, ''),
|
|
189
|
+
protocol: 'openai-compatible',
|
|
190
|
+
modelDiscovery: 'openai',
|
|
191
|
+
custom: true,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return registered;
|
|
195
|
+
}
|
|
196
|
+
async function readStoredCredentials() {
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(await fs.readFile(CREDENTIALS_PATH, 'utf-8'));
|
|
199
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
|
|
200
|
+
return {};
|
|
201
|
+
return Object.fromEntries(Object.entries(parsed)
|
|
202
|
+
.filter((entry) => typeof entry[1] === 'string'));
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
return {};
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
export async function getInferenceApiKey(provider) {
|
|
209
|
+
for (const envKey of provider.envKeys) {
|
|
210
|
+
const apiKey = process.env[envKey]?.trim();
|
|
211
|
+
if (apiKey)
|
|
212
|
+
return { envKey, apiKey };
|
|
213
|
+
}
|
|
214
|
+
const stored = await readStoredCredentials();
|
|
215
|
+
for (const envKey of provider.envKeys) {
|
|
216
|
+
const apiKey = stored[envKey]?.trim();
|
|
217
|
+
if (apiKey)
|
|
218
|
+
return { envKey, apiKey };
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
export function hasInferenceApiKeySync(provider) {
|
|
223
|
+
return provider.envKeys.some((envKey) => Boolean(process.env[envKey]?.trim()));
|
|
224
|
+
}
|
|
225
|
+
export async function storeInferenceCredential(envKey, apiKey) {
|
|
226
|
+
const normalizedEnvKey = envKey.trim();
|
|
227
|
+
const normalizedApiKey = apiKey.trim();
|
|
228
|
+
if (!/^[A-Z_][A-Z0-9_]*$/.test(normalizedEnvKey)) {
|
|
229
|
+
throw new Error('Environment variable names may only contain uppercase letters, digits, and underscores');
|
|
230
|
+
}
|
|
231
|
+
if (!normalizedApiKey) {
|
|
232
|
+
throw new Error('API key cannot be empty');
|
|
233
|
+
}
|
|
234
|
+
const stored = await readStoredCredentials();
|
|
235
|
+
await fs.mkdir(path.dirname(CREDENTIALS_PATH), { recursive: true, mode: 0o700 });
|
|
236
|
+
await fs.writeFile(CREDENTIALS_PATH, JSON.stringify({ ...stored, [normalizedEnvKey]: normalizedApiKey }, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
237
|
+
await fs.chmod(CREDENTIALS_PATH, 0o600);
|
|
238
|
+
process.env[normalizedEnvKey] = normalizedApiKey;
|
|
239
|
+
}
|
|
240
|
+
export function isValidInferenceTarget(value) {
|
|
241
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
242
|
+
return false;
|
|
243
|
+
const target = value;
|
|
244
|
+
if (typeof target.providerId !== 'string'
|
|
245
|
+
|| !target.providerId
|
|
246
|
+
|| typeof target.modelId !== 'string'
|
|
247
|
+
|| !target.modelId) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
if (target.providerId !== 'custom') {
|
|
251
|
+
return Boolean(getInferenceProvider(target.providerId));
|
|
252
|
+
}
|
|
253
|
+
return (typeof target.baseUrl === 'string'
|
|
254
|
+
&& /^https?:\/\//.test(target.baseUrl)
|
|
255
|
+
&& typeof target.envKey === 'string'
|
|
256
|
+
&& /^[A-Z_][A-Z0-9_]*$/.test(target.envKey)
|
|
257
|
+
&& (target.providerName === undefined || typeof target.providerName === 'string'));
|
|
258
|
+
}
|
|
259
|
+
export function describeInferenceTarget(target) {
|
|
260
|
+
if (!target)
|
|
261
|
+
return 'Not configured';
|
|
262
|
+
const provider = resolveInferenceProvider(target);
|
|
263
|
+
return `${provider?.name || target.providerName || target.providerId} / ${target.modelId}`;
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=inferenceProviders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inferenceProviders.js","sourceRoot":"","sources":["../../src/utils/inferenceProviders.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { InferenceTarget } from '../types.js';
|
|
2
|
+
import type { InferenceModel, InferenceProviderDefinition } from './inferenceProviders.js';
|
|
3
|
+
export interface InferenceSetupResult {
|
|
4
|
+
primary: InferenceTarget;
|
|
5
|
+
backup: InferenceTarget | null;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Backwards-compatible search exports for integrations that used the original
|
|
9
|
+
* readline setup flow. The Ink wizard uses the same fuzzy ranking helpers.
|
|
10
|
+
*/
|
|
11
|
+
export declare function searchInferenceProviders(query: string): InferenceProviderDefinition[];
|
|
12
|
+
export declare function searchInferenceModels(models: InferenceModel[], query: string): InferenceModel[];
|
|
13
|
+
/**
|
|
14
|
+
* Render the same interactive wizard used by the settings popup during
|
|
15
|
+
* first-run onboarding. Keeping one UI prevents the old numbered/readline
|
|
16
|
+
* selector from resurfacing outside tmux popups.
|
|
17
|
+
*/
|
|
18
|
+
export declare function runInferenceSetup(): Promise<InferenceSetupResult | null>;
|
|
19
|
+
//# sourceMappingURL=inferenceSetup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inferenceSetup.d.ts","sourceRoot":"","sources":["../../src/utils/inferenceSetup.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,cAAc,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAG3F,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,eAAe,CAAC;IACzB,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;CAChC;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,2BAA2B,EAAE,CAErF;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,cAAc,EAAE,EACxB,KAAK,EAAE,MAAM,GACZ,cAAc,EAAE,CAElB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAoB9E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from 'ink';
|
|
3
|
+
import { InferenceSetupApp } from '../components/popups/inferenceSetupPopup.js';
|
|
4
|
+
import { rankInferenceModels, rankInferenceProviders } from './inferenceWizard.js';
|
|
5
|
+
/**
|
|
6
|
+
* Backwards-compatible search exports for integrations that used the original
|
|
7
|
+
* readline setup flow. The Ink wizard uses the same fuzzy ranking helpers.
|
|
8
|
+
*/
|
|
9
|
+
export function searchInferenceProviders(query) {
|
|
10
|
+
return rankInferenceProviders(query);
|
|
11
|
+
}
|
|
12
|
+
export function searchInferenceModels(models, query) {
|
|
13
|
+
return rankInferenceModels(models, query);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Render the same interactive wizard used by the settings popup during
|
|
17
|
+
* first-run onboarding. Keeping one UI prevents the old numbered/readline
|
|
18
|
+
* selector from resurfacing outside tmux popups.
|
|
19
|
+
*/
|
|
20
|
+
export async function runInferenceSetup() {
|
|
21
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
22
|
+
return null;
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
let settled = false;
|
|
25
|
+
const settle = (result) => {
|
|
26
|
+
if (settled)
|
|
27
|
+
return;
|
|
28
|
+
settled = true;
|
|
29
|
+
resolve(result);
|
|
30
|
+
};
|
|
31
|
+
const app = render(React.createElement(InferenceSetupApp, { onComplete: settle }), { exitOnCtrlC: false });
|
|
32
|
+
app.waitUntilExit()
|
|
33
|
+
.then(() => settle(null))
|
|
34
|
+
.catch(() => settle(null));
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=inferenceSetup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inferenceSetup.js","sourceRoot":"","sources":["../../src/utils/inferenceSetup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,6CAA6C,CAAC;AAGhF,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAOnF;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAa;IACpD,OAAO,sBAAsB,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,MAAwB,EACxB,KAAa;IAEb,OAAO,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAE/D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,MAAmC,EAAE,EAAE;YACrD,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,CAChB,KAAK,CAAC,aAAa,CAAC,iBAAiB,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,EAC9D,EAAE,WAAW,EAAE,KAAK,EAAE,CACvB,CAAC;QAEF,GAAG,CAAC,aAAa,EAAE;aAChB,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;aACxB,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { InferenceTarget } from '../types.js';
|
|
2
|
+
import { type InferenceModel, type InferenceProviderDefinition } from './inferenceProviders.js';
|
|
3
|
+
import { type CodexAccountInfo } from '../services/CodexAppServerClient.js';
|
|
4
|
+
import { type GrokBuildStatus } from '../services/GrokBuildClient.js';
|
|
5
|
+
/**
|
|
6
|
+
* Pure helpers backing the Ink inference-setup wizard. Everything here is
|
|
7
|
+
* side-effect free (except the credential probes at the bottom) so the popup
|
|
8
|
+
* UI stays a thin rendering layer.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Score how well `query` matches `text`. Higher is better; null means no
|
|
12
|
+
* match. Exact > prefix > substring (word boundaries beat mid-word) >
|
|
13
|
+
* scattered subsequence, so search-as-you-type surfaces the obvious pick
|
|
14
|
+
* first while still tolerating abbreviations like "grq" for Groq.
|
|
15
|
+
*/
|
|
16
|
+
export declare function fuzzyMatchScore(query: string, text: string): number | null;
|
|
17
|
+
/** Drop control characters (stray escape bytes, etc.) that can sneak into a terminal input buffer. */
|
|
18
|
+
export declare function sanitizeSearchQuery(query: string): string;
|
|
19
|
+
export declare function rankInferenceProviders(query: string, providers?: readonly InferenceProviderDefinition[]): InferenceProviderDefinition[];
|
|
20
|
+
export declare function rankInferenceModels(models: readonly InferenceModel[], query: string): InferenceModel[];
|
|
21
|
+
/**
|
|
22
|
+
* Compute the [start, end) slice of a list that keeps the selection visible
|
|
23
|
+
* inside a fixed-height viewport, centering it once the list scrolls.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getVisibleWindow(selectedIndex: number, total: number, maxVisible: number): {
|
|
26
|
+
start: number;
|
|
27
|
+
end: number;
|
|
28
|
+
};
|
|
29
|
+
export declare function clampSelection(index: number, total: number): number;
|
|
30
|
+
export declare function normalizeCustomBaseUrl(input: string): string;
|
|
31
|
+
export declare function isValidCustomBaseUrl(input: string): boolean;
|
|
32
|
+
export declare function normalizeEnvKeyName(input: string): string;
|
|
33
|
+
export declare function isValidEnvKeyName(input: string): boolean;
|
|
34
|
+
export interface CustomProviderFields {
|
|
35
|
+
name: string;
|
|
36
|
+
baseUrl: string;
|
|
37
|
+
envKey: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function buildCustomPartialTarget(fields: CustomProviderFields): Omit<InferenceTarget, 'modelId'>;
|
|
40
|
+
export type ProviderCredentialBadge = {
|
|
41
|
+
kind: 'api-key';
|
|
42
|
+
envKey: string;
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'chatgpt';
|
|
45
|
+
email?: string;
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'grok-build';
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Probe every registry provider for an existing credential (environment or
|
|
51
|
+
* dmux credential store) so the picker can show a "key detected" badge.
|
|
52
|
+
*/
|
|
53
|
+
export declare function detectProviderCredentials(providers?: readonly InferenceProviderDefinition[]): Promise<Map<string, ProviderCredentialBadge>>;
|
|
54
|
+
/**
|
|
55
|
+
* Best-effort check for an existing ChatGPT (Codex) login. Bounded by a
|
|
56
|
+
* timeout because it spawns the Codex app-server.
|
|
57
|
+
*/
|
|
58
|
+
export declare function detectChatGptAccount(timeoutMs?: number): Promise<CodexAccountInfo | null>;
|
|
59
|
+
/** Best-effort check for a cached Grok Build subscription login. */
|
|
60
|
+
export declare function detectGrokBuildAccount(timeoutMs?: number): Promise<GrokBuildStatus | null>;
|
|
61
|
+
//# sourceMappingURL=inferenceWizard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inferenceWizard.d.ts","sourceRoot":"","sources":["../../src/utils/inferenceWizard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,2BAA2B,EACjC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEL,KAAK,gBAAgB,EACtB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,gCAAgC,CAAC;AAExC;;;;GAIG;AAEH;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwB1E;AAOD,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAmCD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,SAAS,GAAE,SAAS,2BAA2B,EAAwB,GACtE,2BAA2B,EAAE,CAO/B;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,cAAc,EAAE,EACjC,KAAK,EAAE,MAAM,GACZ,cAAc,EAAE,CAMlB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,MAAM,EACb,UAAU,EAAE,MAAM,GACjB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAMhC;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGnE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,oBAAoB,GAC3B,IAAI,CAAC,eAAe,EAAE,SAAS,CAAC,CAOlC;AAED,MAAM,MAAM,uBAAuB,GAC/B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC;AAE3B;;;GAGG;AACH,wBAAsB,yBAAyB,CAC7C,SAAS,GAAE,SAAS,2BAA2B,EAAwB,GACtE,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,CAe/C;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,SAAO,GACf,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAUlC;AAED,oEAAoE;AACpE,wBAAsB,sBAAsB,CAC1C,SAAS,SAAO,GACf,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAOjC"}
|