tailii-host 0.1.1 → 0.4.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 +28 -10
- package/dist/{broker.d.ts → approval/broker.d.ts} +9 -5
- package/dist/{broker.js → approval/broker.js} +42 -6
- package/dist/approval/broker.js.map +1 -0
- package/dist/{hook.d.ts → approval/hook.d.ts} +48 -7
- package/dist/{hook.js → approval/hook.js} +359 -50
- package/dist/approval/hook.js.map +1 -0
- package/dist/backend/herdr.d.ts +260 -0
- package/dist/backend/herdr.js +838 -0
- package/dist/backend/herdr.js.map +1 -0
- package/dist/backend/sessionBackend.d.ts +81 -0
- package/dist/backend/sessionBackend.js +114 -0
- package/dist/backend/sessionBackend.js.map +1 -0
- package/dist/backend/tmux.d.ts +125 -0
- package/dist/backend/tmux.js +392 -0
- package/dist/backend/tmux.js.map +1 -0
- package/dist/{chatTailController.d.ts → chat/chatTailController.d.ts} +29 -6
- package/dist/{chatTailController.js → chat/chatTailController.js} +94 -18
- package/dist/chat/chatTailController.js.map +1 -0
- package/dist/{imageService.d.ts → chat/imageService.d.ts} +12 -1
- package/dist/{imageService.js → chat/imageService.js} +39 -11
- package/dist/chat/imageService.js.map +1 -0
- package/dist/chat/remoteQuestionMonitor.d.ts +27 -0
- package/dist/chat/remoteQuestionMonitor.js +128 -0
- package/dist/chat/remoteQuestionMonitor.js.map +1 -0
- package/dist/chat/subagentTailer.d.ts +30 -0
- package/dist/chat/subagentTailer.js +704 -0
- package/dist/chat/subagentTailer.js.map +1 -0
- package/dist/chat/subagentTranscript.d.ts +20 -0
- package/dist/chat/subagentTranscript.js +273 -0
- package/dist/chat/subagentTranscript.js.map +1 -0
- package/dist/{transcriptTailer.d.ts → chat/transcriptTailer.d.ts} +12 -1
- package/dist/{transcriptTailer.js → chat/transcriptTailer.js} +183 -10
- package/dist/chat/transcriptTailer.js.map +1 -0
- package/dist/cli.js +24 -10
- package/dist/cli.js.map +1 -1
- package/dist/codex/codexAccountUsage.d.ts +22 -0
- package/dist/codex/codexAccountUsage.js +128 -0
- package/dist/codex/codexAccountUsage.js.map +1 -0
- package/dist/codex/codexAppServer.d.ts +166 -0
- package/dist/codex/codexAppServer.js +1297 -0
- package/dist/codex/codexAppServer.js.map +1 -0
- package/dist/codex/codexNativeTurnController.d.ts +153 -0
- package/dist/codex/codexNativeTurnController.js +673 -0
- package/dist/codex/codexNativeTurnController.js.map +1 -0
- package/dist/codex/codexRolloutTailer.d.ts +100 -0
- package/dist/codex/codexRolloutTailer.js +568 -0
- package/dist/codex/codexRolloutTailer.js.map +1 -0
- package/dist/{codexSessionStore.d.ts → codex/codexSessionStore.d.ts} +10 -2
- package/dist/{codexSessionStore.js → codex/codexSessionStore.js} +184 -15
- package/dist/codex/codexSessionStore.js.map +1 -0
- package/dist/codex/codexSubagentTracker.d.ts +21 -0
- package/dist/codex/codexSubagentTracker.js +281 -0
- package/dist/codex/codexSubagentTracker.js.map +1 -0
- package/dist/codex/codexToolActivity.d.ts +69 -0
- package/dist/codex/codexToolActivity.js +425 -0
- package/dist/codex/codexToolActivity.js.map +1 -0
- package/dist/{codexUsage.d.ts → codex/codexUsage.d.ts} +1 -1
- package/dist/{codexUsage.js → codex/codexUsage.js} +19 -26
- package/dist/codex/codexUsage.js.map +1 -0
- package/dist/commands/doctor.d.ts +65 -0
- package/dist/commands/doctor.js +425 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/{hookSettings.d.ts → commands/hookSettings.d.ts} +14 -1
- package/dist/{hookSettings.js → commands/hookSettings.js} +96 -12
- package/dist/commands/hookSettings.js.map +1 -0
- package/dist/{kick.js → commands/kick.js} +16 -1
- package/dist/commands/kick.js.map +1 -0
- package/dist/{launch.d.ts → commands/launch.d.ts} +67 -5
- package/dist/commands/launch.js +716 -0
- package/dist/commands/launch.js.map +1 -0
- package/dist/commands/legacyHomeMigration.js.map +1 -0
- package/dist/{pairingCode.d.ts → commands/pairingCode.d.ts} +29 -2
- package/dist/{pairingCode.js → commands/pairingCode.js} +120 -11
- package/dist/commands/pairingCode.js.map +1 -0
- package/dist/{pushTokenCommand.d.ts → commands/pushTokenCommand.d.ts} +1 -1
- package/dist/{pushTokenCommand.js → commands/pushTokenCommand.js} +2 -2
- package/dist/commands/pushTokenCommand.js.map +1 -0
- package/dist/commands/selfUpdate.d.ts +71 -0
- package/dist/commands/selfUpdate.js +536 -0
- package/dist/commands/selfUpdate.js.map +1 -0
- package/dist/{setup.d.ts → commands/setup.d.ts} +17 -6
- package/dist/{setup.js → commands/setup.js} +133 -75
- package/dist/commands/setup.js.map +1 -0
- package/dist/engine/context.d.ts +145 -0
- package/dist/engine/context.js +184 -0
- package/dist/engine/context.js.map +1 -0
- package/dist/engine/engine.d.ts +121 -0
- package/dist/engine/engine.js +808 -0
- package/dist/engine/engine.js.map +1 -0
- package/dist/engine/handlers/accountUsage.d.ts +53 -0
- package/dist/engine/handlers/accountUsage.js +203 -0
- package/dist/engine/handlers/accountUsage.js.map +1 -0
- package/dist/engine/handlers/claudeModels.d.ts +2 -0
- package/dist/engine/handlers/claudeModels.js +23 -0
- package/dist/engine/handlers/claudeModels.js.map +1 -0
- package/dist/engine/handlers/codex.d.ts +2 -0
- package/dist/engine/handlers/codex.js +97 -0
- package/dist/engine/handlers/codex.js.map +1 -0
- package/dist/engine/handlers/conversation.d.ts +2 -0
- package/dist/engine/handlers/conversation.js +259 -0
- package/dist/engine/handlers/conversation.js.map +1 -0
- package/dist/engine/handlers/core.d.ts +2 -0
- package/dist/engine/handlers/core.js +66 -0
- package/dist/engine/handlers/core.js.map +1 -0
- package/dist/engine/handlers/git.d.ts +2 -0
- package/dist/engine/handlers/git.js +127 -0
- package/dist/engine/handlers/git.js.map +1 -0
- package/dist/engine/handlers/index.d.ts +2 -0
- package/dist/engine/handlers/index.js +34 -0
- package/dist/engine/handlers/index.js.map +1 -0
- package/dist/engine/handlers/mode.d.ts +2 -0
- package/dist/engine/handlers/mode.js +194 -0
- package/dist/engine/handlers/mode.js.map +1 -0
- package/dist/engine/handlers/officialApps.d.ts +2 -0
- package/dist/engine/handlers/officialApps.js +79 -0
- package/dist/engine/handlers/officialApps.js.map +1 -0
- package/dist/engine/handlers/preview.d.ts +2 -0
- package/dist/engine/handlers/preview.js +59 -0
- package/dist/engine/handlers/preview.js.map +1 -0
- package/dist/engine/handlers/selfUpdate.d.ts +2 -0
- package/dist/engine/handlers/selfUpdate.js +52 -0
- package/dist/engine/handlers/selfUpdate.js.map +1 -0
- package/dist/engine/handlers/session.d.ts +2 -0
- package/dist/engine/handlers/session.js +385 -0
- package/dist/engine/handlers/session.js.map +1 -0
- package/dist/engine/handlers/usage.d.ts +2 -0
- package/dist/engine/handlers/usage.js +96 -0
- package/dist/engine/handlers/usage.js.map +1 -0
- package/dist/engine/handlers/workspace.d.ts +2 -0
- package/dist/engine/handlers/workspace.js +110 -0
- package/dist/engine/handlers/workspace.js.map +1 -0
- package/dist/engine/slashCommands.d.ts +3 -0
- package/dist/engine/slashCommands.js +211 -0
- package/dist/engine/slashCommands.js.map +1 -0
- package/dist/hub/engineRelaySocket.d.ts +58 -0
- package/dist/hub/engineRelaySocket.js +161 -0
- package/dist/hub/engineRelaySocket.js.map +1 -0
- package/dist/hub/hubClient.d.ts +28 -0
- package/dist/hub/hubClient.js +187 -0
- package/dist/hub/hubClient.js.map +1 -0
- package/dist/hub/hubDaemon.d.ts +69 -0
- package/dist/hub/hubDaemon.js +466 -0
- package/dist/hub/hubDaemon.js.map +1 -0
- package/dist/hub/hubProtocol.d.ts +161 -0
- package/dist/hub/hubProtocol.js +379 -0
- package/dist/hub/hubProtocol.js.map +1 -0
- package/dist/hub/panePreviewPump.d.ts +65 -0
- package/dist/hub/panePreviewPump.js +187 -0
- package/dist/hub/panePreviewPump.js.map +1 -0
- package/dist/hub/questionInjection.d.ts +19 -0
- package/dist/hub/questionInjection.js +126 -0
- package/dist/hub/questionInjection.js.map +1 -0
- package/dist/hub/reaper.d.ts +74 -0
- package/dist/hub/reaper.js +333 -0
- package/dist/hub/reaper.js.map +1 -0
- package/dist/hub/sessionHub.d.ts +203 -0
- package/dist/hub/sessionHub.js +1862 -0
- package/dist/hub/sessionHub.js.map +1 -0
- package/dist/protocol/common.d.ts +18 -0
- package/dist/protocol/common.js +78 -0
- package/dist/protocol/common.js.map +1 -0
- package/dist/protocol/decode.d.ts +3 -0
- package/dist/protocol/decode.js +1058 -0
- package/dist/protocol/decode.js.map +1 -0
- package/dist/protocol/encode.d.ts +3 -0
- package/dist/protocol/encode.js +84 -0
- package/dist/protocol/encode.js.map +1 -0
- package/dist/protocol/messages.d.ts +1025 -0
- package/dist/protocol/messages.js +8 -0
- package/dist/protocol/messages.js.map +1 -0
- package/dist/protocol.d.ts +4 -329
- package/dist/protocol.js +13 -531
- package/dist/protocol.js.map +1 -1
- package/dist/push/apnsConfigStore.js.map +1 -0
- package/dist/push/apnsJwtProvider.js.map +1 -0
- package/dist/{apnsSender.js.map → push/apnsSender.js.map} +1 -1
- package/dist/{approvalPushNotifier.js → push/approvalPushNotifier.js} +1 -1
- package/dist/push/approvalPushNotifier.js.map +1 -0
- package/dist/push/deviceTokenStore.js.map +1 -0
- package/dist/{pushTypes.js → push/pushTypes.js} +1 -1
- package/dist/push/pushTypes.js.map +1 -0
- package/dist/push/sendLog.js.map +1 -0
- package/dist/services/accountIdentity.d.ts +44 -0
- package/dist/services/accountIdentity.js +184 -0
- package/dist/services/accountIdentity.js.map +1 -0
- package/dist/services/claudeCredentialRefresh.d.ts +30 -0
- package/dist/services/claudeCredentialRefresh.js +345 -0
- package/dist/services/claudeCredentialRefresh.js.map +1 -0
- package/dist/services/claudeModelCatalog.d.ts +21 -0
- package/dist/services/claudeModelCatalog.js +181 -0
- package/dist/services/claudeModelCatalog.js.map +1 -0
- package/dist/{dirLister.d.ts → services/dirLister.d.ts} +9 -4
- package/dist/services/dirLister.js +169 -0
- package/dist/services/dirLister.js.map +1 -0
- package/dist/services/fileService.d.ts +10 -0
- package/dist/services/fileService.js +123 -0
- package/dist/services/fileService.js.map +1 -0
- package/dist/services/gitService.d.ts +79 -0
- package/dist/services/gitService.js +648 -0
- package/dist/services/gitService.js.map +1 -0
- package/dist/services/hostVersions.d.ts +38 -0
- package/dist/services/hostVersions.js +120 -0
- package/dist/services/hostVersions.js.map +1 -0
- package/dist/services/officialApps.d.ts +148 -0
- package/dist/services/officialApps.js +1079 -0
- package/dist/services/officialApps.js.map +1 -0
- package/dist/services/planUsageFetcher.d.ts +119 -0
- package/dist/services/planUsageFetcher.js +357 -0
- package/dist/services/planUsageFetcher.js.map +1 -0
- package/dist/services/previewServer.d.ts +31 -0
- package/dist/services/previewServer.js +233 -0
- package/dist/services/previewServer.js.map +1 -0
- package/dist/services/quicGateway.d.ts +143 -0
- package/dist/services/quicGateway.js +292 -0
- package/dist/services/quicGateway.js.map +1 -0
- package/dist/services/serveService.d.ts +50 -0
- package/dist/services/serveService.js +302 -0
- package/dist/services/serveService.js.map +1 -0
- package/dist/services/usageAggregator.js.map +1 -0
- package/dist/sessions/claudeSessionStore.d.ts +80 -0
- package/dist/sessions/claudeSessionStore.js +477 -0
- package/dist/sessions/claudeSessionStore.js.map +1 -0
- package/dist/sessions/heartbeat.d.ts +24 -0
- package/dist/sessions/heartbeat.js +86 -0
- package/dist/sessions/heartbeat.js.map +1 -0
- package/dist/sessions/liveSessionJoin.d.ts +20 -0
- package/dist/sessions/liveSessionJoin.js +80 -0
- package/dist/sessions/liveSessionJoin.js.map +1 -0
- package/dist/sessions/sessionActivityProvider.d.ts +14 -0
- package/dist/sessions/sessionActivityProvider.js +57 -0
- package/dist/sessions/sessionActivityProvider.js.map +1 -0
- package/dist/{sessionListService.d.ts → sessions/sessionListService.d.ts} +3 -3
- package/dist/{sessionListService.js → sessions/sessionListService.js} +23 -6
- package/dist/sessions/sessionListService.js.map +1 -0
- package/dist/{sessionMetadataStore.d.ts → sessions/sessionMetadataStore.d.ts} +18 -0
- package/dist/{sessionMetadataStore.js → sessions/sessionMetadataStore.js} +36 -1
- package/dist/sessions/sessionMetadataStore.js.map +1 -0
- package/dist/{sessionSearch.d.ts → sessions/sessionSearch.d.ts} +1 -1
- package/dist/sessions/sessionSearch.js.map +1 -0
- package/dist/shared/hostDisplayName.d.ts +11 -0
- package/dist/shared/hostDisplayName.js +50 -0
- package/dist/shared/hostDisplayName.js.map +1 -0
- package/dist/{lineWriter.d.ts → shared/lineWriter.d.ts} +1 -1
- package/dist/{lineWriter.js → shared/lineWriter.js} +1 -1
- package/dist/shared/lineWriter.js.map +1 -0
- package/dist/{observationLog.js.map → shared/observationLog.js.map} +1 -1
- package/dist/{paths.d.ts → shared/paths.d.ts} +7 -0
- package/dist/{paths.js → shared/paths.js} +9 -0
- package/dist/shared/paths.js.map +1 -0
- package/dist/shared/permissionMode.d.ts +10 -0
- package/dist/shared/permissionMode.js +51 -0
- package/dist/shared/permissionMode.js.map +1 -0
- package/dist/shared/skillInjection.d.ts +9 -0
- package/dist/shared/skillInjection.js +16 -0
- package/dist/shared/skillInjection.js.map +1 -0
- package/dist/shared/sleep.js.map +1 -0
- package/dist/{socketPath.d.ts → shared/socketPath.d.ts} +4 -0
- package/dist/{socketPath.js → shared/socketPath.js} +22 -0
- package/dist/shared/socketPath.js.map +1 -0
- package/dist/shared/version.js.map +1 -0
- package/package.json +13 -7
- package/dist/apnsConfigStore.js.map +0 -1
- package/dist/apnsJwtProvider.js.map +0 -1
- package/dist/approvalPushNotifier.js.map +0 -1
- package/dist/broker.js.map +0 -1
- package/dist/chatTailController.js.map +0 -1
- package/dist/claudeSessionStore.d.ts +0 -15
- package/dist/claudeSessionStore.js +0 -201
- package/dist/claudeSessionStore.js.map +0 -1
- package/dist/codexRolloutTailer.d.ts +0 -56
- package/dist/codexRolloutTailer.js +0 -303
- package/dist/codexRolloutTailer.js.map +0 -1
- package/dist/codexSessionStore.js.map +0 -1
- package/dist/codexUsage.js.map +0 -1
- package/dist/deviceTokenStore.js.map +0 -1
- package/dist/dirLister.js +0 -98
- package/dist/dirLister.js.map +0 -1
- package/dist/doctor.d.ts +0 -36
- package/dist/doctor.js +0 -162
- package/dist/doctor.js.map +0 -1
- package/dist/engine.d.ts +0 -85
- package/dist/engine.js +0 -962
- package/dist/engine.js.map +0 -1
- package/dist/hook.js.map +0 -1
- package/dist/hookSettings.js.map +0 -1
- package/dist/idleReaper.d.ts +0 -13
- package/dist/idleReaper.js +0 -30
- package/dist/idleReaper.js.map +0 -1
- package/dist/imageService.js.map +0 -1
- package/dist/kick.js.map +0 -1
- package/dist/launch.js +0 -396
- package/dist/launch.js.map +0 -1
- package/dist/legacyHomeMigration.js.map +0 -1
- package/dist/lineWriter.js.map +0 -1
- package/dist/mdnsAdvertiser.d.ts +0 -46
- package/dist/mdnsAdvertiser.js +0 -268
- package/dist/mdnsAdvertiser.js.map +0 -1
- package/dist/pairingCode.js.map +0 -1
- package/dist/paths.js.map +0 -1
- package/dist/permissionMode.d.ts +0 -8
- package/dist/permissionMode.js +0 -32
- package/dist/permissionMode.js.map +0 -1
- package/dist/planUsageFetcher.d.ts +0 -35
- package/dist/planUsageFetcher.js +0 -172
- package/dist/planUsageFetcher.js.map +0 -1
- package/dist/pushTokenCommand.js.map +0 -1
- package/dist/pushTypes.js.map +0 -1
- package/dist/sendLog.js.map +0 -1
- package/dist/sessionActivityProvider.d.ts +0 -7
- package/dist/sessionActivityProvider.js +0 -44
- package/dist/sessionActivityProvider.js.map +0 -1
- package/dist/sessionIdleTracker.d.ts +0 -19
- package/dist/sessionIdleTracker.js +0 -42
- package/dist/sessionIdleTracker.js.map +0 -1
- package/dist/sessionListService.js.map +0 -1
- package/dist/sessionMetadataStore.js.map +0 -1
- package/dist/sessionSearch.js.map +0 -1
- package/dist/setup.js.map +0 -1
- package/dist/sleep.js.map +0 -1
- package/dist/socketPath.js.map +0 -1
- package/dist/subagentTailer.d.ts +0 -15
- package/dist/subagentTailer.js +0 -399
- package/dist/subagentTailer.js.map +0 -1
- package/dist/tmux.d.ts +0 -62
- package/dist/tmux.js +0 -163
- package/dist/tmux.js.map +0 -1
- package/dist/transcriptTailer.js.map +0 -1
- package/dist/usageAggregator.js.map +0 -1
- package/dist/version.js.map +0 -1
- /package/dist/{kick.d.ts → commands/kick.d.ts} +0 -0
- /package/dist/{legacyHomeMigration.d.ts → commands/legacyHomeMigration.d.ts} +0 -0
- /package/dist/{legacyHomeMigration.js → commands/legacyHomeMigration.js} +0 -0
- /package/dist/{apnsConfigStore.d.ts → push/apnsConfigStore.d.ts} +0 -0
- /package/dist/{apnsConfigStore.js → push/apnsConfigStore.js} +0 -0
- /package/dist/{apnsJwtProvider.d.ts → push/apnsJwtProvider.d.ts} +0 -0
- /package/dist/{apnsJwtProvider.js → push/apnsJwtProvider.js} +0 -0
- /package/dist/{apnsSender.d.ts → push/apnsSender.d.ts} +0 -0
- /package/dist/{apnsSender.js → push/apnsSender.js} +0 -0
- /package/dist/{approvalPushNotifier.d.ts → push/approvalPushNotifier.d.ts} +0 -0
- /package/dist/{deviceTokenStore.d.ts → push/deviceTokenStore.d.ts} +0 -0
- /package/dist/{deviceTokenStore.js → push/deviceTokenStore.js} +0 -0
- /package/dist/{pushTypes.d.ts → push/pushTypes.d.ts} +0 -0
- /package/dist/{sendLog.d.ts → push/sendLog.d.ts} +0 -0
- /package/dist/{sendLog.js → push/sendLog.js} +0 -0
- /package/dist/{usageAggregator.d.ts → services/usageAggregator.d.ts} +0 -0
- /package/dist/{usageAggregator.js → services/usageAggregator.js} +0 -0
- /package/dist/{sessionSearch.js → sessions/sessionSearch.js} +0 -0
- /package/dist/{observationLog.d.ts → shared/observationLog.d.ts} +0 -0
- /package/dist/{observationLog.js → shared/observationLog.js} +0 -0
- /package/dist/{sleep.d.ts → shared/sleep.d.ts} +0 -0
- /package/dist/{sleep.js → shared/sleep.js} +0 -0
- /package/dist/{version.d.ts → shared/version.d.ts} +0 -0
- /package/dist/{version.js → shared/version.js} +0 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
// tmux.ts
|
|
2
|
+
// tailii (TS host) — tmux セッションの list / reattach / kill / send-keys / capture-pane
|
|
3
|
+
// Swift 版 TmuxSessionManager.swift の移植。
|
|
4
|
+
// 生存集合は `tmux ls -F '#{session_name}'`、cwd は SessionMetadataStore を権威とする。
|
|
5
|
+
import { execFile } from "node:child_process";
|
|
6
|
+
import { PROTOCOL_V1 } from "../protocol.js";
|
|
7
|
+
import { SessionMetadataStore, validateSessionName } from "../sessions/sessionMetadataStore.js";
|
|
8
|
+
/** tmux 実行ファイルの既定絶対パス(PATH 外のため絶対指定)。 */
|
|
9
|
+
export const DEFAULT_TMUX_PATH = "/opt/homebrew/bin/tmux";
|
|
10
|
+
/** pane_current_command がこの集合なら、Claude 本体は終了してシェルだけが残っている。 */
|
|
11
|
+
const SHELL_COMMANDS = new Set(["zsh", "bash", "sh", "dash", "fish", "tcsh", "csh", "ksh", "login"]);
|
|
12
|
+
/** tmux の pane_current_command がエージェント実行中に見えるか。空文字は判定不能なので安全側。 */
|
|
13
|
+
export function paneCommandLooksLikeAgent(command) {
|
|
14
|
+
const normalized = command.trim().toLowerCase();
|
|
15
|
+
return normalized.length === 0 || !SHELL_COMMANDS.has(normalized);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* claude TUI 入力欄の先頭に付くモード記号。
|
|
19
|
+
* - `❯`(276F) / `›`(203A): 通常入力
|
|
20
|
+
* - `!`: シェルモード(空入力の先頭 `!` が記号として吸われ、本文には残らない)
|
|
21
|
+
*
|
|
22
|
+
* 実測 2.1.220: `#` はモード記号ではなく本文の一部(`❯ #メモ` と描画される)。
|
|
23
|
+
*/
|
|
24
|
+
const INPUT_PROMPT_SIGILS = ["❯", "›", "!"];
|
|
25
|
+
/** 入力欄がシェルモード(プロンプトが `!`)か。 */
|
|
26
|
+
export function inputBoxIsShellMode(box) {
|
|
27
|
+
return box?.prompt === "!";
|
|
28
|
+
}
|
|
29
|
+
/** 行が入力欄の水平罫線(`────…`)か。名前付き会話は上罫線中央にタイトルが埋まる。 */
|
|
30
|
+
function isInputBoxRuleLine(line) {
|
|
31
|
+
const scalars = [...line];
|
|
32
|
+
if (scalars.length < 3)
|
|
33
|
+
return false;
|
|
34
|
+
let leading = 0;
|
|
35
|
+
for (const ch of scalars) {
|
|
36
|
+
if (ch === "─" || ch === "━")
|
|
37
|
+
leading += 1;
|
|
38
|
+
else
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
if (leading === scalars.length)
|
|
42
|
+
return true;
|
|
43
|
+
if (leading < 3)
|
|
44
|
+
return false;
|
|
45
|
+
let trailing = 0;
|
|
46
|
+
for (const ch of [...scalars].reverse()) {
|
|
47
|
+
if (ch === "─" || ch === "━")
|
|
48
|
+
trailing += 1;
|
|
49
|
+
else
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
return trailing >= 2;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 画面から claude TUI の入力欄を取り出す(TESTABLE)。
|
|
56
|
+
*
|
|
57
|
+
* 入力欄は末尾側の 2 本の水平罫線に挟まれた領域。`❯` 行だけを探す旧実装は
|
|
58
|
+
* シェルモード(プロンプトが `!` になる)で入力欄を見失い、注入検証が必ず失敗
|
|
59
|
+
* → 本文を 3 回重ね打ちして入力欄を壊し、送信失敗として throw していた
|
|
60
|
+
* (実障害 2026-08-03: `!` 始まりの送信が HerdrFailedError)。
|
|
61
|
+
* 罫線が見つからない画面は最後の `❯` 行 **1 行だけ**へフォールバックする
|
|
62
|
+
* (旧 `inputBoxHasPendingText` と同じ判定なので退行しない)。
|
|
63
|
+
* 判定不能は null(呼び出し側は fail-open 材料として扱う)。
|
|
64
|
+
*
|
|
65
|
+
* **前提**: 選択ダイアログ表示中は本文側の罫線ペア(`──── Planning: … ────` 等)を
|
|
66
|
+
* 入力欄と誤認しうる。注入前にダイアログを閉じるのは呼び出し側の責務
|
|
67
|
+
* (`sendTextSubmit` が `selectionDialogVisible` → Esc で担保)。
|
|
68
|
+
*/
|
|
69
|
+
export function extractClaudeInputBox(screen) {
|
|
70
|
+
const lines = screen.split("\n").map((line) => line.trim());
|
|
71
|
+
let bottom = -1;
|
|
72
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
73
|
+
if (isInputBoxRuleLine(lines[index] ?? "")) {
|
|
74
|
+
bottom = index;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
let top = -1;
|
|
79
|
+
for (let index = bottom - 1; index >= 0; index -= 1) {
|
|
80
|
+
if (isInputBoxRuleLine(lines[index] ?? "")) {
|
|
81
|
+
top = index;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (top >= 0 && bottom > top)
|
|
86
|
+
return splitInputPrompt(lines.slice(top + 1, bottom));
|
|
87
|
+
// 罫線が無い画面は最後の `❯` 行 1 行だけを入力欄とみなす(下の行まで含めると
|
|
88
|
+
// フッターを未送信テキストと誤認して送信確定ループが終わらない)。
|
|
89
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
90
|
+
if ((lines[index] ?? "").startsWith("❯"))
|
|
91
|
+
return splitInputPrompt([lines[index] ?? ""]);
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 入力が空のとき claude TUI が入力欄へ薄字で出すプレースホルダ(実測 2.1.220)。
|
|
97
|
+
* 未送信テキストと誤認すると、シェルモード離脱(空入力の Backspace)に入れず
|
|
98
|
+
* 通常メッセージがシェルコマンドとして実行される(実機フレーム 2026-08-03)。
|
|
99
|
+
*
|
|
100
|
+
* 割り切り: 薄字かどうかは capture では判別できないため文言一致で判定する。
|
|
101
|
+
* ユーザーが偶然この文言だけを打つと「空」と誤判定するが、その場合の実害は
|
|
102
|
+
* 残留 flush の Enter が飛ばないこと(次の注入で本文が連結される)に留まる。
|
|
103
|
+
*/
|
|
104
|
+
function isInputPlaceholder(text) {
|
|
105
|
+
if (text === "Press up to edit queued messages")
|
|
106
|
+
return true;
|
|
107
|
+
if (text.startsWith('Try "') && text.endsWith('"'))
|
|
108
|
+
return true;
|
|
109
|
+
return text.startsWith("Message @") && text.endsWith("…");
|
|
110
|
+
}
|
|
111
|
+
/** 入力欄の行群を「モード記号 + 本文」へ分解する。 */
|
|
112
|
+
function splitInputPrompt(bodyLines) {
|
|
113
|
+
const body = [...bodyLines];
|
|
114
|
+
const first = body[0] ?? "";
|
|
115
|
+
const sigil = INPUT_PROMPT_SIGILS.find((s) => first.startsWith(s));
|
|
116
|
+
if (sigil !== undefined)
|
|
117
|
+
body[0] = first.slice(sigil.length);
|
|
118
|
+
const text = body.join("\n").trim();
|
|
119
|
+
return { prompt: sigil ?? "", text: isInputPlaceholder(text) ? "" : text };
|
|
120
|
+
}
|
|
121
|
+
/** 実 tmux を絶対パスで起動する既定ランナー。tmux 非0 exit は throw せず結果で表現する。 */
|
|
122
|
+
export function processTmuxCommandRunner(tmuxPath = DEFAULT_TMUX_PATH) {
|
|
123
|
+
return (args) => new Promise((resolve, reject) => {
|
|
124
|
+
execFile(tmuxPath, args, { maxBuffer: 16 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
125
|
+
if (error && typeof error.code === "string") {
|
|
126
|
+
// 実行ファイル起動自体の失敗(ENOENT 等)のみ throw(Swift 版と同じ境界)。
|
|
127
|
+
reject(error);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const exitCode = error && typeof error.code === "number" ? error.code : error ? 1 : 0;
|
|
131
|
+
resolve({ exitCode, stdout: String(stdout), stderr: String(stderr) });
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/** TmuxSessionManager が投げる型付きエラー。 */
|
|
136
|
+
export class TmuxFailedError extends Error {
|
|
137
|
+
args;
|
|
138
|
+
exitCode;
|
|
139
|
+
stderr;
|
|
140
|
+
constructor(args, exitCode, stderr) {
|
|
141
|
+
super(`tmux ${args.join(" ")} failed (exit ${exitCode}): ${stderr}`);
|
|
142
|
+
this.args = args;
|
|
143
|
+
this.exitCode = exitCode;
|
|
144
|
+
this.stderr = stderr;
|
|
145
|
+
this.name = "TmuxFailedError";
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/** tmux セッションの list / reattach / kill とメタデータ統合。 */
|
|
149
|
+
export class TmuxSessionManager {
|
|
150
|
+
runner;
|
|
151
|
+
store;
|
|
152
|
+
captureLines;
|
|
153
|
+
protocolVersion;
|
|
154
|
+
constructor(options = {}) {
|
|
155
|
+
this.runner = options.runner ?? processTmuxCommandRunner();
|
|
156
|
+
this.store = options.store ?? new SessionMetadataStore();
|
|
157
|
+
this.captureLines = options.captureLines ?? 50;
|
|
158
|
+
this.protocolVersion = options.protocolVersion ?? PROTOCOL_V1;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* 現存する各セッションを name/cwd/alive で列挙する(name 昇順、メタのみは alive:false)。
|
|
162
|
+
* updatedAt はここでは付与しない。tmux `#{session_activity}` はセッション作成自体を「活動」
|
|
163
|
+
* として刻むため、会話ゼロの新規セッションが実会話より上に浮く。整列時刻の権威は
|
|
164
|
+
* SessionActivityProvider(セッション自身の transcript mtime)に一本化する。
|
|
165
|
+
*/
|
|
166
|
+
async list() {
|
|
167
|
+
const alive = await this.liveSessionNames();
|
|
168
|
+
// herdr backend のメタは HerdrSessionManager が列挙する(Composite で和を取る)。
|
|
169
|
+
const metas = this.store.all().filter((meta) => meta.backend !== "herdr");
|
|
170
|
+
const cwdByName = new Map();
|
|
171
|
+
const claudeSessionIdByName = new Map();
|
|
172
|
+
const providerSessionIdByName = new Map();
|
|
173
|
+
const agentByName = new Map();
|
|
174
|
+
for (const meta of metas) {
|
|
175
|
+
cwdByName.set(meta.name, meta.cwd);
|
|
176
|
+
if (meta.claudeSessionId !== undefined)
|
|
177
|
+
claudeSessionIdByName.set(meta.name, meta.claudeSessionId);
|
|
178
|
+
const agent = meta.agent ?? "claude";
|
|
179
|
+
if (meta.agent !== undefined)
|
|
180
|
+
agentByName.set(meta.name, meta.agent);
|
|
181
|
+
const providerSessionId = meta.providerSessionId ?? (agent === "claude" ? meta.claudeSessionId : undefined);
|
|
182
|
+
if (providerSessionId !== undefined)
|
|
183
|
+
providerSessionIdByName.set(meta.name, providerSessionId);
|
|
184
|
+
}
|
|
185
|
+
const names = new Set(alive);
|
|
186
|
+
for (const meta of metas)
|
|
187
|
+
names.add(meta.name);
|
|
188
|
+
const infos = [...names].map((name) => ({
|
|
189
|
+
name,
|
|
190
|
+
cwd: cwdByName.get(name) ?? "",
|
|
191
|
+
alive: alive.has(name),
|
|
192
|
+
...(claudeSessionIdByName.has(name) ? { claudeSessionId: claudeSessionIdByName.get(name) } : {}),
|
|
193
|
+
...(agentByName.has(name) ? { agent: agentByName.get(name) } : {}),
|
|
194
|
+
...(providerSessionIdByName.has(name)
|
|
195
|
+
? { providerSessionId: providerSessionIdByName.get(name) }
|
|
196
|
+
: {}),
|
|
197
|
+
}));
|
|
198
|
+
return infos.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
199
|
+
}
|
|
200
|
+
/** 既存セッションへ reattach(生存: attached / 不在: session_not_found エラー封筒)。 */
|
|
201
|
+
async reattach(name) {
|
|
202
|
+
validateSessionName(name);
|
|
203
|
+
const aliveNames = await this.liveSessionNames();
|
|
204
|
+
if (!aliveNames.has(name)) {
|
|
205
|
+
return {
|
|
206
|
+
kind: "notFound",
|
|
207
|
+
error: {
|
|
208
|
+
type: "error",
|
|
209
|
+
v: this.protocolVersion,
|
|
210
|
+
code: "session_not_found",
|
|
211
|
+
message: `セッション '${name}' は存在しません。新規に起動できます。`,
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
// Claude が終了してシェルだけ残った tmux は、存在していても入力先としては無効。
|
|
216
|
+
// stale session を消して notFound と同じ再開経路へ流し、engine に --resume 起動させる。
|
|
217
|
+
// Codex のターンは App Server が駆動し、TUI が shell command に見える待機期間もあるため除外する。
|
|
218
|
+
if ((this.store.get(name)?.agent ?? "claude") === "claude" && !(await this.agentProcessAlive(name))) {
|
|
219
|
+
await this.kill(name);
|
|
220
|
+
return {
|
|
221
|
+
kind: "notFound",
|
|
222
|
+
error: {
|
|
223
|
+
type: "error",
|
|
224
|
+
v: this.protocolVersion,
|
|
225
|
+
code: "session_not_found",
|
|
226
|
+
message: `セッション '${name}' のエージェントを再起動します。`,
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const cwd = this.store.get(name)?.cwd ?? "";
|
|
231
|
+
const recent = await this.capturePane(name);
|
|
232
|
+
return { kind: "attached", info: { name, cwd, alive: true }, recentOutput: recent };
|
|
233
|
+
}
|
|
234
|
+
/** pane 内のエージェント生存判定。tmux エラーや空出力は二重起動を避けて true に倒す。 */
|
|
235
|
+
async agentProcessAlive(name) {
|
|
236
|
+
validateSessionName(name);
|
|
237
|
+
try {
|
|
238
|
+
const result = await this.runner([
|
|
239
|
+
"display-message", "-p", "-t", this.paneTarget(name), "#{pane_current_command}",
|
|
240
|
+
]);
|
|
241
|
+
if (result.exitCode !== 0)
|
|
242
|
+
return true;
|
|
243
|
+
return paneCommandLooksLikeAgent(result.stdout);
|
|
244
|
+
}
|
|
245
|
+
catch {
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* 会話カスタムタイトルの端末表示追随(session-title)。tmux はセッション名自体が
|
|
251
|
+
* 識別子(rename は全経路の解決を壊す)のため no-op。
|
|
252
|
+
*/
|
|
253
|
+
async setDisplayTitle(name, _title) {
|
|
254
|
+
validateSessionName(name);
|
|
255
|
+
}
|
|
256
|
+
/** 指定セッションのみを終了する(tmux kill-session -t <name>)。 */
|
|
257
|
+
async kill(name) {
|
|
258
|
+
validateSessionName(name);
|
|
259
|
+
const args = ["kill-session", "-t", name];
|
|
260
|
+
const result = await this.runner(args);
|
|
261
|
+
if (result.exitCode !== 0) {
|
|
262
|
+
throw new TmuxFailedError(args, result.exitCode, result.stderr);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* 本文入力と送信確定を 1 操作で行う(chat 注入・kick 用, SessionBackend 共通面)。
|
|
267
|
+
* literal 送出 → 150ms(Ink 再描画待ち)→ Enter。
|
|
268
|
+
*/
|
|
269
|
+
async sendTextSubmit(name, text) {
|
|
270
|
+
// 中断(停止)直後は claude が queued メッセージを入力欄へ書き戻す。残存したまま
|
|
271
|
+
// 注入すると今回の本文がその後ろへ連結され 1 メッセージになる(実機FB 2026-07-29)。
|
|
272
|
+
// 残存は先に Enter で独立メッセージとして送信し切ってから注入する。空入力への
|
|
273
|
+
// Enter は no-op なので誤検出は無害(herdr 側 sendTextSubmit と同じ防御)。
|
|
274
|
+
if (await this.inputBoxHasPendingText(name)) {
|
|
275
|
+
await this.sendKeys(name, ["Enter"]);
|
|
276
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
277
|
+
}
|
|
278
|
+
// 入力欄がシェルモード(プロンプト `!`)のまま残っていると、注入した通常メッセージが
|
|
279
|
+
// そのままシェルコマンドとして実行される。空入力の Backspace(tmux キー名は BSpace)で
|
|
280
|
+
// 記号を消して通常入力へ戻す。`!` 始まりの本文は注入時に自分でシェルモードへ入るので、
|
|
281
|
+
// 常に通常モードから始めるのが決定的で安全(herdr 側 exitShellMode と同じ防御)。
|
|
282
|
+
await this.exitShellMode(name);
|
|
283
|
+
await this.sendKeys(name, [text], true);
|
|
284
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
285
|
+
await this.sendKeys(name, ["Enter"]);
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* 入力欄がシェルモードなら BSpace で通常入力へ戻す。判定不能・tmux エラーは no-op
|
|
289
|
+
* (fail-open。この補助操作のエラーを表に出すと「送信できない」原因が BSpace 送出の
|
|
290
|
+
* 失敗に見えてしまうので、実エラーは続く本文注入の send-keys 失敗として顕在化させる)。
|
|
291
|
+
*/
|
|
292
|
+
async exitShellMode(name) {
|
|
293
|
+
try {
|
|
294
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
295
|
+
const box = extractClaudeInputBox(await this.captureVisibleScreen(name));
|
|
296
|
+
if (!inputBoxIsShellMode(box) || (box?.text.length ?? 0) > 0)
|
|
297
|
+
return;
|
|
298
|
+
await this.sendKeys(name, ["BSpace"]);
|
|
299
|
+
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// no-op(fail-open)
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/** 入力欄に未送信テキストが残っているか。判定不能は false。 */
|
|
307
|
+
async inputBoxHasPendingText(name) {
|
|
308
|
+
try {
|
|
309
|
+
const box = extractClaudeInputBox(await this.captureVisibleScreen(name));
|
|
310
|
+
return box !== null && box.text.length > 0;
|
|
311
|
+
}
|
|
312
|
+
catch {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* 入力欄判定用に **viewport 全体**を取る(末尾 N 行で切らない)。
|
|
318
|
+
*
|
|
319
|
+
* claude TUI の入力欄の最大高さは端末サイズにほぼ比例する(実測 2.1.220:
|
|
320
|
+
* 63 行端末で 26 行 / 120 行端末で 55 行)。固定行数の窓では大きな端末で上罫線が
|
|
321
|
+
* 窓外に出て入力欄を見失い、本文を重ね打ちして送信失敗する。窓を広く取っても
|
|
322
|
+
* `extractClaudeInputBox` は罫線で入力欄を切り出すので過検出にはならない。
|
|
323
|
+
* tmux は `-S` を付けなければ viewport のみ(履歴を引かない)。
|
|
324
|
+
*/
|
|
325
|
+
async captureVisibleScreen(name) {
|
|
326
|
+
const args = ["capture-pane", "-p", "-t", this.paneTarget(name)];
|
|
327
|
+
const result = await this.runner(args);
|
|
328
|
+
if (result.exitCode !== 0) {
|
|
329
|
+
throw new TmuxFailedError(args, result.exitCode, result.stderr);
|
|
330
|
+
}
|
|
331
|
+
const lines = result.stdout.split("\n");
|
|
332
|
+
while (lines.length > 0 && (lines[lines.length - 1] ?? "").trim() === "") {
|
|
333
|
+
lines.pop();
|
|
334
|
+
}
|
|
335
|
+
return lines.join("\n");
|
|
336
|
+
}
|
|
337
|
+
/** 指定セッションの pane へ tmux send-keys を発行する(literal は -l)。 */
|
|
338
|
+
async sendKeys(name, keys, literal = false) {
|
|
339
|
+
validateSessionName(name);
|
|
340
|
+
if (keys.length === 0)
|
|
341
|
+
return;
|
|
342
|
+
const args = ["send-keys", "-t", this.paneTarget(name)];
|
|
343
|
+
if (literal)
|
|
344
|
+
args.push("-l");
|
|
345
|
+
args.push(...keys);
|
|
346
|
+
const result = await this.runner(args);
|
|
347
|
+
if (result.exitCode !== 0) {
|
|
348
|
+
throw new TmuxFailedError(args, result.exitCode, result.stderr);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
/** `capture-pane -p -t <name> -S -<N>` で末尾 N 行のペイン内容を返す(末尾空行は削る)。 */
|
|
352
|
+
async capturePane(name, options = {}) {
|
|
353
|
+
const args = ["capture-pane", "-p"];
|
|
354
|
+
if (options.joinWrappedLines ?? false)
|
|
355
|
+
args.push("-J");
|
|
356
|
+
args.push("-t", this.paneTarget(name), "-S", `-${options.lines ?? this.captureLines}`);
|
|
357
|
+
const result = await this.runner(args);
|
|
358
|
+
if (result.exitCode !== 0) {
|
|
359
|
+
throw new TmuxFailedError(args, result.exitCode, result.stderr);
|
|
360
|
+
}
|
|
361
|
+
const lines = result.stdout.split("\n");
|
|
362
|
+
while (lines.length > 0 && (lines[lines.length - 1] ?? "").trim() === "") {
|
|
363
|
+
lines.pop();
|
|
364
|
+
}
|
|
365
|
+
return lines.join("\n");
|
|
366
|
+
}
|
|
367
|
+
/** pane ID が記録済みなら `%N` を使い、旧メタデータでは session 名へ戻す。 */
|
|
368
|
+
paneTarget(name) {
|
|
369
|
+
validateSessionName(name);
|
|
370
|
+
return this.store.get(name)?.tmuxPaneId ?? name;
|
|
371
|
+
}
|
|
372
|
+
/** `tmux ls` の生存セッション名集合。サーバ未起動 = 空集合として扱う。 */
|
|
373
|
+
async liveSessionNames() {
|
|
374
|
+
const args = ["ls", "-F", "#{session_name}"];
|
|
375
|
+
const result = await this.runner(args);
|
|
376
|
+
if (result.exitCode !== 0) {
|
|
377
|
+
const combined = (result.stdout + result.stderr).toLowerCase();
|
|
378
|
+
if (combined.includes("no server running") || combined.includes("no sessions")) {
|
|
379
|
+
return new Set();
|
|
380
|
+
}
|
|
381
|
+
throw new TmuxFailedError(args, result.exitCode, result.stderr);
|
|
382
|
+
}
|
|
383
|
+
const out = new Set();
|
|
384
|
+
for (const raw of result.stdout.split("\n")) {
|
|
385
|
+
const line = raw.trim();
|
|
386
|
+
if (line.length > 0)
|
|
387
|
+
out.add(line);
|
|
388
|
+
}
|
|
389
|
+
return out;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=tmux.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tmux.js","sourceRoot":"","sources":["../../src/backend/tmux.ts"],"names":[],"mappings":"AAAA,UAAU;AACV,mFAAmF;AACnF,wCAAwC;AACxC,0EAA0E;AAE1E,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAyC,MAAM,gBAAgB,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAYhG,yCAAyC;AACzC,MAAM,CAAC,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AAE1D,8DAA8D;AAC9D,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;AAErG,kEAAkE;AAClE,MAAM,UAAU,yBAAyB,CAAC,OAAe;IACvD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAChD,OAAO,UAAU,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;AACpE,CAAC;AASD;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAUrD,+BAA+B;AAC/B,MAAM,UAAU,mBAAmB,CAAC,GAA0B;IAC5D,OAAO,GAAG,EAAE,MAAM,KAAK,GAAG,CAAC;AAC7B,CAAC;AAED,kDAAkD;AAClD,SAAS,kBAAkB,CAAC,IAAY;IACtC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACrC,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACzB,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,CAAC;;YACtC,MAAM;IACb,CAAC;IACD,IAAI,OAAO,KAAK,OAAO,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,OAAO,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,KAAK,MAAM,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QACxC,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,QAAQ,IAAI,CAAC,CAAC;;YACvC,MAAM;IACb,CAAC;IACD,OAAO,QAAQ,IAAI,CAAC,CAAC;AACvB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5D,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC;IAChB,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1D,IAAI,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3C,MAAM,GAAG,KAAK,CAAC;YACf,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC;IACb,KAAK,IAAI,KAAK,GAAG,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,kBAAkB,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC3C,GAAG,GAAG,KAAK,CAAC;YACZ,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,GAAG,IAAI,CAAC,IAAI,MAAM,GAAG,GAAG;QAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACpF,4CAA4C;IAC5C,mCAAmC;IACnC,KAAK,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,gBAAgB,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,IAAI,KAAK,kCAAkC;QAAE,OAAO,IAAI,CAAC;IAC7D,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAChE,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC5D,CAAC;AAED,gCAAgC;AAChC,SAAS,gBAAgB,CAAC,SAAmB;IAC3C,MAAM,IAAI,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,IAAI,KAAK,KAAK,SAAS;QAAE,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE,EAAE,IAAI,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAC7E,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,wBAAwB,CAAC,QAAQ,GAAW,iBAAiB;IAC3E,OAAO,CAAC,IAAI,EAAE,EAAE,CACd,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9B,QAAQ,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAClF,IAAI,KAAK,IAAI,OAAQ,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACvE,iDAAiD;gBACjD,MAAM,CAAC,KAAK,CAAC,CAAC;gBACd,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,KAAK,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtF,OAAO,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAED,qCAAqC;AACrC,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAEtB,IAAI;IACJ,QAAQ;IACR,MAAM;IAHxB,YACkB,IAAc,EACd,QAAgB,EAChB,MAAc;QAE9B,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,QAAQ,MAAM,MAAM,EAAE,CAAC,CAAC;oBAJrD,IAAI;wBACJ,QAAQ;sBACR,MAAM;QAGtB,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAOD,mDAAmD;AACnD,MAAM,OAAO,kBAAkB;IACZ,MAAM,CAAoB;IAClC,KAAK,CAAuB;IACpB,YAAY,CAAS;IACrB,eAAe,CAAS;IAEzC,YAAY,OAAO,GAKf,EAAE;QACJ,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,wBAAwB,EAAE,CAAC;QAC3D,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,oBAAoB,EAAE,CAAC;QACzD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;QAC/C,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,WAAW,CAAC;IAChE,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC5C,iEAAiE;QACjE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;QAE1E,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC5C,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACxD,MAAM,uBAAuB,GAAG,IAAI,GAAG,EAAkB,CAAC;QAC1D,MAAM,WAAW,GAAG,IAAI,GAAG,EAA8B,CAAC;QAC1D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,IAAI,CAAC,eAAe,KAAK,SAAS;gBAAE,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;YACnG,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC;YACrC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;gBAAE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;YACrE,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC5G,IAAI,iBAAiB,KAAK,SAAS;gBAAE,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QACjG,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS,KAAK,CAAC,CAAC;QACrC,KAAK,MAAM,IAAI,IAAI,KAAK;YAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE/C,MAAM,KAAK,GAAkB,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACrD,IAAI;YACJ,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;YAC9B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YACtB,GAAG,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC;gBACnC,CAAC,CAAC,EAAE,iBAAiB,EAAE,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAE,EAAE;gBAC3D,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC,CAAC;QACJ,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,QAAQ,CAAC,IAAY;QACzB,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACjD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE;oBACL,IAAI,EAAE,OAAO;oBACb,CAAC,EAAE,IAAI,CAAC,eAAe;oBACvB,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE,UAAU,IAAI,sBAAsB;iBAC9C;aACF,CAAC;QACJ,CAAC;QACD,gDAAgD;QAChD,kEAAkE;QAClE,qEAAqE;QACrE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,QAAQ,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACpG,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtB,OAAO;gBACL,IAAI,EAAE,UAAU;gBAChB,KAAK,EAAE;oBACL,IAAI,EAAE,OAAO;oBACb,CAAC,EAAE,IAAI,CAAC,eAAe;oBACvB,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EAAE,UAAU,IAAI,mBAAmB;iBAC3C;aACF,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;QAC5C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5C,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IACtF,CAAC;IAED,wDAAwD;IACxD,KAAK,CAAC,iBAAiB,CAAC,IAAY;QAClC,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC;gBAC/B,iBAAiB,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,yBAAyB;aAChF,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACvC,OAAO,yBAAyB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,IAAY,EAAE,MAAqB;QACvD,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,mDAAmD;IACnD,KAAK,CAAC,IAAI,CAAC,IAAY;QACrB,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,IAAY,EAAE,IAAY;QAC7C,kDAAkD;QAClD,oDAAoD;QACpD,4CAA4C;QAC5C,yDAAyD;QACzD,IAAI,MAAM,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;YACrC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC;QACD,8CAA8C;QAC9C,wDAAwD;QACxD,+CAA+C;QAC/C,qDAAqD;QACrD,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC;QACxC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACzD,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACvC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,aAAa,CAAC,IAAY;QACtC,IAAI,CAAC;YACH,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;gBAChD,MAAM,GAAG,GAAG,qBAAqB,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;gBACzE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC;oBAAE,OAAO;gBACrE,MAAM,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACtC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mBAAmB;QACrB,CAAC;IACH,CAAC;IAED,sCAAsC;IAC9B,KAAK,CAAC,sBAAsB,CAAC,IAAY;QAC/C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,qBAAqB,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;YACzE,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,oBAAoB,CAAC,IAAY;QAC7C,MAAM,IAAI,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACzE,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,0DAA0D;IAC1D,KAAK,CAAC,QAAQ,CAAC,IAAY,EAAE,IAAc,EAAE,OAAO,GAAG,KAAK;QAC1D,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAC9B,MAAM,IAAI,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACxD,IAAI,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,OAAO,GAAuB,EAAE;QAC9D,MAAM,IAAI,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;QACpC,IAAI,OAAO,CAAC,gBAAgB,IAAI,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YACzE,KAAK,CAAC,GAAG,EAAE,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,sDAAsD;IAC9C,UAAU,CAAC,IAAY;QAC7B,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,IAAI,IAAI,CAAC;IAClD,CAAC;IAED,+CAA+C;IACvC,KAAK,CAAC,gBAAgB;QAC5B,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;YAC/D,IAAI,QAAQ,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC/E,OAAO,IAAI,GAAG,EAAE,CAAC;YACnB,CAAC;YACD,MAAM,IAAI,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;QAC9B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { LineWriter } from "
|
|
1
|
+
import type { LineWriter } from "../shared/lineWriter.js";
|
|
2
2
|
import type { ImageService } from "./imageService.js";
|
|
3
3
|
import { TranscriptTailer } from "./transcriptTailer.js";
|
|
4
4
|
import { SubagentTailer } from "./subagentTailer.js";
|
|
5
|
-
import {
|
|
5
|
+
import { type SubagentTranscriptResult } from "./subagentTranscript.js";
|
|
6
|
+
import { CodexRolloutTailer, type CodexTurnLifecycleEvent } from "../codex/codexRolloutTailer.js";
|
|
6
7
|
/** tail 対象エージェント種別(claude=既定 / codex=Codex CLI)。 */
|
|
7
8
|
export type ChatAgent = "claude" | "codex";
|
|
8
9
|
/** セッション連動で transcript を tail し chat_output を engine チャネルへ流す制御子。 */
|
|
@@ -11,7 +12,7 @@ export declare class ChatTailController {
|
|
|
11
12
|
private readonly tailer;
|
|
12
13
|
private readonly subagentTailer;
|
|
13
14
|
private readonly projectsRoot;
|
|
14
|
-
/** チャット添付(user 発話の `@"path"
|
|
15
|
+
/** チャット添付(user 発話の `@"path"` / Tailii upload path)のサムネ発行に使う。 */
|
|
15
16
|
private readonly imageService;
|
|
16
17
|
/** subagent_node の送出可否を判断する negotiated protocol version。 */
|
|
17
18
|
private readonly protocolVersion;
|
|
@@ -39,22 +40,30 @@ export declare class ChatTailController {
|
|
|
39
40
|
protocolVersion?: () => number;
|
|
40
41
|
agent?: ChatAgent;
|
|
41
42
|
codexTailer?: CodexRolloutTailer;
|
|
43
|
+
onCodexTurnLifecycle?: (event: CodexTurnLifecycleEvent) => void;
|
|
42
44
|
});
|
|
45
|
+
/** 全文取得要求向けに、現在の subagent transcript パスを解決する。 */
|
|
46
|
+
subagentTranscriptPath(nodeId: string): string | null;
|
|
47
|
+
/** Hub からのオンデマンド要求に、現在 tail 中のノード全文を返す。 */
|
|
48
|
+
subagentTranscript(nodeId: string): SubagentTranscriptResult;
|
|
43
49
|
/**
|
|
44
50
|
* `cwd` からそのセッションの project dir を解決し、transcript tail を開始/切替する。
|
|
45
51
|
* 同一会話(解決先 jsonl が同じ)への張り直しはスキップする。
|
|
46
52
|
*/
|
|
47
53
|
open(cwd: string, preferredSessionId: string | null, newerThanMs?: number | null, agent?: ChatAgent): void;
|
|
48
54
|
/**
|
|
49
|
-
* codex モードの tail 開始/切替。
|
|
50
|
-
* cwd から rollout を解決して chat_output
|
|
55
|
+
* codex モードの tail 開始/切替。Claude の slug/subagent transcript 監視は使わず、
|
|
56
|
+
* cwd から rollout を解決して chat_output を流す。Codex sub-agent の進捗は App Server の
|
|
57
|
+
* collabAgentToolCall を CodexNativeTurnController が subagent_node へ変換する。
|
|
51
58
|
*/
|
|
52
59
|
private openCodex;
|
|
53
60
|
/** 画像として扱う拡張子集合(小文字・ドットなし)。添付検出と Read サムネ判定で共有。 */
|
|
54
61
|
private static readonly IMAGE_EXTENSIONS;
|
|
55
62
|
/**
|
|
56
63
|
* user 発話テキストから添付「画像」ファイルの絶対パスを抽出する(chat-attachments, TESTABLE)。
|
|
57
|
-
* `@"/path with space.png"
|
|
64
|
+
* `@"/path with space.png"`(引用形式)、`@/path/to/file.png`(非引用)に加え、
|
|
65
|
+
* iOS の添付チップが本文へ合成する裸の `~/.tailii/uploads/<name>` も対象にする。
|
|
66
|
+
* 裸パスは Tailii 管理配下に限定し、通常本文の任意の画像パスを添付と誤認しない。
|
|
58
67
|
*/
|
|
59
68
|
static attachmentImagePaths(text: string): string[];
|
|
60
69
|
/**
|
|
@@ -80,6 +89,20 @@ export declare class ChatTailController {
|
|
|
80
89
|
* (=Claude の状態)が codex 会話に表示されてしまうため(2026-07-07 ユーザー指摘)。
|
|
81
90
|
*/
|
|
82
91
|
currentAgent(): ChatAgent;
|
|
92
|
+
/**
|
|
93
|
+
* kill された tmux セッションのメタから、その会話を tail 中なら tail を停止する。
|
|
94
|
+
*
|
|
95
|
+
* tail を生かしたままだと、次の再オープン(session_start)の `open()` が
|
|
96
|
+
* 「同一会話を tail 中」としてスキップして履歴を再生しない。kill 後の再オープンは
|
|
97
|
+
* tmux 名が変わり得る(生存別名 → `cs-<id>`)ためクライアントのキャッシュも外れ、
|
|
98
|
+
* 何も表示されなくなる。kill の全経路(session_kill / idle reaper / 処理完了時 kill)
|
|
99
|
+
* から呼ぶこと。
|
|
100
|
+
*/
|
|
101
|
+
stopIfSession(meta: {
|
|
102
|
+
cwd: string;
|
|
103
|
+
agent?: ChatAgent;
|
|
104
|
+
claudeSessionId?: string;
|
|
105
|
+
} | null): void;
|
|
83
106
|
/** tail を停止する(engine チャネル断)。 */
|
|
84
107
|
stop(): void;
|
|
85
108
|
/** 診断ログ(`~/.tailii/engine-tail.log` に追記)。失敗は握り潰す。 */
|