mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
Adds `mode: 'deepseek'` alongside claude/shell/opencode/codex/gemini/ antigravity/pi/grok, plus a shortcut that opens the harness's own browser UI as a Codeman web tab. DeepSeek is wired unlike its siblings in three ways, each of which is the reason for a design decision rather than an accident: 1. The agent is a PROFILE, not the binary. `dsh` is a launcher over $DSH_HOME/profiles/<name>, and DeepSeek ships only `web`, `headless` and `base` -- the interactive terminal front door is always a third-party plugin. So availability is two questions: `isDeepSeekAvailable()` (binary) and `isDeepSeekRunnable()` (binary AND a pane-capable profile). The Run button gates on the latter, because reporting only the binary would spawn a pane that dies on arrival. When the binary is present but no profile is, the run menu offers to install one (POST /api/deepseek/install-profile). 2. The permission switch is an env var, not a flag. The harness has no command-line permission option; its sandbox/approval rows read DSH_PERMISSION_MODE (read-only / workspace-write / danger-full-access). Exported via `tmux setenv`, never on the spawn line. Absent = the harness's own workspace-write, which still asks, so the multi-user clamp is the only-if-sent branch and clamps to workspace-write, never read-only. 3. It is the only non-claude mode that passes hooksAvailableForMode(), and it earned that. The terminal front door reports idle/working/blocked to a supervising process over a generic env-gated contract; a generated shim (deepseek-status-shim.ts) makes Codeman that supervisor and forwards each report to /api/hook-event as stop / agent_working / permission_prompt. So a dsh session gets definitive respawn triggers, real wait-endpoint signals and real Approvals Inbox items instead of output-stabilization guesswork. `agent_working` is new (157th SSE constant) and joins APPROVAL_RESOLVING_EVENTS so a dialog answered in the terminal clears its alert at once. The resolver needs the strictest identity probe of the family: `dsh` is not merely a squattable npm name, Debian ships an unrelated `dsh` (dancer's shell), so `dsh --help` must print the harness's own banner before a candidate is handed a spawn line. Model is deliberately not a session field -- it is a composition entry in the profile's config tree. Env allowlist gains DSH_* and DEEPSEEK_* only; provider keys named by a settings-file `apiKeyEnv` stay out, which is pi's 34-provider-key problem in a new shape. Verified live against dsh 0.1.1-rc.2 and @deepseek-harness-tui/dsh-tui: the status endpoint's two-part answer, the no-profile refusal, the profile bootstrap, a real session whose pane runs `dsh --profile dsh-tui` with the permission mode injected via setenv, and the full status bridge -- a send-and-wait returned signal "stop" from a real turn, and blocked/working created and cleared an Approvals Inbox item. Docs: docs/deepseek-integration.md (guide), docs/deepseek-integration-plan.md (decisions + honest gaps). Tests: test/deepseek-mode.test.ts, test/deepseek-cli-resolver.test.ts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
64 lines
2.4 KiB
TypeScript
64 lines
2.4 KiB
TypeScript
/**
|
|
* @fileoverview Utility module exports.
|
|
*
|
|
* This module re-exports all utility classes and functions for easy import.
|
|
*
|
|
* @module utils
|
|
*/
|
|
|
|
export { BufferAccumulator } from './buffer-accumulator.js';
|
|
export { CleanupManager } from './cleanup-manager.js';
|
|
export { Debouncer, KeyedDebouncer } from './debouncer.js';
|
|
export { startEventLoopMonitor } from './event-loop-monitor.js';
|
|
export type { EventLoopMonitorHandle } from './event-loop-monitor.js';
|
|
export { StaleExpirationMap } from './stale-expiration-map.js';
|
|
export {
|
|
ANSI_ESCAPE_PATTERN_FULL,
|
|
ANSI_ESCAPE_PATTERN_SIMPLE,
|
|
TOKEN_PATTERN,
|
|
SPINNER_PATTERN,
|
|
CLAUDE_WORKING_LINE_PATTERN,
|
|
stripAnsi,
|
|
SAFE_PATH_PATTERN,
|
|
execPattern,
|
|
} from './regex-patterns.js';
|
|
export { MAX_SESSION_TOKENS } from './token-validation.js';
|
|
export { isSafePushEndpoint } from './push-endpoint-validation.js';
|
|
export { stringSimilarity, fuzzyPhraseMatch, todoContentHash } from './string-similarity.js';
|
|
export { assertNever } from './type-safety.js';
|
|
export { wrapWithNice } from './nice-wrapper.js';
|
|
export { resolveLocalShell, loginShellArgs } from './shell-resolver.js';
|
|
export {
|
|
findClaudeDir,
|
|
getAugmentedPath,
|
|
getClaudeCliVersion,
|
|
getClaudeBinaryPath,
|
|
getClaudeNotFoundMessage,
|
|
} from './claude-cli-resolver.js';
|
|
export { spawnPtyWithHelperRepair } from './node-pty-repair.js';
|
|
export { resolveOpenCodeDir, getOpenCodeNotFoundMessage } from './opencode-cli-resolver.js';
|
|
export { resolveCodexDir, isCodexAvailable, getCodexNotFoundMessage } from './codex-cli-resolver.js';
|
|
export { resolveGeminiDir, isGeminiAvailable, getGeminiNotFoundMessage } from './gemini-cli-resolver.js';
|
|
export {
|
|
resolveAntigravityDir,
|
|
isAntigravityAvailable,
|
|
getAntigravityNotFoundMessage,
|
|
} from './antigravity-cli-resolver.js';
|
|
export { resolvePiDir, isPiAvailable, getPiCliVersion, getPiNotFoundMessage } from './pi-cli-resolver.js';
|
|
export { resolveGrokDir, isGrokAvailable, getGrokCliVersion, getGrokNotFoundMessage } from './grok-cli-resolver.js';
|
|
export {
|
|
resolveDeepSeekDir,
|
|
isDeepSeekAvailable,
|
|
isDeepSeekRunnable,
|
|
getDeepSeekCliVersion,
|
|
getDeepSeekNotFoundMessage,
|
|
listDeepSeekProfiles,
|
|
resolveDefaultDeepSeekProfile,
|
|
isLaunchableProfile,
|
|
resolveDshHome,
|
|
profileExists,
|
|
} from './deepseek-cli-resolver.js';
|
|
export type { DeepSeekProfile, DeepSeekProfileKind } from './deepseek-cli-resolver.js';
|
|
export { compileFileQuery, matchFileQuery } from './file-query.js';
|
|
export type { FileQueryMatcher } from './file-query.js';
|