aicodeman 1.45.0 → 1.47.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.md +26 -6
- package/dist/agent-codex-identity.d.ts +26 -0
- package/dist/agent-codex-identity.d.ts.map +1 -0
- package/dist/agent-codex-identity.js +253 -0
- package/dist/agent-codex-identity.js.map +1 -0
- package/dist/agent-inspection.d.ts +32 -0
- package/dist/agent-inspection.d.ts.map +1 -0
- package/dist/agent-inspection.js +196 -0
- package/dist/agent-inspection.js.map +1 -0
- package/dist/agent-staging.d.ts +130 -0
- package/dist/agent-staging.d.ts.map +1 -0
- package/dist/agent-staging.js +312 -0
- package/dist/agent-staging.js.map +1 -0
- package/dist/cli-agent.d.ts +31 -2
- package/dist/cli-agent.d.ts.map +1 -1
- package/dist/cli-agent.js +279 -34
- package/dist/cli-agent.js.map +1 -1
- package/dist/cli-history.d.ts +20 -0
- package/dist/cli-history.d.ts.map +1 -0
- package/dist/cli-history.js +61 -0
- package/dist/cli-history.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -1
- package/dist/cli.js.map +1 -1
- package/dist/codex-rollout-format.d.ts +66 -0
- package/dist/codex-rollout-format.d.ts.map +1 -0
- package/dist/codex-rollout-format.js +111 -0
- package/dist/codex-rollout-format.js.map +1 -0
- package/dist/codex-transcript.d.ts +3 -0
- package/dist/codex-transcript.d.ts.map +1 -1
- package/dist/codex-transcript.js +13 -41
- package/dist/codex-transcript.js.map +1 -1
- package/dist/config/cli-registry/schema.d.ts +12 -7
- package/dist/config/cli-registry/schema.d.ts.map +1 -1
- package/dist/config/cli-registry/schema.js +26 -0
- package/dist/config/cli-registry/schema.js.map +1 -1
- package/dist/config/cli-registry/stock.d.ts.map +1 -1
- package/dist/config/cli-registry/stock.js +40 -1
- package/dist/config/cli-registry/stock.js.map +1 -1
- package/dist/config/cli-registry/types.d.ts +57 -0
- package/dist/config/cli-registry/types.d.ts.map +1 -1
- package/dist/config/server-timing.d.ts +6 -0
- package/dist/config/server-timing.d.ts.map +1 -1
- package/dist/config/server-timing.js +9 -0
- package/dist/config/server-timing.js.map +1 -1
- package/dist/daemon-control.d.ts +1 -0
- package/dist/daemon-control.d.ts.map +1 -1
- package/dist/daemon-control.js +2 -0
- package/dist/daemon-control.js.map +1 -1
- package/dist/deepseek-transcript.d.ts +9 -7
- package/dist/deepseek-transcript.d.ts.map +1 -1
- package/dist/deepseek-transcript.js +9 -7
- package/dist/deepseek-transcript.js.map +1 -1
- package/dist/docker-hosts.d.ts +8 -0
- package/dist/docker-hosts.d.ts.map +1 -1
- package/dist/docker-hosts.js +29 -0
- package/dist/docker-hosts.js.map +1 -1
- package/dist/git-fetch-scheduler.d.ts +124 -0
- package/dist/git-fetch-scheduler.d.ts.map +1 -0
- package/dist/git-fetch-scheduler.js +249 -0
- package/dist/git-fetch-scheduler.js.map +1 -0
- package/dist/git-fetch.d.ts +241 -0
- package/dist/git-fetch.d.ts.map +1 -0
- package/dist/git-fetch.js +392 -0
- package/dist/git-fetch.js.map +1 -0
- package/dist/git-workspace-status.d.ts +36 -1
- package/dist/git-workspace-status.d.ts.map +1 -1
- package/dist/git-workspace-status.js +42 -5
- package/dist/git-workspace-status.js.map +1 -1
- package/dist/hooks-config.d.ts +14 -2
- package/dist/hooks-config.d.ts.map +1 -1
- package/dist/hooks-config.js +39 -3
- package/dist/hooks-config.js.map +1 -1
- package/dist/local-history.d.ts +71 -0
- package/dist/local-history.d.ts.map +1 -0
- package/dist/local-history.js +750 -0
- package/dist/local-history.js.map +1 -0
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +2 -2
- package/dist/mcp-server.js.map +1 -1
- package/dist/mux-interface.d.ts +5 -2
- package/dist/mux-interface.d.ts.map +1 -1
- package/dist/prompt-cache-keepwarm.d.ts.map +1 -1
- package/dist/prompt-cache-keepwarm.js +5 -3
- package/dist/prompt-cache-keepwarm.js.map +1 -1
- package/dist/ralph-fix-plan-watcher.d.ts +13 -1
- package/dist/ralph-fix-plan-watcher.d.ts.map +1 -1
- package/dist/ralph-fix-plan-watcher.js +21 -3
- package/dist/ralph-fix-plan-watcher.js.map +1 -1
- package/dist/ralph-tracker.d.ts +6 -0
- package/dist/ralph-tracker.d.ts.map +1 -1
- package/dist/ralph-tracker.js +8 -0
- package/dist/ralph-tracker.js.map +1 -1
- package/dist/session.d.ts +113 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +341 -13
- package/dist/session.js.map +1 -1
- package/dist/terminal-input-classifier.d.ts +8 -0
- package/dist/terminal-input-classifier.d.ts.map +1 -0
- package/dist/terminal-input-classifier.js +60 -0
- package/dist/terminal-input-classifier.js.map +1 -0
- package/dist/tmux-manager.d.ts +23 -1
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +54 -6
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types/session.d.ts +15 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/web/network-auth-policy.d.ts +13 -3
- package/dist/web/network-auth-policy.d.ts.map +1 -1
- package/dist/web/network-auth-policy.js +15 -3
- package/dist/web/network-auth-policy.js.map +1 -1
- package/dist/web/ports/infra-port.d.ts +2 -0
- package/dist/web/ports/infra-port.d.ts.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.fe8a6b4c.js +43 -0
- package/dist/web/public/app.fe8a6b4c.js.br +0 -0
- package/dist/web/public/app.fe8a6b4c.js.gz +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/{constants.0b3cdde9.js → constants.affcdde6.js} +611 -12
- package/dist/web/public/constants.affcdde6.js.br +0 -0
- package/dist/web/public/constants.affcdde6.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/git-status-ui.js +88 -5
- package/dist/web/public/git-status-ui.js.br +0 -0
- package/dist/web/public/git-status-ui.js.gz +0 -0
- package/dist/web/public/header-divider.eb2d2463.js.gz +0 -0
- package/dist/web/public/home-sessions.js.gz +0 -0
- package/dist/web/public/host-wake-ui.js.gz +0 -0
- package/dist/web/public/i18n.a618ef4e.js +2 -0
- package/dist/web/public/i18n.a618ef4e.js.br +0 -0
- package/dist/web/public/i18n.a618ef4e.js.gz +0 -0
- package/dist/web/public/{image-input.941386e7.js → image-input.a5d0f8f3.js} +18 -9
- package/dist/web/public/image-input.a5d0f8f3.js.br +0 -0
- package/dist/web/public/image-input.a5d0f8f3.js.gz +0 -0
- package/dist/web/public/index.html +110 -19
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
- package/dist/web/public/{keyboard-accessory.4e8b20ac.js → keyboard-accessory.ff64fafc.js} +5 -1
- package/dist/web/public/keyboard-accessory.ff64fafc.js.br +0 -0
- package/dist/web/public/keyboard-accessory.ff64fafc.js.gz +0 -0
- package/dist/web/public/{mobile-handlers.1c0cbcd8.js → mobile-handlers.f7c3f692.js} +22 -0
- package/dist/web/public/mobile-handlers.f7c3f692.js.br +0 -0
- package/dist/web/public/mobile-handlers.f7c3f692.js.gz +0 -0
- package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
- package/dist/web/public/mobile-overview.js.gz +0 -0
- package/dist/web/public/mobile.1bbd2d67.css +1 -0
- package/dist/web/public/mobile.1bbd2d67.css.br +0 -0
- package/dist/web/public/mobile.1bbd2d67.css.gz +0 -0
- package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.78c3defb.js → panels-ui.4a56ee63.js} +1 -1
- package/dist/web/public/panels-ui.4a56ee63.js.br +0 -0
- package/dist/web/public/panels-ui.4a56ee63.js.gz +0 -0
- package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
- package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
- package/dist/web/public/readmymind-ui.js.gz +0 -0
- package/dist/web/public/reboot-restore-ui.js.gz +0 -0
- package/dist/web/public/respawn-ui.d7adcf6a.js.gz +0 -0
- package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
- package/dist/web/public/session-lineage.js.gz +0 -0
- package/dist/web/public/{session-ui.ea6b1994.js → session-ui.426fb671.js} +8 -8
- package/dist/web/public/session-ui.426fb671.js.br +0 -0
- package/dist/web/public/session-ui.426fb671.js.gz +0 -0
- package/dist/web/public/{settings-ui.085dd202.js → settings-ui.a191154e.js} +11 -11
- package/dist/web/public/settings-ui.a191154e.js.br +0 -0
- package/dist/web/public/settings-ui.a191154e.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
- package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
- package/dist/web/public/styles.4f0c67a0.css +1 -0
- package/dist/web/public/styles.4f0c67a0.css.br +0 -0
- package/dist/web/public/styles.4f0c67a0.css.gz +0 -0
- package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
- package/dist/web/public/sw.js +2 -2
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/tab-layout-browser.2d6189f7.js.gz +0 -0
- package/dist/web/public/{tab-rail-resize.7157e0bd.js → tab-rail-resize.b5cdceaf.js} +1 -1
- package/dist/web/public/tab-rail-resize.b5cdceaf.js.br +0 -0
- package/dist/web/public/tab-rail-resize.b5cdceaf.js.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js +1 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js.gz +0 -0
- package/dist/web/public/terminal-split.js.gz +0 -0
- package/dist/web/public/terminal-tile.js +10 -6
- package/dist/web/public/terminal-tile.js.br +0 -0
- package/dist/web/public/terminal-tile.js.gz +0 -0
- package/dist/web/public/terminal-ui.7e787829.js +4 -0
- package/dist/web/public/terminal-ui.7e787829.js.br +0 -0
- package/dist/web/public/terminal-ui.7e787829.js.gz +0 -0
- package/dist/web/public/tile-grid.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
- package/dist/web/public/vendor/fflate.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/{xterm-predictive-echo.ae5e3d5d.js → xterm-predictive-echo.276b11d9.js} +1 -1
- package/dist/web/public/vendor/xterm-predictive-echo.276b11d9.js.br +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.276b11d9.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.1be42307.js +5 -0
- package/dist/web/public/vendor/xterm-zerolag-input.1be42307.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.1be42307.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
- package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/public/whats-new.json +8 -9
- package/dist/web/request-body-parser.d.ts +23 -0
- package/dist/web/request-body-parser.d.ts.map +1 -0
- package/dist/web/request-body-parser.js +57 -0
- package/dist/web/request-body-parser.js.map +1 -0
- package/dist/web/routes/agent-session-routes.d.ts +20 -0
- package/dist/web/routes/agent-session-routes.d.ts.map +1 -0
- package/dist/web/routes/agent-session-routes.js +160 -0
- package/dist/web/routes/agent-session-routes.js.map +1 -0
- package/dist/web/routes/case-routes.d.ts.map +1 -1
- package/dist/web/routes/case-routes.js +32 -26
- package/dist/web/routes/case-routes.js.map +1 -1
- package/dist/web/routes/config-backup-routes.js +2 -2
- package/dist/web/routes/config-backup-routes.js.map +1 -1
- package/dist/web/routes/file-routes.d.ts +5 -0
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +5 -1
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/git-status-routes.d.ts +21 -7
- package/dist/web/routes/git-status-routes.d.ts.map +1 -1
- package/dist/web/routes/git-status-routes.js +78 -12
- package/dist/web/routes/git-status-routes.js.map +1 -1
- package/dist/web/routes/index.d.ts +1 -0
- package/dist/web/routes/index.d.ts.map +1 -1
- package/dist/web/routes/index.js +1 -0
- package/dist/web/routes/index.js.map +1 -1
- package/dist/web/routes/ralph-routes.d.ts.map +1 -1
- package/dist/web/routes/ralph-routes.js +52 -18
- package/dist/web/routes/ralph-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +101 -28
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +87 -59
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/routes/ws-routes.d.ts +5 -0
- package/dist/web/routes/ws-routes.d.ts.map +1 -1
- package/dist/web/routes/ws-routes.js +84 -47
- package/dist/web/routes/ws-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +30 -7
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +40 -1
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts +5 -2
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +102 -18
- package/dist/web/server.js.map +1 -1
- package/dist/web/settings-writer.d.ts +47 -0
- package/dist/web/settings-writer.d.ts.map +1 -0
- package/dist/web/settings-writer.js +110 -0
- package/dist/web/settings-writer.js.map +1 -0
- package/package.json +1 -1
- package/skills/codeman/SKILL.md +25 -6
- package/skills/codeman/reference/history.md +84 -0
- package/skills/codeman/reference/inspection-and-staging.md +152 -0
- package/skills/codeman/reference/messaging.md +1 -1
- package/skills/codeman/reference/verbs.md +18 -3
- package/dist/web/public/app.42d0abae.js +0 -43
- package/dist/web/public/app.42d0abae.js.br +0 -0
- package/dist/web/public/app.42d0abae.js.gz +0 -0
- package/dist/web/public/constants.0b3cdde9.js.br +0 -0
- package/dist/web/public/constants.0b3cdde9.js.gz +0 -0
- package/dist/web/public/i18n.1e68220d.js +0 -2
- package/dist/web/public/i18n.1e68220d.js.br +0 -0
- package/dist/web/public/i18n.1e68220d.js.gz +0 -0
- package/dist/web/public/image-input.941386e7.js.br +0 -0
- package/dist/web/public/image-input.941386e7.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.4e8b20ac.js.br +0 -0
- package/dist/web/public/keyboard-accessory.4e8b20ac.js.gz +0 -0
- package/dist/web/public/mobile-handlers.1c0cbcd8.js.br +0 -0
- package/dist/web/public/mobile-handlers.1c0cbcd8.js.gz +0 -0
- package/dist/web/public/mobile.12fb18de.css +0 -1
- package/dist/web/public/mobile.12fb18de.css.br +0 -0
- package/dist/web/public/mobile.12fb18de.css.gz +0 -0
- package/dist/web/public/panels-ui.78c3defb.js.br +0 -0
- package/dist/web/public/panels-ui.78c3defb.js.gz +0 -0
- package/dist/web/public/session-ui.ea6b1994.js.br +0 -0
- package/dist/web/public/session-ui.ea6b1994.js.gz +0 -0
- package/dist/web/public/settings-ui.085dd202.js.br +0 -0
- package/dist/web/public/settings-ui.085dd202.js.gz +0 -0
- package/dist/web/public/styles.3b59b41d.css +0 -1
- package/dist/web/public/styles.3b59b41d.css.br +0 -0
- package/dist/web/public/styles.3b59b41d.css.gz +0 -0
- package/dist/web/public/tab-rail-resize.7157e0bd.js.br +0 -0
- package/dist/web/public/tab-rail-resize.7157e0bd.js.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js +0 -1
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
- package/dist/web/public/terminal-ui.fb2a27f5.js +0 -2
- package/dist/web/public/terminal-ui.fb2a27f5.js.br +0 -0
- package/dist/web/public/terminal-ui.fb2a27f5.js.gz +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.br +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js +0 -4
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
package/dist/web/server.js
CHANGED
|
@@ -78,7 +78,7 @@ import { createRequire } from 'node:module';
|
|
|
78
78
|
import { RunSummaryTracker } from '../run-summary.js';
|
|
79
79
|
import { OrchestratorLoop } from '../orchestrator-loop.js';
|
|
80
80
|
import { getLifecycleLog } from '../session-lifecycle-log.js';
|
|
81
|
-
import { applyWorkspaceHooks, pruneAgentSessionPreambles, readKeepWarmSettingsOrThrow, readPlanUsageTelemetryEnabled, removeAgentSessionPreamble, } from '../hooks-config.js';
|
|
81
|
+
import { applyWorkspaceHooks, pruneAgentSessionPreambles, readGitFetchSettings, readKeepWarmSettingsOrThrow, readPlanUsageTelemetryEnabled, removeAgentSessionPreamble, } from '../hooks-config.js';
|
|
82
82
|
import { PushSubscriptionStore } from '../push-store.js';
|
|
83
83
|
import webpush from 'web-push';
|
|
84
84
|
import { SseStreamManager } from './sse-stream-manager.js';
|
|
@@ -93,6 +93,10 @@ import { AI_CHECK_MODEL } from '../config/ai-defaults.js';
|
|
|
93
93
|
import { approvalInbox } from './approval-inbox.js';
|
|
94
94
|
import { SCREEN_BLOCKED_SOURCE } from './screen-blocked.js';
|
|
95
95
|
import { PromptCacheKeepWarmService } from '../prompt-cache-keepwarm.js';
|
|
96
|
+
import { fetchWorkspaceOnce } from '../git-fetch.js';
|
|
97
|
+
import { GitFetchScheduler } from '../git-fetch-scheduler.js';
|
|
98
|
+
import { probePathKind } from '../utils/bounded-path-probe.js';
|
|
99
|
+
import { defaultDockerWorkspaces } from './routes/git-status-routes.js';
|
|
96
100
|
import { composerIsEmpty, plainFrame } from '../session-submit-verifier.js';
|
|
97
101
|
import { detectUsageLimitPause } from '../usage-limit-patterns.js';
|
|
98
102
|
import { stopDeepSeekWeb } from '../deepseek-web-server.js';
|
|
@@ -120,6 +124,7 @@ import { MAX_PASTE_IMAGE_BYTES } from '../config/buffer-limits.js';
|
|
|
120
124
|
import { resolveTerminalHistoryConfig } from '../config/terminal-history.js';
|
|
121
125
|
import { SseEvent } from './sse-events.js';
|
|
122
126
|
import { MAX_ROUTE_PARAM_LENGTH } from './route-helpers.js';
|
|
127
|
+
import { mutateSettingsFile } from './settings-writer.js';
|
|
123
128
|
import { getLatestPlanUsage, setLatestCodexPlanUsage, setLatestCopilotPlanUsage } from './plan-usage-latest.js';
|
|
124
129
|
import { telemetrySignature } from '../usage-telemetry.js';
|
|
125
130
|
import { readCodexPlanUsage, resolveCodexBinaryPath } from '../utils/codex-cli-resolver.js';
|
|
@@ -129,8 +134,9 @@ import { registerAuthMiddleware, registerSecurityHeaders, registerHostGuard, isL
|
|
|
129
134
|
import { isMultiUserMode } from '../config/multiuser.js';
|
|
130
135
|
import { bootstrapInitialAdmin, hasUsers, resolveClaudeModeForUsername } from '../user-store.js';
|
|
131
136
|
import { installRouteErrorHandler } from './route-error-handler.js';
|
|
137
|
+
import { installEmptyApiPostParser } from './request-body-parser.js';
|
|
132
138
|
import { isExplicitlyEnabled, isLoopbackBindHost, buildHostPolicy } from './network-auth-policy.js';
|
|
133
|
-
import { registerPushRoutes, registerTeamRoutes, registerMuxRoutes, registerFileRoutes, registerHtmlViewRoutes, registerScheduledRoutes, registerHookEventRoutes, registerApprovalRoutes, registerInboxRoutes, registerRebootRestoreRoutes, registerReadMyMindRoutes, registerGitStatusRoutes, registerStatusTelemetryRoutes, registerSystemRoutes, registerCaseRoutes, registerWorktreeRoutes, registerSessionRoutes, registerRespawnRoutes, registerRalphRoutes, registerPlanRoutes, registerClipboardRoutes, registerSearchRoutes, registerOrchestratorRoutes, registerCronRoutes, registerMeRoutes, registerAdminRoutes, registerWsRoutes, registerVoiceRoutes, registerWebviewRoutes, registerTabLayoutRoutes, registerMcpSyncRoutes, registerConfigBackupRoutes, runConfigBackup, registerWebhookRoutes, registerDoctorRoutes, registerCustomModelRoutes, refreshAllCustomModelHosts, readCustomModelEndpointsEnabled, closeAllLlamaSwapLogTails, detectCustomModelSwapDisplacements, pruneIdleLlamaSwapLogTails, tryWebviewRefererFallback, registerCliRegistryRoutes, } from './routes/index.js';
|
|
139
|
+
import { registerPushRoutes, registerTeamRoutes, registerMuxRoutes, registerFileRoutes, registerHtmlViewRoutes, registerScheduledRoutes, registerHookEventRoutes, registerApprovalRoutes, registerInboxRoutes, registerRebootRestoreRoutes, registerReadMyMindRoutes, registerGitStatusRoutes, registerStatusTelemetryRoutes, registerSystemRoutes, registerCaseRoutes, registerWorktreeRoutes, registerSessionRoutes, registerAgentSessionRoutes, registerRespawnRoutes, registerRalphRoutes, registerPlanRoutes, registerClipboardRoutes, registerSearchRoutes, registerOrchestratorRoutes, registerCronRoutes, registerMeRoutes, registerAdminRoutes, registerWsRoutes, registerVoiceRoutes, registerWebviewRoutes, registerTabLayoutRoutes, registerMcpSyncRoutes, registerConfigBackupRoutes, runConfigBackup, registerWebhookRoutes, registerDoctorRoutes, registerCustomModelRoutes, refreshAllCustomModelHosts, readCustomModelEndpointsEnabled, closeAllLlamaSwapLogTails, detectCustomModelSwapDisplacements, pruneIdleLlamaSwapLogTails, tryWebviewRefererFallback, registerCliRegistryRoutes, } from './routes/index.js';
|
|
134
140
|
import { isLostWebviewFrameNavigation } from './webview-proxy.js';
|
|
135
141
|
import { CronService } from '../cron/cron-service.js';
|
|
136
142
|
import { caseSessionSettled } from '../case-rename.js';
|
|
@@ -168,7 +174,7 @@ function escapeHtmlText(value) {
|
|
|
168
174
|
export function escapeScriptJson(json) {
|
|
169
175
|
return json.replace(/</g, '\\u003c');
|
|
170
176
|
}
|
|
171
|
-
import { SESSIONS_LIST_CACHE_TTL, SCHEDULED_CLEANUP_INTERVAL, SCHEDULED_RUN_MAX_AGE, SSE_HEARTBEAT_INTERVAL, SESSION_LIMIT_WAIT_MS, ITERATION_PAUSE_MS, STATS_COLLECTION_INTERVAL_MS, INACTIVITY_TIMEOUT_MS, CRON_TICK_INTERVAL, } from '../config/server-timing.js';
|
|
177
|
+
import { SESSIONS_LIST_CACHE_TTL, SCHEDULED_CLEANUP_INTERVAL, SCHEDULED_RUN_MAX_AGE, SSE_HEARTBEAT_INTERVAL, SESSION_LIMIT_WAIT_MS, ITERATION_PAUSE_MS, STATS_COLLECTION_INTERVAL_MS, INACTIVITY_TIMEOUT_MS, CRON_TICK_INTERVAL, GIT_FETCH_TICK_INTERVAL_MS, } from '../config/server-timing.js';
|
|
172
178
|
/**
|
|
173
179
|
* Get or generate a self-signed TLS certificate for HTTPS.
|
|
174
180
|
* Certs are stored in ~/.codeman/certs/ and reused across restarts.
|
|
@@ -254,6 +260,38 @@ export class WebServer extends EventEmitter {
|
|
|
254
260
|
},
|
|
255
261
|
log: (message) => console.log(message),
|
|
256
262
|
});
|
|
263
|
+
// Git fetch on an interval (git-fetch-scheduler.ts): the due-tracking lives in the service; the server
|
|
264
|
+
// lends it the facts a decision needs and stores what it reports on the session. A field initializer for
|
|
265
|
+
// the same reason as the keep-warm one above, and the scheduler reads the app setting FRESH on every tick:
|
|
266
|
+
// that is what makes a live toggle take effect on the next tick, and what makes turning it off actually
|
|
267
|
+
// stop the fetching. Default OFF, so an install that never enabled it spawns nothing at all.
|
|
268
|
+
gitFetchScheduler = new GitFetchScheduler({
|
|
269
|
+
sessionIds: () => this.sessions.keys(),
|
|
270
|
+
getSession: (id) => this.sessions.get(id),
|
|
271
|
+
readSettings: readGitFetchSettings,
|
|
272
|
+
// The same Docker list the panel's Fetch button uses: the rule has to be one rule. It rejects on a list
|
|
273
|
+
// that cannot be read, and the tick then fetches nothing (fail closed).
|
|
274
|
+
dockerWorkspaces: defaultDockerWorkspaces,
|
|
275
|
+
// Bounded probe, DEFAULT options (rule #516): a tick is a bulk scan, so it keeps the stall cap and must
|
|
276
|
+
// never be handed `pastCap`. A folder on a mount that stopped answering is skipped, not fetched.
|
|
277
|
+
probePath: (path) => probePathKind(path),
|
|
278
|
+
// Through the join, so the tick and the panel's Fetch button are the same run: a click on a folder the
|
|
279
|
+
// tick is already fetching joins it rather than starting a second `git fetch` in the same clone, and the
|
|
280
|
+
// run that gets published is the one that ran, with its own trigger.
|
|
281
|
+
fetch: (cwd, opts, trigger) => fetchWorkspaceOnce(cwd, opts, trigger),
|
|
282
|
+
publish: (id, status) => {
|
|
283
|
+
const session = this.sessions.get(id);
|
|
284
|
+
if (!session?.setGitFetchStatus(status))
|
|
285
|
+
return;
|
|
286
|
+
// No new SSE event: the status rides the session state the page already listens for, and the Git
|
|
287
|
+
// panel polls on its own clock. It is written to disk with the rest of the record, but the restore
|
|
288
|
+
// copies only the fields its own config lists and this is not one of them (src/types/session.ts), so
|
|
289
|
+
// what a run found is the panel's truth for the life of the session, not across a restart.
|
|
290
|
+
this.persistSessionState(session);
|
|
291
|
+
this.broadcast(SseEvent.SessionUpdated, this.getSessionStateWithRespawn(session));
|
|
292
|
+
},
|
|
293
|
+
log: (message) => console.log(message),
|
|
294
|
+
});
|
|
257
295
|
/**
|
|
258
296
|
* Wake-on-LAN registry, returned by `registerSessionRoutes`. Held for its LIFETIME
|
|
259
297
|
* only — `drop()` on session cleanup, `stop()` on shutdown. Waking from here would
|
|
@@ -319,12 +357,14 @@ export class WebServer extends EventEmitter {
|
|
|
319
357
|
windowTitle;
|
|
320
358
|
indexHtmlTemplate;
|
|
321
359
|
allowUnauthenticatedNetwork;
|
|
360
|
+
/** `--allow-unauthenticated-tunnel`; the tunnel guard reads it through the route context (#706). */
|
|
361
|
+
allowUnauthenticatedTunnel;
|
|
322
362
|
_pasteImageGcStop = null;
|
|
323
363
|
_eventLoopMonitor = null;
|
|
324
364
|
/** Opt-in hooks-only listener on the docker bridge gateway (CODEMAN_DOCKER_BRIDGE_HOOKS). */
|
|
325
365
|
_dockerBridgeServer = null;
|
|
326
366
|
teamWatcherHandlers = null;
|
|
327
|
-
constructor(port = 3000, https = false, testMode = false, host = '127.0.0.1', titleHostname, allowUnauthenticatedNetwork = false, basePath = '') {
|
|
367
|
+
constructor(port = 3000, https = false, testMode = false, host = '127.0.0.1', titleHostname, allowUnauthenticatedNetwork = false, basePath = '', allowUnauthenticatedTunnel = false) {
|
|
328
368
|
super();
|
|
329
369
|
this.setMaxListeners(0);
|
|
330
370
|
this.host = host;
|
|
@@ -335,6 +375,7 @@ export class WebServer extends EventEmitter {
|
|
|
335
375
|
this.testMode = testMode;
|
|
336
376
|
this.allowUnauthenticatedNetwork =
|
|
337
377
|
allowUnauthenticatedNetwork || isExplicitlyEnabled(process.env.CODEMAN_ALLOW_UNAUTHENTICATED_NETWORK);
|
|
378
|
+
this.allowUnauthenticatedTunnel = allowUnauthenticatedTunnel;
|
|
338
379
|
this.titleHostname = titleHostname || getHostname();
|
|
339
380
|
this.windowTitle = `codeman:${this.titleHostname}`;
|
|
340
381
|
this.indexHtmlTemplate = readFileSync(join(__dirname, 'public', 'index.html'), 'utf-8');
|
|
@@ -692,6 +733,7 @@ export class WebServer extends EventEmitter {
|
|
|
692
733
|
scheduledRuns: this.scheduledRuns,
|
|
693
734
|
teamWatcher: this.teamWatcher,
|
|
694
735
|
tunnelManager: this.tunnelManager,
|
|
736
|
+
allowUnauthenticatedTunnel: this.allowUnauthenticatedTunnel,
|
|
695
737
|
pushStore: this.pushStore,
|
|
696
738
|
startScheduledRun: this.startScheduledRun.bind(this),
|
|
697
739
|
stopScheduledRun: this.stopScheduledRun.bind(this),
|
|
@@ -776,6 +818,8 @@ export class WebServer extends EventEmitter {
|
|
|
776
818
|
this.userFailures = authState.userFailures;
|
|
777
819
|
this.userIpFailures = authState.userIpFailures;
|
|
778
820
|
}
|
|
821
|
+
// Bodyless API POSTs may arrive as empty chunked streams through a proxy.
|
|
822
|
+
installEmptyApiPostParser(this.app);
|
|
779
823
|
// WebSocket support (terminal I/O — low-latency bidirectional channel)
|
|
780
824
|
await this.app.register(fastifyWebsocket);
|
|
781
825
|
// Multipart parsing (used by paste-image). Replaces a hand-rolled
|
|
@@ -1042,6 +1086,17 @@ export class WebServer extends EventEmitter {
|
|
|
1042
1086
|
registerRebootRestoreRoutes(this.app, ctx);
|
|
1043
1087
|
registerReadMyMindRoutes(this.app, ctx);
|
|
1044
1088
|
registerGitStatusRoutes(this.app, ctx);
|
|
1089
|
+
// Git fetch on an interval: this is only the wake-up, the scheduler itself decides what is due. Off in
|
|
1090
|
+
// tests for the same reason as the polls below: a test drives `tick()` directly instead of waiting on
|
|
1091
|
+
// a timer the harness would have to keep alive. The setting is read FRESH inside `tick()`, so turning
|
|
1092
|
+
// it on takes effect on the next tick and turning it off actually stops the fetching.
|
|
1093
|
+
if (!this.testMode) {
|
|
1094
|
+
this.cleanup.setInterval(() => {
|
|
1095
|
+
this.gitFetchScheduler.tick().catch((err) => {
|
|
1096
|
+
console.error('[git fetch] interval tick failed:', getErrorMessage(err));
|
|
1097
|
+
});
|
|
1098
|
+
}, GIT_FETCH_TICK_INTERVAL_MS, { description: 'git fetch interval checker' });
|
|
1099
|
+
}
|
|
1045
1100
|
registerStatusTelemetryRoutes(this.app, ctx);
|
|
1046
1101
|
registerSystemRoutes(this.app, ctx);
|
|
1047
1102
|
registerCaseRoutes(this.app, ctx);
|
|
@@ -1049,6 +1104,7 @@ export class WebServer extends EventEmitter {
|
|
|
1049
1104
|
// The registry's lifetime is the server's: it drops per-session wake state on every
|
|
1050
1105
|
// cleanup path and resolves in-flight wakes on shutdown.
|
|
1051
1106
|
this.remoteWake = registerSessionRoutes(this.app, ctx);
|
|
1107
|
+
registerAgentSessionRoutes(this.app, ctx);
|
|
1052
1108
|
registerRespawnRoutes(this.app, ctx);
|
|
1053
1109
|
registerRalphRoutes(this.app, ctx);
|
|
1054
1110
|
registerPlanRoutes(this.app, ctx);
|
|
@@ -1272,6 +1328,9 @@ export class WebServer extends EventEmitter {
|
|
|
1272
1328
|
async _doCleanupSession(sessionId, killMux, reason, coordinateLayout = true) {
|
|
1273
1329
|
const session = this.sessions.get(sessionId);
|
|
1274
1330
|
this.keepWarmService.remove(sessionId);
|
|
1331
|
+
// A closed session takes its place in the fetch schedule with it: otherwise a detached-and-forgotten id
|
|
1332
|
+
// would still count as tracked, and its next run would land on a session that no longer exists.
|
|
1333
|
+
this.gitFetchScheduler.remove(sessionId);
|
|
1275
1334
|
const pinned = session?.pinned === true || this.store.getSession(sessionId)?.pinned === true;
|
|
1276
1335
|
if (coordinateLayout && session && killMux && !pinned) {
|
|
1277
1336
|
return this.tabLayouts.runSessionDeletion([{ id: sessionId, owner: session.owner }], () => this._doCleanupSession(sessionId, killMux, reason, false));
|
|
@@ -1645,6 +1704,13 @@ export class WebServer extends EventEmitter {
|
|
|
1645
1704
|
.filter((entry) => entry.capabilities.transcriptPageKeys === true)
|
|
1646
1705
|
.map((entry) => entry.id);
|
|
1647
1706
|
html = html.replace('</head>', () => `<script>window.__codemanTranscriptPageKeys=${JSON.stringify(pageKeyClis)};</script>\n</head>`);
|
|
1707
|
+
// Which run modes keep their PTY rows under a phone keyboard (inline renderers,
|
|
1708
|
+
// the `keyboardHold` capability; `_keyboardHoldEligible` in terminal-ui.js). Same
|
|
1709
|
+
// shape and reasoning as the page-key list above.
|
|
1710
|
+
const keyboardHoldClis = enabledClis()
|
|
1711
|
+
.filter((entry) => entry.capabilities.keyboardHold === 'inline')
|
|
1712
|
+
.map((entry) => entry.id);
|
|
1713
|
+
html = html.replace('</head>', () => `<script>window.__codemanKeyboardHoldModes=${JSON.stringify(keyboardHoldClis)};</script>\n</head>`);
|
|
1648
1714
|
if (!soloSessionId && process.env.CODEMAN_GESTURE === '1') {
|
|
1649
1715
|
html = html.replace('</head>', () => `<script>window.__codemanGestureAvailable=true;</script>\n</head>`);
|
|
1650
1716
|
if (settings.gestureControlEnabled === true) {
|
|
@@ -1714,12 +1780,23 @@ export class WebServer extends EventEmitter {
|
|
|
1714
1780
|
const summaryTracker = new RunSummaryTracker(session.id, session.name);
|
|
1715
1781
|
this.runSummaryTrackers.set(session.id, summaryTracker);
|
|
1716
1782
|
summaryTracker.recordSessionStarted(session.mode, session.workingDir);
|
|
1717
|
-
// Set working directory for Ralph tracker to auto-load @fix_plan.md (not supported for external CLIs)
|
|
1783
|
+
// Set working directory for Ralph tracker to auto-load @fix_plan.md (not supported for external CLIs).
|
|
1784
|
+
// A remote session's workingDir is a path on the remote host, and the watcher reads and
|
|
1785
|
+
// fs.watch()es it on the LOCAL disk, so a remote session only records the path: the fix plan stays
|
|
1786
|
+
// authoritative as for a local session (keeping the output-based completion guessers off), and its
|
|
1787
|
+
// file is read over ssh only on an explicit import (fix-plan/read).
|
|
1718
1788
|
if (!isExternalCliMode(session.mode)) {
|
|
1719
|
-
|
|
1789
|
+
if (session.remote) {
|
|
1790
|
+
session.ralphTracker.setRemoteWorkingDir(session.workingDir);
|
|
1791
|
+
}
|
|
1792
|
+
else {
|
|
1793
|
+
session.ralphTracker.setWorkingDir(session.workingDir);
|
|
1794
|
+
}
|
|
1720
1795
|
}
|
|
1721
|
-
// Start watching for new images in this session's working directory (if enabled globally and per-session)
|
|
1722
|
-
|
|
1796
|
+
// Start watching for new images in this session's working directory (if enabled globally and per-session).
|
|
1797
|
+
// A remote session's workingDir is a path on the remote host, and the watcher watches it on the LOCAL
|
|
1798
|
+
// disk, so it is skipped there (the per-session and app-wide toggles skip it too).
|
|
1799
|
+
if ((await this.isImageWatcherEnabled()) && session.imageWatcherEnabled && !session.remote) {
|
|
1723
1800
|
imageWatcher.watchSession(session.id, session.workingDir);
|
|
1724
1801
|
}
|
|
1725
1802
|
// Create and attach all listener handlers via dependency injection
|
|
@@ -2917,17 +2994,13 @@ export class WebServer extends EventEmitter {
|
|
|
2917
2994
|
// Tunnel only starts when user clicks the toggle in the UI — never on boot.
|
|
2918
2995
|
// Reset persisted tunnelEnabled so the UI toggle reflects actual state.
|
|
2919
2996
|
if (await this.isTunnelEnabled()) {
|
|
2920
|
-
const settingsPath = dataPath('settings.json');
|
|
2921
2997
|
try {
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
settings.tunnelEnabled = false;
|
|
2925
|
-
await fs.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
2998
|
+
await mutateSettingsFile((settings) => ({ ...settings, tunnelEnabled: false }));
|
|
2999
|
+
console.log('Cloudflare tunnel setting reset (tunnel only starts on explicit UI toggle)');
|
|
2926
3000
|
}
|
|
2927
|
-
catch {
|
|
2928
|
-
|
|
3001
|
+
catch (err) {
|
|
3002
|
+
console.warn('Could not reset the Cloudflare tunnel setting:', getErrorMessage(err));
|
|
2929
3003
|
}
|
|
2930
|
-
console.log('Cloudflare tunnel setting reset (tunnel only starts on explicit UI toggle)');
|
|
2931
3004
|
}
|
|
2932
3005
|
// Start team watcher for agent team awareness (always on — lightweight polling)
|
|
2933
3006
|
this.teamWatcher.start();
|
|
@@ -3102,6 +3175,9 @@ export class WebServer extends EventEmitter {
|
|
|
3102
3175
|
if (saved.autoClearEnabled !== undefined || saved.autoClearThreshold !== undefined) {
|
|
3103
3176
|
session.setAutoClear(saved.autoClearEnabled ?? false, saved.autoClearThreshold);
|
|
3104
3177
|
}
|
|
3178
|
+
if (saved.gitFetchEnabled !== undefined || saved.gitFetchIntervalSeconds !== undefined) {
|
|
3179
|
+
session.setGitFetchSettings(saved.gitFetchEnabled, saved.gitFetchIntervalSeconds);
|
|
3180
|
+
}
|
|
3105
3181
|
if (saved.autoResumeEnabled) {
|
|
3106
3182
|
// The stamp is re-armed by default, because a Codeman restart leaves the
|
|
3107
3183
|
// limit footer un-reprinted and dropping it there would strand the pause.
|
|
@@ -3318,6 +3394,11 @@ export class WebServer extends EventEmitter {
|
|
|
3318
3394
|
// below, a future `expiresAt` re-arms the timer once the pane is attached.
|
|
3319
3395
|
lastRealPromptAt: savedState?.lastRealPromptAt,
|
|
3320
3396
|
keepWarmEnabled: savedState?.keepWarmEnabled,
|
|
3397
|
+
// The session's own fetch switch and interval, carried over rather than reset to the app default:
|
|
3398
|
+
// the choice is the user's and outlives the run that made it. The scheduler reads them fresh
|
|
3399
|
+
// on its next tick, so a restored session is back on its own schedule without a restart.
|
|
3400
|
+
gitFetchEnabled: savedState?.gitFetchEnabled,
|
|
3401
|
+
gitFetchIntervalSeconds: savedState?.gitFetchIntervalSeconds,
|
|
3321
3402
|
// Conversations this pane provably owned, oldest first. Its tail is
|
|
3322
3403
|
// the conversation the CLI was on when the server stopped, which is
|
|
3323
3404
|
// what a re-attach must point the viewer at instead of the launch id.
|
|
@@ -3749,6 +3830,9 @@ export class WebServer extends EventEmitter {
|
|
|
3749
3830
|
sessionWaits.cancelEverything();
|
|
3750
3831
|
approvalInbox.stop();
|
|
3751
3832
|
this.keepWarmService.stop();
|
|
3833
|
+
// Stops the fetch sweep from starting another run while the server is closing; a git process already
|
|
3834
|
+
// running is left to finish, which is what a fetch does to a repository nothing else is touching.
|
|
3835
|
+
this.gitFetchScheduler.stop();
|
|
3752
3836
|
// A post within the debounce window before shutdown would otherwise not reach disk.
|
|
3753
3837
|
// Flushed again after `app.close()` below, for a post that lands in between.
|
|
3754
3838
|
agentInboxPersistence.flush();
|
|
@@ -3887,8 +3971,8 @@ export class WebServer extends EventEmitter {
|
|
|
3887
3971
|
}
|
|
3888
3972
|
}
|
|
3889
3973
|
}
|
|
3890
|
-
export async function startWebServer(port = 3000, https = false, testMode = false, host = '127.0.0.1', titleHostname, allowUnauthenticatedNetwork = false, basePath = '') {
|
|
3891
|
-
const server = new WebServer(port, https, testMode, host, titleHostname, allowUnauthenticatedNetwork, basePath);
|
|
3974
|
+
export async function startWebServer(port = 3000, https = false, testMode = false, host = '127.0.0.1', titleHostname, allowUnauthenticatedNetwork = false, basePath = '', allowUnauthenticatedTunnel = false) {
|
|
3975
|
+
const server = new WebServer(port, https, testMode, host, titleHostname, allowUnauthenticatedNetwork, basePath, allowUnauthenticatedTunnel);
|
|
3892
3976
|
await server.start();
|
|
3893
3977
|
return server;
|
|
3894
3978
|
}
|