tailii-host 0.1.0 → 0.3.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 +35 -14
- 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 +226 -0
- package/dist/backend/herdr.js +749 -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 +15 -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/{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 +799 -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 +32 -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/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 +1036 -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 +1002 -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,385 @@
|
|
|
1
|
+
// engine/handlers/session.ts
|
|
2
|
+
// セッションライフサイクル: 一覧・reattach(resume 再起動含む)・kill(worktree 掃除含む)・
|
|
3
|
+
// 新規/再開起動(session_start)・離脱(session_idle_hint)。
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { gitWorktreeIsClean, gitWorktreeRemove, gitWorktreeUnlock, isTailiiWorktreePath, } from "../../services/gitService.js";
|
|
6
|
+
import { makeSessionLauncher, claudeInnerCommand } from "../../commands/launch.js";
|
|
7
|
+
import { activateOrTouchSession, claimRuntime, emitPendingQuestion, engineDiag, subscribeConversation, waitForLiveSession, writeError, writeSessionListResponse, } from "../context.js";
|
|
8
|
+
export const sessionHandlers = {
|
|
9
|
+
session_list_request: async (message, ctx) => {
|
|
10
|
+
const { writer, state, sessionManager } = ctx;
|
|
11
|
+
const v = state.negotiatedVersion;
|
|
12
|
+
// ページング応答。service 未注入時は従来の全件 list にフォールバックする(後方互換)。
|
|
13
|
+
try {
|
|
14
|
+
if (ctx.sessionListService !== null) {
|
|
15
|
+
const page = await ctx.sessionListService.page(message.limit, message.cursor);
|
|
16
|
+
writeSessionListResponse(writer, v, message.id, page.sessions, page.nextCursor);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const sessions = await sessionManager.list();
|
|
20
|
+
writeSessionListResponse(writer, v, message.id, sessions, null);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
writeError(writer, v, message.id, "tmux_error", String(error));
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
session_reattach: async (message, ctx) => {
|
|
28
|
+
const { writer, state, sessionManager, metadataStore } = ctx;
|
|
29
|
+
const v = state.negotiatedVersion;
|
|
30
|
+
// 再アクティブ化(heartbeat 更新 = アイドル計時リセット)→ 生存なら即 reattach /
|
|
31
|
+
// メタあり tmux 不在は記録 cwd で resume 再起動 → attached / メタ無しは従来の not_found。
|
|
32
|
+
try {
|
|
33
|
+
const result = await sessionManager.reattach(message.name);
|
|
34
|
+
if (result.kind === "attached") {
|
|
35
|
+
writeSessionListResponse(writer, v, message.id, [result.info], null);
|
|
36
|
+
subscribeConversation(ctx, message.name);
|
|
37
|
+
await emitPendingQuestion(ctx, message.name);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const meta = metadataStore?.get(message.name) ?? null;
|
|
41
|
+
if (ctx.resumeLauncher !== null && meta !== null) {
|
|
42
|
+
// codex セッションは codex 用 resume launcher で再起動する。
|
|
43
|
+
const reAgent = meta.agent ?? ctx.defaultAgent;
|
|
44
|
+
const providerSessionId = meta.providerSessionId ?? meta.claudeSessionId ?? null;
|
|
45
|
+
// claude で会話 id が記録済みなら通常 launcher の `--resume <id>` で同一会話を
|
|
46
|
+
// 厳密に再開する(resumeLauncher の `--continue` は cwd の最新会話を拾うため、
|
|
47
|
+
// 別会話を再開して tail 束縛と食い違い得る)。id 未記録の旧メタは従来経路。
|
|
48
|
+
const strictClaudeResume = reAgent === "claude" && providerSessionId !== null && ctx.launcher !== null;
|
|
49
|
+
const chosenResume = reAgent === "codex"
|
|
50
|
+
? (ctx.codexResumeLauncher ?? ctx.resumeLauncher)
|
|
51
|
+
: strictClaudeResume
|
|
52
|
+
? ctx.launcher
|
|
53
|
+
: ctx.resumeLauncher;
|
|
54
|
+
const claim = await claimRuntime(ctx, message.name);
|
|
55
|
+
if (claim === "held") {
|
|
56
|
+
const appeared = await waitForLiveSession(sessionManager, (info) => info.name === message.name);
|
|
57
|
+
if (appeared !== null) {
|
|
58
|
+
writeSessionListResponse(writer, v, message.id, [appeared], null);
|
|
59
|
+
subscribeConversation(ctx, message.name);
|
|
60
|
+
await emitPendingQuestion(ctx, message.name);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
writeError(writer, v, message.id, "launch_failed", "他の接続による会話の起動を確認できませんでした。");
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
let res;
|
|
68
|
+
try {
|
|
69
|
+
res = await chosenResume(meta.cwd, message.name, null, reAgent === "codex" || strictClaudeResume ? providerSessionId : null);
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
ctx.hubLink.send({ type: "runtime_claim_release", session: message.name });
|
|
73
|
+
}
|
|
74
|
+
if (res.exitCode === 0) {
|
|
75
|
+
// launcher は worktree 削除済み resume で cwd を repo ルートへ振り替え得る
|
|
76
|
+
// (deleted-worktree-resume)ため、応答は起動後の権威記録 cwd を返す。
|
|
77
|
+
const launchedCwd = metadataStore?.get(message.name)?.cwd ?? meta.cwd;
|
|
78
|
+
const info = {
|
|
79
|
+
name: message.name,
|
|
80
|
+
cwd: launchedCwd,
|
|
81
|
+
alive: true,
|
|
82
|
+
...(meta.agent !== undefined ? { agent: meta.agent } : {}),
|
|
83
|
+
...(providerSessionId !== null ? { providerSessionId } : {}),
|
|
84
|
+
...(meta.claudeSessionId !== undefined
|
|
85
|
+
? { claudeSessionId: meta.claudeSessionId }
|
|
86
|
+
: {}),
|
|
87
|
+
};
|
|
88
|
+
writeSessionListResponse(writer, v, message.id, [info], null);
|
|
89
|
+
subscribeConversation(ctx, message.name);
|
|
90
|
+
await emitPendingQuestion(ctx, message.name);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const m = res.errorText || `resume 失敗 (exit ${res.exitCode})`;
|
|
94
|
+
writeError(writer, v, message.id, "launch_failed", m);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (result.error.type === "error") {
|
|
98
|
+
writeError(writer, v, message.id, result.error.code, result.error.message);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
writeError(writer, v, message.id, "session_not_found", `セッション '${message.name}' は存在しません。`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
writeError(writer, v, message.id, "tmux_error", String(error));
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
session_kill: async (message, ctx) => {
|
|
110
|
+
const { writer, state, sessionManager, metadataStore } = ctx;
|
|
111
|
+
const v = state.negotiatedVersion;
|
|
112
|
+
try {
|
|
113
|
+
// cwd の権威は tmux の現在位置ではなく永続 SessionMetadataStore。
|
|
114
|
+
const killedCwd = metadataStore?.get(message.name)?.cwd ?? null;
|
|
115
|
+
// 明示 kill はユーザー意思なので処理中保護より優先する(保護記録も掃除)。
|
|
116
|
+
ctx.processingSessions.delete(message.name);
|
|
117
|
+
ctx.backgroundChatSessions.delete(message.name);
|
|
118
|
+
ctx.hubLink.send({ type: "conversation_unsubscribe", session: message.name });
|
|
119
|
+
ctx.codexTurnController?.closeSession(message.name);
|
|
120
|
+
// kill する会話を tail 中なら止める(生かしたままだと再オープンの open() が
|
|
121
|
+
// 「同一会話 tail 中」でスキップし、履歴が再生されず空表示になる)。
|
|
122
|
+
if (ctx.activeChatSession.name === message.name) {
|
|
123
|
+
ctx.activeChatSession.name = null;
|
|
124
|
+
}
|
|
125
|
+
await sessionManager.kill(message.name);
|
|
126
|
+
// kill 成功後だけ Hub の actor / durable queue / delivered receipt を廃棄する。
|
|
127
|
+
// 同名セッションを後日作り直しても、旧会話の queued 入力を注入させない。
|
|
128
|
+
ctx.hubLink.send({ type: "session_retire", session: message.name });
|
|
129
|
+
let worktreeResponse = null;
|
|
130
|
+
if (killedCwd !== null && isTailiiWorktreePath(killedCwd)) {
|
|
131
|
+
worktreeResponse = { worktreePath: killedCwd };
|
|
132
|
+
try {
|
|
133
|
+
if (await gitWorktreeIsClean(killedCwd)) {
|
|
134
|
+
const removed = await gitWorktreeRemove(killedCwd, false);
|
|
135
|
+
if (removed.ok) {
|
|
136
|
+
worktreeResponse.worktreeRemoved = true;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
engineDiag(`session_kill worktree 削除失敗 path=${killedCwd}: ${removed.error ?? "unknown"}`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
engineDiag(`session_kill worktree dirty または clean 判定不能のため保持 path=${killedCwd}`);
|
|
144
|
+
worktreeResponse.worktreeDirty = true;
|
|
145
|
+
const unlocked = await gitWorktreeUnlock(killedCwd);
|
|
146
|
+
if (!unlocked.ok) {
|
|
147
|
+
engineDiag(`session_kill worktree unlock 失敗 path=${killedCwd}: ${unlocked.error ?? "unknown"}`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
// worktree の判定・掃除は fail-open。ユーザーが要求した tmux kill の成功を覆さない。
|
|
153
|
+
engineDiag(`session_kill worktree 掃除失敗 path=${killedCwd}: ${String(error)}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// kill 成功は list 応答(現況一覧)で返す(疎通確認)。
|
|
157
|
+
let sessions = [];
|
|
158
|
+
try {
|
|
159
|
+
sessions = await sessionManager.list();
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
sessions = [];
|
|
163
|
+
}
|
|
164
|
+
writeSessionListResponse(writer, v, message.id, sessions, null, null, worktreeResponse);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
writeError(writer, v, message.id, "tmux_error", String(error));
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
session_idle_hint: async (message, ctx) => {
|
|
171
|
+
const { writer, state } = ctx;
|
|
172
|
+
const v = state.negotiatedVersion;
|
|
173
|
+
// アイドル起点を更新する(chat 離脱, 要件 4.2)。以後 reaper daemon が timeout 超過で kill する。
|
|
174
|
+
// state は保持(bump): 処理中(active)に離脱しても idle へ降格させない — state の権威は
|
|
175
|
+
// hook / turn controller のライフサイクル通知であり、離脱はただの計時リセット。
|
|
176
|
+
if (ctx.activeChatSession.name === message.name) {
|
|
177
|
+
ctx.activeChatSession.name = null;
|
|
178
|
+
if (ctx.processingSessions.has(message.name)) {
|
|
179
|
+
ctx.backgroundChatSessions.add(message.name);
|
|
180
|
+
ctx.hubLink.send({ type: "conversation_subscribe", session: message.name, preview: false });
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
ctx.hubLink.send({ type: "conversation_unsubscribe", session: message.name });
|
|
184
|
+
}
|
|
185
|
+
// 未回答の設問を残して離脱した → 一覧バッジへ引き継ぐ(question-hook-relay)。
|
|
186
|
+
const pending = await ctx.requestHubState(message.name);
|
|
187
|
+
if (pending !== null) {
|
|
188
|
+
const first = pending.questions[0];
|
|
189
|
+
writer.write({
|
|
190
|
+
type: "remote_pending",
|
|
191
|
+
v,
|
|
192
|
+
id: pending.id,
|
|
193
|
+
session: message.name,
|
|
194
|
+
kind: "question",
|
|
195
|
+
summary: first?.question || first?.header || "Question prompt",
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// focus の有無にかかわらず、指定 session の離脱時刻を Hub に記録する。
|
|
200
|
+
ctx.hubLink.send({ type: "conversation_unsubscribe", session: message.name });
|
|
201
|
+
},
|
|
202
|
+
session_title_set: async (message, ctx) => {
|
|
203
|
+
const { writer, state, sessionManager } = ctx;
|
|
204
|
+
const v = state.negotiatedVersion;
|
|
205
|
+
// 会話カスタムタイトルの端末表示追随(session-title): herdr はタブラベルへ反映、
|
|
206
|
+
// tmux は no-op(SessionBackend が backend 毎に吸収)。空 title は解除=セッション名へ戻す。
|
|
207
|
+
engineDiag(`session_title_set id=${message.id} session=${message.session} title=${message.title.slice(0, 40)}`);
|
|
208
|
+
try {
|
|
209
|
+
await sessionManager.setDisplayTitle(message.session, message.title);
|
|
210
|
+
writer.write({ type: "session_title_set_result", v, id: message.id, ok: true, error: null });
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
engineDiag(`session_title_set 失敗 id=${message.id}: ${String(error)}`);
|
|
214
|
+
writer.write({
|
|
215
|
+
type: "session_title_set_result", v, id: message.id, ok: false, error: String(error),
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
session_start: async (message, ctx) => {
|
|
220
|
+
const { writer, state, sessionManager, metadataStore } = ctx;
|
|
221
|
+
const v = state.negotiatedVersion;
|
|
222
|
+
// session_start → launch() 結線。agentType でセッション毎に claude/codex を選ぶ
|
|
223
|
+
//(未指定は host 既定 defaultAgent)。codex は agentType=codex 時の専用 launcher を使う。
|
|
224
|
+
const sessionAgent = message.agentType ?? ctx.defaultAgent;
|
|
225
|
+
// claude 新規起動でモデル/permission mode 指定があれば、その flags(--model /
|
|
226
|
+
// --permission-mode)を持つ launcher をその場で組む(起動前選択の反映)。
|
|
227
|
+
// resume は元セッションの設定を継ぐため既定 launcher を使う。
|
|
228
|
+
const perSessionClaudeLauncher = sessionAgent === "claude" &&
|
|
229
|
+
message.resumeSessionId === undefined &&
|
|
230
|
+
(message.model !== undefined || message.permissionMode !== undefined)
|
|
231
|
+
? makeSessionLauncher({
|
|
232
|
+
...(ctx.metadataStore !== null && { store: ctx.metadataStore }),
|
|
233
|
+
agent: "claude",
|
|
234
|
+
backend: ctx.backendKind,
|
|
235
|
+
innerCommand: claudeInnerCommand({
|
|
236
|
+
model: message.model ?? null,
|
|
237
|
+
permissionMode: message.permissionMode ?? null,
|
|
238
|
+
}),
|
|
239
|
+
})
|
|
240
|
+
: null;
|
|
241
|
+
const chosenLauncher = sessionAgent === "codex"
|
|
242
|
+
? (ctx.codexLauncher ?? ctx.launcher)
|
|
243
|
+
: (perSessionClaudeLauncher ?? ctx.launcher);
|
|
244
|
+
const resumeSessionId = message.resumeSessionId ?? null;
|
|
245
|
+
const shouldSubscribe = message.deferSubscribe !== true;
|
|
246
|
+
if (resumeSessionId !== null && metadataStore !== null) {
|
|
247
|
+
const aliases = await sessionManager.list();
|
|
248
|
+
const liveAliases = aliases.filter((info) => {
|
|
249
|
+
if (!info.alive || info.name === message.name)
|
|
250
|
+
return false;
|
|
251
|
+
const aliasAgent = info.agent ?? "claude";
|
|
252
|
+
return aliasAgent === sessionAgent && info.providerSessionId === resumeSessionId;
|
|
253
|
+
});
|
|
254
|
+
let liveAlias;
|
|
255
|
+
for (const candidate of liveAliases) {
|
|
256
|
+
// Claude の tmux が残っていても pane がシェルだけなら再利用不能。launcher の
|
|
257
|
+
// --resume 経路へ進める。Codex は App Server 駆動なので tmux TUI の状態に依存しない。
|
|
258
|
+
if (sessionAgent === "codex" || await sessionManager.agentProcessAlive(candidate.name)) {
|
|
259
|
+
liveAlias = candidate;
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (liveAlias !== undefined) {
|
|
264
|
+
engineDiag(`session_start resume alias reuse existing=${liveAlias.name} requested=${message.name} providerSessionId=${resumeSessionId}`);
|
|
265
|
+
// 通常再開はここで購読してアクティブ化する。prepare は正しい serve が開くまで遅延する。
|
|
266
|
+
if (!await activateOrTouchSession(ctx, writer, v, message.id, liveAlias.name, shouldSubscribe))
|
|
267
|
+
return;
|
|
268
|
+
writeSessionListResponse(writer, v, message.id, shouldSubscribe ? aliases : [liveAlias], null, liveAlias.name);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (chosenLauncher === null) {
|
|
273
|
+
// 未注入(テスト構成漏れ等): 安全側 — 実起動せず構造化 error を返す。
|
|
274
|
+
process.stderr.write("[tailii-host engine] session_start: launcher 未構成\n");
|
|
275
|
+
writeError(writer, v, message.id, "launch_failed", "launch 機能が構成されていません。");
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const runtimeClaim = await claimRuntime(ctx, message.name);
|
|
279
|
+
if (runtimeClaim === "held") {
|
|
280
|
+
const appeared = await waitForLiveSession(sessionManager, (info) => {
|
|
281
|
+
if (resumeSessionId === null)
|
|
282
|
+
return info.name === message.name;
|
|
283
|
+
return (info.agent ?? "claude") === sessionAgent && info.providerSessionId === resumeSessionId;
|
|
284
|
+
});
|
|
285
|
+
if (appeared !== null) {
|
|
286
|
+
if (!await activateOrTouchSession(ctx, writer, v, message.id, appeared.name, shouldSubscribe))
|
|
287
|
+
return;
|
|
288
|
+
if (shouldSubscribe) {
|
|
289
|
+
try {
|
|
290
|
+
writeSessionListResponse(writer, v, message.id, await sessionManager.list(), null, appeared.name);
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
writeSessionListResponse(writer, v, message.id, [appeared], null, appeared.name);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
writeSessionListResponse(writer, v, message.id, [appeared], null, appeared.name);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
writeError(writer, v, message.id, "launch_failed", "他の接続による会話の起動を確認できませんでした。");
|
|
302
|
+
}
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
// 新規起動は host 生成の session-id で claude を起動し(`--session-id <uuid>`)、
|
|
306
|
+
// 会話 jsonl 名を事前に確定させる。tail はその id の jsonl だけを追うため、同一 cwd に
|
|
307
|
+
// 別の稼働セッションがあっても、そのログが新セッションへ流れ込まない(取り違え防止)。
|
|
308
|
+
const newSessionId = sessionAgent === "claude" && resumeSessionId === null ? randomUUID() : null;
|
|
309
|
+
// codex は session-id 固定を持たず mtime で rollout を解決するため、新規起動は
|
|
310
|
+
// 「起動時刻より後に更新された rollout」に限定する(古い rollout の流入防止)。
|
|
311
|
+
// claude は preferred=newSessionId で厳密束縛するため newerThanMs は効かない(無害)。
|
|
312
|
+
const launchedAtMs = Date.now();
|
|
313
|
+
engineDiag(`session_start launcher 呼出前 cwd=${message.cwd} name=${message.name} resume=${resumeSessionId ?? "nil"} newId=${newSessionId ?? "nil"}`);
|
|
314
|
+
let result;
|
|
315
|
+
try {
|
|
316
|
+
result = await chosenLauncher(message.cwd, message.name, message.baseDir ?? null, resumeSessionId, newSessionId, message.title ?? null, sessionAgent === "codex"
|
|
317
|
+
? {
|
|
318
|
+
codexModel: message.codexModel ?? null,
|
|
319
|
+
codexSandbox: message.codexSandbox ?? null,
|
|
320
|
+
}
|
|
321
|
+
: undefined);
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
ctx.hubLink.send({ type: "runtime_claim_release", session: message.name });
|
|
325
|
+
}
|
|
326
|
+
engineDiag(`session_start launcher 結果 exit=${result.exitCode} err=${result.errorText.slice(0, 100)}`);
|
|
327
|
+
if (result.exitCode === 0) {
|
|
328
|
+
const providerSessionId = result.providerSessionId ?? resumeSessionId ?? newSessionId;
|
|
329
|
+
// cwd は launcher が権威記録した解決後 cwd(メタ)を優先。
|
|
330
|
+
// 通常起動/再開はここで購読してアクティブ化する。prepare は reattach まで遅延する。
|
|
331
|
+
// tail は確定した会話 id(resume=既存 id / 新規=生成 id)だけを追う。newerThanMs は
|
|
332
|
+
// codex(mtime 解決)の新規起動でのみ効き、claude は preferred で厳密束縛される。
|
|
333
|
+
if (!await activateOrTouchSession(ctx, writer, v, message.id, message.name, shouldSubscribe, providerSessionId === null && resumeSessionId === null ? launchedAtMs : undefined))
|
|
334
|
+
return;
|
|
335
|
+
// 成功: 現況一覧で応答する(kill と同じ疎通様式)。
|
|
336
|
+
if (!shouldSubscribe) {
|
|
337
|
+
// prepare 応答にも採用 session 1 件を載せ、iOS が reattach 前から実 backend を
|
|
338
|
+
// 観測できるようにする。購読は引き続き開始しない(sessions は状態スナップショットのみ)。
|
|
339
|
+
let adopted;
|
|
340
|
+
try {
|
|
341
|
+
adopted = (await sessionManager.list()).find((info) => info.name === message.name);
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
// launcher 成功後の一覧取得失敗は、下のメタデータ由来 1 件へ縮退する。
|
|
345
|
+
}
|
|
346
|
+
if (adopted === undefined) {
|
|
347
|
+
const meta = metadataStore?.get(message.name) ?? null;
|
|
348
|
+
adopted = {
|
|
349
|
+
name: message.name,
|
|
350
|
+
cwd: meta?.cwd ?? message.cwd,
|
|
351
|
+
alive: true,
|
|
352
|
+
...(meta?.backend === "herdr" ? { backend: "herdr" } : {}),
|
|
353
|
+
...(meta?.claudeSessionId !== undefined
|
|
354
|
+
? { claudeSessionId: meta.claudeSessionId }
|
|
355
|
+
: {}),
|
|
356
|
+
...(meta?.agent !== undefined ? { agent: meta.agent } : {}),
|
|
357
|
+
...(meta?.providerSessionId !== undefined
|
|
358
|
+
? { providerSessionId: meta.providerSessionId }
|
|
359
|
+
: {}),
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
writeSessionListResponse(writer, v, message.id, [adopted], null, message.name);
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
try {
|
|
366
|
+
const sessions = await sessionManager.list();
|
|
367
|
+
writeSessionListResponse(writer, v, message.id, sessions, null, message.name);
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
// 起動自体は成功しているため、一覧取得失敗時は当該セッション単独で応答する。
|
|
371
|
+
try {
|
|
372
|
+
writeSessionListResponse(writer, v, message.id, [{ name: message.name, cwd: message.cwd, alive: true }], null, message.name);
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
// 書込失敗は握り潰す(Swift 版 try? と同じ)。
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
else {
|
|
380
|
+
const m = result.errorText || `launch 失敗 (exit ${result.exitCode})`;
|
|
381
|
+
writeError(writer, v, message.id, "launch_failed", m);
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
};
|
|
385
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../../src/engine/handlers/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// engine/handlers/usage.ts
|
|
2
|
+
// 使用量応答: tail 中会話のエージェント種別で分岐する。codex は rollout 集計
|
|
3
|
+
// (rate_limits 含む)、claude は transcript 合算 + OAuth プラン使用量 API。
|
|
4
|
+
import * as os from "node:os";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import { CodexRolloutTailer } from "../../codex/codexRolloutTailer.js";
|
|
7
|
+
import { aggregateCodexUsage } from "../../codex/codexUsage.js";
|
|
8
|
+
import { claudeProjectSlug } from "../../shared/paths.js";
|
|
9
|
+
import { aggregateUsage, emptyUsageTotals } from "../../services/usageAggregator.js";
|
|
10
|
+
import { TranscriptTailer } from "../../chat/transcriptTailer.js";
|
|
11
|
+
export const usageHandlers = {
|
|
12
|
+
usage_request: async (message, ctx) => {
|
|
13
|
+
const { writer, state, metadataStore } = ctx;
|
|
14
|
+
const v = state.negotiatedVersion;
|
|
15
|
+
// 開いている会話が codex なら常に codex 集計で応答する(rate_limits を含む, codex-input)。
|
|
16
|
+
// 分岐は「rollout が解決済みか」ではなく「tail 中の会話が codex か」で行う。rollout 未解決でも
|
|
17
|
+
// Claude の OAuth プラン使用量 API へは絶対に落とさない(codex 会話に Claude の状態が出る不具合
|
|
18
|
+
// の防止, 2026-07-07 ユーザー指摘)。codex は OAuth プラン使用量非対応なので planUsage は使わない。
|
|
19
|
+
// ドラフトは activeChatSession をまだ持たないため、iOS が画面上の agentType を明示する。
|
|
20
|
+
// 旧クライアント(agentType 欠落)は従来どおり tail metadata / host 既定へフォールバックする。
|
|
21
|
+
const tailAgent = message.agentType
|
|
22
|
+
?? (ctx.activeChatSession.name === null
|
|
23
|
+
? ctx.defaultAgent
|
|
24
|
+
: metadataStore?.get(ctx.activeChatSession.name)?.agent ?? ctx.defaultAgent);
|
|
25
|
+
if (tailAgent === "codex") {
|
|
26
|
+
const currentMeta = ctx.activeChatSession.name === null ? null : metadataStore?.get(ctx.activeChatSession.name) ?? null;
|
|
27
|
+
const codexRollout = currentMeta === null ? null : new CodexRolloutTailer().resolve(currentMeta.cwd, null, currentMeta.providerSessionId ?? null);
|
|
28
|
+
// rollout 未解決(起動直後等)は空集計で返す。Claude 分岐へは落とさない。
|
|
29
|
+
const cu = codexRollout !== null ? aggregateCodexUsage(codexRollout) : { ...emptyUsageTotals() };
|
|
30
|
+
// レート制限は rollout の最終イベントより App Server のアカウント値を優先する。
|
|
31
|
+
// ドラフトにも値を返せ、primary/secondary の位置が固定でないプランも正しく分類できる。
|
|
32
|
+
let accountUsage = null;
|
|
33
|
+
try {
|
|
34
|
+
accountUsage = await ctx.codexAccountUsage();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
accountUsage = null;
|
|
38
|
+
}
|
|
39
|
+
const fiveHourUtilization = accountUsage?.fiveHourPercent ?? cu.fiveHourUtilization;
|
|
40
|
+
const fiveHourResetsAt = accountUsage?.fiveHourResetsAt ?? cu.fiveHourResetsAt;
|
|
41
|
+
const sevenDayUtilization = accountUsage?.weeklyPercent ?? cu.sevenDayUtilization;
|
|
42
|
+
const sevenDayResetsAt = accountUsage?.weeklyResetsAt ?? cu.sevenDayResetsAt;
|
|
43
|
+
try {
|
|
44
|
+
writer.write({
|
|
45
|
+
type: "usage_response",
|
|
46
|
+
v,
|
|
47
|
+
id: message.id,
|
|
48
|
+
inputTokens: cu.inputTokens,
|
|
49
|
+
outputTokens: cu.outputTokens,
|
|
50
|
+
cacheReadTokens: cu.cacheReadTokens,
|
|
51
|
+
cacheCreationTokens: cu.cacheCreationTokens,
|
|
52
|
+
turns: cu.turns,
|
|
53
|
+
...(fiveHourUtilization !== undefined && { fiveHourUtilization }),
|
|
54
|
+
...(fiveHourResetsAt !== undefined && { fiveHourResetsAt }),
|
|
55
|
+
...(sevenDayUtilization !== undefined && { sevenDayUtilization }),
|
|
56
|
+
...(sevenDayResetsAt !== undefined && { sevenDayResetsAt }),
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// 書込失敗は握り潰す。
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// 使用量(claude): プラン使用率(OAuth 使用量 API, ベストエフォート)+ tail 中会話の usage 合算。
|
|
65
|
+
const currentMeta = ctx.activeChatSession.name === null ? null : metadataStore?.get(ctx.activeChatSession.name) ?? null;
|
|
66
|
+
const transcript = currentMeta === null ? null : TranscriptTailer.resolveJsonl(path.join(os.homedir(), ".claude", "projects", claudeProjectSlug(currentMeta.cwd)), currentMeta.providerSessionId ?? currentMeta.claudeSessionId ?? null, null);
|
|
67
|
+
const totals = transcript !== null ? aggregateUsage(transcript) : emptyUsageTotals();
|
|
68
|
+
const plan = await ctx.planUsage();
|
|
69
|
+
try {
|
|
70
|
+
writer.write({
|
|
71
|
+
type: "usage_response",
|
|
72
|
+
v,
|
|
73
|
+
id: message.id,
|
|
74
|
+
inputTokens: totals.inputTokens,
|
|
75
|
+
outputTokens: totals.outputTokens,
|
|
76
|
+
cacheReadTokens: totals.cacheReadTokens,
|
|
77
|
+
cacheCreationTokens: totals.cacheCreationTokens,
|
|
78
|
+
turns: totals.turns,
|
|
79
|
+
...(plan?.fiveHourUtilization != null && { fiveHourUtilization: plan.fiveHourUtilization }),
|
|
80
|
+
...(plan?.fiveHourResetsAt != null && { fiveHourResetsAt: plan.fiveHourResetsAt }),
|
|
81
|
+
...(plan?.sevenDayUtilization != null && { sevenDayUtilization: plan.sevenDayUtilization }),
|
|
82
|
+
...(plan?.sevenDayResetsAt != null && { sevenDayResetsAt: plan.sevenDayResetsAt }),
|
|
83
|
+
...(plan?.sevenDayFableUtilization != null && {
|
|
84
|
+
sevenDayFableUtilization: plan.sevenDayFableUtilization,
|
|
85
|
+
}),
|
|
86
|
+
...(plan?.sevenDayFableResetsAt != null && {
|
|
87
|
+
sevenDayFableResetsAt: plan.sevenDayFableResetsAt,
|
|
88
|
+
}),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// 書込失敗は握り潰す(Swift 版 try? と同じ)。
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/engine/handlers/usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// engine/handlers/workspace.ts
|
|
2
|
+
// 作業ディレクトリまわり: slash コマンド候補・ディレクトリ候補/ブラウズ/作成・
|
|
3
|
+
// ファイル一覧(git バッジ付き)/読み取り。
|
|
4
|
+
import { dirCanCreate, dirChildren, dirCreate, dirList } from "../../services/dirLister.js";
|
|
5
|
+
import { fileList, fileRead } from "../../services/fileService.js";
|
|
6
|
+
import { gitEntryStatuses } from "../../services/gitService.js";
|
|
7
|
+
import { engineDiag } from "../context.js";
|
|
8
|
+
import { collectSlashCommands } from "../slashCommands.js";
|
|
9
|
+
export const workspaceHandlers = {
|
|
10
|
+
slash_list_request: (message, ctx) => {
|
|
11
|
+
const { writer, state } = ctx;
|
|
12
|
+
const v = state.negotiatedVersion;
|
|
13
|
+
// セッション/プロジェクト由来の slash command 候補をベストエフォートで収集する。
|
|
14
|
+
const commands = collectSlashCommands(ctx.homeDir, message.cwd);
|
|
15
|
+
try {
|
|
16
|
+
writer.write({ type: "slash_list_response", v, id: message.id, commands });
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
process.stderr.write(`[tailii-host engine] slash_list_response 書込失敗: ${String(error)}\n`);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
dir_list_request: (message, ctx) => {
|
|
23
|
+
const { writer, state } = ctx;
|
|
24
|
+
const v = state.negotiatedVersion;
|
|
25
|
+
// ディレクトリ候補問い合わせ。base 外・不正・一致なしは空 entries(エラーにしない)。
|
|
26
|
+
const entries = dirList(message.baseDir, message.partial);
|
|
27
|
+
try {
|
|
28
|
+
writer.write({ type: "dir_list_response", v, id: message.id, entries });
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
process.stderr.write(`[tailii-host engine] dir_list_response 書込失敗: ${String(error)}\n`);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
browse_request: (message, ctx) => {
|
|
35
|
+
const { writer, state } = ctx;
|
|
36
|
+
const v = state.negotiatedVersion;
|
|
37
|
+
// ディレクトリ非限定ブラウズ。不存在・読取不能は空 entries(エラーにしない)。
|
|
38
|
+
engineDiag(`browse_request id=${message.id} path=${message.path}`);
|
|
39
|
+
const entries = dirChildren(message.path);
|
|
40
|
+
try {
|
|
41
|
+
writer.write({
|
|
42
|
+
type: "browse_response", v, id: message.id, path: message.path, entries,
|
|
43
|
+
canCreateDirectory: dirCanCreate(message.path),
|
|
44
|
+
});
|
|
45
|
+
engineDiag(`browse_response id=${message.id} entries=${entries.length}`);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
engineDiag(`browse_response 書込失敗 id=${message.id}: ${String(error)}`);
|
|
49
|
+
process.stderr.write(`[tailii-host engine] browse_response 書込失敗: ${String(error)}\n`);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
dir_create_request: (message, ctx) => {
|
|
53
|
+
const { writer, state } = ctx;
|
|
54
|
+
const v = state.negotiatedVersion;
|
|
55
|
+
// ディレクトリ作成。base 外/`..` 脱出は ok=false。
|
|
56
|
+
const result = dirCreate(message.baseDir, message.relative);
|
|
57
|
+
try {
|
|
58
|
+
writer.write({
|
|
59
|
+
type: "dir_create_response", v, id: message.id, path: result.path, ok: result.ok,
|
|
60
|
+
error: result.error,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
process.stderr.write(`[tailii-host engine] dir_create_response 書込失敗: ${String(error)}\n`);
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
file_list_request: async (message, ctx) => {
|
|
68
|
+
const { writer, state } = ctx;
|
|
69
|
+
const v = state.negotiatedVersion;
|
|
70
|
+
engineDiag(`file_list_request id=${message.id} path=${message.path}`);
|
|
71
|
+
try {
|
|
72
|
+
const response = fileList(message.path);
|
|
73
|
+
let statuses = new Map();
|
|
74
|
+
try {
|
|
75
|
+
statuses = await gitEntryStatuses(message.path, response.entries.map((entry) => entry.name));
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
engineDiag(`file_list gitStatus badge 取得失敗 id=${message.id}: ${String(error)}`);
|
|
79
|
+
}
|
|
80
|
+
const entries = response.entries.map((entry) => {
|
|
81
|
+
const gitStatus = statuses.get(entry.name);
|
|
82
|
+
return gitStatus === undefined ? entry : { ...entry, gitStatus };
|
|
83
|
+
});
|
|
84
|
+
writer.write({ type: "file_list_response", v, id: message.id, ...response, entries });
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
engineDiag(`file_list_response 失敗 id=${message.id}: ${String(error)}`);
|
|
88
|
+
writer.write({
|
|
89
|
+
type: "file_list_response", v, id: message.id, path: message.path,
|
|
90
|
+
entries: [], truncated: false,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
file_read_request: async (message, ctx) => {
|
|
95
|
+
const { writer, state } = ctx;
|
|
96
|
+
const v = state.negotiatedVersion;
|
|
97
|
+
engineDiag(`file_read_request id=${message.id} path=${message.path}`);
|
|
98
|
+
try {
|
|
99
|
+
const response = await fileRead(message.path);
|
|
100
|
+
writer.write({ type: "file_read_response", v, id: message.id, ...response });
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
writer.write({
|
|
104
|
+
type: "file_read_response", v, id: message.id, path: message.path,
|
|
105
|
+
kind: "error", size: 0, mtimeMs: 0, error: String(error),
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=workspace.js.map
|