UI ãšã³ã¢ããžãã¯ãå®å šã«åé¢ãããã³ã¢ã¯ Ink/React ã«äžåäŸåãããåäœã§ãã¹ãå¯èœã«ããã
ââ ui/ (Ink + React) âââââââââââââââââââââââââââââââââ
â App / SessionList / PromptInput â
â PermissionDialog / ProgressBadge â
â â² useSyncExternalStore ã§è³Œèª â
ââââââââââŒâââââââââââââââââââââââââââââââââââââââââââââ
ââââââââââŽâ core/ (çŽTypeScript, UIãªã) ââââââââââââââ
â SessionManager ⊠ã»ãã·ã§ã³ã®çæã»ä¿æã»ã€ãã³ãçºç« â
â Session ⊠1ã»ãã·ã§ã³ = 1 ãšãŒãžã§ã³ã + ç¶æ
â
â reduce() ⊠CodivaEvent â SessionState ç³ã¿èŸŒã¿â
â applyAgentEvent() ⊠AgentEvent â SessionState â
â AgentAdapter ⊠provider ã® DI å¢çïŒclaude/âŠïŒ â
â Worktree å / MergeConflictError / çŽé¢æ° â
ââââââââââ¬âââââââââââââââââââââââââââââââââââââââââââââ
ââââââââââŽâ utils/ (I/O ã©ãã, core ã«ã®ã¿äŸå) âââââââ
â WorktreeManager⊠git worktree ã®äœæã»åé€ã»ããŒãž â
â git() / config / state-store / pr / notify ⊠â
ââââââââââ¬âââââââââââââââââââââââââââââââââââââââââââââ
ââââââââââŽâ å€éš ââââââââââââââââââââââââââââââââââââââ
â @anthropic-ai/claude-agent-sdk (query) â
â git CLI (worktree / diff / merge) â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââ
äŸåæ¹åã¯äžæ¹åïŒui â core â utilsïŒãWorktreeManager 㯠fs + git å®è¡ã® I/O å
·è±¡ãªã®ã§
utils ã¬ã€ã€ã«çœ®ãïŒcore 㯠node ã® I/O ã import ããªãïŒãcore/worktree.ts ã«ã¯çŽç²ãªå
ïŒWorktree / DiffStatïŒã»MergeConflictErrorã»ignoredCopyEntries() ã ããæ®ãã
SessionManager 㯠WorktreeService ã€ã³ã¿ãŒãã§ãŒã¹è¶ãã«å
·è±¡ã DI ã§åããã
src/index.tsx / src/main.tsx / src/app.tsx / src/bootstrap/ ã¯åæã¬ã€ã€ïŒã©ã®ã¬ã€ã€ã«ãå±ãã
core ãš utils ãæããïŒãå¯äœçšã®é
ç·ïŒmanager çµã¿ç«ãŠã»åŸ©å
ã»æ°žç¶ã»ç«¯æ«ã¢ãŒãã»PR ããŒãªã³ã°ïŒã¯
bootstrap/ ã«åãåºããmain.tsx ã¯ã解決 â preflight â build â restore â render â shutdownãã®
çŽåã ãã«ä¿ã€ã
src/index.tsx ã¯èµ·åã·ã ã ãïŒNODE_ENV ãç«ãŠãŠãã ./main ãåç import ãã 4 æïŒã
static import ã 1 æ¬ã§ãè¶³ããšå·»ãäžããããŠæå³ãæ¶ããã®ã§ãtests/entry-shim.test.ts ãåºå®ããŠããã
çç±ã¯äžèšãReact ã® dev ãã«ããšããŒãæ¯æžããç«ãŠã NODE_ENV ãåããã»ã¹ãžæŒãããªãä»çµã¿
ïŒcore/child-env.ts / utils/child-env.tsïŒã¯åãç¯ã®ãåããã»ã¹ãžæž¡ãç°å¢å€æ°ããåç
§ã
codiva/
âââ src/
â âââ index.tsx # bin ãšã³ããªã解決 â preflight â build â restore â render â shutdownïŒåæã«ãŒãã»èãïŒ
â âââ app.tsx # ã«ãŒãã³ã³ããŒãã³ããlist â detail ã®ãã¥ãŒåæ¿
â âââ bootstrap/ # å¯äœçšã®é
ç·ïŒåæã®åè§£ãcore/utils ã«ã®ã¿äŸåïŒ
â â âââ build-manager.ts # config + I/O seam â SessionManager çµã¿ç«ãŠ + /modelã»/agent ã® config æ°žç¶ïŒConfigStore çµç±ïŒã»/prompt ã® prompt.md æ°žç¶
â â âââ config-store.ts # ~/.codiva/config.json ã®å¯äžã®æžãæïŒå·®åãããŒãžããŠä¿åïŒ
â â âââ restore-sessions.ts # state.json + transcript ãã埩å
â â âââ persist-controller.ts # debounceä¿å / SIGTERMåæflush / æçµflush ãéçŽ
â â âââ crash-handler.ts # uncaughtException/unhandledRejection â 端æ«åŸ©å
+ ã¯ã©ãã·ã¥ãã°
â â âââ runtime.ts # PRããŒãªã³ã°ã»alt-screen/mouseã»SIGTERM/SIGHUP ãã©ãã·ã¥
â âââ core/ # çŽç²ãã¡ã€ã³ïŒInk/React/node/utils éäŸåãSDK ã«è§Šãã®ã¯ claude-*.ts ã ãïŒ
â â âââ index.ts # ãã¬ã«ïŒexport *ïŒ
â â âââ types.ts # SessionState, SessionStatus, CodivaEvent, AgentId, AgentStopCause çã®åå®çŸ©
â â âââ status-reducer.ts # reduce(state, CodivaEvent): SessionStateïŒcodiva èµ·ç¹ã®ã€ãã³ãã»çŽé¢æ°ïŒ
â â âââ agent-ports.ts # ãšãŒãžã§ã³ãã® DI å¢çïŒAgentAdapter/AgentRun/AgentCapabilities/PermissionDecisionã»leafïŒ
â â âââ agent-events.ts # AgentEvent ã®èªåœ + applyAgentEvent()ïŒå
š provider å
±éã®ç³ã¿èŸŒã¿ã»çŽç²ïŒ
â â âââ agent-capabilities.ts # capability ã«ãã UI çž®éã®å€å®ïŒäžæãªãçž®éããªãã»showsAccountInfoïŒ
â â âââ agent-display.ts # ãã©ã®ã»ãã·ã§ã³ãäœã§èµ°ã£ãŠããããã®å€å®ïŒsessionAgentId / usesMultipleAgentsïŒ
â â âââ agent-handoff.ts # åæ¿å
ãžæž¡ãç¶æ³èª¬æïŒè±èªåºå®ã»systemPrompt ã« 1 åã ãèŒãïŒ
â â âââ claude-adapter.ts # Claude çš AgentAdapterïŒquery() ã®çµã¿ç«ãŠã»canUseTool ã®ååïŒ
â â âââ claude-parse.ts # parseClaudeMessage()ïŒSDK ã¡ãã»ãŒãžåœ¢ç¶ã®è§£éãéçŽã»çŽç²ïŒ
â â âââ claude-errors.ts # Claude CLI ã®å€±æåé¡ïŒæèš/typed kind/HTTP status â AgentStopCauseïŒ
â â âââ codex-adapter.ts / codex-parse.ts / codex-errors.ts # Codex çšã® 3 ç¹ã»ããïŒ1 ã¿ãŒã³ = 1 ããã»ã¹ïŒ
â â âââ codex-events.ts / codex-models.ts / codex-rollout.ts # codex exec --json ã® JSONL å / ã¢ãã«äžèЧ / rollout ãã解決æžã¿ã¢ãã«
â â âââ grok-adapter.ts / grok-parse.ts / grok-errors.ts # Grok çšã® 3 ç¹ã»ããïŒACP = JSON-RPC over stdioã»1 ã»ãã·ã§ã³ 1 ããã»ã¹ïŒ
â â âââ grok-events.ts / grok-models.ts # ACP ã¡ãã»ãŒãžã®åãšåçã¬ãŒã / initialize ãéã¶ã¢ãã«äžèЧ
â â âââ jsonl.ts # è¡åºåã JSON ã®æ åã createJsonlSplitterïŒprovider éäŸåãCodex / Grok ãå
±çšïŒ
â â âââ status-meta.ts # STATUS_METAïŒterminal/attention/active/resumable/埩å
å
/éç¥ããŒã®äžå
衚ïŒ
â â âââ session.ts # 1 ãšãŒãžã§ã³ãã¹ããªãŒã ã®ã©ã€ããµã€ã¯ã«ïŒsetAgent ã§éäžåæ¿ïŒ
â â âââ session-store.ts # 賌èªå¯èœã¹ãããã·ã§ããïŒé åºã»ç¶æ
ã»åç
§åäžæ§ä¿æïŒ
â â âââ session-manager.ts # create/restore/dispose + passthrough ã®ãã¡ãµãŒã
â â âââ session-actions.ts # merge/discard/diffStatïŒgit æäœã®çŽç²ãªãŒã±ã¹ãã¬ãŒã·ã§ã³ïŒ
â â âââ pr-coordinator.ts # PrCoordinatorïŒautoPr/refreshPrs/èªåç«ãŠçŽãïŒ
â â âââ pr-recovery.ts # è©°ãŸã£ã PR ã®ç«ãŠçŽãå€å®ã»æç€ºæïŒçŽç²ïŒ
â â âââ pr-detect.ts # ã»ãã·ã§ã³èªèº«ãäœã£ã PR ã®æ€ç¥ã»è¡šç€ºãã«ãïŒçŽç²ïŒ
â â âââ run-mode.ts # RunMode + createModePolicy
â â âââ session-ports.ts # codiva åŽã® DI seamïŒWorktreeService/SessionHandle/âŠã»leafïŒ
â â âââ worktree.ts # Worktree å + MergeConflictError + ignoredCopyEntriesïŒçŽç²ïŒ
â â âââ list-hit.ts # äžèЧã®ããŠã¹åœããå€å®ïŒçŽç²ïŒ
â â âââ format.ts / math.ts / ansi.ts / errors.ts # å°ããªçŽç²ãã«ãïŒformatDuration/clamp/âŠïŒ
â â âââ privacy.ts # åŠç¿ããŒã¿å©çšïŒgroveïŒã®å€å®ïŒJSONâTrainingOptInã»çŽç²ïŒ
â â âââ async-queue.ts / slug.ts / config.ts / cost.ts / notify.ts / persistence.ts / update.ts
â â âââ choice-lines.ts # éžæè¢ïŒã©ãã« + 説æïŒã®æè¿ãïŒçŽç²ã»è¡šç€ºå¹
ããŒã¹ïŒ
â â âââ scroll.ts / text-buffer.ts / composer-layout.ts / layout.ts / mouse.ts / key-sequence.ts / model.ts / models.ts / transcript.ts
â â âââ *.spec.ts # åäœãã¹ãã¯å®è£
ã®é£ã« co-located
â â âââ __fixtures__/ # ãµãã¿ã€ãºæžã¿å® SDK ã¡ãã»ãŒãžïŒclaude-parse ãã¹ãçšïŒ
â âââ ui/ # Ink ã³ã³ããŒãã³ãïŒkebab-case, èå¥å㯠PascalCaseïŒ
â â âââ index.ts # ãã¬ã«
â â âââ theme.ts # ã¢ã¯ã»ã³ãè²ã»ç¶æ
è²ã»logColorã»ã°ãªãïŒè²ã¯å¿
ãããçµç±ïŒ
â â âââ banner.tsx # èµ·åæãããïŒãã¹ã³ãã + ãã©ã³/ã¢ãã« + cwd + 䜿çšç¶æ³ã²ãŒãž, æ ãªãïŒ
â â âââ session-list.tsx # äžèЧç»é¢ïŒcomposer/list ã®2ãã©ãŒã«ã¹ãŸãŒã³ïŒ
â â âââ session-detail.tsx # 詳现ç»é¢ïŒãã° + è¿œå æç€º + ããŒãž/ç Žæ£ãSDK ã»ãã·ã§ã³ã«çŽçµïŒ
â â âââ composer.tsx # å
¥åæ¬ã®å
±éå®è£
ïŒuseComposer = ããŒ/ããŠã¹/ãããã¡, <Composer> = æç»ïŒ
â â âââ prompt-input.tsx # äžäžæšªçœ«ç· + ⯠ãã£ã¬ããã®å
¥åæ¬ïŒpresentationalïŒ
â â âââ repo-prompt-editor.tsx # /prompt ã®ãªããžããªè¿œå æç€ºãšãã£ã¿ïŒã¢ãŒãã«ã»composer ã眮æïŒ
â â âââ config-select.tsx # /config ã®èšå® ON/OFF ãã€ã¢ãã°ïŒã¢ãŒãã«ã»composer ã眮æïŒ
â â âââ dialog-box.tsx / confirm-prompt.tsx / choice-row.tsx # å
±æ presentationalïŒè§äžžæ ã»y/n 確èªè¡ã»éžæè¢1ä»¶ïŒ
â â âââ update-dialog.tsx # /update ã®è¡šç€ºïŒpresentationalã»useInput ãæããªãïŒ
â â âââ status-footer.tsx / permission-dialog.tsx / model-select.tsx / command-palette.tsx / progress-badge.tsx
â â âââ hooks.ts # useSessions / useClock / useTextBufferRef / useCommandRunner / useLifecycleAction
â â âââ input.ts # ããŒâããã¹ããããã¡æäœã®å¯Ÿå¿ïŒeditText/resolveEnter/normalizeChordïŒ
â âââ utils/ # ãã¹ãŠã® I/OïŒcore ã«ã®ã¿äŸåïŒäžæ¹åïŒ
â âââ index.ts # ãã¬ã«
â âââ git.ts # execFile ããŒã¹ã® git å®è¡ãã«ã
â âââ worktree-manager.ts # WorktreeManagerïŒgit worktree ã® I/OïŒ
â âââ exec.ts / terminal-mode.ts # fireAndForget / toggleEscapeïŒå
±é I/O ã©ããïŒ
â âââ config.ts # ~/.codiva/config.json ã®èªã¿æžã
â âââ repo-prompt.ts # <repo>/.codiva/prompt.md ã®èªã¿æžãïŒloadRepoPrompt / saveRepoPromptïŒ
â âââ privacy.ts # åŠç¿ããŒã¿å©çšã®ç¶æ
ååŸïŒ~/.claude.json ãã£ãã·ã¥ â éå
¬é APIïŒ
â âââ notify.ts / open-url.ts / pr.ts / title.ts / transcript.ts
â âââ alt-screen.ts / mouse.ts # alt screen / SGR ããŠã¹ã®æå¹åã»ç¡å¹å
â âââ state-store.ts # <repo>/.codiva/state.json ã®èªã¿æžã + prune
âââ scripts/
â âââ spike.ts # Phase 1: SDK æåæ€èšŒã¹ã¯ãªãã
âââ tests/ # App å
šäœãéãæ©èœ/çµ±åãã¹ãïŒ*.test.tsxïŒ+ helpers.tsïŒå
±æãã§ã€ã¯ïŒ
âââ docs/ # æ¬ããã¥ã¡ã³ã矀
# ãã¹ã: åäœã¯å®è£
é£ã® *.spec.tsãæ©èœ/çµ±å㯠tests/*.test.tsxã
# import 㯠`@/*` â `./src/*` ãšã€ãªã¢ã¹ïŒãã£ã¬ã¯ããªè·šãïŒããã«ã㯠tsupãåãã§ãã¯ã¯ tsc --noEmitã
codiva ã¯åœå Claude CodeïŒ@anthropic-ai/claude-agent-sdkïŒå°çšã§ãSDKMessage ãçŽæ¥
SessionState ãžç³ã¿èŸŒãã§ããïŒæ§ core/sdk-parse.ts ã® applySdkMessageïŒããã®ãã
ãSDK ã¡ãã»ãŒãžã®åœ¢ã®ç¥èããšãç¶æ
ãã©ãå€ããããã 1 ãæã«æ··ãããå¥ã®ãšãŒãžã§ã³ã
ïŒCodex / GrokïŒãè¶³ãã«ã¯ç³ã¿èŸŒã¿ããšæžãçŽããããªãã£ããPhase A ã§ã¯ããã 2 段ã«å²ãã
provider ãå·®ãæ¿ããããå¢çãå
¥ããPhase B ã§ 2 ã€ç®ã® providerïŒCodexïŒããPhase C ã§
3 ã€ç®ïŒGrokïŒãèŒããã
provider ã®ã¡ãã»ãŒãž ââ[ã¢ããã¿ã® parse]âââ¶ AgentEvent[] ââ[applyAgentEvent]âââ¶ SessionState
SDKMessage claude-parse.ts agent-events.ts core/types.ts
codex ã® JSONL codex-parse.ts ïŒå
š provider å
±éïŒ
grok ã® ACP éç¥ grok-parse.ts
3 ã€ãšã圢ã¯ãŸã£ããéãïŒé·å¯¿åœã® streaming input / 1 ã¿ãŒã³ 1 ããã»ã¹ã® JSONL / JSON-RPC ã®åæ¹åã¹ããªãŒã ïŒããéãã¯ã¢ããã¿ã®äžã§åžåãããå³åå㯠1 æ¬ã®ãŸãŸã
æœè±¡åã®ç·ã¯ 1 ã¿ãŒã³ã¶ãã®ã¹ããªãŒã ã«åŒãïŒcore/agent-ports.tsïŒãçç±ã¯ 2 ã€:
SessionManagerããäžïŒUIã»æ°žç¶åã»PR èªååã»worktreeã»éç¥ïŒã¯æ¢ã«SessionHandleè¶ãã«ããã»ãã·ã§ã³ãè§Šã£ãŠããããããšããšãšãŒãžã§ã³ãéäŸåã ã£ããå¢çãæ°èšãã å¿ èŠã¯ãªãããã®äžã«AgentAdapterãè¶³ãã ãã§æžãã- éã« SDK ã®
query()ã®çœ²åïŒAsyncIterable<SDKUserMessage>+Options+canUseTool+ control requestïŒãå ±é IF ã«ãããšãå š provider ã« Claude ã®å¶åŸ¡ã¢ãã«ã®æš¡å£ã匷ããã Codex / Grok ã control request ãæã€ä¿èšŒã¯ãªãã
ã¢ããã¿ã®è²¬å㯠3 ã€ã ã: (1) ã¹ããªãŒã ãéãïŒopenïŒã(2) provider ã®ã¡ãã»ãŒãžã
AgentEvent[] ãžåãã(3) 倱ææèšã AgentStopCause ãžåé¡ããïŒclassifyErrorïŒã
èš±å¯èŠæ±ã®åã SDK ã® PermissionResult ã§ã¯ãªãèªåã® PermissionDecision ã«ããŠãprovider 圢ãžã®
ååã¯ã¢ããã¿ã«çœ®ãïŒPermissionRequest ãæ¢ã«èªååãªã®ã§å¯Ÿã«ããïŒã
@anthropic-ai/claude-agent-sdk ã import ããŠããã®ã¯ core/claude-adapter.ts /
core/claude-parse.ts / core/claude-errors.ts ã ããä»ã® core/ ã¯åã宿°ãåŒããªãã
ãã®å¢çã®ããã«å€ãããã®ã 2 ã€ãã:
core/config.tsã®EffortLevel/PermissionModeã SDK ã®åå union ã®åãšã¯ã¹ããŒããã èªåã®é å + å°åºåã«ããïŒå€ã®éåã¯åãïŒãå¯äœçšãšã㊠SDK åŽã«å€ãå¢ããŠãåã§ã¯ æ°ä»ããªãã®ã§ãSDK æŽæ°æã«ç®èŠã§è¿œåŸãããããšãã«permissionMode㯠Claude Code åºæã® æŠå¿µã§ãä»ãšãŒãžã§ã³ãã§ã¯è§£éãå€ããããïŒåžåããã®ã¯ã¢ããã¿ã®ä»äºïŒãcore/status-reducer.tsããUSAGE_LIMIT_ERROR_PREFIXESã® import ãšisRateLimitErrorã æ¶ããCLI ã®æèšã»typed error kindã»HTTP ã¹ããŒã¿ã¹ã®ç¥èã¯core/claude-errors.tsã«éãŸã£ãã ã䜿çšå¶éã®æèšã¯ CLI åŽã§å€ããã®ã§ SDK ã«è¿œåŸãããããšããèŠæ±ã¯æ£ãããã远åŸããŠããã®ã¯ ã¢ããã¿ã®äžã ãã
applyAgentEvent(state, event, at, agent?)ïŒcore/agent-events.tsïŒãå
š provider å
±éã®å¯äžã®
ç³ã¿èŸŒã¿ã§ããã°ã®äžéïŒpushLogEntryïŒã»é²æïŒTODOïŒã»ãµããšãŒãžã§ã³ãã®å®äºã²ãŒã
ïŒactiveTaskIds / deferredResultïŒã»PR æ€åºïŒgh pr create ã® tool_use â tool_resultïŒã»
ã³ã¹ãéèšã»ã¹ããªãŒãã³ã°ãã¬ãã¥ãŒã¯ãã¹ãŠããã«ãããæ°ãããšãŒãžã§ã³ãã¯èªåã®ã¹ããªãŒã ã
AgentEvent ã®èªåœãžåãã ãã§ãããcodiva åºæã®æ¯ãèããåå®è£
ããªãã
AgentEvent 㯠provider éäŸåã®èªåœã«ãªãããéžãã§ãã:
session_started / assistant_message / assistant_text / tool_use / tool_result /
stream_reset / stream_text / notice / task_started / task_settled / turn_completed /
turn_stopped / usageãããŒã«å㯠AgentToolKindïŒedit / shell / todo / question /
otherïŒãžãTODO æäœã¯ TodoOpïŒcreate / update / replaceïŒãžã倱æã¯ AgentStopCause
ïŒauth / rate_limit / connection / failedïŒãžã¢ããã¿åŽã§æ£èŠåããŠããæž¡ã
ïŒturn_stopped.rollup ã¯ãããã¯æ¢ã«èšºææžã¿ã®åæ¢ã®èŠçŽãã®å°ã§ã2 åç®ã®å ±åã§åé¡ã
ããçŽããŠç²ŸåºŠãèœãšããªãããã®ãã®ïŒã
applyClaudeMessageïŒclaude-parse.tsïŒã¯ parse â fold ãåæããèãç³è¡£ã§ã1,100 è¡è¶
ã®å®ããŒã¿
ãã¹ãïŒclaude-parse.spec.ts + __fixtures__/*.jsonlïŒãåå²åãšåãå
¥å£ãå©ãç¶ããããããã«
æ®ããŠãã = åå²ã®ãªã°ã¬ãã·ã§ã³ç¶²ãæ°ããåŒã³åºãåŽã¯ãããå¢ããã AgentEvent çµç±ã«ããã
Session.setAgent(adapter) â CodivaEvent ã® agent_switchedãworktreeïŒïŒå®éã®ææç©ïŒã¯
provider ã«äŸåããªãã®ã§ãClaude ã§å§ããäœæ¥ãéäžãã Codex ã«åŒãç¶ãããäžæ¹ã¢ãã«åŽã®
æè㯠provider ããŸãããªãïŒå CLI ãèªåã®ãã©ã³ã¹ã¯ãªãããæã€ïŒãããåæ¿ã¯
ãä»ã®ã¿ãŒã³ãçµãã â å¥ provider ã®æ°ããã»ãã·ã§ã³ãåã worktree ã§éãããšãã圢ã«ãªãã
/agentïŒui/agent-select.tsxïŒã¯ /model ãšåãäºå±€æ§é ã§ãéžæè¢ã¯ã©ã¡ãã
listAgents()ïŒ= åæã¬ã€ã€ãç»é²ããã¢ããã¿ïŒã ããåºã:
- äžèЧãã¥ãŒ = æ°èŠã»ãã·ã§ã³ã®æ¢å®ãéžã¶ïŒ
mode:'default'ïŒãéžã¶ãšSessionManager.setDefaultAgent(id)ãæ¢å®ãå·®ãæ¿ããonDefaultAgentChangeâconfig.agentã«èªåä¿åããïŒæç·šéäžèŠ = ãèšå®ãããã§åãæ¿ãããããïŒã - 詳现ãã¥ãŒ = ãã®ã»ãã·ã§ã³ãéäžã§åãæ¿ããïŒ
mode:'session'âSessionManager.setSessionAgent(id, agentId)ïŒã
ã©ã®ãšãŒãžã§ã³ãã䜿ãããã¯æ€åºããŠèŠããã åã¢ããã¿ã® optional ãª
checkAvailability()ïŒå® I/O 㯠utils/claude.ts / utils/codex.ts / utils/grok.tsãkeychain ã¯èªãŸãã
Claude ã®ãã°ã€ã³ã¯ env / è³æ Œæ
å ±ãã¡ã€ã«ã§åãããšãã ã trueã»ãã以å€ã¯ 'unknown'ïŒã
SessionManager.checkAgents() ãéçŽïŒå€éèµ·åã 1 æ¬ã«ç³ã¿ãã£ãã·ã¥ïŒãã/agent ã®åè¡ã«
䜿çšã§ããŸã / æªãã°ã€ã³ / æªå°å
¥ ãåºããèšå® agent ãç¡ããã°èµ·åææ€åºã§å°å
¥æžã¿ã®
ãã®ãæ¢å®ã«èªåã§å¯ãïŒcore/agent-availability.ts ã® resolveDefaultAgentIdãæ°žç¶ã¯ããªãïŒã
ã©ããæªå°å
¥ãªãäžèЧã«ã»ããã¢ããæ¡å
ãåºãïŒnoAgentInstalledïŒããã®æ€åºã®ãããã§
claude ã codex ã grok ãå
¥ã£ãŠããªããŠã codiva ã¯èµ·åã§ããïŒèµ·åæã®ãããŒãã¯ãã¹ãŠ
倱æãæ¡ã朰ãïŒã
ãµã€ã³ã€ã³ã TUI ã®äžã§å®çµããïŒ/login / /agent ã® lïŒã端æ«ã¯æãæž¡ããã<cli> login ã
è£ã§èµ·åããŠåºåã®èªèšŒ URLã»ããã€ã¹ã³ãŒãããã€ã¢ãã°ã«åºãïŒèªåã§ãã©ãŠã¶ãéãïŒãé²è¡ã®
ç³ã¿èŸŒã¿ã¯çŽç²ãª core/agent-login.tsãããã»ã¹èµ·å㯠utils/agent-login.tsãseam ã¯
AgentAdapter.login() +SessionManager.startLogin / refreshAgentsãCodex ãš Grok ã¯
login --device-authïŒããŒã«ã«ãµãŒãã stdin ãèŠããªã headless åããããŒïŒãClaude ã¯
auth loginãlogin CLI 㯠URL ãè²ä»ãïŒANSIïŒã§åºãã®ã§ãæŸãåã«ãšã¹ã±ãŒããå¥ãã
ïŒå®æž¬ã§åãããŒããŠçŽããïŒããã©ãŠã¶åŽã§èªèšŒãçµãã£ãŠããã»ã¹ãçµäºããã refreshAgents ã§
ç¶æ
ãåå€å®ããã
åæ¿ã®å®äœã¯ãä»ã® run ã®å
¥åãã¥ãŒãéããŠãæ°ãããã¥ãŒã«å·®ãæ¿ãããããšã
this.run = undefined ã¯åç
§ãæšãŠãã ãã§ãconsume ã«ãŒãã¯ãã® AgentRun ãæŽãã ãŸãŸåãç¶ãã
ã¢ããã¿åŽã¯å
±æãã¥ãŒã await ããŠæ¢ãŸã£ãŠãã â ã€ãŸãéããªãéãåæ¿åŸã«éã£ãæç€ºã¯
å€ããšãŒãžã§ã³ããåãåãïŒåãæ¿ããã®ã«äœãèµ·ããªãããã«èŠãããPhase A ã®ç©ã¿æ®ãã§ã
/agent ãå
¥ããŠåããŠèžããçµè·¯ã ã£ãïŒãã»ãã·ã§ã³å
šäœã® abortController ã abort ããæã¯
䜿ããªãïŒããã¯ã»ãã·ã§ã³ããšçµããããããïŒãç³ãã ã«ãŒããçµãã£ãæç¹ã§ãã¥ãŒã«ç©ã¿æ®ãã
ããã°ïŒAsyncQueue.pendingïŒãæ°ãããšãŒãžã§ã³ãã§æ¶è²»ãçŽãã
| åŒãç¶ããããã® | åŒãç¶ãããªããã® |
|---|---|
| worktreeã»ãã©ã³ãã»äœæ¥ããªãŒã®å 容 | ã¢ãã«åŽã®äŒè©±æèïŒprovider ããšã«å¥ã®ãã©ã³ã¹ã¯ãªããïŒ |
codiva åŽã®ãã°ïŒmessagesïŒã»ã¿ã€ãã«ã»PRã»çšŒåæé |
sdkSessionIdïŒåæ¿å
ã® agentSessions ã«ç¡ããã° undefined ïŒæ°ããäŒè©±ïŒ |
agentSessionsïŒprovider ããšã® resume idïŒ |
streamingTextïŒåã®ãšãŒãžã§ã³ãã®éäžè¡šç€ºïŒ |
ã»ãã·ã§ã³ã®ç¶æ
ïŒSessionStatusïŒ |
modelïŒè§£æ±ºæžã¿ã¢ãã«ã¯ provider ããšã«å¥ç©ã次ã®ã¿ãŒã³ãåããïŒ |
æ»ã£ãŠãããšãã«ç¶ãããåéã§ãããããagentSessions: Partial<Record<AgentId, string>> ã«
provider ããšã® resume id ãæ§ããããã¯æ°žç¶åããïŒstate.jsonïŒãèœãšããšåèµ·åããŸããã§
ãCodex ã«åãæ¿ããŠããŸã Claude ã«æ»ããããããšãã«éå»ã®äŒè©±ãæ¶ããŠæ°èŠã»ãã·ã§ã³ãã
å§ãŸã£ãŠããŸããä¿åæã¯çŸåšã® sdkSessionId ã agentSessions[agent] ãžç³ãïŒagent_switched ã¯
åæ¿ã®ç¬éã«ããç³ãŸãªãã®ã§ãåæ¿ããã«çµäºããã»ãã·ã§ã³ã® id ãããããæŒããïŒãagent ã®
ç¡ãïŒåæ¿å¯Ÿå¿ããåã®ïŒã¹ãããã·ã§ãã㯠'claude' ãšããŠåŸ©å
ããã
åæ¿ã®å®è£ ã§å®ã£ãŠããããš:
- èµ°ã£ãŠããã¿ãŒã³ãç³ãã§ããå·®ãæ¿ããã2 æ¬ã®ã¹ããªãŒã ãåã worktree ãè§Šããªãããã«
çŸåšã® run ãæšãŠãä¿çäžã®èš±å¯ã¯ deny ã§è§£æ±ºããïŒæªå¿çã®
tool_useã§çµãããã©ã³ã¹ã¯ãªãã㯠åŸã® resume ãå£ã âstop()ãšåãçç±ïŒãæ°ãããšãŒãžã§ã³ããç«ã¡äžããã®ã¯æ¬¡ã®send()ã - resume id 㯠provider ããŸããã§æž¡ããªããåæ¿åŸã¯
agent_switchedãæ®ããsdkSessionIdã ãã䜿ãïŒåŸ©å æã®deps.resumeã¯åæãšãŒãžã§ã³ãçšãªã®ã§ãå¥ provider ãžæã¡èŸŒããšååšããªã äŒè©±ã resume ããããšããŠå£ããïŒã - ãã°è¡ã®åž°å±ïŒ
LogEntry.agentïŒã¯åæ¿ãèµ·ããããšã ãå»ããåäžãšãŒãžã§ã³ãã§å®çµãã ã»ãã·ã§ã³ã®ãã°è¡ã®åœ¢ãå€ããªãããïŒåæ¿ã䜿ã£ãŠããªããŠãŒã¶ãŒã«ã¯äœãå¢ããªãïŒã 詳现ãã¥ãŒã¯ãã®åž°å±ãå€ããå¢çã«åºåãè¡ïŒââ ãããã Codex ââïŒã 1 æ¬æ¿ã ïŒè¡ã®æ¿å ¥ã¯core/scroll.tsã®logLines(âŠ, dividerFor)ãæèšã¯ã«ã¿ãã° + ã¢ããã¿ã®è¡šç€ºåïŒã - åŒãç¶ãã®ç¶æ³èª¬æã 1 åã ãæž¡ãïŒ
core/agent-handoff.tsã®handoffInstructionïŒã åæ¿å ã¯åã®äŒè©±ãæããªãã®ã§ãäœãæž¡ããªããšãéäžãŸã§äœæ¥ãããäœæ¥ããªãŒããçœçŽãã èŠãããšã«ãªããæžãã äœæ¥ãããçŽãããçŽåã®æç€ºãç¡èŠãããããããã©ã³ãã»æåã®æç€ºã» çŽåã®æç€ºã䞊ã¹ãç¶ããåã«èªåã§git status/git diffãèªãããä¿ãæãAgentRunOptions.systemPromptïŒcomposeSystemPromptã®æåŸã®ç¯ïŒã«èŒããã- äœ¿ãæšãŠã«ããïŒ
Sessionãæ¬¡ã®open()ã§æ¶è²»ããïŒãåžžèšã«ãããšãåŒãç¶ããæžãã ããšã®ã¿ãŒã³ãéä¿¡æããã®åèµ·åã§ããåä»»è ããåŒãç¶ãã ããšèšãç¶ããããšã«ãªãã - ãã¥ãŒãžæç€ºãšããŠç©ãŸãªããç©ããšåæ¿çŽåŸã«ãç¶æ³ãèªãã ãã®ã¿ãŒã³ãã 1 æ¬èµ°ãã provider ã®ããã»ã¹ãç¡é§ã«ç«ãŠãïŒãŠãŒã¶ãŒãæ¬¡ã®æç€ºãåºããŸã§äœãèµ·ãããªãã®ãæ£ããïŒã
- åé
ç®ã¯ 1 è¡ã«ç³ãã§
MAX_HANDOFF_FIELD_CHARSã§åãïŒæç€ºæã¯ãã¡ã€ã«ãäžžããšè²Œã£ã ãã®ã«ãªãããã®ã§ãsystemPrompt ãæ¬æãã倧ãããªãã®ãé²ãïŒãAI åãã®æååãªã®ã§ i18n ã«ã¿ãã°ã«ã¯çœ®ããªãïŒè±èªåºå®ãSHARED_IGNORED_FILES_NOTICEãšåãæ±ãïŒã
- äœ¿ãæšãŠã«ããïŒ
AgentCapabilitiesïŒpermissions / interrupt / setModel / resume / modelCatalog /
usage / cost / transcriptïŒã§ããã®ãšãŒãžã§ã³ããäœãã§ããããã衚æãããUI ã¯ãããèŠãŠ
段éçã«çž®éããïŒæããªãæ©èœã®ããŒæäœã»è¡šç€ºãåºããªãïŒãåç
§ãããšãã¯åºå®å€ãšããŠæãã
SessionManager.getSessionAgent(id)ïŒ= SessionHandle.getAgent()ïŒããåŒãïŒã»ãã·ã§ã³éäžã§
åãæ¿ãããšå€ããããããïŒã
| capability | Claude | Codex | Grok |
|---|---|---|---|
permissions |
true | falseïŒexec ã® JSON ã¢ãŒãã¯æ¿èªèŠæ±ãäžããããªãïŒ | trueïŒACP ã®èŠæ±ããã®ãŸãŸå±ãïŒ |
interrupt |
true | true | true |
setModel / modelCatalog |
true | true | true |
resume |
true | true | true |
usage |
true | false | false |
cost |
true | false | false |
transcript |
true | false | false |
çŸç¶ Claude ã ããæã€ïŒïŒä» provider ã§ã¯çž®éãããïŒæ©èœã¯ã䜿çšç¶æ³ã²ãŒãžïŒusageïŒã»
ã³ã¹ã衚瀺ïŒcostïŒã»CLI ãã©ã³ã¹ã¯ãªããããã®ãã°åŸ©å
ïŒtranscriptïŒã»åŠç¿ããŒã¿å©çšã®èŠå
ïŒClaude Code ã®èªèšŒæ
å ±ãèªã utils/privacy.tsïŒãèš±å¯/質åãã€ã¢ãã°ïŒpermissionsïŒã¯
Codex ã ããæããªãïŒçç±ã¯ §6ïŒã
ã¢ãã«ã«ã¿ãã°ãš /modelïŒmodelCatalog / setModelïŒã¯ Codex ã Grok ãæã€ãéžã¹ãã¢ãã«ã
ãããããŸã£ããå¥ãªã®ã§ãUI ã¯é§åäžã®ãšãŒãžã§ã³ãã§éžæè¢ãåºãåãããåºãåãã¯
provider ããšã® propïŒcodexModels ã®ãã㪠ternaryïŒã§ã¯ãªã modelsByAgent
ïŒPartial<Record<AgentId, ModelOption[]>>ïŒã®è¡šã App ãäž¡ view ãžæž¡ã圢ã«ããŠããã
provider ãå¢ããŠããã¥ãŒåŽã®åå²ã¯å¢ããªãïŒæªç»é²ã®ãšãŒãžã§ã³ã㯠Claude åŽã®ã«ã¿ãã°ãž
ãã©ãŒã«ããã¯ïŒãååŸã«å€±æããŠãäºãã®ã¢ãã«åãåºããªãïŒ= DEFAULT_ONLY_MODEL_OPTIONSïŒã
AgentRun.interrupt / setModel ã¯ã¡ãœããèªäœã optional ã§ãæ°ããã¢ããã¿ã¯
NO_CAPABILITIESïŒå
šéš falseïŒããå§ããŠå®è£
ã§ãããã®ã ã true ã«ããã
æèšåŽã i18n.ts ã® AgentLabelïŒè¡šç€ºå + ãã°ã€ã³ã³ãã³ãïŒãå·®ã蟌ã圢ã«ããŠããã
auth.hint / auth.listHint / notify.needsLogin / action.resumeAllPrompt ã¯
(agent: AgentLabel) => stringãå·®ã蟌ãå€ã¯ã»ãã·ã§ã³ã® provider ããåŒã
ïŒagentLabelOf + SessionManager.getSessionAgentLabelãDEFAULT_AGENT_LABEL = Claude ã¯
ã¢ããã¿ãåãããªããšãã®ãã©ãŒã«ããã¯ã«çž®å°ïŒãCodex ã®ã»ãã·ã§ã³ãèªèšŒåãã«ãªã£ããšã
ãclaude ã§ãã°ã€ã³ãçŽããŠããšèšããªãããã®é
ç·ã§ãäžèЧã»è©³çްã»ãã¹ã¯ãããéç¥ã® 3 çµè·¯ã§å¹ãã
ãšãŒãžã§ã³ãåã¯åºæåè©ãªã®ã§ç¿»èš³ããªãïŒã¢ãã«åãšåã i18n ã®äŸå€ïŒã
çž®éã®å€å®ã¯çŽç²ãª core/agent-capabilities.ts ã«å¯ããŠããïŒsupportsCapability /
capabilityLookup / agentSupports / showsAccountInfoïŒãèŠç¹ã¯ 2 ã€:
- capability ãåãããªããšãã¯çž®éããªãïŒ
supportsCapability(undefined, âŠ) === trueïŒã æªç»é²ã® providerã»agentãæããªãå€ãã»ãã·ã§ã³ã§æ©èœãé ããšãåãã¯ãã®æäœãé»ã£ãŠ æ¶ãããæ¢åã®caps && !caps.setModelãšåãèŠçŽã - ãæ°åã 0 ã ããèªç¶ã«æ¶ãããã«é ŒããªããCodex / Grok 㯠USD ãéã°ãªãã®ã§ãããã®
åèšã³ã¹ãã¯ä»ã®ãšããåæã«æ¶ããããããã¯å¶ç¶ã§ãã£ãŠãæ··åšæã«ãClaude ã¶ãã®åèšãã
å
šäœã®ã³ã¹ããšããŠåºãäœå°ãæ®ãã
AgentCapabilitiesãèŠãæç€ºçãªåå²ã«çœ®ãæããã
| çž®éãã察象 | capability | èŠãå Žæ | çž®éã®åœ¢ |
|---|---|---|---|
/model ã®ãã€ã¢ãã° |
setModel / modelCatalog |
ui/session-detail.tsx |
éããã«çç±ãåºãã»éžæè¢ã provider å¥ã«åºãåã |
Ctrl+C ã®ãã³ã |
interrupt |
ui/session-detail.tsx |
ãã³ãè¡ãåºããªã |
| åèšã³ã¹ãïŒãããïŒ | cost |
core/cost.ts ã® totalCostUsd(states, reportsCost) |
å ±åããªã provider ã®ã»ãã·ã§ã³ãåèšã«æ°ããªã |
| ãã©ã³å + 䜿çšç¶æ³ã²ãŒãžïŒãããïŒ | usage |
showsAccountInfoïŒäžèЧã®è¡šç€º + bootstrap/usage-poller.ts ã® enabledïŒ |
æ¢å®ãšãŒãžã§ã³ããå ±åããªããã°åºããªããåãã«ãè¡ããªãïŒ5 åããšã® probe ãç«ãŠãªãïŒ |
| 確èªã¢ãŒãã®ããã¿è¡šç€º | permissions |
ui/status-footer.tsx ã® confirmSupported |
確èªã¢ãŒã (é察å¿) ã«å·®ãæ¿ããïŒäžèšïŒ |
| ãã©ã³ã¹ã¯ãªãã埩å | transcript |
bootstrap/restore-sessions.ts |
ãã® provider ã®ã»ãã·ã§ã³ã§ã¯èªã¿ã«ãè¡ããªã |
| èªèšŒåãã®æèš | âïŒAgentLabelïŒ |
äžèЧã»è©³çްã»éç¥ | é§åäžã® provider ã®ã³ãã³ãåãåºã |
確èªã¢ãŒãã®è¡šç€ºã capability ã§å€ããçç±: permissions: false ã® providerïŒCodexïŒã§ã¯
èš±å¯ãã€ã¢ãã°ãåççã«åºãªããããã§ãããã¿ã 確èªã¢ãŒã ãšèšãåã£ãŠããã®ã§ã
ãåŸ
ã£ãŠããã°èãããããšèªããŠããŸã£ãŠããïŒããŒã«ã¯ç¢ºèªãªãã«å®è¡ãããïŒããã€ã¢ãã°ã
åœè£
ããªãã®ãšåãçç±ã§ãã¢ãŒã衚瀺ã®åŽãæ£çŽã«ããã
ãããã¯ã次ã«åããšãŒãžã§ã³ããã®èª¬æã«ããããšãŒãžã§ã³ãåã»ãã©ã³åã»ã¢ãã«ã»äœ¿çšç¶æ³ã¯
1 ã€ã®ã¢ã«ãŠã³ãã®è©±ãšããŠåãå Žæã«äžŠãã§ããã®ã§ã/agent ã§æ¢å®ãåãæ¿ããã4 ã€æã£ãŠ
å
¥ãæ¿ãããå€å®ã¯ showsAccountInfoïŒ= æ¢å®ãšãŒãžã§ã³ãã usage ãå ±åãããïŒ1 æ¬ã§ã
ãã©ã³åãæ ãåã 1 åã® probeïŒutils/usage-probe.tsïŒãéã¶ã®ã§åããŠããªãã
衚瀺ãšååŸã¯åãçŽé¢æ°ãéãã®ã§ãåºããŠããªãã²ãŒãžã®ããã« claude ã®ãµãããã»ã¹ã
ç«ã€ããšã¯ãªãïŒæ¢å®ã Claude ãžæ»ãã°æ¬¡ã® poll ããåéããïŒã
- ãã€ãŠã¯ãæ¢å®ãšãŒãžã§ã³ã or
archivedã§ãªãã»ãã·ã§ã³ã®ã©ãããå ±åãããã§å€å®ã㊠ãããããCodex / Grok ã«åãæ¿ããŠã Claude ã®ãã©ã³ãšã²ãŒãžãæ®ã£ãŠããã皌åäžã® Claude ã»ãã·ã§ã³ã®æ¶è²»ãèŠãããšããå©ç¹ã¯ãã£ããããããã®èªã¿æ¹ïŒ= æ¢å®ãšãŒãžã§ã³ãã®èª¬æïŒã é ç®ããšã«é£ãéãã»ãã害ã倧ãããšå€æããŠãæ¢å®ãšãŒãžã§ã³ãã ããèŠã圢ã«çããã - ã¢ãã«æ¬ãšæ¢å®ãšãŒãžã§ã³ã㯠manager ã®è³Œèªã§èªãïŒ
ui/hooks.tsã®useDefaultModel/useDefaultAgentãsetModel/setDefaultAgentãstore.notify()ããïŒãèµ·åæã®èšå®å€ã prop ã§é ã£ãŠãããšãã¯ã/modelããšãŒãžã§ã³ãåæ¿ïŒæ¢å®ã¢ãã«ã CLI æ¢å®ãžæ»ãïŒã®ããšã åã®å€ãå± åº§ã£ãŠãå®éã«äœ¿ãããã¢ãã«ãšé£ãéã£ãŠèŠããŠããã
CodexïŒcodex CLIïŒã¯ Phase B ã§å
¥ãã 2 ã€ç®ã® provider ã§ãå®è£
㯠core/codex-events.ts
ïŒJSONL ã®åãšåçã¬ãŒãïŒ/ core/codex-parse.tsïŒAgentEvent[] ãžã®ååïŒ/
core/codex-errors.tsïŒæèš â AgentStopCauseïŒ/ core/codex-adapter.tsïŒå¶åŸ¡ïŒã® 4 ç¹ãšã
å¯äžã® I/O utils/codex.tsãClaude åŽã® 3 ç¹ã»ãããšå¯Ÿç§°ã«çœ®ããŠããã
@openai/codex-sdk ã npm äŸåã«è¶³ããããŠãŒã¶ãŒãã€ã³ã¹ããŒã«ãã codex CLI ãèµ·åãã
ïŒgh / git ãšåãæ±ãïŒãSDK ãäŸåã«ãããš Codex ã䜿ããªããŠãŒã¶ãŒã«ããã©ãããã©ãŒã å¥ã®
倧ããªãã€ããªãéã£ãŠãããããèªèšŒããŠãŒã¶ãŒã® codex login ã«å§ããcodiva ã¯è³æ Œæ
å ±ãè§Šããªãã
Claude ãšæ±ºå®çã«éãã®ãããã»ã¹ã®ç²åºŠãClaude Agent SDK 㯠1 æ¬ã® streaming-input ã»ãã·ã§ã³ã
äœã¿ãŒã³ã§ãç¶ãããcodex exec ã¯1 ã¿ãŒã³èµ°ã£ãŠçµäºããããã»ã¹ã§ãç¶ãã¯
codex exec resume <thread_id> <prompt> ãšããŠèµ·åãçŽããã¢ããã¿ã¯ãã®å·®ãå
åŽã«éã蟌ãã:
prompt ãã¥ãŒ âââ¶ codex exec --json <p1> âââ¶ thread.started(th) ⊠turn.completed
âââ¶ codex exec resume th <p2> âââ¶ thread.started(th) ⊠turn.completed
AgentRunã®éåæã€ãã¬ãŒã¿ãrequest.promptãåããæç€º 1 ä»¶ã«ã€ã 1 ããã»ã¹ãèµ·ãããthread.startedã®thread_idãæ§ããŠæ¬¡ã®ã¿ãŒã³ãžåŒãåãïŒresume ããåãåã id ã å床å±ãã®ã§ãsession_started㯠no-op ã«ãªãïŒã--system-promptçžåœãç¡ãã®ã§ãcomposeSystemPrompt()ã®çµæã¯æåã®ã¿ãŒã³ã®æç€ºæã« å眮ããïŒ2 ã¿ãŒã³ç®ä»¥éã¯åãã¹ã¬ããã® resume ãªã®ã§ã¢ãã«ã¯æ¢ã«èªãã§ããïŒãAGENTS.mdãæžãæ¹æ³ã¯åããªã â 察象ãªããžããªã®ãã¡ã€ã«ã codiva ãåæã«è§ŠããªããããsetModelã¯ã次ã®ã¿ãŒã³ãããå¹ãïŒèµ°ã£ãŠããããã»ã¹ã«ã¯åæ ãããªãïŒãã¿ãŒã³ããšã« èµ·åãçŽã圢ãªã®ã§ããããèªç¶ãªå¥çŽã«ãªãã- çµç«¯ã€ãã³ãïŒ
turn.completed/turn.failedïŒãæ¥ãªããŸãŸããã»ã¹ãçµããããšããã ïŒäžæã»codexæªå°å ¥ã§ã®èµ·å倱æïŒã®ã§ããã®ãšãã ãçµäºã³ãŒããš stderr ã§è£ãã
| capability | Codex | çç± |
|---|---|---|
permissions |
false | exec ã® JSON ã¢ãŒãã¯æ¿èªèŠæ±ãäžããããªãïŒäžèšïŒ |
interrupt |
true | ããã»ã¹ã殺ãã°ã¿ãŒã³ãæ¢ãŸã |
setModel |
true | 次ã®ã¿ãŒã³ã® --model ãšããŠå¹ã |
resume |
true | codex exec resume <thread_id> |
modelCatalog |
true | codex debug models ãããŒã«ã«ã®ã«ã¿ãã°ã JSON ã§åãïŒæšè«ãã³ã¹ããç¡ãïŒ |
usage |
false | ã¢ã«ãŠã³ãå šäœã®äœ¿çšç¶æ³ãéã¶ã€ãã³ããç¡ã |
cost |
false | turn.completed ã¯ããŒã¯ã³æ°ã ãã§ USD ãéã°ãªã |
transcript |
false | rolloutïŒ~/.codex/sessionsïŒã¯ Claude CLI ã® JSONL ãšå¥åœ¢åŒ |
permissions: false ãäžçªéãå¶çŽãcodex exec ã® JSON ã¢ãŒãã¯ãã³ãã³ãå®è¡ã»ãããé©çšã»
MCP ã®ãããã®æ¿èªèŠæ±ã CLI å
éšã§èªå reject ããJSONL ã«ã¯äœãåºããªã
ïŒCodex ã® codex-rs/exec/src/lib.rs ã® handle_server_requestïŒãã€ãŸã
codiva ãèš±å¯èŠæ±ã UI ã«äžããçµè·¯ãåççã«ç¡ããããã§ãããããããã€ã¢ãã°ããåºããšã
ãŠãŒã¶ãŒã y ãæŒããŠãå®éã«ã¯æåŠãããŠãããšããææªã®åã«ãªãã®ã§ãcapability ã false ã«
ããŠé»ã£ãŠåºããªãæ¹ãéžãã ïŒAgentAdapter.requestPermission 㯠Codex ã§ã¯åŒã°ããªãïŒã
ãã®çµæãCodex ã»ãã·ã§ã³ã«å¯Ÿããå®å
šåŒã¯ãµã³ãããã¯ã¹ã ãã«ãªããã ããèšå®
codexSandboxïŒæ¢å® workspace-write = æžã蟌ã¿ã¯ worktree å
ã«éå®ã»èªã¿åãã¯å
šäœïŒã
è¶³ããapproval_policy="never" ãæç€ºããŠãèãããŠæ¢ãŸããçµè·¯ã朰ããŠããã
codexNetworkAccess ã®æ¢å®ã true ã«ããŠããã®ã¯ãCodex èªèº«ã® workspace-write æ¢å®ã
ãããã¯ãŒã¯é®æã§ããã®ãŸãŸã ãš npm install / gh ã倱æããŠå€§åã®äœæ¥ãå®äºããªããã
ïŒå®å
šåŽã«åããããšã㯠false ã«ã§ããïŒã
Codex ã¯æ¥ç¶ãåãããš {"type":"error","message":"Reconnecting... 1/5 (stream disconnected âŠ)"}
ã stdout ã® JSONL ãšããŠæµããªããå詊è¡ãã諊ãããšãã ã turn.failed ãåºãïŒå®æž¬ã
__fixtures__/codex-failure.jsonlïŒãerror ãçŽ çŽã«çµäºæ±ãã«ãããšãæŸã£ãŠããã°èªåã§
å埩ããã»ãã·ã§ã³ãèµ€ããªããããã§:
errorã¯noticeïŒsystem è¡ïŒ1 è¡ã«èœãšãã ãã§ç¶æ ãåãããªããå詊è¡ã®å®æ³ã¯coalesceKeyïŒ'Reconnecting'ïŒã§çŽåã®åçš®è¡ãæžãæãã5 é£çºã§ãã°ãåããªã ïŒClaude ã® API ãªãã©ã€è¡šç€ºãšåãä»çµã¿ïŒã- ã¿ãŒã³ãæ¬åœã«èœã¡ãä¿¡å·ã¯
turn.failedãšãçµç«¯ã€ãã³ãç¡ãã®éãŒãçµäºã³ãŒãã ãã ããããclassifyCodexErrorãauth/rate_limit/connection/failedãžåé¡ãã ïŒå€å®é 㯠Claude åŽãšåããèªèšŒåããæåªå ïŒã
GrokïŒxAI ã® grok CLIïŒã¯ Phase C ã§å
¥ãã 3 ã€ç®ã® provider ã§ãå®è£
㯠core/grok-events.ts
ïŒACP ã¡ãã»ãŒãžã®åãšåçã¬ãŒãïŒ/ core/grok-parse.tsïŒAgentEvent[] ãžã®ååïŒ/
core/grok-errors.tsïŒerror_type ãšæèš â AgentStopCauseïŒ/ core/grok-adapter.tsïŒå¶åŸ¡ïŒãš
core/grok-models.tsãå¯äžã® I/O utils/grok.tsãClaude / Codex ã® 3 ç¹ã»ãããšå¯Ÿç§°ã«çœ®ããŠããã
CLI ã忢±ãããŠãŒã¶ãŒã® grok ãèµ·åããæ¹éããèªèšŒã grok login ã«å§ããæ¹éã Codex ãšåãã
é§åããã®ã¯ ACPïŒAgent Client ProtocolïŒ= stdio äžã® JSON-RPC 2.0 ã§ãgrok agent --no-leader stdio ãèµ·ãããheadless ã® -p --output-format streaming-json ã䜿ããªãã®ã¯ããããäžæ¹éè¡
ïŒèªã¿åãå°çšïŒã ãã â ããŒã«äœ¿çšã®èš±å¯ã質åãããšãŒãžã§ã³ãåŽããèŠæ±ãé£ãã§ããŠã
ã¯ã©ã€ã¢ã³ããçãããŸã§åãããæ¢ãŸãã圢ã§ãã衚çŸã§ãããåæ¹åã®ãã£ã³ãã«ãèŠãã
ããã CodexïŒpermissions: falseïŒãšã®æ±ºå®çãªéãã§ãGrok ã§ã¯èš±å¯ã»è³ªåãã€ã¢ãã°ãæ¬ç©ãšããŠ
åºããã--no-leader ã¯å
±æã® leader ããã»ã¹ãžçžä¹ãããªãããïŒçžä¹ããããšå¥ã¯ã©ã€ã¢ã³ãã®
ã»ãã·ã§ã³ã®ç¶æ
å€åãŸã§æµã蟌ãïŒã
ãªãã1 ã»ãã·ã§ã³ 1 ããã»ã¹ + 察å¿è¡šãã§ãCodex ã®ã1 ã¿ãŒã³ 1 ããã»ã¹ãã§ã¯ãªãã®ã
ããã»ã¹ã®ç²åºŠã¯ provider ãæ±ºãããcodex exec 㯠1 ã¿ãŒã³ã§çµäºããã®ã§ã¢ããã¿ã
ããã»ã¹ãèµ·ããçŽããããªãã£ãããACP 㯠1 æ¬ã®æ¥ç¶ã®äžã§äœã¿ãŒã³ã§ãç¶ãïŒã¿ãŒã³ =
session/prompt ã® 1 åŸåŸ©ã§ãå¿çã® stopReason ãçµãããåããïŒãã ãã Grok ã§ã¯
âââââ session/prompt(id=3) ââââââââââââââ¶
codivaïŒclientïŒ âââââ session/update éç¥ïŒæ¬æã»ããŒã«ã»planïŒ
âââââ session/request_permission(id=7) ââ èŠæ±
âââââ å¿ç(id=7) ââââââââââââââââââââââââ¶
âââââ å¿ç(id=3) stopReason:end_turn ââââ ã¿ãŒã³çµäº
ã®ããã« 1 æ¬ã®ããã»ã¹ã«è€æ°ã®åŸåŸ©ãåæã«èŒããJSON-RPC ã® id ã§ããèŠæ±ãšå¿çã
察å¿ã¥ããããªãã®ã§ãã¢ããã¿ã¯ Map<number, Pending> ã®å¯Ÿå¿è¡šãæã€ãCodex ã®
ã1 ããã»ã¹ = 1 ã¿ãŒã³ããªãããã»ã¹ã®å¯¿åœããã®ãŸãŸå¢çã«ãªãããããã§ã¯ããã䜿ããªãã
AgentRun ã®å¥çŽã¯ãAgentEvent ãæµãéåæã€ãã¬ãŒã¿ãã ããªã®ã§ããã®éãã¯å€ãžæŒããªãã
å®ã£ãŠããããš:
- ãšãŒãžã§ã³ãããæ¥ãèŠæ±ã«ã¯å¿
ãçããïŒ
session/request_permission/_x.ai/ask_user_questionïŒãçãããŸã§åããã¯æ¢ãŸã£ãŠããã®ã§ãåãããŒããšã¿ãŒã³ãæ°žä¹ ã« çµãããªãããã©ã¡ãŒã¿ãèªããªããŠå€æã§ããªãèŠæ±ããé»ã£ãŠæšãŠãã«cancelledãè¿ã㊠å ãžé²ãŸãããéã«ãã¡ãçºã®èŠæ±ïŒrpc()ïŒã®åŸ ã¡ã¯ãããã»ã¹ãæ»ãã æç¹ã§å šéšèµ·ããã session/cancelã¯éç¥ïŒnotificationïŒãidãä»ããŠèŠæ±ãšããŠéããš-32601 Method not foundãè¿ãïŒå®æž¬ïŒã®ã§ãäžæã¯ id ç¡ãã§éãã- äžæãæ¢ããããã®ã¯ãä»èµ°ã£ãŠããã¿ãŒã³ãã ãã
Ctrl+Cã¯ã»ãã·ã§ã³ã®ç«ã¡äžã ïŒinitializeâsession/new/session/resumeïŒã®æäžã«ãæŒããããããã§session/cancelã éã£ãŠãæ¢ãã察象ãç¡ã空æ¯ãããããã®ãŸãŸsession/promptãåºããšãUI ã¯ãäžæããããš èšã£ãŠããã®ã«ãšãŒãžã§ã³ãã ãã worktree ãæžãæãç¶ããïŒå®äºã€ãã³ãã¯interruptedã§ ææ¢ãããã®ã§ãèª°ãæ°ä»ããªããŸãŸé²ãïŒãç«ã¡äžãäžã«äžæãããã¿ãŒã³ã¯å§ããã«æç€ºããš æšãŠãïŒããçŽãã¯ãŠãŒã¶ãŒãæ¹ããŠéãïŒã1 ããã»ã¹ãè€æ°ã¿ãŒã³ãè·šã provider ã§ã¯ã ãããã»ã¹ã殺ãã°æ¢ãŸããïŒCodexïŒãæãç«ããªãã¶ããããèªåã®è²¬åã«ãªãã - èš±å¯ã®
optionIdã¯åºå®æååã§ã¯ãªãïŒããŒã«ããšã«å€ããïŒãkindïŒallow_once/allow_always/reject_once/reject_alwaysïŒã§éžã¶ã - 質åã®å¿çã«ã¯
outcomeãå¿ ãä»ããã{"outcome":"accepted","answers":{âŠ}}/{"outcome":"cancelled"}ã® 2 éãã§ãçããšãã¯ã©ã€ã¢ã³ãã®å¿çãäžæ£ããšããŠããŒã«ã倱æãã ïŒå®æž¬ïŒã - 埩å
ã¯
session/loadã§ã¯ãªãsession/resumeãloadã¯äŒè©±ãäžžããšéç¥ãšããŠåçã㊠ããŸããcodiva ã®ãã°ãäºéã«ãªããresumeã¯ã¢ãã«åŽã®æèã ããæ»ãïŒå®æž¬: å¥ããã»ã¹ã§ resume ããã¹ã¬ããã§ãbackend ãå ã®ã¿ãŒã³ãèŠããŠããïŒã - éç¥ã¯ 2 系統ã§å±ããACP æšæºã®
session/updateïŒcamelCaseïŒãš xAI æ¡åŒµã®_x.ai/session_notificationïŒåãupdateã®å°çã§ snake_caseïŒãgrok-parse.tsã¯äž¡æ¹ã åãå ¥å£ãžæµããagent_message_chunk/agent_thought_chunk/tool_call/tool_call_update/planïŒ= TODOïŒ/retry_stateã ããåããŠæ®ãã¯æšãŠãã - systemPrompt ã¯
session/newã®_meta.rulesã§æž¡ãïŒCLI ãèªåã® system prompt ãžè¿œèš ããïŒãsystemPromptOverrideã¯äœ¿ããªã â Grok èªèº«ã® system prompt ã眮ãæããŠããŸãããã
Grok ã¯ãå®éã«åããŠããã¢ãã«ããèªåã§å ±åããïŒsession/new / session/resume ã®çµæã®
models.currentModelIdãã¿ãŒã³å¿çã® _meta.modelIdãå€æŽæã® _x.ai/models/updateïŒãã ãã
Codex ã§å¿
èŠã ã£ã rollout ã®æ¢ãèªã¿ïŒcodex-rollout.tsïŒã«çžåœãããã®ã¯ååšããªã
ïŒgrok-rollout.ts ã¯ç¡ãïŒã/model ã®ã«ã¿ãã°ã initialize ã®å¿çã®
_meta.modelState.availableModels ããåããã®ã§ãutils/grok.ts ã® fetchGrokModelCatalog ã¯
ãšãŒãžã§ã³ãã 1 åèµ·ãã㊠initialize ã ãéããã«ã¿ãã°ãèªãã§ããã»ã¹ã殺ã
ïŒã»ãã·ã§ã³ãæšè«ãäœããªãïŒãgrok models ã䜿ããªãã®ã¯ã人éåãã®ããã¹ãããåºãã
ïŒ--json ãç¡ãïŒããµã€ã³ã¢ãŠãç¶æ
ã§ã 0 ã§çµããã®ã§èªèšŒã®å€å®ã«ã䜿ããªããããå°å
¥å€å®ã¯
grok --versionããã°ã€ã³å€å®ã¯ XAI_API_KEY ã ~/.grok/auth.json ã®æç¡ïŒããŒã¯ã³ã®æå¹æ§ãŸã§ã¯èŠãªãïŒã
倱æåé¡ã¯ä»ã® 2 ã€ã«ç¡ãæãããã䜿ã: retry_state éç¥ã CLI èªèº«ã®åé¡ïŒerror_typeïŒã
éã¶ã®ã§ãåãããªããããåªå
ããç¡ããšãã ãæèšãèŠãïŒgrokStopCauseïŒããã ã
error_type: "api" 㯠4xx/5xx ãäžç·ããã«ããã®ã§ãããšæèšå€å®ãžèœãšã â ããã§ failed ã«
äžžãããš 401 ããããåãããªã倱æãã«æ Œäžããããåãã°ã€ã³ãä¿ããªããªãã
Codex ã® stdout ã Grok ã® stdio ãã1 è¡ 1 JSONããªã®ã§ãæ åã createJsonlSplitter
ïŒéšåè¡ã»CRLFã»æ«å°Ÿè¡ã»1 è¡ã®äžéïŒã codex-events.ts ããprovider éäŸåã® core/jsonl.ts
ãžç§»ããŠå
±çšãããããã ã㯠provider åºæã®ç¥èãå«ãŸãªãçŽç²ãª framing ãªã®ã§ã
ãprovider ã®åœ¢ã®ç¥èã¯ã¢ããã¿ã«éãããèŠçŽã«åããªãã
SessionStatus ã®é·ç§»ãå°åºå
ã¯ãã¹ãŠãšãŒãžã§ã³ãã®ã€ãã³ãã¹ããªãŒã ïŒAgentEventïŒãšèš±å¯èŠæ±ã
以äžã®èšè¿°ã¯ Claude ã¢ããã¿ã§ã®å
·äœïŒSDKMessage ã® subtype ãªã©ïŒãå«ãããç¶æ
æ©æ¢°ãã®ãã®ã¯
provider éäŸåã
creating ââ(worktreeäœæå®äº & queryéå§)âââ¶ running
running ââ(canUseTool çºç«)ââââââââââââââââ¶ awaiting_permission
awaiting_permission ââ(ãŠãŒã¶ãŒå¿ç)âââââââââ¶ running
running ââ(result åä¿¡ & 質åã§çµäº)âââââââââ¶ awaiting_input
running ââ(result åä¿¡ & æ£åžžçµäº & ãµããšãŒãžã§ã³ãæªçšŒå)âââ¶ completed
running ââ(result åä¿¡ & ãµããšãŒãžã§ã³ã皌åäž)âââ¶ running # çµæã deferredResult ã«ä¿çã running ç¶ç¶
running ââ(æåŸã® task 決çã§å
šã¿ã¹ã¯å®äº & ä¿ççµæãã)âââ¶ completed # task_notification / çµç«¯ã® task_updated
awaiting_* ââ(è£ã§ã²ãŒãã空ã«ãªã£ãŠããç¶æ
ã§ãŠãŒã¶ãŒå¿ç)âââ¶ completed # ä¿çããŠããçµæã permission_resolved ã確å®
running ââ(result subtype ããšã©ãŒç³»)ââââââââ¶ failed
running ââ(ã¬ãŒãå¶éã«å°é)ââââââââââââââââââ¶ rate_limited # rate_limit_event(rejected) / error='rate_limit' / usage-limit resultã»throw
running ââ(èªèšŒåã)ââââââââââââââââââââââââ¶ needs_login # assistant error='authentication_failed' / is_error ä»ã result / auth æèšã® errors[]ã»throw
awaiting_input ââ(è¿œå æç€ºéä¿¡)ââââââââââââââ¶ running
completed ââ(è¿œå æç€ºéä¿¡)ââââââââââââââââââ¶ running # å®äºåŸã®è¿œå äœæ¥ãèš±ã
running ââ(éä¿¡æã§ query ã throw / ãšã©ãŒ result & sdkSessionId ãã)âââ¶ interrupted # æ¥ç¶äžæãresumable
running ââ(å¿çéäžã§ API ãšã©ãŒ)ââââââââââââ¶ interrupted # assistant error='server_error'/'overloaded' / terminal_reason='api_error' & äžæç㪠status
* ââ(query ã® throw / abort)âââââââââââââââ¶ failed # éä¿¡æä»¥å€ïŒor sdkSessionId ç¡ãïŒ
completed ââ(ããŒãžã§ç«¶åæ€ç¥ â merge --abort)âââ¶ conflict # èªåè§£æ¶ããªããè§£æ¶ã¯äººæïŒçµç«¯æ±ãïŒ
conflict ââ(æåè§£æ¶åŸã®åããŒãž or ç Žæ£)âââââ¶ archived
completed ââ(ããŒãž or ç Žæ£)âââââââââââââââââ¶ archived
running/awaiting_* ââ(ã¢ããªçµäº â ä¿å)âââââ¶ interrupted # ã¡ã¢ãªäžã¯ç¶æ
äžå€ãä¿åæã«äžžããïŒrestorableStatusïŒ
rate_limited ââ(ã¢ããªçµäº â ä¿å)âââââââââââ¶ interrupted # å¶éã¯äžæçã埩å
æã¯ resumable 㪠interrupted ã«äžžãã
needs_login ââ(åãã°ã€ã³åŸ è¿œå æç€º / åéã¢ã¯ã·ã§ã³)âââ¶ running # èªèšŒãæ»ãã°åã SDK äŒè©±ã resume
needs_login ââ(ã¢ããªçµäº â ä¿å)ââââââââââââ¶ interrupted # 次åèµ·åæã«ã¯åãã°ã€ã³æžã¿ãããããªã
interrupted ââ(è¿œå æç€ºéä¿¡ / åéã¢ã¯ã·ã§ã³ã§ resume)ââââââââ¶ running # çåäžã»ãã·ã§ã³ããã®å Žã§åéïŒconsume ã«ãŒãåèµ·åïŒ
running/awaiting_* ââ(ãŠãŒã¶ãŒã Ctrl+C)ââââââ¶ interrupted # 詳现ãã¥ãŒã®äžæãresumableïŒåŸè¿°ïŒ
running/awaiting_* ââ(ã¹ããªãŒã ãçµç«¯ã€ãã³ãç¡ãã§çµãã£ã)âââ¶ interrupted # æåŸã®ç ŠïŒåŸè¿°ïŒ
running/awaiting_* ââ(ãšãŒãžã§ã³ãåæ¿ã§ã¿ãŒã³ãç³ãã )âââ¶ interrupted # ç©ã¿æ®ããããã°çŽåŸã« running ãžæ»ã
interrupted ã¯ãã¯ãªãŒã³ã«å®äºããŠããªãã resume ã§ç¶è¡ã§ãããã»ãã·ã§ã³ã衚ããçºçå
ã¯6ã€:
(1) éä¿¡æïŒSession.consume ã® for-await ã throwããŸãã¯æ¥ç¶æã瀺ããšã©ãŒ resultãå€å®ã¯
ã¢ããã¿ã® classifyErrorïŒClaude 㯠core/claude-errors.ts ã® isConnectionErrorïŒã§ãresume å
ãšãªã
sdkSessionId ãããå Žåã®ã¿ãç¡ãïŒinit åã®æ©æå€±æã¯ failedïŒã(2) å¿çéäžã® API ãšã©ãŒïŒåŸè¿°ïŒã(3) ã¢ããªçµäºæã®äžžãïŒrestorableStatus ãå®è¡äž/
å
¥ååŸ
ã¡ãä¿åæã« interrupted ã«ãããstop() ã¯ã¡ã¢ãªäžã®ç¶æ
ãå€ããªãïŒã(4) ãŠãŒã¶ãŒã«ããäžæ
ïŒè©³çްãã¥ãŒã® Ctrl+CãåŸè¿°ïŒã(5) ã¹ããªãŒã ã®æ³å®å€çµäºïŒåŸè¿°ã®ãæåŸã®ç ŠãïŒã
(6) ãšãŒãžã§ã³ãåæ¿ïŒsetAgent() ãé²è¡äžã®ã¿ãŒã³ãç³ãã ãšããagent_switched èªäœã¯ status ã
åãããªãã®ã§ãããã§æ¢ããªããšç©ã¿æ®ããç¡ãåæ¿ã running ã®ãŸãŸåŒµãä»ãïŒã
ãããã completed ãšåãã idle ã§ resumableãè¿œå æç€ºãŸãã¯
åéã¢ã¯ã·ã§ã³ïŒäžèЧ/詳现㮠rïŒ ã§ resume ã§ãã â éä¿¡ãããš SessionManager.send â Session.send
ãïŒéä¿¡æã§çµäºããïŒconsume ã«ãŒãã resume: sdkSessionId ä»ãã§åèµ·åããåã SDK äŒè©±ãç¶è¡ãã
ïŒçåäžã»ãã·ã§ã³ã§ããã®å Žã§åéã§ããã¢ããªåèµ·åãåŸ
ããªããŠããïŒãéä¿¡æé·ç§»æã¯ãã¹ã¯ãããéç¥
ïŒnotify.interruptedïŒã§äžæããŠãŒã¶ãŒã«ç¥ããããå€å®ãã«ã㯠core/status-meta.ts ã® isResumable
ïŒSTATUS_META[status].resumable = interrupted / rate_limited / needs_loginïŒãåéæã«éãæç€ºæã¯
core/resume.ts ã® resumeInstruction(status, m)ïŒæ¢å®ã¯ resume.instructionãèªèšŒåãã¯
resume.authInstructionïŒã
埩垰ã¯ã¯ã³ããã·ã¥ïŒCtrl+RïŒãäžæã®åå ïŒéä¿¡æã»ã¬ãŒãå¶éã»èªèšŒåãïŒã«é¢ããããäžèЧã§ã詳现ã§ã
ãã©ãŒã«ã¹ïŒæäœããã«ã®ç¶æ
ã«é¢ä¿ãªãå¹ã chord ã«ããŠããããã©ãŒã«ã¹äŸåã®ããŒïŒäžèЧãªã¹ãã® rã
è©³çŽ°ã®æäœããã«ã® rïŒã¯ãTab ã§ç§»å â rãã®2æãå¿
èŠã§ãæ¢å®ãã©ãŒã«ã¹ãå
¥åæ¬ã§ãã以äžããã¯
ãæ¥œãªãªã«ããªãã«ãªããªããå°åããŒã朰ããªã chord ãªã®ã§ãå
¥åäžã«æã£ãŠãæåãåããªãã
æ¡å
ïŒresume.oneKeyHint / èªèšŒåã㯠auth.hintïŒã¯ããã¿ã§ã¯ãªãç¬ç«ããè¡ãšããŠåºã â
ããã¿ãã³ãã¯ãã©ãŒã«ã¹ã§åãæ¿ããã®ã§ãå
¥åæ¬ã«ããéã ãåŸ©åž°æ¹æ³ãæ¶ããŠããŸãã
äžæ¬åé㯠Ctrl+AïŒäžèЧã®ã¿ã2件以äžã®ãšãã ããy/n 確èªããïŒãåç·ãèœã¡ãã»èãéãããšèµ°ã£ãŠ
ããã»ãã·ã§ã³ãæã£ãŠäžæãããããã1ä»¶ãã€éžã³çŽãããªãã察象㯠core/resume.ts ã®
resumableSessions(sessions)ïŒçŽé¢æ°ïŒã§ãä»¶æ°ã resume.allHint(n) / action.resumeAllPrompt(n, auth)
ã«åºããåäœã® Ctrl+R ã確èªãªãã§å³éãã®ã«å¯Ÿãäžæ¬ã¯ç¢ºèªãæãïŒå
šäžæã»ãã·ã§ã³ãžåæã«æç€º =
誀çã課éã«çŽçµããããïŒãç¢ºèªæã«ã¯èªèšŒåãã®ä»¶æ°ãåºã â needs_login ã«ã¯ããã°ã€ã³ãçŽããã
ãšããæç€ºæãéãã®ã§ããŸã ãã°ã¢ãŠãã®ãŸãŸã ãš transcript ã«åãæ®ãã
èªåãªãã©ã€ã¯ããªãïŒåæã«èµ°ãåºããªãã»æå³ãã課éãé²ãŸãªãããšãåªå
ïŒã
å€ééä¿¡ã®é²æ¢ã¯ SessionManager.resume(id, instruction) ã«çœ®ãïŒView ã§ã¯ãªã core åŽïŒãUI ã®
ã¹ãã¢è³Œèªã¯ ~100ms ã¹ãããã«ãªã®ã§ãéä¿¡çŽåŸããã¥ãŒåŽã® status 㯠interrupted ã®ãŸãŸèŠãã â
ããŒã®é£æã»ãªãŒããªããŒãã§åãæç€ºã2åç©ãŸãããšäºé課éïŒãã°äºéåã«ãªããresume() ã¯
ã¹ãã¢ã®çŸåšå€ïŒsend ãåæçã« running ãžé²ããïŒã§ isResumable ã確ãããŠããéããéã£ããã
è¿ããViewïŒCtrl+R / äžèŠ§ã® r / äžæ¬ïŒã¯ãã¹ãŠãããçµç±ããã
ãŠãŒã¶ãŒã«ããäžæïŒè©³çްãã¥ãŒã® Ctrl+CïŒ: èµ°ã£ãŠããã¿ãŒã³ãæ¢ãããã ãã§ãã»ãã·ã§ã³ãæšãŠãã
ããã§ã¯ãªãïŒClaude Code ã® Ctrl+C ãšåãæäœïŒãSessionDetail â SessionManager.interrupt(id) â
Session.interrupt() â SDK ã® Query.interrupt() ã§ãç¶æ
㯠interruptedïŒidle & resumableïŒ ã«èœã¡ãã
stop()ïŒç¶æ
ãå€ããããã»ã¹ã ãèœãšãïŒ/ abort()ïŒfailed ã«ããïŒãšã¯å¥ç©ã
- ç¶æ
㯠SDK ã®å¿çãåŸ
ããã«å
ã«ç¢ºå®ããããçç±ã¯2ã€ã(a) äœæ: interrupt 㯠control request ãªã®ã§
CLI ã®å¿çãŸã§åŸ
ã€ãšæŒããŠãæ°çŸ ms åå¿ããªãã(b) åé¡: CLI ã¯äžæãããã¿ãŒã³ã
subtype: 'error_during_execution'+is_error: true+terminal_reason: 'aborted_streaming'ã® result ã§éããïŒå®æž¬:__fixtures__/session-interrupt.jsonlïŒããã蚺æãç¡ããšfailedã«èœã¡ãã å ã«interruptedãç«ãŠãŠããã°ãresult åŽã¯ãã§ã« resumable ãªã蚺æãç¶æããããŒã«ã¢ããã¬ãŒã ïŒisResumableïŒã§ã³ã¹ãã ããæŸãã claude-parseåŽãaborted_streamingãinterruptedã«åé¡ããïŒä¿éºïŒãäžæã®ããšã« assistant ã¡ãã»ãŒãžã 1 éæãŸã£ãŠ status ãrunningãžæ»ã£ãŠããã¿ãŒã³ã®çµããã¯failedã«ãªããªãããã°ã« æžãã®ã¯USER_INTERRUPT_DETAILïŒ='interrupted by user'ïŒã§ãCLI ã®å éšèšºæ ïŒerrors: ['[ede_diagnostic] âŠ']ïŒã¯åºããªãã2 çµè·¯ã§åãæèšã䜿ãã®ã§toInterruptedã® éè€ç³ã¿èŸŒã¿ãå¹ãããã°ã¯ 1 è¡ã ãã«ãªãã- èš±å¯/質ååŸ
ã¡ã§ãäžæã§ããïŒ
isInterruptible=running/awaiting_permission/awaiting_inputïŒã ãã€ã¢ãã°ã®nïŒdenyïŒã¯ããã® 1 ããŒã«ãæããã ãã§ã¿ãŒã³ã¯ç¶ãã®ã§ãããã®äœæ¥èªäœãããããåºå£ã¯ ãããããªããCtrl+Cã¯è©³çްãã¥ãŒã®useInputã§**pendingã¬ãŒãããå**ã«åŠçããtoInterruptedãpendingPermissionãèœãšãããšã§commit()ã®æ¢åçµè·¯ã canUseTool ã® promise ã deny ã§éãã ïŒæªå¿çã®tool_useã§çµãã transcript ã¯åŸã® resume ãå£ã âstop()ãšåãçç±ïŒã - 飿ã®åžåã¯
SessionManager.interrupt(id)ïŒresume()ãšåãçç±ã§ core åŽãUI ã®è³Œèªã¯ ~100ms ã¹ãããã«ãããŠããŠãããäžææžã¿ããåæçã«ç¥ããªãïŒãã¹ãã¢ã®çŸåšå€ã§isInterruptibleã 確ãããäžæã詊ã¿ãããè¿ãã - äžæåŸã¯
interruptedãªã®ã§ãã®ãŸãŸCtrl+R/ è¿œå æç€ºã§ç¶ãããããæ¡å ãdetail.cancelHintïŒå®è¡äžïŒâresume.oneKeyHintïŒäžæåŸïŒãšåã 1 è¡ãç¶æ ã§å ¥ãæ¿ããã
å¿çéäžã® API ãšã©ãŒïŒAPI Error: Connection closed mid-response.ïŒ: ã¹ããªãŒãã³ã°äžã«æ¥ç¶ãåãããš
CLI ã¯ããããŸã§ã®éšåå¿çã確å®ãããŠãã¿ãŒã³ãçµãããã¯ã€ã€äžã¯ error: 'server_error' ãç«ãŠã
assistant ã¡ãã»ãŒãžïŒæ¬æã API Error: Connection closed mid-response. The response above may be incomplete.ïŒâ ãããéçŽãã resultïŒsubtype: 'success' + is_error: true +
terminal_reason: 'api_error' + api_error_status: nullïŒã®2é£ã§å±ããå¿çã¯éäžã§åããŠããã®ã«
subtype ã ãèŠããšæåãªã®ã§ãçŽ çŽã«æ±ããšå°»åãã®åçãç·ã®ãCompletedãã«ãªããå€å®ã¯2段æ§ã:
- assistant ã¡ãã»ãŒãžã®åä»ã
errorçš®å¥ïŒisTransientApiErrorKind=server_error/overloadedïŒã æèšã»ãã±ãŒã«ã«äŸåããªãã®ã§ãããäž»ã·ã°ãã«ãmax_output_tokens㯠CLI ãã¿ãŒã³ãç¶ç¶ããŠå埩ãã ãã察象å€ãinvalid_request/billing_errorã¯å詊è¡ã§çŽããªãã®ã§failedã®ãŸãŸã察象㯠ãããã¬ãã«ã¿ãŒã³ã®ã¿ïŒparent_tool_use_idã nullïŒâ ãµããšãŒãžã§ã³ãå ã®åçš®ãšã©ãŒã¯å€±æãã tool_result ãšããŠæ¬äœã¿ãŒã³ãžè¿ã Claude ãåé¿ã§ããã®ã§ãã»ãã·ã§ã³ã¯æ¢ããªãã - result ã®
terminal_reason: 'api_error'+api_error_statusïŒisTransientApiStatusãæç€ºçãªnullïŒHTTP å¿çããç¡ãæ¥ç¶æã5xx/408/429 ãäžæçïŒãCLI ã®æèšã¯å€æ°ïŒServer error mid-response/Response stalled mid-stream/Please wait a moment and try againâŠïŒã§å€ãããã ãããisConnectionErrorã®æååäžèŽã¯æåŸã®ä¿éºãšããŠæ®ãããã£ãŒã«ããç¡ãïŒundefinedïŒå Žåã¯ äžæçæ±ãã«ããªã âapi_error_status㯠success ããªã¢ã³ãã«ããååšãããerror_during_executionã® result ã§ã¯æ¬ èœãäœãæå³ããªãã®ã§ãæ¬ èœããHTTP å¿çç¡ãããšèªããš 400 ãŸã§ resumable ã«ãªãã
ã©ã¡ãã toInterrupted ã«èœã¡ããåã倱æã assistant â result ã®2åå±ããã:
toInterrupted㯠æåŸã®systemãã°ãåæãªã no-opïŒstatus === 'interrupted'ã®éã ãïŒã éã«å¥ã®ãã°ïŒå®ã¶ãããã® tool_use ã«å¯Ÿãã tool_result çïŒãæãŸã£ãŠãéè€ããªãã- result åŽã¯ ãã§ã« resumable ãªç¶æ
ïŒ
isResumable= interrupted / rate_limited / needs_loginïŒãªã ã³ã¹ãã ãæŸã£ãŠååé¡ããªããåä»ãã·ã°ãã«ã®æ¹ãæèšå€å®ããæ£ç¢ºãªã®ã§ãCLI ã®èšãåããæªç¥ãª ãšãã«ããã°ã€ã³ãçŽãããfailedã®è¢å°è·¯ãžèœãšããªãã
å ã㊠system/api_retryïŒCLI ãå詊è¡ããæã«æµããïŒã system ãã°ãž1è¡æ®ã â åºããªããšäžå®å®ãªåç·ã
ããã æ¢ãŸã£ãŠãããããã«ããèŠãããå詊è¡ãå°œããæã®äžæéç¥ã«ååŸã®æèãæ®ããªããé£ç¶ããå詊è¡ã¯
åãè¡ãæžãæããïŒ1ãªã¯ãšã¹ãã§æå€§ max_retries ä»¶æ¥ãã®ã§ã远èšãããšäŒè©±ããã¥ãŒããŒããã
æŒãåºãããïŒããã€ã¢ãã°ä¿çäžã«äžæããå Žå㯠Session.commit ã canUseTool ã® Promise ã deny ããŠ
解決ããïŒæªå¿çã® tool_use ã§ transcript ãçµãããšåŸã® resume ã倱æãããïŒã
ãµããšãŒãžã§ã³ãïŒTask ããŒã«ïŒã®å®äºã²ãŒã: ãµããšãŒãžã§ã³ãã ããã¯ã°ã©ãŠã³ãå®è¡ããããšã
ãã® tool_result ã¯å³åº§ã«è¿ãæ¬äœã¿ãŒã³ã¯ç¶è¡ããããããµããšãŒãžã§ã³ãããŸã 皌åäžã§ããããã¬ãã«ã®
result/success ãå
ã«å±ãããã® result ããã®ãŸãŸ completed ã«ãããšãå®éã«ã¯äœæ¥ç¶ç¶äžãªã®ã«
ãããžããCompletedããžåããŠããŸãïŒæ¬ issue ã®äžå
·åïŒã察çãšã㊠system/task_started /
system/task_notification ã§çšŒåäžã¿ã¹ã¯éåïŒactiveTaskIdsïŒã远跡ããresult åä¿¡æã«ã¿ã¹ã¯ãæ®ã£ãŠ
ããã° completed ã«ããçµæã deferredResult ã«ä¿çã㊠running ãç¶æãããæåŸã®ã¿ã¹ã¯ã
task_notification ã§ settle ãéåã空ã«ãªã£ãæç¹ã§ä¿ççµæã䜿ã£ãŠ completed ã確å®ããã
圢ã®è§£éïŒsystem/task_started â task_started ã€ãã³ãïŒã¯ claude-parse.tsãã²ãŒããã®ãã®ã¯
agent-events.ts ã® applyAgentEventïŒtask_started / task_settled / completeTurnïŒã«ãã
å
š provider å
±éãªã®ã§ãä»ã®ãšãŒãžã§ã³ãã¯ãã¿ã¹ã¯ãå§ãŸã£ã/çä»ããããå ±åããã ãã§ããã
skip_transcript ã®éåã¿ã¹ã¯ã¯
ã²ãŒã察象å€ãactiveTaskIds / deferredResult 㯠transient ã§æ°žç¶ããªããå®ããŒã¿ã¯
__fixtures__/session-subagent.jsonlïŒã¹ãã€ã¯ã® subagent ã·ããªãªã§æ¡åïŒã
ã²ãŒãã¯ãè§£ããªããªããæ¹ããæ©ãããå®äºãããå±éºãã²ãŒããåãŸã£ããŸãŸã ãšã»ãã·ã§ã³ã¯
running ããæ°žä¹
ã«åºãããïŒçä»ããã¿ã¹ã¯ãžã®æ±ºçéç¥ã¯ããæ¥ãªãïŒããããžãåäœæéãåã«ãªãã
ãã®ããæ¬¡ã® 6 ç¹ã§å¿
ãè§£ããããã«ããŠããïŒã©ããããã£ãš Runningãã®å®ãã°ïŒ:
- ã¬ãã«ä¿¡å·ã§èªå·±ä¿®åŸ©ããïŒãã¡ã°ã匷ãæ
ä¿ïŒã
system/background_tasks_changed㯠ãããŸçããŠããããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã®å šéåããéã³ãREPLACE ã»ãã³ãã£ã¯ã¹ãæã€ã SDK èªèº«ãããšããžïŒtask_started/task_notificationïŒã®åãããŒãã§ running 衚瀺ã wedge ããªããããéåããšå·®ãæ¿ããããšæç€ºããŠããã®ã§ããšããžïŒå€ã CLI ã§ãåã primaryïŒãš 䜵çšããŠéåãå¿ ãæ£ãïŒtasks_changedã€ãã³ãïŒã - CLI ããã»ã¹ãèµ·ãçŽã£ããã²ãŒããç©ºã«æ»ãïŒ
session_startedïŒãã¬ãã«ä¿¡å·ã¯èµ·åæã« äœãåºããªãïŒmembership ãå€ãã£ããšãã ãïŒã®ã§ãåã®ããã»ã¹ã® id ãæ®ããšèª°ãçä»ããããªãã - 決çã®ä¿¡å·ã¯ 2 系統èŠã â
system/task_notificationã«å ããŠãçµç«¯ç¶æ ã®system/task_updatedïŒpatch.statusãpending/running/pausedã®ãããã§ããªãïŒãtask_settledã«åããéç¥ãæ¥ãªããŸãŸçµããã¿ã¹ã¯ïŒæ¢ããããã»èœã¡ãïŒãåãããŒããªãããã å€å®ã¯ããŸã èµ°ã£ãŠããç¶æ ã®åŠå®ãã§æžãïŒå°æ¥å€ãå¢ããŠã決çåŽã«åããïŒãpausedãæ±ºçæ±ãã«ããªã â äžæåæ¢ã¯ãçµãã£ããã§ã¯ãªãã®ã§ã決çã«ãããšåéãã ã¿ã¹ã¯ã誰ã远跡ããŠããªãç¶æ ã§ completed ã«ãªãããã®åŸã®ã¡ãã»ãŒãžã§runningãžæ»ã£ãŠ äºåºŠãšçµãããªããªãïŒãã®äžå ·åãå¥ã®æããåå°å ¥ããããšã«ãªãïŒã - åž°å±ã§ããªã決çéç¥ã¯ã²ãŒãã空ã«ããïŒ
task_settledã®taskIdãç¡ãå ŽåïŒããã©ãã åãããªãã®ã§äœãããªãã㯠1 éã§æ°žä¹ ã«åŒµãä»ãïŒClaude ã®task_idã¯å¿ é ãªã®ã§å®è³ªã¯ ä» provider åãã®é²åŸ¡ïŒã - ä¿çããå®äºã¯èš±å¯/質ååŸ
ã¡ã®çªãè¶ããŠçãæ®ããã²ãŒãã空ã«ãªã£ãç¬éã
awaiting_*ïŒããã¯ã°ã©ãŠã³ãã® Task ã質åãäžããŠããçïŒã ãšããã®å Žã§ã¯å®äºã§ãããã²ãŒãã¯ç©ºãªã®ã§task_settledãäºåºŠãšæ¥ãªããåçããŠrunningã«æ»ãpermission_resolvedãsettleDeferredã§æŸã£ãŠç¢ºå®ããã - ã¿ãŒã³ã®å¢çã§ã¿ãŒã³éãã®æ
å ±ãæšãŠããçµããåŽã¯
clearTurnStateïŒinterrupted/needs_login/rate_limited/failed/completedãããã³agent_switchedïŒãå§ãŸãåŽã¯user_inputãdeferredResultãèœãšãïŒåã®ã¿ãŒã³ã®å®äºã次ã®ã¿ãŒã³ã®éäžã§ç¢ºå®ã㊠ããŸããããã²ãŒãèªäœã¯ãŸã çããŠããå¯èœæ§ãããã®ã§æ®ãïŒã
èš±å¯èŠæ±ã¯åŸ
ã¡è¡åïŒSession.pendingQueueïŒããšãŒãžã§ã³ã㯠1 éã®ã¡ãã»ãŒãžã§è€æ°ã®
tool_use ã䞊è¡ã«æãããããconfirm ã¢ãŒãã§ã¯ãã®æ°ã ã canUseTool ãåæã«èµ°ãã
åäžã¹ãããã«äžæžããããšå
ã® promise ãæ°žä¹
ã«è§£æ±ºããããprovider ã¯ãã® 1 æ¬ãåŸ
ã¡ç¶ãã
ã¿ãŒã³çµäºã€ãã³ããåºããªã â ã¹ããªãŒã ã¯çãããŸãŸãªã®ã§äžã®ãæåŸã®ç Šãã§ãæããã
ã»ãã·ã§ã³ãæ°žä¹
ã«èš±å¯åŸ
ã¡ïŒrunning ã§åŒµãä»ããUI ã«åºãã®ã¯å
é ã ãã§ãåçãããã³ã«
次ãäžããïŒpermission_resolved ã§äžæŠ running ã«æ»ããªãïŒãã¿ãŒã³ãæ»ã¬ãšãã¯
åŸ
ã¡è¡åããã¶ã deny ããïŒæªå¿çã® tool_use ã 1 ã€ã§ãæ®ããšåŸã® resume ãå£ããïŒã
æåŸã®ç ŠïŒSession.consume ã® finallyïŒ: ãšãŒãžã§ã³ãã®ã¹ããªãŒã ãçµç«¯ã€ãã³ã
ïŒturn_completed / turn_stoppedïŒãåºããã«çµãã£ãããinterrupted ã«èœãšããstreaming input mode
ã§ã¯ããã³ããæºãéãããŸã§ã¹ããªãŒã ã¯çµãããªãã®ãæ£åžžãªã®ã§ãããã«æ¥ãã®ã¯æ³å®å€ã®çµäº
ïŒCLI ãµãããã»ã¹ãé»ã£ãŠèœã¡ãã»transport ã EOF ã«ãªã£ãçïŒãç¶æ
æ©æ¢°ã«ã¯äœãå±ããªãããã
æŸçœ®ãããšã»ãã·ã§ã³ãæ°žä¹
ã« runningïŒãŸãã¯å¿çäžèœãªèš±å¯åŸ
ã¡ïŒã®ãŸãŸåŒµãä»ããåäœæéã ãã
å¢ãç¶ãããstop() / abort() 㯠abortController ã abort ããã®ã§ããã«ã¯æ¥ãªãïŒquiet 忢ã®
æå³ã¯ä¿ãããïŒã
rate_limited ã¯ã䜿çšéïŒã¬ãŒãå¶éã«éããŠæ¢ãŸã£ããã»ãã·ã§ã³ã衚ããcompleted/failed ãšåãã
idle ã ãããšã©ãŒæ±ãïŒfailedïŒã«ã¯ãããå¶éãè§£ããã®ãåŸ
ã£ãŠåéã§ãããç¶æ
ãšããŠåºå¥ããã
æ€ç¥å
㯠SDK ã® rate_limit_eventïŒrate_limit_info.status === 'rejected'ïŒãassistant ã¡ãã»ãŒãžã®
error === 'rate_limit'ãããã³ usage-limit ã瀺ã resultïŒthrow ããããšã©ãŒæèš
ïŒcore/claude-errors.ts ã® isRateLimitErrorãSDK ã® USAGE_LIMIT_ERROR_PREFIXES ã«è¿œåŸïŒã
å¶éã¯äžæçãªã®ã§ä¿åæã¯ interrupted ã«äžžããã
needs_login ã¯ããšãŒãžã§ã³ãã®èªèšŒãåããŠæ¢ãŸã£ããã»ãã·ã§ã³ã衚ããäœæ¥èªäœã®å€±æã§ã¯ãªãããŠãŒã¶ãŒã
å¥ã¿ãŒããã«ã§ claude ã« /login ãçŽãã° resume ã§ããã®ã§ãfailed ãšã¯åºå¥ããã
ãšãã« completed ã«ããŠã¯ãããªããCLI ã¯èªèšŒãšã©ãŒã次ã®2ã¡ãã»ãŒãžã§å ±åããïŒå®ãã€ããªã§ç¢ºèªïŒ:
subtype === 'success' ã ããèŠãŠå®äºæ±ãã«ãããšãäœãäœæ¥ããŠããªãã®ã«ç·ã® Completedãã«ãªãã
auto-PR ãŸã§èµ°ã£ãŠããŸãïŒæ¬ issue ã®äžå
·åïŒããã®ãã result åŠç㯠subtype === 'success' && !is_error
ã®ã¿ãå®äºãšãããã以å€ã¯æèšåé¡ïŒèªèšŒ â ã¬ãŒãå¶é â éä¿¡æ â failedïŒãžæµãããšã©ãŒç³» subtype ã¯
result ãæãã errors: string[] ã§çç±ãéã¶ïŒSDKResultSuccess / SDKResultErrorïŒã®ã§äž¡æ¹ãèªãã
æ€ç¥ã®åªå é ã¯æ¬¡ã®éã:
- assistant ã¡ãã»ãŒãžã®åä»ã
errorïŒcore/claude-errors.tsã®isAuthErrorKind=authentication_failed/oauth_org_not_allowedïŒãSDKAssistantMessageErrorãšããŠåå®çŸ©ãããŠããæèšã»ãã±ãŒã«ã«äŸåããªã ããããããäžæ¬¡ã·ã°ãã«ã«ããïŒæ¢åã®error === 'rate_limit'ããã¯ãšåãäœçœ®ïŒãbilling_errorïŒæ®é«äžè¶³ïŒã¯åãã°ã€ã³ã§çŽããªãã®ã§å¯Ÿè±¡å€ïŒfailedã®ãŸãŸã is_errorä»ã resultãããã³èªèšŒæèšãå«ãresult/errors[]/ throw ãããäŸå€ ïŒisAuthErrorãCLI ã®å®æèš = OAuth 倱å¹ã»ããŒã¯ã³å€±å¹ã»APIããŒäžæ£ã»ã¯ã©ãŠãè³æ Œæ å ±å€±å¹ã»/loginæç€ºã»re-authenticate ãç¶²çŸ ããäºæ¬¡ã·ã°ãã«ïŒã
èªèšŒåãã¯åŸ
ã£ãŠãçŽããªãã®ã§ãã¬ãŒãå¶éã»éä¿¡æããå
ã«å€å®ããïŒSession.consume ã® throw çµè·¯ã
åæ§ãFailed to authenticate through the broker: request timed out ã®ãããªæèšãéä¿¡æãšèª€åé¡ããªãïŒã
åéå¯èœãªç¶æ
ãžèœã¡ããšãã¯ä¿çäžã®èš±å¯ã deny ããŠè§£æ±ºããŠããïŒå®ã¶ãããã® tool_use ã¯åŸã® resume ã
倱æããåŸããstop() ãšåãçç±ïŒãåã倱æã assistant ãš result ã®2åå±ããã toNeedsLogin ã¯
åªçïŒåäž detail ãªãåäžåç
§ãè¿ãïŒã
attention: trueïŒäžèŠ§ã« â ãåºãïŒãªã®ã¯ãrate_limited ãšéãæŸçœ®ããŠã解決ãããŠãŒã¶ãŒã®æäœã
å¿
é ã ãããUI ã¯ãå¥ã¿ãŒããã«ã§ claude ã«ãã°ã€ã³ããŠåéããšããæé ãã®ãã®ãåºã
ïŒi18n auth.hint / auth.listHintãã©ã¡ãããšãŒãžã§ã³ãåãšãã°ã€ã³ã³ãã³ããå·®ã蟌ã
(agent: AgentLabel) => string ã§ãæ¢å®ã¯ DEFAULT_AGENT_LABEL = ClaudeïŒãä¿åæã¯ interrupted ã«äžžããïŒæ¬¡åèµ·åæã«ã¯åãã°ã€ã³æžã¿ãã
ãããªãïŒããªã auth_status ã¡ãã»ãŒãžã¯ CLI ã®å¯Ÿè©±ç /login UI çšã§ã--enable-auth-status
ãªããã€ã³æã®ã¿æµããïŒãã® SDK çã®åã«ãç¡ãïŒãã API èªèšŒãšã©ãŒã®æ€ç¥ã«ã¯äœ¿ããªãã
rate_limit_event 㯠rejected ã§ã»ãã·ã§ã³ã rate_limited ã«ããäžæ¹ãallowed / allowed_warning
ãå«ã㊠ã¢ã«ãŠã³ãå
šäœã® claude.ai ãµãã¹ã¯ãªãã·ã§ã³äœ¿çšç¶æ³ïŒ5æéæ ã»é±æ¬¡æ ãªã©ïŒãéãã§ããã
ããã¯ã»ãã·ã§ã³ç¶æ
ã§ã¯ãªãã¢ã«ãŠã³ã暪æã®æ
å ±ãªã®ã§ãSession 㯠onRateLimitïŒDIïŒã§çã®
rate_limit_info ã SessionManager ãžæž¡ããmanager ã ãŠã£ã³ããŠçš®å¥ããšã«ææ°å€ãä¿æãã
ïŒcore/rate-limit.ts ã® toRateLimitWindow ã§æ£èŠå = resetsAt ã¯ç§âmsãutilization 㯠0-100%ïŒã
getRateLimits() ã¯è¡šç€ºé ã«ãœãŒãããå®å®åç
§ãè¿ããBanner ã useRateLimit ã§è³ŒèªããŠ
ãçŸåšã®ã»ãã·ã§ã³ ââââââââ 42% 2æé45ååŸã«ãªã»ãããã®ããã«æç»ããïŒæ ãç¡ãïŒAPI ããŒå©çšæã¯é衚瀺ïŒã
rate_limit_event 㯠ã»ãã·ã§ã³ãã¿ãŒã³ãåããŠããéããå±ããªãã®ã§ãèµ·åçŽåŸãå
šã»ãã·ã§ã³ã
åŸ
æ©äžã®ãšãã¯äœãåºããªããããã§ Claude Code ã®ã¹ããŒã¿ã¹ã©ã€ã³çžåœã®è¡šç€ºãäœããããSDK ã®
control channel ãå©ã probe ã第2ã®æ
å ±æºãšããŠè¶³ããŠããã
ââ Session.onRateLimit âââ¶ rate_limit_eventïŒã¿ãŒã³éå§ããšã»status ãæã€ïŒââ
ã¢ã«ãŠã³ã暪æã®æ
å ± â†âââ¶ SessionManager
ââ bootstrap/usage-poller ââ¶ utils/usage-probeïŒ5åããšã»plan ãš utilizationïŒâ
- probe ã®äœãïŒ
utils/sdk-probe.tsïŒ:query()ã streaming-input ã§éããäœãéããªããŸãŸ control channel ã®å¿çïŒsupportedModels()/accountInfo()/usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET()ïŒã ããèªãã§å³ abort ããã æšè«ã¯èµ°ããªãã®ã§ããŒã¯ã³æ¶è²»ã¯ãŒããfetchModelCatalogããã®å ±éåºç€ã«èŒãæ¿ããã - ãã©ã³åã®åºæã¯
accountInfo()ã ãïŒcore/account.tsã®toAccountSummaryïŒãsubscriptionTypeïŒäŸ'Claude Team'ïŒã¯ SDK ç±æ¥ã®è¡šç€ºæååãªã®ã§ãã®ãŸãŸåºã ïŒi18n ã®äŸå€ãã¢ãã«åãšåãæ±ãïŒãçµç¹å㯠Team / Enterprise ã®ãšãã ãä»ãã - usage å¿çã®è§£éã¯
core/usage.tsã ãïŒtoUsageSnapshotïŒã宿ž¬ïŒTECH_NOTES åç §ïŒã§rate_limits_available: trueã§ãrate_limits: nullãããåŸãããããavailableããæ ¹æ ã« æ ãæããªããæ ãç¡ããã°ã€ãã³ãåŽã®æ å ±ã ãã§è¡šç€ºããã - 2ã€ã®æ
å ±æºã®åæµã¯
mergeUsageWindowïŒçŽé¢æ°ïŒãusage å¿çã«ã¯statusãç¡ããå®éã®five_hourã€ãã³ãã«ã¯utilizationãç¡ãã®ã§ãã©ã¡ãã仿¹ã®äžäœéåã§ã¯ãªãããã£ãŒã«ãåäœã§ åæµããstatusã¯æåŸã«ã€ãã³ããèšã£ãå€ãåŒãç¶ãã衚瀺ã«åœ±é¿ãç¡ããã° åäžåç §ãè¿ã ïŒuseRateLimit/useAccountã®åæç»æå¶ãããã«äŸåïŒã - ããŒãªã³ã°éé㯠5 åïŒ
bootstrap/usage-poller.tsïŒãæ èªäœã 5æéïŒ7æ¥åäœã§ããªã»ãããŸã§ã® ã«ãŠã³ãããŠã³ã¯useClockãããŒã«ã«ã§æ¯ç§é²ãã皌åäžã»ãã·ã§ã³ã¯ã¿ãŒã³ããšã«ã€ãã³ããæŒããŠãã ââã®ã§ãããŒãªã³ã°ã¯ãåŸ æ©äžãåããã圹ã§ããã1åããšã«ãµãããã»ã¹ã1æ¬ç«ã€ããç§åäœã«ã¯ããªãã 2åé£ç¶ã§äœãåããªããã°åæ¢ããïŒAPI ã㌠/ Bedrock / Vertex ãã°ã€ã³ã§ã¯æ°žä¹ ã«åããªãããïŒã - 衚瀺å
ã¯ãããïŒ
BannerïŒã ãããã©ã³è¡ã¯bannerLines()ã䜿çšç¶æ³ã®è¡ïŒã²ãŒãž + 䜿çšç + æ®ãæéïŒã¯bannerUsageRows()+gaugeCells()ãçµãïŒèšå·ã¯theme.tsã詳现ã¯äžã®Bannerã®é ïŒãutilizationãç¡ãæ ã«ã²ãŒãžã¯æããªãïŒ0% ãšèªããŠããŸããããæ®ãæéã ãåºãïŒã StatusFooterã¯äœ¿çšç¶æ³ãæããªãã以åã¯ããã¿å³ç«¯ã«ããã©ã³å + äžäœ2æ ãåºããŠãããã 1è¡ã«åããããã®æ®µéççž®éïŒ2æ â 1æ â ã²ãŒãž â ãã©ã³åïŒãå¿ èŠã§ãã¢ãŒããšãã³ããšãã ããã¿æ¬æ¥ã®æ å ±ãèªã¿ã¥ãããªã£ãŠããããã©ã³ / 䜿çšç¶æ³ã¯ããããžéçŽããããã¿ã¯ ãã¢ãŒã衚瀺ïŒçž®ãŸãªãïŒ + ãã³ãïŒå¯äžçž®ãïŒãã®2èŠçŽ ã ãã«ããïŒã©ã®å¹ ã§ã1è¡ãä¿ã€ç¹ã¯äžå€ã§ãstatus-footer.spec.tsxãå®éã®æç»å¹ ã§æ€èšŒããŠããïŒãããããæããªã詳现ãã¥ãŒã§ã¯åºãªã ïŒèŠãããšã㯠Esc ã§äžèŠ§ãžæ»ãïŒã
SessionStateïŒUI ã賌èªããäžå€ã¹ãããã·ã§ããïŒ:
interface SessionState {
id: string;
title: string; // ã¿ã¹ã¯åãèµ·åçŽåŸã¯æç€ºæç±æ¥ã®æ«å®å€ãHaiku èŠçŽãè¿ãæ¬¡ç¬¬å·®ãæ¿ãïŒtitle ã€ãã³ãïŒ
status: SessionStatus;
prompt: string; // æåã®æç€ºæ
branch: string; // codiva/<slug>
worktreePath: string;
todos: TodoItem[]; // TaskCreate/TaskUpdateïŒ+ æ§ TodoWriteïŒããæ§ç¯ããææ°ã¹ãããã·ã§ãã
progress?: { done: number; total: number }; // todos ããå°åº
messages: LogEntry[]; // æŽåœ¢æžã¿ãã°ïŒ**äžéä»ã**: core/log-buffer.tsïŒãSessionDetail ã®ãã°ãã¥ãŒã§è¡šç€ºãã埩å
æã¯ SDK transcript ããåæ§ç¯
pendingPermission?: PermissionRequest; // awaiting_permission / awaiting_input æã®ã¿
sdkSessionId?: string; // system/init ããååŸãresume çšã«ä¿æ
model?: string; // ã»ãã·ã§ã³åå¥ã®ã¢ãã«äžæžãïŒ/modelïŒ
pr?: PrRef; // codiva ã远跡ãã PR ã®çªå·ã»URLïŒéåžžã¯ãã©ã³ãã® PRãç¡ããã°èªäœ PR ãææ Œã**æ°žç¶ãã**ïŒ
extraPrs?: readonly PrRef[];// ã»ãã·ã§ã³èªèº«ãå¥ãã©ã³ãã§äœã£ã PRïŒ`gh pr create` ã®çµæããæ€ç¥ã**æ°žç¶ãã**ïŒ
prCreateToolIds?: readonly string[]; // çµæåŸ
ã¡ã® `gh pr create` ã® tool_use idïŒå¯Ÿå¿ä»ãçšãtransientïŒ
prStatus?: PrStatus; // merge å¯åŠ / checks / draftïŒæºãããtransientã»æéä»ããã£ãã·ã¥ïŒ
prLookup?: PrLookupState; // 'loading'ïŒç¢ºèªäžïŒ/ 'error'ïŒgh ãçããããªãã£ãïŒãtransient
conflictFiles?: string[]; // conflict æã®ç«¶åãã¡ã€ã«ïŒèªåè§£æ¶ã¯ããªãïŒ
startedAt: number;
finishedAt?: number;
activeMs: number; // ãå®éã«åããæéãã®çޝç©ïŒactive ãªåºéã®ã¿ç©ç®ïŒ
activeSince?: number; // çŸçšŒåã»ã°ã¡ã³ãã®éå§æå»ïŒidle ãªãæªèšå®ïŒ
totalCostUsd?: number; // result ã® total_cost_usd 环èš
error?: string;
rateLimitResetsAt?: number; // rate_limited ã®ãšãã®è§£é€äºå®æå»
streamingText?: string; // stream_event ã® text_deltaïŒæžãããã®æ¬æãtransientã»æ°žç¶ããªãïŒ
activeTaskIds?: string[]; // 皌åäžã®ãµããšãŒãžã§ã³ãïŒå®äºã²ãŒãçšãtransientïŒ
deferredResult?: { at: number; totalCostUsd?: number; resultText: string }; // ä¿çãã resultïŒåäžïŒ
logSeq: number; // LogEntry ã®æ¡çªã«ãŠã³ã¿
}- Step n/m:
assistantã¡ãã»ãŒãžå ã® tool_use ãã TODO ã¹ãããã·ã§ãããæ§ç¯ãããTodoWriteïŒinput.todosé åã§å šçœ®æïŒãšTaskCreate/TaskUpdateïŒå¢åæŽæ°ïŒã®äž¡æ¹ã«å¯Ÿå¿ããïŒSDKã®äžä»£ã«ããæµããŠããããŒã«ãç°ãªããTECH_NOTES.md åç §ïŒãdone = status === 'completed' ã®æ°,total = å šæ°ã - 質åãã: Claude ããŠãŒã¶ãŒãžã®è³ªåã«äœ¿ã
AskUserQuestionããŒã«ã¯ãallow ã«ãŒã«ã«é¢ä¿ãªãå¿ ãcanUseToolã³ãŒã«ããã¯ã«å±ãïŒå ¬åŒä»æ§ïŒãtoolName === 'AskUserQuestion'ãæ€ç¥ãããawaiting_inputã«é·ç§»ãã質åãšéžæè¢ã UI ã«è¡šç€ºããŠãŒã¶ãŒã®åçãupdatedInputã«èŒã㊠allow ã§è¿ããè£å©ãšããŠãresultåä¿¡æã«çŽè¿ assistant ããã¹ããçåæã§çµããå Žåãawaiting_inputã«ããïŒããŒã«ã䜿ããå°ã®æã§è³ªåããã±ãŒã¹ïŒã - èš±å¯åŸ
ã¡:
canUseToolã³ãŒã«ããã¯ïŒAskUserQuestion以å€ïŒãåŒã°ãããPermissionRequestã state ã«ç©ã¿ãUI ã®å¿çã§ Promise ã resolve ãããã³ãŒã«ããã¯ã® Promise ã解決ããããŸã§ã»ãã·ã§ã³ã¯ãããã¯ãããïŒå ¬åŒä»æ§ãšããŠä¿èšŒïŒã
1ã»ãã·ã§ã³ã®ã©ã€ããµã€ã¯ã«ãä¿æããã
- ã³ã³ã¹ãã©ã¯ã¿ã§
agentïŒAgentAdapterïŒã DI ã§åãåãïŒçç¥æã¯queryFnãã Claude ã¢ããã¿ãçµã¿ç«ãŠãç瞮圢ïŒããã¹ãã§ã¯åæã€ãã³ãã¹ããªãŒã ãè¿ããã§ã€ã¯ã¢ããã¿ãæ³šå ¥ããã - å
¥å㯠provider éäŸåã®
AsyncIterable<string>: å éšãã¥ãŒïŒpush å¯èœãª async queueïŒãAgentRunRequest.promptãšããŠæž¡ããsend(text)ã§ãã€ã§ã远å ã§ãããSDKUserMessageãžã®å ã¿çŽãã¯ã¢ããã¿ã®ä»äºã - åä¿¡ã«ãŒã:
for await (const event of run)ã§åAgentEventãapplyAgentEvent()ïŒcore/agent-events.tsïŒã«ç³ã¿èŸŒããprovider ã®ã¡ãã»ãŒãžåœ¢ç¶ã®è§£éã¯ã¢ããã¿ïŒClaude ãªãcore/claude-parse.tsïŒã«éããçŽç² reducerïŒreduce(state, CodivaEvent)ïŒã¯ codiva èµ·ç¹ã®åä»ãã€ãã³ãã ããæ±ããUI ã¢ã¯ã·ã§ã³ïŒè¿œå æç€ºã»èš±å¯ã»ã¢ãã«åæ¿çïŒã¯reduceãž dispatchã倿Žã®ãã³ã«onChangeãçºç«ã getAgent()/setAgent(adapter): é§åãããšãŒãžã§ã³ãã®èªã¿åããšå·®ãæ¿ãïŒåŸè¿°ããšãŒãžã§ã³ãæœè±¡ãïŒãUI ã¯getAgent().capabilitiesãèŠãŠæããªãæ©èœãé ãã- äŸå€çµè·¯ã®åé¡ãã¢ããã¿ä»»ã:
catchããæååã¯adapter.classifyError?.(error) ?? 'failed'ã§AgentStopCauseã«ããŠããaborted/interruptedã dispatch ããã respondToPermission(result): ä¿çäžã® canUseTool Promise ã resolveãinterrupt()/abort(): SDK ã® interrupt / AbortControllerãinterrupt()ã¯ãèµ°ã£ãŠããã¿ãŒã³ã ããããããïŒè©³çްãã¥ãŒã®Ctrl+CïŒ: ãµãããã»ã¹ã¯çããããŸãŸinterruptedïŒidle & resumableïŒã«ããè¿œå æç€º /Ctrl+Rã§åã SDK äŒè©±ãç¶ããããç¶æ ã«ãããç¶æ 㯠SDK ã®å¿çãåŸ ããã«å ã«ç¢ºå®ãããïŒäœæ + åé¡ãäžèšããŠãŒã¶ãŒã«ããäžæããåç §ïŒãèš±å¯/質ååŸ ã¡ã§åŒã°ããå Žåã¯commit()ã®æ¢åçµè·¯ã canUseTool ã® promise ã deny ã§éããïŒæªå¿çã®tool_useã¯åŸã® resume ãå£ãïŒãisInterruptibleã§ãªãç¶æ ã§ã¯äœãããªããSessionOptionsïŒmodel/effort/permissionMode/maxBudgetUsd/appendSystemPrompt/ignoredFilesïŒã DI ã§åããprovider éäŸåã®AgentRunOptionsã«åããŠã¢ããã¿ãžæž¡ãïŒèšå®ãã¡ã€ã«ç±æ¥ïŒãSDK ã®OptionsïŒcanUseTool/settingSources/includePartialMessages/permissionModeæªæå®æã®acceptEditsïŒãçµã¿ç«ãŠãã®ã¯ã¢ããã¿åŽã- systemPrompt ã®çµã¿ç«ãŠã¯çŽé¢æ°
core/system-prompt.tsïŒcomposeSystemPromptïŒãèŠçŽ ã¯ãworktree ã®ç°å¢èª¬æãâããªããžããªè¿œå æç€ºãã®é ïŒåæã®èª¬æãå ãèè ã®å ·äœçãªæç€ºãåŸïŒã§ãã©ã¡ããç¡ããã°undefinedïŒ=systemPromptãæž¡ããªãïŒãsession.tsã¯æèšãçµåé ãæããªãã - worktree ã®ç°å¢èª¬æïŒå
±æ symlink ã®æ³šææžãïŒ:
ignoredFiles: 'symlink'ïŒæ¢å®ïŒã§ã¯ ignore æžã¿ãã¹ãå ãªããžããªã®å®äœãæããããã»ãã·ã§ã³ãäŸåæŽæ°ããã«ããèµ°ããããšã¡ã€ã³ãã§ãã¯ã¢ãŠããšäžŠè¡ã»ãã·ã§ã³ã«æ³¢åãããããã§ãã®ã¢ãŒãã®ãšãã ãSHARED_IGNORED_FILES_NOTICEã systemPrompt ã«èŒãããèªãã®ã¯å®å š / æžãåã«ãã®ãã¹ã ããªã³ã¯ãåã£ãŠç¬ç«ããã / ãªã³ã¯è¶ãã«æ¶ããªãïŒrm -rf <path>/çŠæ¢ïŒ/ è§Šããªãäœæ¥ã§ã¯äœãããªãããäŒãããã¢ãŒãã¯åæã¬ã€ã€ã®sessionOptionsFrom(config, appendSystemPrompt)ïŒbootstrap/build-manager.tsãconfig âSessionOptionsã®å¯Ÿå¿ä»ãã ããæã€çŽé¢æ°ã§ãspec ã§åºå®ããŠããïŒãresolveIgnoredFilesMode(config)ã§è§£æ±ºããŠSessionOptions.ignoredFilesãžæž¡ããè§£æ±ºç®æã¯åæã¬ã€ã€ã®2ã€ïŒindex.tsxã®WorktreeManagerçæãšããïŒã ããã©ã¡ããåã config ç±æ¥ãªã®ã§äžèŽãããæ¢ç¥ã®å¶çŽ: ã¢ãŒã㯠state.json ã«æ°žç¶ããŠããªãã®ã§ãsymlinkã§äœã£ã worktree ãåŸããcopy/noneèšå®ã§åŸ©å ãããšæ³šææžããèŒããªãïŒèšå®ãå€ããå Žåã®ã¿ãéåãïŒå®äœãããã®ã«æ³šææžããèŒãã±ãŒã¹ã¯ãæé 1ã®test -Lå€å®ã§ç¡å®³åãããïŒãcodiva åŽã§ãªã³ã¯ãåŒµãæ¿ããããšã¯ããªã â äœãæžã蟌ã¿å¯Ÿè±¡ãã¯æç€ºå 容次第ã§ãå åãããŠå šéšã³ããŒãããš symlink ã¢ãŒãã®å©ç¹ïŒè€è£œã³ã¹ããŒãïŒãæ¶ããããã倿ã¯ã»ãã·ã§ã³ã«å§ãããæèšã¯ AI åããªã®ã§è±èªã»i18n ã«ã¿ãã°å¯Ÿè±¡å€ïŒutils/title.tsãšåãæ±ãïŒã - ãªããžããªè¿œå æç€ºïŒ
.codiva/prompt.mdïŒ: åæã«ãŒãïŒindex.tsxïŒãèµ·åæã«loadRepoPrompt(repoRoot)ã§èªã¿ãbuildManagerâSessionOptions.appendSystemPromptãžæµããconsume()ã¯äžèšãšåæããŠoptions.systemPromptãšããŠæž¡ããSDK 㯠systemPrompt çç¥æã«ç©ºæåãžååããïŒclaude_code ããªã»ããã¯äœ¿ããªãïŒãããæååãæž¡ãã®ã¯ã空ãžã®è¿œèšããšç䟡ã§çŸæåãå€ããªããCLAUDE.md ã¯settingSources: ['project']çµç±ã§å¥éæ³šå ¥ãããã®ã§ãããã¯ãããžã®äžä¹ããå°æ¥ããŒã¹ã® systemPrompt ãå°å ¥ããå Žå㯠array / preset-append 圢ãžåãæ¿ããïŒsession.tsã®æ³šå ¥ã³ã¡ã³ãåç §ïŒã - 埩å
察å¿:
resumeïŒSDK ã»ãã·ã§ã³IDïŒãšrestoredïŒåŸ©å æžã¿SessionStateïŒã DI ã§åããããã埩å ã»ãã·ã§ã³ã¯start()ãããæåã®send()ã§é å»¶çã« query ãéå§ïŒresumeä»ãïŒãããã§èµ·åæã«ãµãããã»ã¹ãä¹±ç«ãããªãã stop(): ç¶æ ãå€ããã«ãµãããã»ã¹ã ãèœãšã quiet 忢ãã¢ããªçµäºæã¯ããã䜿ããå®è¡äžã»ãã·ã§ã³ã resumable ã®ãŸãŸä¿åããïŒabort()㯠failed ã«ããç¹ãéãïŒãä¿çäžã®èš±å¯èŠæ±ãããã° deny ã§è§£æ±ºããŠãã忢ããïŒæªå¿çã®tool_useã§ resume ãå£ããã®ãé²ãïŒã
create(prompt): slugçæ â WorktreeManager.add() â Session èµ·åãåæçã«creatingç¶æ ã®ãšã³ããªã峿è¿ãïŒUI ãåŸ ãããªãïŒã- ã¿ã€ãã«çæ:
generateTitleïŒDIãutils/title.tsã Haiku ã§å®è£ ïŒãå fresh ã»ãã·ã§ã³ã«æž¡ããSession.start()ãæç€ºæãèŠçŽãããè¿ã次第titleã€ãã³ãã§æ«å®ã¿ã€ãã«ãå·®ãæ¿ããïŒrestore æžã¿ã»ãã·ã§ã³ã¯ä¿åæžã¿ã¿ã€ãã«ãç¶æãåçæããªãïŒãI/O ã¯æ³šå ¥ãªã®ã§ reducer/session ã¯çŽç²ã»ãã¹ãå¯èœã - å
šã»ãã·ã§ã³ã®
Map<id, Session>ãä¿æããsubscribe(listener)/getSnapshot(): SessionState[]ãæäŸïŒReact ã®useSyncExternalStoreã«ãã®ãŸãŸæ¥ç¶ã§ãã圢ïŒã - ã¹ãããã·ã§ããã¯æ¯åæ°ããé ååç §ãè¿ããã倿Žã®ãã£ãã»ãã·ã§ã³ä»¥å€ã®ãªããžã§ã¯ãåç §ã¯ç¶æããïŒäžèŠãªåæç»é²æ¢ïŒã
dispose(): å šã»ãã·ã§ã³ãstop()ïŒquietïŒïŒworktree ã¯æ®ãïŒãå®è¡äžã§ã resumable ãªãŸãŸãonTransition(prev,next): ã¹ããŒã¿ã¹é·ç§»ããšã«çºç«ïŒãã¹ã¯ãããéç¥ã«é ç·ïŒãonPersist(): æ°žç¶å¯Ÿè±¡ãå€ãã£ãåå³ïŒåæã«ãŒãã§ debounce ä¿åã«é ç·ïŒãpersistableState()ã state.json çšã¹ãããã·ã§ãããçµã¿ç«ãŠãã- ã¢ãã«åæ¿ïŒ
/modelïŒ:SessionOptionsãå¯å€ãã£ãŒã«ããšããŠä¿æããgetModel()/setModel(model)ã§å ¬éãsetModelã¯ä»¥éã®æ°èŠã»ãã·ã§ã³ã«é©çšïŒå®è¡äžã»ãã·ã§ã³ã¯èµ·åæã®ã¢ãã«ãç¶æïŒããonModelChange(model)ã§åæã«ãŒãã«éç¥ â~/.codiva/config.jsonã®modelã«ããŒãžä¿åããããéžæè¢ã¯ Claude Code ã®ã«ã¿ãã°ïŒQuery.supportedModels()ïŒãå¯äžã®åºæã«ããååŸã¯utils/model-catalog.tsïŒfetchModelCatalogïŒã»å€æãšçªãåããã¯core/models.tsïŒtoModelOptions/isCurrentModelïŒãæ ãïŒè©³çŽ°ã¯ TECH_NOTES.md ã® supportedModels ç¯ïŒãã³ãã³ãè§£æã¯core/commands.tsïŒparseSlashCommandïŒã - ãªããžããªè¿œå æç€ºã®ç·šéïŒ
/promptïŒ: ã¢ãã«åæ¿ãšåã圢ãgetRepoPrompt()/setRepoPrompt(text)ã§SessionOptions.appendSystemPromptãå¯å€ç®¡çããsetRepoPromptã¯ä»¥éã®æ°èŠã»ãã·ã§ã³ã«é©çšïŒå®è¡äžã»ãã·ã§ã³ã¯èµ·åæã®æç€ºãç¶æãsystemPrompt 㯠query éå§æã«ç¢ºå®ããããïŒãonRepoPromptChange(text)ã§åæã«ãŒãã«éç¥ âutils/saveRepoPrompt()ã<repo>/.codiva/prompt.mdãžæ°žç¶åïŒç©ºãªãåé€ïŒãUI ã¯äžèЧã®/promptã§ui/repo-prompt-editor.tsxïŒçŸåšå€ãã·ãŒãããã¢ãŒãã«ãEnter ä¿å / Shift+Enter æ¹è¡ / Esc åæ¶ãcomposer ãšåãinput.tsã® chord ã¢ãã«ïŒãéããèµ·åæèªèŸŒã¯åŸæ¥ã©ããloadRepoPrompt()ã - èšå®ã®å¯Ÿè©±ç倿ŽïŒ
/configïŒ: ã¢ãã«åæ¿ã»ãªããžããªæç€ºãšéããããã¯SessionManagerãéããªãïŒå¯Ÿè±¡ããcodiva èªèº«ã®èšå®ãã§ã»ãã·ã§ã³ã®ç¶æ ã§ã¯ãªãããïŒãé ç®ã®è¡šãšå転ã¯çŽç²ãªcore/config-items.tsïŒCONFIG_TOGGLES/configToggleRows/toggleConfigPatchïŒã衚瀺ã¯ui/config-select.tsxãä»ã®å€ã®ä¿æã¯app.tsxã® stateãä¿åã¯åæã«ãŒãã®bootstrap/config-store.tsïŒConfigStoreïŒã- UI ãäžããã®ã¯å
šäœã§ã¯ãªãå·®åïŒ
Partial<CodivaConfig>ïŒã«ããŠãããsaveConfigã¯ãã¡ã€ã«ãäžžããšäžæžãããã®ã§ãæžãæïŒ/model//agent//configïŒãããããèµ·åæã®ã¹ãããã·ã§ãããæã€ãšåŸåã¡ã§äºãã®å€æŽãæ¶ããConfigStoreãå¯äžã®æžãæã«ããŠmergeConfigïŒcore/config.tsãundefinedã¯ããŒåé€ = æ¢å®ãžæ»ãïŒã§ç³ãã/modelãš/agentã®æ°žç¶åãbuildManagerã®saveConfigPatchçµç±ã§åãã¹ãã¢ãéãã - æžã蟌ã¿ã¯ 1 æ¬ãã€çŽåã«ããåŸ
ã£ãŠããéã«æ¥ãæŽæ°ã¯ææ°ã® 1 ã€ãžç³ãïŒ
flush()ã§åŸ ãŠããçµäºæã«main.tsxãåŸ ã€ïŒã䞊è¡ã«æãããšå®äºé ãå ¥ãæ¿ãããå ã«å§ãŸã£ãå€ãã¹ãããã·ã§ãããåŸããçå°ããŠæ°ããèšå®ãå·»ãæ»ãïŒ/configã®çŽåŸã«/modelãè§Šããšèµ·ãããissue #111ïŒãã¡ã¢ãªäžã®å€ã ããæ£ãããŠãã£ã¹ã¯ãå€ãç¶æ ã¯æ¬¡åèµ·åãŸã§æ°ä»ããªãã®ã§ãå¯äžã®æžãæã«ããæå³ãæ¶ããã - å®ãã¡ã€ã«ãžã®æžã蟌ã¿ã¯äžæãã¡ã€ã« â renameïŒ
utils/config.tsïŒãå šçœ®æã®éäžã§èœã¡ããšå£ãã JSON ãæ®ããloadConfigã®ãã©ãŒã«ããã¯ã§èšå®ãäžžããšæ¢å®ãžæ»ãã - èŒããã®ã¯çåœå€ãšããŠæå³ãéãé
ç®ã ãïŒå€è¢éžæã¯èšå®ãã¡ã€ã«çŽç·šéïŒã
claudeSettingSourcesã¯é åã ãã'user'å±€ãèªããã= Claude Code ã®ãã©ã°ã€ã³ã䜿ããã«ç³ããã®ã§ãå°çšã® read/write ãæãããŠäŸå€çã«èŒããŠããã - çŸç¶ã®é ç®ã¯ãã¹ãŠèµ·åæã«ããèªãŸããªãïŒã¢ããã¿ã»WorktreeManagerã»ç«¯æ«ã»ããã¢ããã«çŒã蟌ãŸããïŒã®ã§ããã€ã¢ãã°ã¯ãä¿åæžã¿ã»åæ ã¯æ¬¡åèµ·åãããã 1 è¡åºããå³æåæ ã§ããé ç®ãè¶³ããšãã«è¡ããšã®å°ãå°å ¥ããã
- UI ãäžããã®ã¯å
šäœã§ã¯ãªãå·®åïŒ
restore(persisted): èµ·åæã«ååã»ãã·ã§ã³ãåæ§ç¯ïŒworktree meta ãåé ç·ããSessionã«resume/restoredãæž¡ããid/slug ãäºçŽããŠè¡çªåé¿ïŒã- 責ååå²: SessionManager ã¯ã©ã€ããµã€ã¯ã«ãšé
ç·ã®ãã¡ãµãŒãã§ã以äžãå§è²ãã:
core/session-store.tsïŒSessionStoreïŒâŠ è³Œèªå¯èœã¹ãããã·ã§ããïŒé åºã»ç¶æ ã»åç §åäžæ§ä¿æïŒcore/session-actions.tsâŠmergeSession/discardSession/sessionDiffStatïŒgit æäœïŒcore/pr-coordinator.tsïŒPrCoordinatorïŒâŠmaybeAutoPr/refreshPrs/maybeAutoRecoverïŒPR èªååïŒcore/pr-recovery.ts⊠詰ãŸã£ã PR ã®ç«ãŠçŽãå€å®ãšæç€ºæïŒçŽç²ïŒcore/run-mode.tsâŠRunMode+createModePolicyïŒshift+tab ã®ããŒã«èš±å¯ã¢ãŒãïŒcore/persistence.tsã®assemblePersistedState⊠state.json ã¹ãããã·ã§ããã®çµã¿ç«ãŠ- DI seam ã® interfaceïŒ
WorktreeService/SessionHandle/PrAutomation/PrLookup/ActionResultïŒã¯core/session-ports.tsïŒleafïŒã«éçŽã埪ç°ãé²ãããšãŒãžã§ã³ãåŽã® seamïŒAgentAdapter/AgentRun/AgentRunRequest/AgentCapabilities/PermissionDecisionïŒã¯core/agent-ports.tsïŒåãã leafïŒãSessionManagerãagentã DI ã§åãããããå·®ãæ¿ããã ãã§æ°èŠã»ãã·ã§ã³ã® provider ãå€ããã
- åæãã§ãã¯: GitãªããžããªããHEAD ãååšãããïŒã³ããã0ã®ãªããžããªã§ã¯ worktree ãäœããªãïŒã
add(slug):git worktree add .codiva/worktrees/<slug> -b codiva/<slug>ãçŸåšã® HEAD ããäœæãslug è¡çªæã¯-2,-3ãä»äžã.codiva/.gitignoreïŒäžèº«ã¯*ã® 1 è¡ïŒãèªåçæïŒç¡ããšãã ããèµ·åæãšadd()ã®äž¡æ¹ããensureIgnored()ïŒã*ã¯åããã£ã¬ã¯ããªã®.gitignoreèªèº«ã«ãäžèŽããã®ã§ããã® 1 ãã¡ã€ã«ã ãã§.codiva/ãäžžããš git ããæ¶ããïŒcargo ã®target/.gitignoreãšåãæïŒããã€ãŠã¯.git/info/excludeãžè¿œèšããŠãããã.gitã¯ãã£ã¬ã¯ããªãšã¯éããªã â linked worktree / submodule ã§ã¯gitdir:ãæžãããã ã®ãã¡ã€ã«ãªã®ã§ãããã§ codiva ãèµ·åãããšè¿œèšã ENOTDIR ã§å€±æããæ¡ãæœ°ããŠããªãã£ããã worktree äœæããšå€±æããŠãããäœæ¥ããªãŒåŽã®ãã¡ã€ã«ãªã git ã®å éšé 眮ã«äŸåããªããæ¢åã®.codiva/.gitignoreã¯äžæžãããªãïŒå©çšè ãäŸå€ãè¶³ããŠãããããããªãïŒãå¯äœçšãšããŠgit ls-files --others --ignored --directoryã.codiva/ã 1 ä»¶ã«ç³ãŸãªããªãïŒé€å€ã®åºæããã®ãã£ã¬ã¯ããªã®äžã«ãããã git ãäžãžéããïŒã®ã§ãåŒãç¶ã察象ã®ãã£ã«ã¿ã¯å é ã»ã°ã¡ã³ãã§.codiva/.gitãèœãšãïŒå®å šäžèŽã ãš.codiva/worktrees/ãåŒãç¶ãããæ° worktree ã®äžã« worktree 矀èªèº«ãžã®ãªã³ã¯ã匵ãããŠä»¥åŸã®worktree removeã ELOOP ã§å€±æããïŒã- ignore æžã¿ãã¡ã€ã«ã®åŒãç¶ã:
ignoredFilesïŒ'symlink'|'copy'|'none'ãæ¢å®'symlink'ïŒã'none'以å€ãªããgit ls-files --others --ignored --exclude-standard --directoryã§åæãã.gitignore察象ïŒnode_modules/ã».envãªã©ïŒããªããžããªã«ãŒããã worktree ãžåŒãç¶ããgit worktree ã¯è¿œè·¡å¯Ÿè±¡ããåŒãç¶ããªããããããã§äŸåã®åã€ã³ã¹ããŒã«ãç°å¢å€æ°ã®åèšå®ãªãã«ã»ãã·ã§ã³ãå³å®è¡ã§ããã'symlink'ã¯fs.symlinkã§å ãžã®ãªã³ã¯ã匵ãã ãïŒè€è£œã³ã¹ããŒãã»å®äœå ±æïŒã'copy'ã¯fs.cpã§å®äœãè€è£œïŒworktree å®å šç¬ç«ã»å€§ãããšéãïŒãæ¢å®ã'symlink'ã«ããŠããã®ã¯ãnode_modules/çã®è€è£œã³ã¹ããé¿ããŠèµ·åãéããããããåæçµæã®ãã£ã«ã¿ã¯çŽé¢æ°ignoredCopyEntries()ã«åãåºãïŒ.codiva/ã».gitã¯ååž°ã»å éšç¶æ ç Žå£ãé¿ãããããé äžãå«ããŠå é ã»ã°ã¡ã³ãã§å¿ ãé€å€ïŒãå®äœåã¯ãšã³ããªåäœã®ãã¹ããšãã©ãŒãïŒ1ä»¶ã®å€±æã§ worktree äœæãæ¢ããªãïŒãèšå®å€ããã¢ãŒããžã®è§£æ±ºã¯çŽé¢æ°resolveIgnoredFilesMode()ïŒéæšå¥šcopyIgnoredã®åŸæ¹äºæ:trueâ'copy'/falseâ'none'ïŒã - ãã«ãçæç©ã»ãã£ãã·ã¥ã¯ã¢ãŒãã«é¢ä¿ãªãåŒãç¶ããªãïŒ
DEFAULT_IGNORED_EXCLUDESïŒã.gitignoreã¯äŸåïŒåŒãç¶ãããïŒãšçæç©ïŒåŒãç¶ããããªãïŒãåºå¥ããªãããã.next/dist/target/coverage/*.tsbuildinfoçã®æ¢ç¥ã®ååãåæããŠé€å€ãããçç±ã¯ (1) çæç©ãªã®ã§ã»ãã·ã§ã³åŽã§äœãçŽããã(2) å ±æãããšå ãªããžããªãšå worktree ã®éçºãµãŒãïŒãã«ããåãå®äœãžåæã«æžã蟌ãã(3) worktree ããªããžããªé äžïŒ.codiva/worktrees/<slug>ïŒã«ãããããã«ãŒãã§ååž°ç£èŠããŠããéçºãµãŒãïŒNext.js / TurbopackïŒããã¯èªåãæžã蟌ãã§ãããã£ã¬ã¯ããªã worktree ã®æ°ã ãå¥çµè·¯ãšããŠèŠãã倿Žéç¥ãå€éã«è·³ãè¿ã£ãŠ OS ããšããªãŒãºããïŒissue #81 ã®å®æž¬: worktree 6 å +next dev --turbopackïŒãå€å®ã¯çŽé¢æ°isExcludedIgnoredEntry()ïŒ/ç¡ãã®ãã¿ãŒã³ã¯æçµã»ã°ã¡ã³ãã«äžèŽ = ãã¹ãããapps/web/.next/ã«ãå¹ã /*åçœ®ã¯æ¥å°ŸäžèŽ / æåŸã«äžèŽãããã¿ãŒã³ãåã€ïŒãååã®åæã¯å¿ ãå€ããã®ã§ãèšå®ignoredFilesExcludeã§è¿œå ïŒ.venvïŒãšæã¡æ¶ãïŒ!distïŒãã§ããïŒignoredExcludePatterns()ãæ¢å®ã®åŸãã«é£çµïŒããªããžããªã®.gitignoreã¯æžãæããªãæ¹éã¯ç¶æããç£èŠé€å€ã¯å©çšè ã®èšå®ã«å§ããïŒREADME ã®è©²åœç¯ïŒã - æ¢å worktree ã®åŸçä»ã: é€å€ãªã¹ããå¢ãããŠãã以åã®ããŒãžã§ã³ã匵ã£ããªã³ã¯ã¯æ®ãïŒ= ããªãŒãºèŠå ãæ®ãïŒã®ã§ãèµ·åæã«
pruneExcludedLinks()ïŒindex.tsxã® preflight çŽåŸã»best-effortïŒã§ãããŸã®èšå®ãªãåŒãç¶ããªããšã³ããªãã®ãªã³ã¯ã ããå€ãã察象ã®åæã¯çŽé¢æ°excludedIgnoredEntries()ïŒignoredCopyEntries()ã®è£è¿ãïŒã§ãworktree ã®äžãèµ°æ»ããªãã®ã§ã³ã¹ãã¯äžå®ãã·ã³ããªãã¯ãªã³ã¯ããæ¶ããªãã®ãå®å šåŒã§ãå®äœã®ãã£ã¬ã¯ããªïŒã»ãã·ã§ã³èªèº«ã®ãã«ãçµæã§ããããïŒãšãªã³ã¯å ïŒå ãªããžããªïŒã«ã¯è§Šããªãã diffStat(session):git -C <worktree> diff <base>...HEAD --statçžåœãæªã³ããã倿Žãããå Žåã¯ãã®æšãè¿ããmerge(session): ã»ãã·ã§ã³ãã©ã³ããããŒã¹ãã©ã³ããžããŒãžïŒsquash ã¯ããªããã³ã³ããªã¯ãæã¯ãšã©ãŒãè¿ããæå解決ãä¿ãã¡ãã»ãŒãžã衚瀺ããã®ã¿ïŒãremove(session, { force }):git worktree remove+git branch -Dã
Claude Code ã®å®ç»é¢ã«å¯ãã: ç»é¢ã¯ç«¯æ«ã®çžŠå¹
ãã£ã±ãïŒweb ã® 100dvh çžåœãApp ã root Box ã« useWindowSize() ã® rows ãæå®ã極端ã«äœã端æ«ã§ã¯ isFullscreenViewport ã false ã«ãªãã€ã³ã©ã€ã³æç»ãžãã©ãŒã«ããã¯ïŒã«æç»ããå
šç»é¢æã¯èµ·åæã« alt screenïŒutils/alt-screen.tsïŒãžå
¥ã£ãŠã¹ã¯ããŒã«ããã¯ãç¡å¹åïŒäžãžã®ã¹ã¯ããŒã«ãããã¯ïŒããäžéšã«äžäžã®å
šå¹
暪眫ç·ã ãã®å
¥åæ¬ïŒPromptInputãè§äžžæ ã§ã¯ãªãïŒããã®äžã«ã¢ãŒãè¡ïŒStatusFooter = âµâµ auto mode on (shift+tab to cycle) + æèãã³ãïŒã flexGrow ã¹ããŒãµã§æäžéšã«åºå®ããããã¯æ ãªãã®ã¯ãŒãããŒã¯ãè²ãšã°ãªã㯠theme.ts ã«éçŽã
App: å šç»é¢ã¬ã€ã¢ãŠãã® root ãš Ctrl+C ã®å®å šç¶²ãlist â detail ã®ãã¥ãŒåæ¿ãViewstate ã§æã¡ã äžèŠ§ã§ Enter/â ãããšonOpen(id)ã§è©³çްãžã詳现㧠Esc ãããšonBackã§äžèŠ§ãžæ»ããBanner: èµ·åæãããïŒãã¹ã³ãã + ã¯ãŒãããŒã¯ / ãã©ã³ + ã¢ãã« + ãã©ã³ã / cwd + 䜿çšç¶æ³ã²ãŒãžïŒãæ ãªãã§ äžèЧäžéšã«è¡šç€ºãçŽç²ã« presentational ã§ã衚瀺è¡ã¯ core ã®bannerLines()ïŒcore/banner-lines.tsïŒã çµãïŒBannerLine[]= 1 èŠçŽ 1 衚瀺è¡ãè²ã¯BannerToneãšããæœè±¡ã§åãåããå®éã®è²ã¯theme.tsïŒã å¯èªæ§ã®ãããã©ã³ã»ã¢ãã«ã»çŸåšãã©ã³ã㯠1 è¡ã«ãŸãšãïŒPlan: Claude Max Model: sonnet Branch: mainïŒã ãµãã¿ã€ãã«ã¯åºããªãããã©ã³ãã cwd è¡ã§ã¯ãªãããã«çœ®ãã®ã¯ã(1) cwd ã¯é·ããªããã¡ã§è¡æ«ãtruncate-endã§åããïŒçã端æ«ã§çã£å ã«æ¶ããïŒã(2) cwd è¡ã¯ãã¹ãåãåºããã©ãã°çšéãªã®ã§ã è¡æ«ãžäžžãã dragïŒbannerCaretAtã®'clamp'ïŒã§ãã©ã³ãåãŸã§äžç·ã«ã³ããŒããããã® 2 ç¹ã å€ã¯app.tsxã®useBranchïŒåæã«ãŒããæ³šå ¥ããWorktreeManager.currentBranch()ã 5 ç§ããšã« èªã¿çŽãïŒãäŸçµŠãããcodiva ã®å€ïŒå¥ã¿ãŒããã«ã®git switchïŒã§ãå€ããã®ã§è³Œèªã§ããçžæã ãããã宿çã«èªã¿çŽããããªããstate ãAppã«çœ®ãã®ã¯ãã¥ãŒåæ¿ã§å€±ããªãããïŒäžèŠ§ã« çœ®ããšè©³çްããæ»ã£ã 1 ãã¬ãŒã ã ãæ¶ããæ»ããã³ã«åãçŽãã«ãªãïŒã§ãååŸã¯äžèЧã®ãšãã ã ïŒview.mode === 'list' ? loadBranch : undefinedïŒãããããæããŠããªã詳现ãã¥ãŒã®éã誰ãèªãŸãªã å€ã®ããã« git ã®ããã»ã¹ãç«ãŠãªããäžèŠ§ãžæ»ããšå³åº§ã« 1 åèªã¿çŽããdetached HEADïŒsymbolic-refã倱æïŒãš git ã®å€±æã¯ undefined = 衚瀺ããªãïŒrev-parse --abbrev-refã®'HEAD'ãåºããšãHEAD ãšãããã©ã³ããã«èŠãããããbaseBranch()ãšã¯å¥ã¡ãœããã«ããŠããïŒã ãããã®ããã¹ãã¯ãã©ãã°ã§ç¯å²éžæããŠã³ããŒã§ããïŒcwd ã®çµ¶å¯Ÿãã¹ãåãåºãçšéïŒãåœããå€å®ã¯ ãè¡ index = 衚瀺è¡ããåæã«bannerCaretAt()ã§éç®ãããããè¡ã¯wrap="truncate-end"ã§ 1 è¡ 1 è¡ã« åºå®ããéžæå¯èœãªããã¹ãå¡ïŒtextRefã® BoxïŒã®äžã« margin ãå ¥ããªãïŒæè¿ãã»margin ãå ¥ããšä»¥éã® è¡ãå šãŠãºã¬ãïŒãäœçœ®ã®å®æž¬ ref ã¯äžå€®å¯ãã®å€åŽã§ã¯ãªãè¡ã ããå ãå åŽ Box ã«ä»ããã 䜿çšç¶æ³ïŒUsageSectionïŒãšåŠç¿ããŒã¿å©çšã®èŠåïŒPrivacySectionïŒã¯ãã®å¡ã®å€ã«æãã®ã§ã ç¯ã®ééã¯marginTopã§ç©ºããŠããïŒè¡æ§æãæºãããªãïŒã䜿çšç¶æ³ã®è¡ããŒã¿ã¯çŽç²ãªbannerUsageRows()ïŒèŠåºããè¡šç€ºå¹ ã§æãã䜿çšçãå³è©°ãã«ããBannerUsageRow[]ïŒãçµã¿ã ã²ãŒãžã®ã»ã«æ°ã¯gaugeCells()ãèšå·ïŒâ / âïŒã¯theme.tsã®glyphããåãïŒcore ã«èšå·ã眮ããªãïŒã ã²ãŒãžå¹ ã¯ç«¯æ«å¹ ã§æ®µéçã«çž®éãããïŒbannerGaugeWidth(columns)= 20 / 12 / 8 / 0 ã»ã«ïŒã äœã端æ«ã§ã¯ããããçž®ãã§äžæ®µ UI ã«å Žæãè²ãïŒflexShrinkãæ¢ããªãïŒãããæœ°ããŠäžèЧã®è¡ã« éãªã£ãå Žåã¯äžèЧã®ã¯ãªãã¯ãåªå ããïŒSessionListåŽã§y >= rowsBox.topãé€å€ïŒã çžŠã«æœ°ãããšäžå€®å¯ãã®è² ãªãã»ããã§äžç«¯ã®è¡ããèœã¡ãã®ã§ãSessionListã¯å®æž¬é«ã ïŒuseBoxHeightïŒãè¡æ°ããå°ããéã¯ãããã®åœããå€å®ãããããäžæ¹ãã¹ã³ããã® Box ã ãã¯flexShrink={0}ïŒæšªæ¹åã®çž®å°ã§ã¢ã¹ããŒã¢ãŒããæãè¿ããŠåŽ©ããã®ãé²ãã瞊ã®è²ãåãã«ã¯å¹ããªãïŒãSessionList: äžèЧç»é¢ãBanner+ äžèЧ + äžéšPromptInput/StatusFooterããã©ãŒã«ã¹ã¯composerïŒèµ·åææ¢å®ãã¿ã€ãã³ã° + ç¢å°ãã£ã¬ããç§»åïŒ/dialogïŒéžæã»ãã·ã§ã³ã®PermissionDialogãããŒãæã€ïŒ/listïŒââéžæã»Enter/â = 詳现ãéãã»m/d/x = ããŒãž/ç Žæ£/åé€ïŒã® 3ãŸãŒã³ïŒListFocusïŒã§ãTab 㯠composer â dialogïŒéžæè¡ãèš±å¯/質ååŸ ã¡ã®ãšãã ãïŒâ list â composer ãš åãããã€ã¢ãã°ã¯ composer 以å€ã®ãŸãŒã³ã§åžžã«èŠããŠããããããŒãåãã®ã¯dialogãŸãŒã³ã ãã åããŠããã®ã¯ ââ ã®è¡ãå ãäžæã«ãããã â 以å㯠list ãã©ãŒã«ã¹ã« çžä¹ããããŠããã®ã§ã質åãåºãŠããè¡ãéžãã§ããéã¯ã»ãã·ã§ã³ãåãæ¿ããããªãã£ãã ãã®ããã§éžãã è¡ãèš±å¯/質ååŸ ã¡ãªãdialogãæ¢å®ãŸãŒã³ã«ããïŒzoneForRowãââ ã®ç§»åã» ãã€ãŒã«ã»è¡ã®ã¯ãªãã¯ã»ç©º Enter ãã¹ãŠå ±éïŒãåçã¯åŸ ãããŠããçšäºãªã®ã§ Tab ãäœåã«èžãŸããã äžèŠ§ãžæ»ãåºå£ã¯ Tab ã«äžæ¬åããŠãããããŠã¹ã¯ãªãã¯ïŒcore/mouse.ts+useAbsolutePositionïŒã§ è¡éžæã»ãã£ã¬ããç§»åããã€ã¢ãã°ã®äžã®ã¯ãªãã¯ãåããïŒPermissionDialogã®onActivateã§ ãŸãŒã³ãdialogãžå¯ããéžæè¢ã®äžãªãã«ãŒãœã«ããããžçœ®ãïŒã®ã§ãäžèЧã®ã¯ãªãã¯ã¯ ãã€ã¢ãã°ãåºãŠããéã飲ãŸãªãïŒé£²ããšãã¢ã¯ãã£ããªãã€ã¢ãã°ããå¥ã»ãã·ã§ã³ãžããŠã¹ã§ç§»ããªããïŒã ã³ã³ããŒã¶äžã®ãã©ãã°ã§ç¯å²éžæããé¢ããšã¯ãªããããŒããžã³ããŒïŒOSC 52 =utils/clipboard.tsã çŽç²ããžãã¯ã¯core/text-selection.tsãç¶æ ã¯å ±æããã¯useDragSelectionïŒã詳现ãã¥ãŒã® ãã©ããŒã¢ããå ¥åæ¬ã»ãã°ãåæ§ïŒãã°ã¯è¡åäœã®useLogDragSelectionïŒããããïŒBannerïŒãåãä»çµã¿ã§éžæã»ã³ããŒã§ããïŒuseDragSelectionã ã³ã³ããŒã¶ãšã¯å¥ã€ã³ã¹ã¿ã³ã¹ã§æã€ = caret index ã®åºæºããã¹ããéãããïŒããããã®ãã©ãã°ã¯ ãã©ãŒã«ã¹ãéžæè¡ãåãããªãïŒãã¹ãã³ããŒãããã ãã®æäœã§ã¿ã€ãã³ã°äœçœ®ã奪ããªãïŒãSessionDetail: 詳现ç»é¢ãã¹ããŒã¿ã¹ãããã¯æãããã³ã³ãã³ãïŒæ«å°Ÿãã¥ãŒããŒãã®ãã°ïŒ+ ããã¿ ïŒè¿œå æç€ºã³ã³ããŒã¶ïŒã ãã®æ§æãSDK ã»ãã·ã§ã³ã«çŽçµããæ«å°Ÿãã¥ãŒããŒãã«ãã°ãæç»ïŒcore/scroll.tsã®logLinesã§ãšã³ããªã CJK å¹ å¯Ÿå¿ã§æãè¿ããç©çè¡ïŒDisplayLine[]ïŒãžå±éããŠãã ïŒå±éã¯ãšã³ããªåäœã§ã¡ã¢åãããäžèšããã°ã®ã¡ã¢ãªäžéãåç §ïŒãlogWindow/scrollUp/scrollDownã§ PgUp/PgDnïŒåç»é¢ïŒã»â/âïŒ1è¡ =ARROW_SCROLL_LINESïŒã» ãã€ãŒã«ïŒWHEEL_SCROLL_LINESïŒã¹ã¯ããŒã«ãããŠã¹ã¬ããŒãã¯parseSgrMouseã§ useInput ã®å é ã§ å åãè§£éããã³ã³ããŒã¶ãžæåå ¥åãšããŠæŒããªãããã«ããïŒããŠã¹ç¡å¹ç°å¢ã§ã¯ç«¯æ«ããã€ãŒã«ã â/â ã«å€æããŠéãã®ã§ãâ/â ããã®åãå£ãå Œãã = alternate scroll modeïŒã ãã°ã¯ãã©ãã°ã§ç¯å²éžæããŠã³ããŒã§ããïŒcore/log-selection.ts+useLogDragSelectionïŒã éžæã®äœçœ®ã¯å¹³åŠãª caret index ã§ã¯ãªããææžã®è¡šç€ºè¡ index + è¡å ã®æ¡ãïŒLogPointïŒã§æã€: è¡ index ã¯ã¹ã¯ããŒã«ããŠãæå³ãå€ãããªãã®ã§ãå¯èŠåã®å€ãžãã©ãã°ãããšèªåã¹ã¯ããŒã« ããªããéžæã䌞ã³ç¶ããïŒlogEdgeAtâ 1 tick = 1 è¡ã®edgeStepã?1002 ã¯éæ¢äžã«ç§»åã å ±åããªãã®ã§LOG_EDGE_SCROLL_MSã®ã¿ã€ããŒã§ç¶ç¶ïŒãåœããå€å®ïŒLogViewportïŒã¯æç»ã« 䜿ã£ã宿ž¬å€ãšåããŠã£ã³ããŠããçµã¿ãæ«å°Ÿå¯ãã®ééãåæ¡ããã 1 è¡ã¶ãã®æç»ïŒkind ããšã® prefix / dim / Markdown ã¹ãã³ / éžæãã€ã©ã€ãïŒã¯ui/log-line.tsxã®LogLineã«åããŠããïŒSessionDetailã¯è¡ã®äžŠã¹æ¹ãšå ¥åã«å°å¿µïŒã æãè¡æ°ã¯å®æž¬ããå¯èŠé«ãïŒuseBoxHeightïŒã«åãã â Ink/Yoga ã¯æº¢ããåãçž®å°ããããã å€ãæããšè¡ãè«é£ãã§æ¬ èœããã ã¹ããªãŒãã³ã°äžã®æ¬æïŒstreamingTextïŒã¯ãã°ã®è¡ãšããŠæãïŒcore/scroll.tsã®streamLinesã§æãè¿ããç¢ºå®æžã¿ã®è¡ã®åŸãã«è¶³ããŠåãlogWindowãžæž¡ãïŒãè¿ã£ãŠãã ã¶ãã ãæ¬æãäžãžäŒžã³ãæ«å°Ÿè¿œåŸïŒåºå®ã¯ã¢ã³ã«ãŒããã®ãŸãŸæ ãïŒ'bottom'ãªãæµããŠããŠã äžãžã¹ã¯ããŒã«ããŠæ°å€ã¢ã³ã«ãŒã«ãªã£ãŠããã° 1 è¡ãåããªãïŒãéäžããã¹ã㯠Markdown æŽåœ¢ããªã â æªå®ã®**ã ``` ã§æ¯ãã«ã¿å šè¡ã®æãè¿ããå€ãããInk ã®äžéãªã ãã£ãã·ã¥ãèšããããïŒäžèšïŒã ãã°ã®ããäžã¯åžžã« 1 è¡ã®ç¶æ è¡ïŒcore/scroll.tsã® `logStatusRow` â `LogStatusRow`ïŒã§ã ãéå»ãã°ã衚瀺äžãã®æ¡å / 空è¡ã®ã©ã¡ãããæãã åºãå ¥ãããªãã®ãèŠç¹ã§ã以åã¯ã¹ããªãŒãã³ã°ã®ãã¬ãã¥ãŒããã°ã®å¯èŠåãå ±æã ïŒæããšãã ã 1 è¡åŒãïŒæ¡å ã¯ãã°æ ã®å€ã«æ¡ä»¶ä»ãã§çŸããŠãããããæ«å°Ÿãã `â` ã 1 åæŒããŠãäžç«¯ãåãã ïŒæ¡å è¡ã®ã¶ããã¥ãŒããŒãã 1 è¡çž®ã¿ãæ«å°Ÿã® 1 è¡ãæ¶ããã ãïŒãã¿ãŒã³ã®éå§ïŒçµäºããšã« ãã°å šäœã 1 è¡äžäžã«æºããŠããïŒ= ãäžãžã¹ã¯ããŒã«ãããšã¬ã¯ã¬ã¯ãããïŒãã¿ãŒã³ããšã« åºå ¥ãããæäœãã³ãè¡ïŒ`Ctrl+C` / åé / èªèšŒïŒãåãçç±ã§åžžã« 1 è¡ã«ããŠããã äžéšã«ã¯è¿œå æç€ºã³ã³ããŒã¶ïŒ`manager.send(id, text)`ïŒãæã€ãTab ã§å ¥åâæäœããã«ãåæ¿ãã æäœããã«ã§ m/d/x = ããŒãž/ç Žæ£/åé€ïŒ`x` ã¯è¡ããšæ¶ãã®ã§æåæã¯äžèŠ§ãžæ»ãïŒã `pendingPermission` ãããã° `PermissionDialog` ã«å§è²ãåäž `useInput` ã® state machineïŒpanel = input | actionsïŒã§ã¿ã€ãã³ã°ãšããŒæäœã®è¡çªãé²ãã èš±å¯/質ååŸ ã¡ã®éã¯ããã« 2 ãŸãŒã³ïŒ`DetailFocus` = dialog | logïŒã Tab ã§åŸåŸ©ãã `log` ãŸãŒã³ã§ã¯ ââ / PgUp / PgDn ããã°ã®ã¹ã¯ããŒã«ã«æ»ãïŒãã€ã¢ãã°ã¯ `active={false}` ã§è¡šç€ºã®ãŸãŸïŒã質åã®èæ¯ïŒäœãããããšããŠããã®ãïŒãèªãã§ããåçããããã®åºå£ã§ã 以å㯠`pending` ã®éããŒãå šéšãã€ã¢ãã°ãžå§è²ããŠããããäŒè©±ãã°ã 1 è¡ãé¡ããªãã£ãã ãŸãŒã³ãåããã®ã¯äžèŠ§ã® `ListFocus` ãšåãçç±ïŒââ ãæã察象ãäžæã«ããïŒãPromptInput/StatusFooter: presentationalãããŒåŠç㯠view ã®åäžuseInputã«éçŽïŒããžãã¯ã¯æããªãïŒãPromptInputã¯è€æ°è¡å¯Ÿå¿ïŒçŽç²ã¢ãã«ã¯core/text-buffer.tsãããŒå¯Ÿå¿ã¯ui/input.tsã®editText/resolveEnterïŒãå¹ ãè¶ ããããã¹ãã¯æãè¿ãïŒtruncate ããªãïŒ: æãè¿ãåŸã®è¡šç€ºè¡ã»ãã£ã¬ããäœçœ®ã»ã¯ãªãã¯éç®ã»éžæç¯å²ã¯ãã¹ãŠçŽç²ãªcore/composer-layout.tsïŒcomposerLayoutïŒãç®åºããæãè¿ãå¹ ã¯ Box ã®å®æž¬å€ïŒuseComposerWidthïŒãæç»ã»åœããå€å®ã»ââ ç§»åã§å ±æãããIME 察å¿ã§å®ç«¯æ«ã«ãŒãœã«ããã£ã¬ããã«éããïŒuseCursorïŒãuseComposer/ComposerïŒui/composer.tsxïŒâ å ¥åæ¬ã¯ 1 å®è£ : å ¥åæ¬ã¯ 4 ãæïŒäžèŠ§ã®æ°èŠæç€ºã» è©³çŽ°ã®è¿œå æç€ºã»/promptã®ãšãã£ã¿ã»è³ªåãã€ã¢ãã°ã®ãèªåã§å ¥åãããïŒã«ãããããããã¡ ïŒuseTextBufferRefïŒã»æãè¿ãå¹ ãšäœçœ®ã®å®æž¬ã»ãã©ãã°ç¯å²éžæïŒuseDragSelectionïŒã»ã¯ãªãã¯ã® åœããå€å®ïŒcaretIndexAtClickïŒã»ããŒå¯Ÿå¿ïŒeditText/resolveEnterïŒã®çµã¿ç«ãŠã¯ãã 1 ãæã« ç³ãã§ããã以åã¯å view ãåãéšåãåå¥ã«çµãã§ãããã仿§ãé£ãéãã質åãã€ã¢ãã°ã®èªç±èšè¿° ã ãresolveEnterãéããŠããããããã ã Shift+Enter ã§æ¹è¡ã§ããªãã»ââ ãå¹ããªãã»ãã©ãã°ã§ ã³ããŒã§ããªããç¶æ ã«ãªã£ãŠãããuseComposerã¯useInputãæããïŒ1ç»é¢ 1useInputã¯ç¶æïŒã view ã®åäžãã³ãã©ããhandleMouse(mouse) â booleanïŒæ±ã£ããïŒãšhandleKey(input, key) â submit | handled | ignoredãåŒã¶åœ¢ã«ããŠãããview åºæã®åå²ïŒäžèЧã®å ¥å å±¥æŽã詳现ã®ãã°ã¹ã¯ããŒã«ãäžèЧãã©ãŒã«ã¹æã®å°åããŒïŒã¯handleKeyã®æåã§ view ãåŠçããã<Composer>ã®èšæž¬ Box ã¯PromptInputã ããå ãïŒã³ãã³ããã¬ãããåã Box ã«å ¥ãããšå®æž¬ãã äžç«¯ããããŠã¯ãªãã¯ãå¥ã®æåã«åœããïŒã- åæç»ã¹ããããªã³ã°: SessionManager ã®éç¥ã UI åŽã§ ~100ms ã«ã¹ãããã«ããã
ã©ã³ã¢ãŒãïŒshift+tab ãã°ã«ïŒ: SessionManager.modeïŒauto | confirmïŒãå
šã»ãã·ã§ã³å
±éã§ä¿æããshift+tab ã§ cycleMode()ãmodePolicy 㯠tool å®è¡æã« mode ãèªãã®ã§ãåæ¿ã¯çšŒåäžã»ãã·ã§ã³ã«ãå³åæ ããããauto = AskUserQuestion 以å€ãèªåæ¿èªãconfirm = æ¯å allow/deny ãæ±ããïŒâ awaiting_permissionïŒäžèЧã«ãèš±å¯åŸ
ã¡ãïŒãUI 㯠useRunMode() ã§è³ŒèªããStatusFooter ã âµâµ auto mode on / âž confirm mode on ã衚瀺ã
UI æååã¯æ¥æ¬èª/è±èªãèšå®ã§åãæ¿ãããããèŠçŽã¯ .claude/rules/i18n.mdã
- ã«ã¿ãã°: å
š UI æååã¯
core/i18n.tsã®messagesïŒRecord<Lang, Messages>ïŒã«éçŽããïŒçŽç²ïŒã UI ã«ãªãã©ã«ãçŽæžããããuseMessages()ïŒui/i18n-context.tsxã® React ã³ã³ããã¹ãïŒã§åŒãã çŽé¢æ°ïŒbadgeForçïŒã¯MessagesãåŒæ°ã§åãããåçå·®ã蟌ã¿ã»è€æ°åœ¢ã¯åå®å šãªæååãã³ãã¬ãŒã颿°ã§æã€ã ïŒbanner/footerã°ã«ãŒããããã«å«ããïŒ - èšå®: 衚瀺èšèªã¯
~/.codiva/config.jsonïŒ{ "language": "ja" | "en" | "auto" }ïŒã«æ°žç¶åãã ïŒClaude Code ã®~/.claude/ãšåããŠãŒã¶ãŒã°ããŒãã«ã®æµåïŒãæ€èšŒå€æã¯core/config.tsã®toConfig()ããã¡ã€ã« I/O ã¯utils/config.tsïŒloadConfig/saveConfigïŒã - èšèªè§£æ±ºïŒ
core/i18n.tsã®resolveLangãåªå é ïŒ:CODIVA_LANGç°å¢å€æ° â èšå®ãã¡ã€ã«ã®languageïŒauto以å€ïŒâ OS ãã±ãŒã«ïŒLC_ALL/LC_MESSAGES/LANGãja*ãªãæ¥æ¬èªãä»ã¯è±èªïŒã é ç·ã¯åæã«ãŒãindex.tsxã§è¡ãã解決æžã¿ã«ã¿ãã°ãAppã®messagesprop ã«æ³šå ¥ããã - çªäºº:
MessagesåãããŒæ¬ èœãåã§æããi18n.spec.tsã ja/en ã®ããŒéåäžèŽãå®è¡æã«ãæ€èšŒããã
çŽç²ããžãã¯ã¯ coreãå¯äœçšã¯ utilsïŒåæã«ãŒããšããåé¢ããã®ãŸãŸèžè¥²ããã
- èšå®ãã¡ã€ã«æ¡åŒµ:
~/.codiva/config.jsonã«model/effort/permissionMode/maxBudgetUsd/notifications/updateCheck/mouse/followOrigin/autoPr/autoSync/autoFixCiã远å ãæ€èšŒå€æã¯core/config.tsã®toConfig()ã« éçŽããäžæ£å€ã¯éãã«æ¢å®ãžèœãšããåæã«ãŒãïŒindex.tsxïŒãSessionOptionsã«æããŠSessionManagerãžæ³šå ¥ãããfollowOrigin/autoPrã¯çåœå€ïŒæ¢å® onãfalseæç€ºã§ç¡å¹ïŒã - ã³ã¹ã衚瀺: reducer ã¯
result.total_cost_usdãstate.totalCostUsdãšããŠæ¢ã«ä¿æãUI çšã®å°åºã ãcore/cost.tsïŒtotalCostUsd()åèš /formatUsd()æŽåœ¢ïŒã«çŽç²é¢æ°ã§è¿œå ãäžèЧã¯ãããŒã«åèšã詳现ã¯åè¡ã - ãã¹ã¯ãããéç¥: çºç«å€å®ã¯çŽç²ãª
core/notify.tsã®notificationFor(prev,next,messages)ïŒç¶æ é·ç§»æã®ã¿è¿ãïŒé£ç¶æŽæ°ã§é³Žãç¶ããªãïŒãå® I/O ã¯utils/notify.tsã§ 2 çµè·¯ããã 端æ«ã«åºãããæ¹ãåªå ãã: (1) OSC éç¥ïŒbuildNotifySequenceãOSC 777 / 9 / 99 ãdetectNotifyProtocolã§äœ¿ãåãïŒâ éç¥ã端æ«ã¢ããªå矩ã«ãªãã®ã§ã¯ãªãã¯ã§ãã®ç«¯æ«ã åé¢ã«æ¥ãã(2) é察å¿ç«¯æ«ã»é TTY åãã®ãã©ãŒã«ããã¯ãšã㊠OS ã³ãã³ãïŒdarwin=osascript, linux=notify-sendãæåå㯠argv æž¡ãã§æ³šå ¥é²æ¢ïŒãmacOS ã§ (1) ãåªå ããã®ã¯osascriptã®éç¥ã Script Editor å矩ã«ãªããã¯ãªãã¯ãããšã¹ã¯ãªãããšãã£ã¿ãéã㊠ããŸãããïŒè©³çŽ°ã¯ TECH_NOTES.mdããã¹ã¯ãããéç¥ã®å®è£ ã¡ã¢ãïŒã ã©ã¡ãã missing binary çã¯æ¡ã朰ã best-effortãSessionManager.onTransitionã«é ç·ããconfig.notifications:falseã§åæã«ãŒããç¡å¹åã - ã»ãã·ã§ã³åŸ©å
: æ°žç¶ã¹ãããã·ã§ããã®åã»å€æã»æ€èšŒã¯çŽç²ãª
core/persistence.tsïŒtoPersistedSession/restoredSessionState/fromPersistedJsonïŒããã¡ã€ã« I/O ã¯utils/state-store.tsïŒ<repo>/.codiva/state.jsonãç Žææã¯ç©ºãžãã©ãŒã«ããã¯ãèµ·åæã«ååšããªã worktree ã pruneïŒãæ°žç¶å¯Ÿè±¡ã¯completed/interrupted/failedãã€sdkSessionIdãæã€ãã®ã®ã¿ ïŒå®è¡äž/å ¥ååŸ ã¡ã¯interruptedïŒresumable ã ããæªå®äºããšåããç¶æ ã«äžžãããarchived/creatingã ããã³ init åã«èœã¡ãŠ resume äžèœãªãã®ã¯é€å€ïŒã ã¡ãã»ãŒãžãã°ã¯ codiva åŽã§ã¯æ°žç¶ããªãããã ã resume ã¯ã¢ãã«åŽã³ã³ããã¹ãã埩å ããã ãã§ éå»ã¡ãã»ãŒãžãã¹ããªãŒã ã«åéåºããªããããUI ã®äŒè©±ãã°ã¯ CLI èªèº«ã®ãã©ã³ã¹ã¯ãªãã ïŒ~/.claude/projects/<munged cwd>/<sessionId>.jsonlïŒããåŸ©å æã«åæ§ç¯ãã â çŽç²å€æã¯core/transcript.tsïŒtranscriptLogEntries/transcriptProjectDirïŒããã¡ã€ã«èªã¿èŸŒã¿ã¯utils/transcript.tsãé ç·ã¯åæã«ãŒãïŒå±¥æŽ Map ãmanager.restore(persisted, histories)ãžæž¡ãïŒã 埩å ã»ãã·ã§ã³ã¯é å»¶ resumeïŒæåã®è¿œå æç€ºãŸã§ query ãç«ãŠãªãïŒãåŸ©å æã¯finishedAtãstartedAtã«ãã©ãŒã«ããã¯ããçµéæéã埩å åŸã«äŒžã³ç¶ããªãããã«ããã åäœæé㯠wall-clock ã§ã¯ãªããå®éã«åããæéãã§èšã:SessionState.activeMsïŒçޝç©ïŒãšactiveSinceïŒçŸçšŒåã»ã°ã¡ã³ãã®éå§æå»ïŒãæã¡ãrunning/creatingïŒïŒSTATUS_META.activeïŒ ã®åºéã ããç©ç®ããããŠãŒã¶ãŒæäœåŸ ã¡ïŒawaiting_*ïŒãçµç«¯ç¶æ 㯠idle ãšããŠé€å€ã ç¶æ é·ç§»ããšã®ç©ç®ã¯accrueActiveïŒçŽé¢æ°ïŒã«éçŽããå šç¶æ æ¡çšã®åäžçµè·¯Session.commitããåŒã¶ïŒreducer/SDK ç±æ¥ã®é·ç§»ãåå¥ã«è§Šããã«æžãïŒã衚瀺ã¯activeElapsedMs(state, now)ïŒçޝç©ïŒïŒçšŒåäžãªãéããŠããã»ã°ã¡ã³ãïŒãformatDurationã§æŽåœ¢ãæ°žç¶æã¯activeElapsedMsã§çšŒåäžã»ã°ã¡ã³ããç³ã¿èŸŒãã§åçµããåŸ©å æã¯activeSinceãæªèšå® ïŒidleïŒã«ããŠãªãã©ã€ã³æéãæ°ããªãã ä¿åã¯onPersistâ debounceïŒåæã«ãŒãïŒïŒçµäºæã®æçµãã©ãã·ã¥ïŒ SIGTERM/SIGHUP æã® åæãã©ãã·ã¥ïŒsaveStateSyncïŒãæžã蟌ã¿ã¯ temp â fsync â rename ã® atomic å·®ãæ¿ãã§ã éåæã®æžã蟌ã¿ã¯ãã¹ããšã«çŽååããïŒutils/state-store.tsïŒãçŽæ¥æžããšãéäžã§æ»ãã ãšãã« åãã JSON ãæ®ã£ãŠloadStateãç©ºç¶æ ãžèœã¡ã埩å ã§ããã»ãã·ã§ã³ãå šéšå€±ãã ä¿åãã snapshot ã¯æžãå§ããæç¹ã§èªãïŒpersist-controllerïŒã®ã§ãé£ãã§ããæäžã® å€ãæžã蟌ã¿ãææ°ç¶æ ãå·»ãæ»ãããšã¯ãªããstop()ã¯ä¿çäžã®èš±å¯èŠæ±ã deny ã§è§£æ±ºããŠãã忢ãã resume å ã®ãã©ã³ã¹ã¯ãªãããæªå¿çã®tool_useã§çµãããªãããã«ããïŒbest-effortïŒã
åãããçŽç²ããžãã¯=coreãå¯äœçš=utilsïŒåæã«ãŒãããèžè¥²ãç Žå£çãªç¢ºå®æäœïŒç«¶åã®è§£æ¶ã» ããŒãžã®ç¢ºå®ïŒã¯èªååãããæ€ç¥ã»è¶³å Žäœãã ããèªååããæ¹éã
- origin èªå远åŸïŒ
followOrigin, æ¢å® onïŒ:WorktreeManager.syncedStartPoint(base)ãgit fetch origin <base>ããŠorigin/<base>ã start point ãšããŠè¿ãïŒorigin ç¡ã/ãªãã©ã€ã³/ ãã©ã³ãäžåšãªãundefinedâ ããŒã«ã« HEAD ã«ãã©ãŒã«ããã¯ïŒãSessionManager.provisionãworktrees.add(slug, startPoint)ã«æž¡ããäœææã®ã¿ææ°ããåãïŒçšŒåäž worktree ãžã¯ pull ããªã ïŒæªã³ããã倿Žãšã®ç«¶åãé¿ããïŒã - PR èªååïŒ
autoPr, æ¢å® onïŒ: ã»ãã·ã§ã³ãcompletedãžé·ç§»ããã〠base ããå ã« ã³ãããæžã¿å·®åããããšãã ããworktrees.pushBranchã§ push âPrAutomation.createPrïŒgh pr create --draft --fillïŒã§ draft PR ãäœæïŒ1 ã»ãã·ã§ã³ 1 åãautoPrAttemptedã§å€éçºç«ãé²ãïŒã以érefreshPrsã® 20 ç§ããŒãªã³ã°ã§ãdraft PR ã®ãã§ãã¯ãç·ïŒPrInfo.checks=passingïŒã«ãªã£ããmarkReadyïŒgh pr readyïŒã§ ready åãããghäŸåã¯ãã¹ãŠutils/pr.tsã«éé¢ããPrAutomationãšã㊠DIïŒå€±æã¯ best-effort ã§ã»ãã·ã§ã³ã«æ³¢åãããªãïŒã - PR ã¹ããŒã¿ã¹ã®ãåãããªãããæœ°ããªãïŒGitHub ã¹ããŒã¿ã¹ãæã
æ¶ããäžå
·åã®ä¿®æ£ïŒ:
lookupPrã¯found/absent/unavailableïŒ+ çç±ïŒã® 3 å€ãè¿ããPrCoordinatorã¯unavailableã®ãšãçŽåã® PR ãä¿æãããŸãŸprLookup: 'error'ãç«ãŠãã空ã»ã«ã¯ ãPR ãç¡ããã ããæå³ãã確èªäžã¯â¯ã確èªã§ããªãã£ããšãã¯?ãåºãããã®å°ã¯ çªå·ãåãã£ãŠãããšããã°ãªãã®äœçœ®ã«åºãïŒâ¯ #12/? #12ïŒâ çªå·ã ãã裞ã§äžŠã¶ãš ãç¶æ ãç¡ãïŒå¥å šïŒããšèŠåããä»ããªããrate_limit/auth/cli㯠5 åïŒPR_LOOKUP_BACKOFF_MSïŒããŒãªã³ã°ãæ¢ããã ãã§ãã¯ç¶æ 㯠PR æ å ±ãšåãgh pr view1 åã§ååŸããïŒ--json mergeable㯠GraphQL ã¯ã©ãŒã¿æ¶è²»ãªã®ã§ãæ¯ããŒãªã³ã° 2 åæããŠããã®ã 1 åã«ïŒã - 1 ã»ãã·ã§ã³ 1 PR ãšã¯éããªãïŒ
core/pr-detect.tsïŒ: ã»ãã·ã§ã³ãèªåã§å¥ãã©ã³ããåã£ãŠgh pr createããããšãããããã©ã³ãåïŒcodiva/<slug>ïŒããã¯èŸ¿ããªãã®ã§ãgh pr createã å®è¡ãã tool_use ã®çµæã«åºã URL ããæŸã£ãŠextraPrsã«ç©ãïŒclaude-parseãtool_use.prCreateãç«ãŠãapplyAgentEventã tool_use id ãæ§ã㊠tool_result ãšçªãåãããã çªãåãã㯠provider å ±éåŽã«ããã®ã§ãä»ã®ãšãŒãžã§ã³ãã¯ãPR äœæã³ãã³ãã ã£ããããšã å ±åããã ãã§ããïŒããã°å šäœãã URL ãæŸããªãã®ã¯èª€æ€åºãé¿ãããã âgh pr listã®åºåãgh pr viewã§èŠããä»äººã® PR ãŸã§æ°ããŠããŸãã 衚瀺ã¯äžèЧã#12 +2ïŒä»£è¡š + ä»¶æ°ãåå¹ ã¯è€æ° PR ã®è¡ããããšãã ãåºããïŒãå šä»¶ã¯è©³çްãã¥ãŒã® 1 è¡ã«åºãã代衚ã¯ã»ãã·ã§ã³ãã©ã³ãã® PRïŒã¯ãªãã¯ã§éãå ã§ãããïŒããããç¡ããšã㯠æåŸã«èŠã€ãã£ãèªäœ PR ã代衚ã«ãªãã - èªäœ PR ã®ç¶æ
ã远ãïŒãã® PR èªèº«ã«åãåãããïŒ: èªäœ PR ã® head ã¯äœ¿ãæšãŠã®
feat/âŠã§ã worktree ã« checkout ãããŠããªãããšãå€ãããã©ã³ãåã§ããèããªãã£ãé ã¯ãããã PR ãabsentãšããŠçãããç¶ããçªå·ã ããåºãŠã°ãªããâ¯/?ãäžçä»ããªãã£ã ïŒãPR ã®ç¶æ³ããã€ãŸã§ã衚瀺ãããªããïŒãããŸã¯æ¢ç¥ã® PRïŒprimaryPrïŒãPrLookupOptions.knownPrã§æž¡ãããã©ã³ãåè£ãå šæ» ãããgh pr view <URL>ã§èãã 解決ã§ãã PR ã¯prã«ææ ŒãïŒreducer ãextraPrsããç³ãïŒã以éã¯æ®éã«ã°ãªããä»ãã æ¢ç¥ PR ã¯æåŸã«è©ŠãïŒã»ãã·ã§ã³ãã©ã³ãã«æ°ããåºã PR ãå€ã PR ã§äžæžãããªãïŒã çªå·ã§ã¯ãªã URL ã§æå®ããã®ãèŠç¹ã§ãPrRefããã®ãŸãŸéã¶ â PR çªå·ã¯ãªããžããªããšãªã®ã§ã ã»ãã·ã§ã³ãå¥ãªããžããªïŒgh pr create -R owner/otherïŒã«äœã£ã PR ãçªå·ã§èããš worktree åŽã® åçªå· PR ãè¿ããç¡é¢ä¿ãª PR ã®ç¶æ ãåºããã ready ã«ããããããready åãåãçç±ã§ URL æå® ïŒstate.branchã§gh pr readyãããšå¥ã® PR ãè§ŠãããïŒã éã«ããã® URL ãŸã§absentïŒ= GitHub ãããã㪠PR ã¯ç¡ãããšçããïŒãªãåç §ãæšãŠã ïŒpr_goneã€ãã³ã âprãšextraPrsã®äž¡æ¹ããé€å»ïŒãsetPr(undefined)ã¯extraPrsã è§Šããªãã®ã§ããããç¡ããšèª€æ€ç¥ãã URL ã裞ã®çªå·ãšããŠæ°žä¹ ã«æ®ãïŒç¶æ ãâ¯/?ã ä»ããªããŸãŸ = çŽããã¯ãã®çç¶ã«æ»ãïŒã確èªã§ããªãã£ãïŒunavailableïŒãšãã¯æµããªãã åç §ãèœãšããŠæ¬¡ã®extraPrã代衚ã«ç¹°ãäžãã£ããšãã¯ããã®è¡ããåçæžã¿ãã«ããªã ïŒanswered/lastFetchedãæŽæ°ããprLookup: 'loading'ïŒãä»åã®çãã¯èœãšãã PR ã« ã€ããŠã®ãã®ãªã®ã§ããã£ãã·ã¥æ±ãã«ãããšæ°ãã代衚ãé³è åãããŸã§ïŒ60ã180 ç§ïŒè£žã®çªå·ã§ åŸ ãããããæ¬¡ã® tickïŒ20 ç§ïŒã§æ°ä»£è¡šãåãåããããããŸã§ã¯â¯ãåºãã - PR ã¯ãèå¥ïŒ
pr: PrRefïŒããšãç¶æ ïŒprStatus: PrStatusïŒãã«åãããçªå·ã»URL 㯠ãã©ã³ãã«å¯ŸããŠäžå€ãªã®ã§state.jsonã«èŒãã埩å çŽåŸããã°ãªãç¡ãã®#<n>ã衚瀺ããã ç¶æ ïŒããŒãžå¯åŠã»ãã§ãã¯ã»draftïŒã¯æ°žç¶ããã埩å åŸã®æåã®ããŒãªã³ã°ïŒprPollIntervalMsã 0 ãè¿ãïŒã§åãã â ååçµäºæã®å€ãã°ãªããèŠããããããŸãçªå·ã ãåºãæ¹ãæ£ããã reducer ã¯ååãã€æ¯èŒããŠåç §ãç¶æããã®ã§ããã§ãã¯ã®é²è¡ã§state.jsonãåä¿åãããªãã - ããŒãªã³ã°ã¯ãã»ãã·ã§ã³æ° à 20 ç§ãããããïŒ
core/pr-refresh.ts/PrCoordinatorïŒ: 20 ç§ tick ã¯ã¹ã±ãžã¥ãŒã©ã§ãå®éã«ghãå©ãã®ã¯é³è åããã»ãã·ã§ã³ã ãïŒãã§ãã¯å®è¡äž 20 ç§ / æªèšç® 60 ç§ / èœã¡çãã PR 180 ç§ /mergedã»archivedã¯æ°žä¹ ã«äžèŠïŒãããã«åäž ãµã€ã¯ã«ã§ 3 件以äžãããšãã¯gh pr list1 åïŒlookupPrsïŒã«ç³ãã§çªãåãããã®ã§ã ã»ãã·ã§ã³ãå¢ãããŠã API ã³ã¹ããã»ãŒå¢ããªãã - ç«¶åæ€ç¥ïŒèªåè§£æ¶ããªãïŒ:
WorktreeManager.mergeã¯ç«¶åæã«ç«¶åãã¡ã€ã«ãåéããŠmerge --abortããäžã§MergeConflictErrorãæããïŒbase ããªãŒã¯æ±ããªãïŒãSessionManager.merge㯠ãããæããŠsession.markConflict(files)â reducer ãstatus: 'conflict'+conflictFilesãç«ãŠãã èªåè§£æ¶ã¯ããªãïŒ-X ours/theirsçã§ã³ãŒããç¡èšã«æšãŠãªãïŒãUI ã¯ãããžè¡šç€ºã®ã¿ã§ãè§£æ¶ã¯äººæãconflictã¯è©³çްãã¥ãŒã§ãçµç«¯ç¶æ æ±ãïŒå·®åã»æäœã衚瀺ïŒã§ãç Žæ£ãåããŒãžã¯äžèЧ/詳现ããå¯èœãgit mergeã®å€±æïŒç«¶åã§ã¯ãªããpre-merge-commit/commit-msgããã¯ã®æåŠã ã³ããã眲åã®å€±æãäžæ£ãª refããã£ã¹ã¯äžè¶³ãåãããã«å€±æãããMergeConflictErrorãž å€æããã®ã¯unmerged ãã¹ã 1 件以äžãããšãã ãã§ãç¡ããã°å ã®GitErrorïŒstderr ä»ãïŒã ãã®ãŸãŸæãçŽãïŒsyncBaseãšåãèŠåïŒãconflictã¯äººæã§ããæããããªãçµç«¯ãããžãªã®ã§ã ãããžäžžãããšåå ã®å¯äžã®æãããã§ãã stderr ãæšãŠãäžã§ã»ãã·ã§ã³ãè©°ãŸãããmerge --abortã¯MERGE_HEADããããšãã ãæã€ïŒindex ã«è§ŠããŠããªã倱æã« abort ãã¹ã ãã®ã¯ç¡ãïŒã
Phase 10 ã§äœã£ãæ€ç¥ïŒprStatus.mergeStatus === 'conflicting' / checks === 'failing'ïŒã¯
ã°ãªããæãã ãã§çµãã£ãŠããããããè¡åã«ç¹ããã®ããã®å±€ãæ¹é㯠Phase 10 ãšåãã§ã
codiva èªèº«ã決å®çã«ã§ããããšã¯ codiva ãããïŒç¡èª²éïŒã倿ãèŠããšããã ãã»ãã·ã§ã³ãžæž¡ãã
-
å€å®ã¯çŽç²ïŒ
core/pr-recovery.tsïŒã2 段ã«åãããŠããã®ãèŠç¹:-
prStuckKind(state)⊠PR ã ããèŠãè©°ãŸãæ¹ïŒsync= ç«¶å /ci= èµ€ããã§ãã¯ïŒã ç«¶åã CI ããåªå ããïŒããŒã¹ãåã蟌ãã°ãã§ãã¯ã¯åãçŽãã®ã§ãå ã« CI ãçŽããŠãç¡é§ïŒã -
recoveryKindFor(state)⊠äžã«ãã»ãã·ã§ã³ãæãæ¢ããŠãããïŒisTerminalStatusãã€archivedã§ãªãïŒãæãããã®ãèµ°è¡äžã«æç€ºãå²ã蟌ãŸããŠãããã®ã¿ãŒã³ã®äœæ¥ãšç«¶åããã ãã -
stuckKinds(state)⊠該åœããè©°ãŸãæ¹ãå šéšïŒç«¶åãš CI 倱æã¯åæã«èµ·ããïŒã -
prRecovered(state)⊠PR ã確ãã«å¥å šã«ãªã£ããïŒç· or ããŒãžæžã¿ïŒã
çµãã£ã PR ã¯è©°ãŸã£ãŠããªãã
mergeStatus === 'merged'ãš'closed'ïŒããŒãžãããã« ã¯ããŒãºïŒã¯ã©ã¡ããstuckKindsã空ãè¿ããéãã PR ãç«¶åãšåãã«æ±ããšãautoSyncã 誰ãåãèŸŒãæ°ã®ç¡ããã©ã³ãã«ããŒã¹ãåã蟌ãã§ push ããautoFixCiãèµ€ããã§ãã¯ã®ä¿®æ£ã 1 ã¿ãŒã³èª²éããŠäŸé ŒããŠããŸããéããã®ã¯äººéã®å€æãªã®ã§ãcodiva ããã¯äœãææ¡ããªã ïŒåéããããã° GitHub ã§ reopen ãã â æ¬¡ã®ããŒãªã³ã°ã§éåžžã®ç¶æ ã«æ»ãïŒã 衚瀺ãå°çšã°ãªãïŒâã»ç³ãã ç°è²ïŒã«ããŠãèµ€ãâïŒ= çŽãïŒãšæ··åãããªããåããã®ã¯èªååã®è©Šè¡åæ°ãæ£ããæ°ãããããçŽ æŽã«ãè©°ãŸã£ãŠããªããªããªã»ããããš ãããš 2 段éã§å£ãã:
- ãä»ã¯èµ°ã£ãŠãããã察象å€ããšãããè©°ãŸã£ãŠããªãããåã颿°ã§è¡šããšãæç€ºãéã£ã çŽåŸïŒ= èµ°è¡äžïŒã«ãªã»ããããã â å®äº â ãŸã èµ€ã â ãŸãéããã®ç¡éã«ãŒãã
- ãããçŽããŠããpush çŽåŸã® PR ã¯å¿
ã
checks: 'pending'/mergeStatus: 'unknown'ã çµç±ããïŒ= è©°ãŸã£ãŠã¯ããªãïŒã®ã§ãããã§ãªã»ããããã â èµ€ã â äŸé Œ â pending â èµ€ããã§äžéãç¡æå³ã«ãªããå®éã«å€ãã®ã¯ãäŸé ŒãããçŽããªãã£ããã»ããªã®ã§ãããã å¡ããªããšæå³ãç¡ãã
ãªã®ã§è¿éã¯
prRecoveredïŒç·ãèŠãïŒãšãã ãã詊ããã©ããã¯recoveryKindForã ã©ã®çš®é¡ã詊ããã¯stuckKindsãæå¹ãªãã©ã°ãšçªãåãããŠå é ããéžã¶ïŒautoFixCiã ãæå¹ãªäººã®ãç«¶åããŠããŠããã€èµ€ããPR ã§ãåªå 床 1 äœã®syncãç¡å¹ã ãã㚠諊ããŠããŸããªãããã«ïŒã -
-
åã蟌ã¿ã¯
WorktreeManager.syncBase(wt, base)ïŒutilsïŒãmerge()ãšåãã cwd ãéã§ã worktree ã®äžã§origin/<base>ïŒfetch 倱ææã¯ããŒã«ã«<base>ïŒãåã蟌ããè¿ãå€ã¯SyncBaseResultã® 4 å€ã§ãæããªã:çµæ æå³ æ¬¡ã®æ upToDateæ¢ã«ããŒã¹ãå«ã äœãããªã updatedã¯ãªãŒã³ã«ããŒãžã§ãã pushBranchããŠçµããïŒã»ãã·ã§ã³ãèµ·ãããªãïŒdirtyæªã³ããã倿Žãããã®ã§ããŒãžããŠããªã äœæ¥ã®æã¡äž»ïŒã»ãã·ã§ã³ïŒã«ãŸãšããŠä»»ãã conflictç«¶åãã merge --abortããç«¶åãæ®ã â ã»ãã·ã§ã³ã«è§£æ±ºãããmerge()ã abort ããã®ã¯å ±æãããããŒã¹ããªãŒãæ±ããªãããã§ãsyncBaseã® worktree 㯠1 ã»ãã·ã§ã³å°çšã ããæ®ãã»ããçŽãããã©ã¡ãã-X oursçžåœã®èªåè§£æ¶ã¯ããªãïŒèŠçŽïŒã 现ãããå¹ã倿ã 3 ã€:- æªè¿œè·¡ãã¡ã€ã«ã¯
dirtyã«ããªãïŒ--untracked-files=noïŒãgit mergeã¯æªè¿œè·¡ãã¡ã€ã«ã ãã£ãŠãæ®éã«éãã®ã§ããšãŒãžã§ã³ãã®èµ°ãæžã 1 åã§ç¡èª²éã®çµè·¯ãæšãŠãŠã¿ãŒã³ã䜿ãã®ã¯æã - æ¢ã« merge éäžïŒ
MERGE_HEADããïŒãªãconflictãè¿ããdirty å€å®ã«èœãšããš ãã³ãããã stash ããŠããåã蟌ãããšããå®è¡äžèœãªæç€ºãéã£ãŠããŸãã - detached HEAD ã¯æåŠãããããŒãžã³ããã㯠HEAD ã«èŒãããã©ã³ã ref ã¯åããªãã®ã§ã push 㯠no-opãPR ã¯è©°ãŸã£ããŸãŸããªã®ã«ãåã蟌ãã§ push ããŸããããšå ±åããŠããŸãã
- æªè¿œè·¡ãã¡ã€ã«ã¯
-
CI ä¿®æ£ã¯è¿œå ã® API ã䜿ããªãã
gh pr view --json âŠstatusCheckRollupã® payload ãã èœã¡ããã§ãã¯åãšdetailsUrlãæŸãïŒutils/pr.tsã®toFailingChecksâPrStatus.failingChecksãMAX_FAILING_CHECKSä»¶ã§æã¡åãïŒããã°ã®ååŸïŒgh run view --log-failedïŒãšä¿®æ£ã¯ã»ãã·ã§ã³ãè¡ããfailingChecksã¯checks === 'failing'ã®ãšãã ãèŒããreducer ã¯å 容æ¯èŒãã ïŒæ¯ããŒãªã³ã°æ°ããé åã«ãªãã®ã§åç §æ¯èŒã ãšå¿ ããå€ãã£ããããšã«ãªããprStatusã® åç §ç¶æãå£ããïŒã -
å®è¡ã¯
SessionManager.recover(id, kind?)ïŒgit ãšsendã®äž¡æ¹ãè§Šããå¯äžã®å±€ïŒãkindçç¥æã¯recoveryKindForãæ±ºããæç€ºãããš/sync//fix-ciãšããŠããŒãªã³ã°åã§ãå¹ãã ã»ãã·ã§ã³ãžéãæç€ºæã¯ i18n ã«ã¿ãã°ïŒm.recover.*ïŒããåŒã â ãã°ã«ãŠãŒã¶ãŒçºè©±ãšã㊠æ®ãã®ã§resume.instructionãšåãæ±ãïŒmessagesæªæ³šå ¥ãªãrecover㯠no-opïŒã -
èªååã¯
PrCoordinatorãããã€ãã ããæ±ºãããautoSync/autoFixCiïŒæ¢å® offã äŸé Œãçºçããæç¹ã§ã¿ãŒã³ãåã = 課éïŒã§æå¹åããå®è¡ã¯ DI ãããrecoverãåŒã¶ã 1 ã»ãã·ã§ã³ã»1 çš®é¡ãããMAX_AUTO_RECOVERY_ATTEMPTSïŒ2ïŒåã§æã¡åã â ããªã¬ãŒã ã€ãã³ãã§ã¯ãªãç¶æ ãªã®ã§ããäŸé Œããã®ã« push ãããªãããšæ¯ããŒãªã³ã°æãç¶ããŠããŸãã -
UI ã¯å ±æããã¯
useRecoveryïŒui/hooks.tsïŒãäžèЧã¯/syncã»/fix-ciïŒéžæè¡ïŒãšCtrl+F=/recoverïŒå šä»¶ãy/n確èªïŒã詳现ã¯/syncã»/fix-ciïŒãã®ã»ãã·ã§ã³ïŒãCtrl+Fããã©ãŒã«ã¹æšªæã® chord ã«ããã®ã¯Ctrl+R/Ctrl+Aãšåãçç±ãäžæ¬ã¯ 鿬¡å®è¡ããïŒåäžãªããžããªã® worktree 矀ãªã®ã§ git ã® index/ref ããã¯ã§æœ°ãåãïŒãrecovery.busyããå šããŒã飲ããbusyã«æ··ããªããäžæ¬ã¯ N ä»¶ã¶ãã® git ãçŽåã« åãã®ã§æ°åã«åã³ãããå šããŒã飲ããš Ctrl+C ãæŸããªãïŒexitOnCtrlC: falseïŒãã® TUI ã§ã¯/exitããæãŠãæäœäžèœã«ãªãïŒ/updateã® installing ã§èžãã çœ ãšåãïŒã å¡ãã®ã¯ãããäžåºŠç«ãŠçŽããå§ãããå ¥å£ã ãã«ããŠãå®è¡äžã¯ç¬ç«ããè¡ã§ç¥ãããã- äžæ¬ã®çµæã¯å®éã«æåããä»¶æ°ã§å ±åãããå
šéšå€±æïŒ
ghæªèªèšŒãªã©ïŒããã®ã« ãN ä»¶ãå®è¡ããŸããããšç·ã§åºããªã â æåã®ãšã©ãŒã¯ãšã©ãŒæ¬ãžåãã
-
worktree ã«è§Šãã®ã¯ã»ãã·ã§ã³ãæãæ¢ããŠãããšãã ãããã®éã¯
recoveryKindForã§ã¯ ãªãSessionManager.recoveråŽã«ãã â æç€ºkindãæž¡ã/sync//fix-ciã«ãå¹ããã å¿ èŠãããããïŒClaude ãç·šéäžã® worktree ã§git mergeãåããšæžã蟌ã¿ãšç«¶åããïŒã 匟ãããšãã¯{ kind: 'busy' }ãè¿ããŠãäœæ¥äžã§ãããšåºãã
codiva ã¯äžŠåã»ãã·ã§ã³ã§å€§éã®ã³ãŒãã Claude ãžæµããããclaude.ai ã®ãHelp improve our AI modelsã ïŒ= ã¢ãã«åŠç¿ãžã®ããŒã¿æäŸãAnthropic å éšå groveïŒã ON ã®ãŸãŸæ°ä»ããã«äœ¿ãç¶ããã®ãé²ãã èŠåããã ãã§ãcodiva åŽã®æåã¯å€ããªãïŒåæã«ç¡å¹åã¯ããªã = ãŠãŒã¶ãŒã®ã¢ã«ãŠã³ãèšå®ã ã¢ããªãæžãæããªãïŒã
- å€å®ã¯ 2 段æ§ãïŒ
utils/privacy.tsã®fetchTrainingOptInãå®ãã»ããã詊ãïŒ: 0. èªèšŒæ¹åŒã®éçª: API ã㌠/ Bedrock / Vertex / ç¬èªANTHROPIC_BASE_URLã®ãšã㯠claude.ai ã® èšå®ãšç¡é¢ä¿ïŒã〠API å©çšã¯åŠç¿å¯Ÿè±¡å€ïŒãªã®ã§ããã£ãã·ã¥ãèªãŸãã«'unknown'ã éå»ã« claude.ai ãžãã°ã€ã³ããæ®éªžã§èª€èŠåããªãããããã®éçªãæåã«æ¥ãã~/.claude.jsonã®groveConfigCache[accountUuid]ïŒClaude Code ãæžããã£ãã·ã¥ããããã¯ãŒã¯ã èªèšŒæ å ±ãäžèŠã7 æ¥ããå€ãå€ã¯äœ¿ããªãïŒãããŒã¯oauthAccount.accountUuidãšäžèŽããã ã¢ã«ãŠã³ããèªããªããšãã«éãåäžãšã³ããªãæµçšããïŒåæ¿åŸã«åã¢ã«ãŠã³ãã®å€ã䜿ããªãïŒãGET https://api.anthropic.com/api/claude_code_groveïŒKeychainClaude Code-credentialsïŒmacOSïŒ ãŸãã¯~/.claude/.credentials.jsonã® OAuth ããŒã¯ã³ã䜿ãïŒã
- ãã£ãã·ã¥ã®ä¿¡é Œã¯é察称:
'off'ã¯ãã®ãŸãŸæ¡çšããŠããã§çµããïŒå®ãïŒãã'on'ã¯å¿ ã åãåããã§ç¢ºèªãããclaude.ai åŽã§ OFF ã«ããŠããã®ãã£ãã·ã¥ã¯æžãæãããªãããã ä¿¡çšãããšãèšãããéãåã£ãã®ã«èŠåãåºç¶ãããããšã«ãªãã確èªãåããªãã£ããšãã ã ãã£ãã·ã¥ã®'on'ã«æ®ã眮ãã - å€å®ã¯
'on' | 'off' | 'unknown'ïŒcore/privacy.tsïŒãèŠåã¯'on'ãšç¢ºå®ãããšãã ãåºãã ã¬ã¹ãã³ã¹ã®domain_excluded === trueïŒæå³ã¯æªæ€èšŒïŒã'unknown'ã«åãã - èµ·åããããã¯ããªã / çµäºãæ¢ããªã: åæã«ãŒãïŒ
index.tsxïŒã render åã«æããuseTrainingOptInã解決ããããããŒã«æ³šæè¡ãå¢ãããçµäºæã¯AbortControllerã§æã¡åããsecurityïŒKeychainïŒåŒã³åºãã«ã¯signalãštimeoutïŒ2 ç§ïŒãå¿ ãæž¡ã â çããåããã»ã¹ã ã€ãã³ãã«ãŒããæŽããšãçµäºããŠãã·ã§ã«ã®ããã³ãããè¿ããªããªããabort æžã¿ã·ã°ãã«ã§ã¯addEventListener('abort')ãçºç«ããªãã®ã§ãåãåããåã«signal.abortedãå æãã§ãã¯ããã - 倱æã¯ãã¹ãŠ
'unknown'ïŒéå ¬éãšã³ããã€ã³ããªã®ã§ä»æ§å€æŽã§å£ããããå£ãããšã㯠ãé»ãã= 誀ã£ãèŠåãåºããªãïŒãèšå®privacyWarning: falseã§å€å®èªäœãèµ°ãããªãã - æãã®ã¯
bannerLinesã®è¡ã§ã¯ãªãããã®å€ã®PrivacySectionããããã®ãã©ãã°éžæã¯bannerText(lines)ãžã® caret index ã§ãåœããå€å®ããè¡ index = 衚瀺è¡ããåæã«ããŠãã ïŒcore/banner-lines.tsã®bannerCaretAtïŒãèŠåã¯ã³ããŒå¯Ÿè±¡ã§ã¯ãªãããâã¯theme.tsã æã€èšå·ãªã®ã§ãéžæå¯èœãªããã¹ãå¡ïŒtextRefã® BoxïŒã®å€ã«çœ®ããŠè¡æ§æãæºãããªãã
ãšã³ããã€ã³ãã®å®æž¬ïŒUser-Agent èŠä»¶ãªã©ïŒã¯ TECH_NOTES.md ãåç §ã
npm é ä¿¡ãããèªåèªèº«ã®æŽæ°ãæ€ç¥ããŠç¥ãããå®å šã«ç¢ºå®ã§ããçµè·¯ã®ãšãã ãé©çšããã ãæ€ç¥ã¯èªåãç¢ºå®æäœã¯äººæããšãã PR èªååãšåãæ¹éã
- çŽç²ããžãã¯ïŒ
core/update.tsïŒ: semver ã® precedence æ¯èŒïŒcompareVersions/isUpdateAvailableãprerelease èŠåãŸã§å®è£ ïŒãçµæ unionïŒUpdateCheck=available/up-to-date/unavailableïŒãžã®å€æïŒresolveUpdateCheckïŒãã€ã³ã¹ããŒã«çµè·¯ ïŒInstallKind=global/local/npx/unknownïŒããæŽæ°ã³ãã³ããçµãupdateCommandForïŒargv é åã§è¿ãïŒ/updateCommandLineãèªå·±æŽæ°ã®å¯åŠcanSelfUpdateã DI å¢çUpdateServiceïŒinitial/check()/install()ïŒãšãã€ã¢ãã°ç¶æ UpdateViewStateãããã - I/OïŒ
utils/update.tsïŒ:fetchLatestVersionãhttps://registry.npmjs.org/<pkg>/latestã 1 åã ãåŒãïŒå š packument 21KB ã§ã¯ãªã 2.3KBãèªèšŒäžèŠã3 ç§ã§ã¿ã€ã ã¢ãŠãã throw ããªãã ã¿ã€ããŒã¯ unrefãå€éšAbortSignalã§ãæã¡åããïŒãinstallKindForã¯packageRoot/execPath/cwd/platformãåŒæ°ã§åãããã¹æ¯èŒã®ã¿ïŒnotifyCommand(spec, platform)ãšåãæ¹éã§ãã¹ãå¯èœïŒãrunUpdateãexecFileïŒã·ã§ã«ãªãïŒã§npm installãå®è¡ãã倱æã¯ stderr ã®æçµè¡ãok: falseã§è¿ããcreateUpdateServiceãããããæããã - çµè·¯å€å®ã®å®å
šåŽ: npx / dlx / bunx ã®ãã£ãã·ã¥ïŒãã¹èŠçŽ ã®å®å
šäžèŽã§å€å®ãéšåäžèŽã ãš
bunx-toolsã®ãããªç¡é¢ä¿ãªãã£ã¬ã¯ããªã誀æ€åºããïŒã¯npxãvolta / asdf é äžã»Windowsã» ãã以å€ã®å€å¥äžèœã¯unknownãå®è¡ããã®ã¯globalã ãïŒcanSelfUpdateïŒã§ãunknown/local/npxã¯å®è¡ãã¹ãã³ãã³ãã®æç€ºã«çãããéçå€å®ãunknownã®ãšãã ãnpm root -gã 1 æ¬èµ·ãããŠglobalãžæ ŒäžãããïŒhomebrew ã® Cellarã»npm config set prefixã» pnpm/yarn global ãæŸããããæšæºçãªé 眮ã§ã¯ãµãããã»ã¹ 0 æ¬ïŒãnpm install -gã® cwd 㯠ããŒã ã«åºå®ããïŒå¯Ÿè±¡ãªããžããªã®.npmrcã«å®å ãæžãæããããªãããïŒã - é
ç·: åæã«ãŒãïŒ
index.tsxïŒãèµ·åæã«createUpdateServiceãäœããawait ããã«initialãæããïŒmodelCatalogãšåãæ±ããçµäºæã«updateAbort.abort()ïŒãAppã¯useUpdateCheck(updater?.initial)ã§ state ã«è§£æ±ºããavailableã®ãšãã ãbannerLinesã®updateLatestãžæž¡ãïŒææ°ã»æªç¢ºèªã§ã¯ãããã«è¡ãå¢ãããªãïŒã ãããã®æåçµã¿ã¯çŽç²ãªcore/banner-lines.tsãè²ã¯accentããŒã³ âui/theme.tsã®theme.accentïŒ.tsxã«çã®è²åãæžããªãïŒã/updateã¯useCommandRunnerã®updateãã³ãã© â æ¯åcheck()ãçŽããUpdateDialogãåºãã - ããŒåŠç:
UpdateDialog㯠presentational ã§useInputãæããªããããŒã¯äžèЧãã¥ãŒã® åäžãã³ãã©ãconfirm/confirmResumeAllãšåãäœçœ®ã§åŠçããïŒæŽæ°å¯èœãªã y/nã ãã以å€ã¯ä»»æããŒã§éããïŒãéåæã®æ±ºçã¯äžä»£ã«ãŠã³ã¿ã§ç¡å¹åããéããåŸã»éãçŽãã åŸã« stale ãªçµæã§ãã€ã¢ãã°ãèããªãããã«ããã - ã¢ãŒãã«ã®çžäºæä»ã¯å¿
é :
PermissionDialogã¯èªåã®useInputãæã¡ãInk 㯠1 ã€ã®å ¥å ãã£ã³ã¯ãããŠã³ãäžã®å šãã³ãã©ãžé ããåæã«åºãŠãããšæŽæ°ç¢ºèªã®yãæªèªã®ããŒã«å®è¡ã® èš±å¯ãå ŒããŠããŸãïŒãã®ãã¥ãŒãããŒã飲ãã§ãçžæã¯ç¬ç«ã«åå¿ããïŒãpendingã®å°åºã«!updateãå ¥ããŠæ§é çã«çŠããããã«ã¢ãŒãã«äžã¯ããŠã¹ã¬ããŒãã飲ã ïŒã¯ãªãã¯ã§focusã list ã«ç§»ããšèš±å¯ãã€ã¢ãã°ãç«ã€çµè·¯ãå¡ãïŒã - å®è¡äžã«æäœäžèœã«ããªã:
installingäžã Esc ã¯éããcodiva 㯠Ctrl+C ãæŸãã ïŒexitOnCtrlC: falseïŒçµäºã¯/exitã ããªã®ã§ãå šããŒã飲ããšnpm installãçµãããŸã§ æé·INSTALL_TIMEOUT_MSã®ããã äœãã§ããªããªããEsc ã¯ãã€ã¢ãã°ãéããã ãã§ npm ã¯ç¶è¡ããã - èšå®:
updateCheckïŒæ¢å® onïŒãfalseã§èµ·åæã®éä¿¡ãå®å šã«æ¢ããïŒ/updateã¯unavailableãè¿ãã ãã«ãªãïŒã
TUI 㯠alt screen + ããŠã¹ã¬ããŒãïŒ?1002/?1006ïŒã§åããããç°åžžçµäºã¯ 2 ã€ã®è¢«å®³ãåæã«åºãã
- 端æ«ãå£ãããŸãŸæ®ããããŠã¹ææãæå¹ãªãŸãŸã ãšã¹ã¯ããŒã«ã®ãã³ã«ç«¯æ«ã
\x1b[<64;âŠMãéããã·ã§ã«ã«ã¯å€§éã®æåãå ¥åãããããã«èŠããã - çç±ãæ®ããªããäŸå€ã®ã¹ã¿ãã¯ã¯ stderr ãžåºãããalt screen ãæããç¬éã«ç»é¢ããšæ¶ãã ïŒãŠãŒã¶ãŒã«ã¯ãçªç¶ã¿ãŒããã«ã«æ»ã£ãããšããèŠããªãïŒã
察ç㯠3 å±€ãã©ã®å±€ãä»ã®å±€ã®ä»£ããã«ã¯ãªããªãïŒäžã«è¡ãã»ã©åŒ·ãæ»ã«æ¹ã«å¯Ÿå¿ããïŒã
| å±€ | å®è£ | å¹ãæ»ã«æ¹ |
|---|---|---|
teardownïŒtoggleEscape ã® process.on('exit') + setupTerminal().teardownïŒ |
utils/alt-screen.ts / utils/mouse.ts / utils/terminal-mode.ts |
æ£åžžçµäºã»process.exitã»ææã§ããäŸå€ |
| ã¯ã©ãã·ã¥ãã³ãã© | bootstrap/crash-handler.ts |
uncaughtException / unhandledRejection |
èµ·åæã®èªå修埩 + --reset-terminal |
setupTerminal() åé ã® disableMouseReports() / core/cli.ts |
匷å¶çµäºïŒOOM ã® abortã»SIGKILLã»segfaultãJS ãäžåèµ°ããªãïŒ |
- ã¯ã©ãã·ã¥ãã³ãã©ã®é åºã¯ 端æ«åŸ©å
â ç¶æ
flush â ã¬ããŒãçµã¿ç«ãŠ â éåžžãããã¡ãžåºå â
ãã°æžãåºã â
exit(1)ã端æ«ãå ã«æ»ãã®ã¯ã以éã®åºåãã¹ã¯ããŒã«ããã¯ã«æ®ãããã - ãã°ã¯
~/.codiva/logs/crash-<ISOæå»>-<pid>.logïŒ20 ä»¶ã§ããŒããŒã·ã§ã³ïŒãæžã蟌ã¿ã¯ åæïŒçŽåŸã« process ãæ¶ããã®ã§éåæã§ã¯éã«åããªãïŒãæŽåœ¢ã»ãã¡ã€ã«åã» ããŒããŒã·ã§ã³å€å®ã¯çŽç²ãªcore/crash.tsãI/O ã¯utils/crash-log.tsã - 蚺ææ
å ±ã«ã¡ã¢ãªäœ¿çšéãšã»ãã·ã§ã³ã®ã¹ããŒã¿ã¹å
èš³ãå«ããã1 ã»ãã·ã§ã³ =
claudeãµãããã»ã¹ 1 æ¬ïŒæå€§ ~1GiBïŒãªã®ã§ãOOM 仮説ã®è£åãã«ã¯ãã® 2 ã€ãèŠãã - V8 ã®ããŒãæ¯æžã¯ JS ãã³ãã©ã§æŸããªãïŒabort ã§å³æ»ããïŒããã®çµè·¯ã ã㯠Node ã®
蚺æã¬ããŒãïŒ
process.report.reportOnFatalErrorïŒã«ä»»ããreport.*.jsonãåã~/.codiva/logs/ãžåºããreportOnSignal/reportOnUncaughtExceptionã¯èªåãã³ãã©ãš äºéã«ãªãã®ã§ offã - ã·ã°ãã«ïŒSIGTERM / SIGHUPïŒã§æ®ºãããå Žåã
kind: signalã§èšé²ããããèœã¡ãããš ãkill ãããïŒç«¯æ«ãéããçïŒããåŸããåãåããããã - èšå®
crashLog: falseã§ãã¡ã€ã«åºåïŒèªåã¬ããŒã + 蚺æã¬ããŒãïŒãæ¢ããããã çç±ã®è¡šç€ºãšç«¯æ«ã®åŸ©å ã¯èšå®ã«é¢ä¿ãªãè¡ãã
å®éã« FATAL ERROR: Ineffective mark-compacts near heap limit ã§èœã¡ããåå ã¯
ãä¿æãããããšã確ä¿ããããã® 2 ã€ã§ã察çã 2 ã€ã«åãããã
| åé¡ | 察ç | å Žæ |
|---|---|---|
SessionState.messages ãç¡å¶éã«äŒžã³ã远èšããšã«å
šäœã³ããŒïŒO(n²)ïŒ |
ä»¶æ° MAX_LOG_ENTRIES ãšåèšæåæ° MAX_LOG_CHARSïŒå
ã«çžãããæ¹ã§å€ãæ¹ããèœãšãïŒ+ 1 ä»¶ããã MAX_LOG_ENTRY_CHARSïŒâŠ ãä»ããŠåãïŒ |
core/log-buffer.ts ã® pushLogEntry |
| 詳现ãã¥ãŒãæŽæ°ããšã«ãã°å šäœãæãè¿ã + Markdown åããŒã¹ | ãšã³ããªåäœã®ã¡ã¢åïŒå¹
ãšãã¬ãã£ãã¯ã¹ãåããªãåå©çšïŒ+ ä¿æè¡æ°ã®äžé MAX_CACHED_ROWSïŒLRUïŒ |
core/scroll.ts ã® logLines |
ããŒã«çµæã®å·šå€§ãã€ããŒãïŒ10MB ã® Read / BashïŒãå¹³åŠå â å
šè¡ split |
èªã 200 æåã ãæè³ªåïŒasStringHeadïŒãtool_use ã®å
¥åïŒBash ã® heredoc çïŒãå
ã«åã |
core/claude-parse.ts |
streamingText ã« 1 ã¡ãã»ãŒãžå
šäœãæºããæ¯ãã¬ãŒã å
šäœã split |
æ«å°Ÿ MAX_STREAM_PREVIEW_CHARS ã ãä¿æïŒæãã®ã¯æåŸã® 1 è¡ïŒ |
core/log-buffer.ts ã® clipStreamText |
| åŸ©å æã«å šã»ãã·ã§ã³ã®ãã©ã³ã¹ã¯ãªããïŒåæ° MBïŒãåæèªã¿èŸŒã¿ | 1 æ¬ãã€èªãïŒå€æåŸããååãããïŒ+ èªã¿ãªããç³ãïŒHistoryïŒ+ capLogEntries |
bootstrap/restore-sessions.ts / core/transcript.ts |
åæãšã㊠**ãã°ã¯äŒè©±ã®ãèšé²ãã§ã¯ãªãã衚瀺ã**ã§ãããæ£æ¬ã¯ CLI ã®ãã©ã³ã¹ã¯ãªãã
ïŒ~/.claude/projects/âŠã埩å
㯠core/transcript.tsïŒãªã®ã§ãå€ãè¡ãèœãšããŠãèªã¿è¿ãææ®µã¯æ®ãã
ä»¶æ°ã ãã§ã¯äœãçžããªãïŒ1 件㯠1 æåã§ã MAX_LOG_ENTRY_CHARS ã§ãããã®ã§ãä»¶æ° Ã 1 ä»¶äžé
= 4000 äžæåïŒãæç»ã³ã¹ãã¯æåæ°ã«æ¯äŸãããããå±éåŸã®è¡ïŒDisplayLine + ã¹ãã³ïŒã¯å
ããã¹ãã®
æ°åãå ããã®ã§ãæåæ°ã®äºç®ãšãã£ãã·ã¥ã®è¡æ°ã®äºç®ã® 2 ã€ãå®éã®äžéã«ãªã£ãŠããã
MAX_CACHED_ROWS 㯠soft budget ã§ãæç»äžã®ãã°ã®è¡ã¯è¿œãåºããªãïŒèªåãæ¬¡ã«äœ¿ãè¡ãæšãŠãŠ
æ¯ãã¬ãŒã åå±éããã®ãé¿ããããïŒããããã£ãŠä¿æéã®å®å¹äžéã¯
ãéããŠãããã° 1 æ¬ïŒMAX_LOG_CHARS ã§çžãããïŒ+ MAX_CACHED_ROWSãã
äžå€æ¡ä»¶:
- 远èšã®çµè·¯ã¯
pushLogEntryã ãã[...state.messages, entry]ãæ°ããæžããªã ïŒappendLogãšapplyAgentEventã®è¿œèšã¯ãã¹ãŠãããéããäŸå€ã¯noticeã® coalesce = æžãæã = æ«å°Ÿ 1 ä»¶ã®å·®ãæ¿ãã§ãä»¶æ°ãå¢ãããªãã®ã§äžéã«é¢ä¿ããªãïŒã seqã¯æ¯ãçŽããªããæç»ããŒã<seq>:<è¡>ãªã®ã§ãããªã ããŠãæ¢åè¡ã®ããŒã¯å€ãããªã ïŒ= React ã®åããŠã³ããèµ·ããªãïŒããã ãåŸè¿°ã®ãšããè¡ index ã¯å€ãããlogLinesã®è¿ãè¡ã¯ read-onlyãã¡ã¢åã§è€æ°ãã¬ãŒã ã«å ±æãããããã åŒã³åºãåŽã§æžãæããªãïŒselectionSlicesã®ããã«å¿ ãæ°ããé åãäœãïŒã
æ¢ç¥ã®ãã¬ãŒããªã: ã¹ã¯ããŒã«äœçœ®ïŒScrollAnchor ã®æ°å€ïŒãšéžæäœçœ®ïŒLogPointïŒã¯
ææžå
é ããã®è¡šç€ºè¡ index ãªã®ã§ãäžéã«éãããã°ãå€ãè¡ãèœãšããšãã®åã ãæå³ããºã¬ã
ïŒäžãžã¹ã¯ããŒã«ããŠèªãã§ããæäžã«æ°ããè¡ãæ¥ããšããã¥ãŒãèœã¡ãè¡æ°ã¶ãæ°ããæ¹ãžåãïŒã
èµ·ããã®ã¯ãäžéã«éããããã€ãã¹ã¯ããŒã«äžããã€ã远èšãç¶ããŠãããã®åææç«æã ãã§ã
èœã¡ãïŒ= å
šéšèªããªããªãïŒããã¯è»œãå¯äœçšãšããŠåãå
¥ããŠããããã ãéžæã¯æšãŠã
ïŒSessionDetail ãå
é ãšã³ããªã® seq ã®å€åãæ€ç¥ããŠã¯ãªã¢ããïŒâ è§Šã£ãŠããªãè¡ãã³ããŒããã
ã®ã¯å¯äœçšãšããŠéããããããçŽããªãè¡ index ã§ã¯ãªã DisplayLine.keyïŒ<seq>:<è¡>ã
ããªã ã§ã远èšã§ãäžå€ïŒãåºæºã«ããå¿
èŠãããã
äžã®ããã°ã®ã¡ã¢ãªäžéããå
¥ããåŸãããŠãŒã¶ãŒç°å¢ã§åã³ OOM ã§ 3 åèœã¡ã
ïŒ~/.codiva/logs/report.*.json = Node ã®èšºæã¬ããŒããold_space ã 4.2GB ã§
large_object_space 㯠55MB ã ã = å°ãããªããžã§ã¯ãã倧éã«çåïŒãååãšã¯å¥ã®åå ã§ã
ä»åã¯ã確ä¿ããããã§ã¯ãªãçŽç²ãªä¿ææŒãã ã£ãã
ããŒãã¹ãããã·ã§ããã®äžäœã¯ PerformanceMeasure à 60,003ïŒ= 20,000 æç» à 3ïŒãš
Components â / Changed Props / Scheduler â ãšãã£ãæååã ã£ããæ£äœã¯
React 19.2 ã® Performance TracksïŒæ¢å ±:
ink#869 /
facebook/react#35761ã
ã©ã¡ãããNode ã® performance ãããã¡ãååãããªããããšãçµè«ã§ã察çã NODE_ENV=productionã
codiva ã§ã¯èšºæã¬ããŒãããç¬ç«ã«åãçµè«ã«è³ã£ãïŒ:
react-reconciler㯠dev ãã«ãã®ã¢ãžã¥ãŒã«è©äŸ¡æã«supportsUserTimingïŒconsole.timeStampãšperformance.measureããããïŒã確å®ããã Node ã«ã¯äž¡æ¹ããã®ã§å¿ ãæå¹ã«ãªãã- 以åŸã¬ã³ããŒããšã«
performance.measure()ã 3 æ¬ç©ããNode ã® user timing 㯠åŒãã åŽãæšãŠããŸã§ä¿æããç¶ããïŒãã©ãŠã¶ã® devtools ãæ¶è²»ããåæã® API ãªã®ã§ã é·æéåã Node ããã»ã¹ã§ã¯åçŽãªãªãŒã¯ã«ãªãïŒã dist/index.jsã¯binããnodeã§çŽã«èµ·åããNODE_ENVã¯æªèšå® = å©çšè ã¯å¿ ã dev ãã«ãã ã£ãã
| æ¡ä»¶ïŒç©º Box ã 8,000 ååæç»ïŒ | æ°žä¹ ä¿æ | perf ãšã³ã㪠| æèŠ |
|---|---|---|---|
| dev ãã«ãïŒåŸæ¥ïŒ | 2,230 B/ãã¬ãŒã | 24,003 ä»¶ | 414ms |
NODE_ENV=production |
117 B/ãã¬ãŒã | 0 ä»¶ | 166ms |
dev + 宿 clearMeasures() |
174 B/ãã¬ãŒã | 1 ä»¶ | 406ms |
ã¹ãã¢è³Œèªã¯ ~100ms ã¹ãããã«ãªã®ã§æç»ã¯çŽ 10/ç§ â çŽ 86MB/æãæ¢å®ã®ããŒãäžé ~4GB ã« åæ¥ã1 æ¥ã§å°éãããæç»å 容ãšã¯ç¡é¢ä¿ãªã®ã§ããã°ã®äžéã§ã¯æ¢ããããªãã£ãã
察ç㯠2 段:
src/index.tsxãèµ·åã·ã ã«ããïŒæ¬çïŒãprocess.env.NODE_ENV ??= 'production'ã./mainã®åç import ããåã«çœ®ããESM ã® static import ã¯å·»ãäžããããŠæ¬æããå ã« è©äŸ¡ããããããã·ã ã« static import ã 1 æ¬è¶³ãã ãã§ç¡å¹åãããïŒtsupã®bannerãã ã·ãã³ã®env -Sãéã«åããªããåŸè ã¯node <path>çŽå©ã = mise çµç±ã®èµ·åã§ ã·ãã³ãéããªãã®ã§ç¹ã«åœãŠã«ãªããªãïŒãtests/entry-shim.test.tsãçªäººãbootstrap/perf-timeline.tsã 30 ç§ããšã«ã¿ã€ã ã©ã€ã³ãæé€ããïŒä¿éºïŒãNODE_ENV=developmentã§èµ·åãããšãããå°æ¥ React / Node ãå¥ã®åœ¢ã§ user timing ã ç©ã¿å§ãããšãã«å¹ããä¿æéã®äžéãã30 ç§ã¶ããã«ãªãã
å¯äœçšãšã㊠dist ã 2 ãã¡ã€ã«ïŒã·ã + ãã£ã³ã¯ïŒã«ãªã£ããbin ãæãã®ã¯ dist/index.js ã®
ãŸãŸã§ãããã±ãŒãžã«ãŒãã®è§£æ±ºïŒpackageRootFromïŒããpackage.json ã® 1 ã€äžããšããåæã
ä¿ã£ãŠããã
process.env ãžã®ä»£å
¥ã¯ spawn ããåããã»ã¹å
šéšã«ç¶æ¿ãããããšãŒãžã§ã³ãã®ã·ã§ã«ã¯
codiva ã®åãªã®ã§ãäžã® NODE_ENV=production ããã®ãŸãŸç¶ããããšãã»ãã·ã§ã³å
ã§å©ã
npm install / npm ci ã --omit=dev ãšè§£éãã devDependencies ãé»ã£ãŠå
¥ããªã
ïŒåå®çŸ©ããã¹ãã©ã³ããŒãæ¬ ããç¶æ
ã«ãªããåºãã®ã¯ãäŸåãç¡ããã§ã¯ãªã TS7016 ã®ãããª
åãšã©ãŒãªã®ã§ãåå ã npm ã ãšæ°ä»ããªããissue #103ïŒãNODE_ENV ãèŠãããŒã«ã¯ã»ãã«ã
ããã®ã§ãnpm åºæã®åé¿ïŒ--include=devïŒã§ã¯ãªã env ãæŒãããªãæ¹åã§çŽãã
- èµ·åã·ã ã¯èªåã§ç«ãŠããšãã ã
CODIVA_NODE_ENV_INJECTED=1ã眮ãïŒ??=ãæ¢åå€ã å°éããã®ãšåãçç±ã§ããŠãŒã¶ãŒãæç€ºããNODE_ENVã¯åã«ããã®ãŸãŸæž¡ãïŒã core/child-env.tsã®childEnv(env)ïŒçŽç²ïŒãããã®ç®å°ãèŠãŠNODE_ENVãšç®å°èªèº«ã èœãšããã³ããŒãè¿ããå®process.envãžã®é©çšã¯utils/child-env.tsã®childProcessEnv()ã- codiva ãèµ·ããããã»ã¹ã«ã¯å¿
ããããæž¡ãïŒ
codex exec/grok agent stdio/git/gh/ login CLI / éç¥ã»URL ãªãŒãã³ /npmïŒãClaude 㯠SDK çµç±ãªã®ã§utils/claude-query.tsã®claudeQueryïŒOptions.envã被ããqueryïŒã«å ¥å£ã 1 æ¬åãããOptions.envã¯process.envãšããŒãžãããäžžããšçœ®ãæããã®ã§ãæž¡ãã®ã¯åžžã«å šäœã®ã³ããŒã«ããã - çªäººã¯
src/utils/child-env.spec.tsïŒnode:child_processã import ãã utils ã¯childProcessEnvãéã / SDK ã®queryãå€ãšã㊠import ããŠããã®ã¯claude-query.tsã ãïŒãštests/entry-shim.test.tsïŒç®å°ã®ä»£å ¥ã??=ããåã«ããïŒã
Ink 7.1.1 㯠measure-text.js ãš wrap-text.js ã§äžéã®ãªãã¢ãžã¥ãŒã«ã¬ãã«ãã£ãã·ã¥
ïŒã㌠= ããã¹ãå
šæïŒãæã¡ãè§£æŸçµè·¯ãç¡ããçŽ 100 æåã®è¡ 1 æ¬ã§çŽ 1.7KBã
4,000 æåã® <Text> 1 æç»ã§çŽ 17.8KB ãæ°žä¹
ã«æ®ããcodiva åŽã§ã§ããã®ã¯
æ¯ãã¬ãŒã å€ããé·ãæååãæž¡ããªãããšãªã®ã§ãã¹ããªãŒãã³ã°äžã®æ¬æã¯
streamLines(text, width, âŠ) ã§è¡ã«æãè¿ããŠãã 1 è¡ãã€æž¡ããæ«å°Ÿã«è¶³ãã ããªã
確å®ããè¡ã®æååã¯å€ãããªãã®ã§ãã£ãã·ã¥ã«åœããç¶ããæ¯ãã«ã¿ã§æ°ããç©ãŸããã®ã¯
æžãããã®æçµè¡ 1 æ¬ã ãã«ãªãïŒéäžããã¹ãã Markdown æŽåœ¢ããããè¡ã®éäžã§é ã
åã£ãããããšãã®æ§è³ªãå£ããŠå
šè¡ãæ¯ãã¬ãŒã å¥ã®ããŒã«ãªãïŒã
äžéãã®ãã®ã¯ ink åŽã®ä¿®æ£ãå¿
èŠãªã®ã§ issue ã§å ±åããŠãã
ïŒink#986ïŒã
| 倿 | çç± |
|---|---|
| 埩å ã¯ãã¡ã¿ + SDK resumeãã§ããã°ã¯æ°žç¶ããªã | state.json ãå°ããä¿ã€ãäŒè©±å±¥æŽã¯ SDK ã® resume ãæã€ã®ã§äºé管çããªãã埩å çŽåŸã¯ã¢ã€ãã«è¡šç€ºãè¿œå æç€ºã§ç¶ç¶ |
| 埩å ã»ãã·ã§ã³ã¯é å»¶ resumeïŒèµ·åæã«èµ·ãããªãïŒ | ã»ãã·ã§ã³æ¯ã« ~1GiB ã®ãµãããã»ã¹ãèµ·åæã«ä¹±ç«ãããªããè§Šããããã®ã ãèµ·ãã |
çµäºã¯ abort() ã§ã¯ãªã stop()ïŒquietïŒ |
å®è¡äžã»ãã·ã§ã³ã failed ã«ãã resumable ã®ãŸãŸä¿åããããïŒquit ãšã1ä»¶ç Žæ£ããåºå¥ïŒ |
ãç Žæ£ïŒdïŒããšãåé€ïŒx / /remove / /clearïŒããåãã |
ç Žæ£ã¯ worktree ãæ¶ããŠè¡ã archived ãšããŠæ®ãïŒäœæ¥ã®èšé²ãèŠããïŒãã ããã©ã³ãã«å€ã PR ãä»ããŠãããšããã®è¡ã¯äžæ¬ç«ãŠçŽãïŒCtrl+F = recoverableSessionsïŒã®åè£ãšããŠæ¯åæããç¶ãããåé€ã¯ store ããè¡ããšèœãšãã®ã§ãèšé²ãäžæ¬æäœã®å¯Ÿè±¡ãåæã«æ¶ããã/clear ã worktree/ãã©ã³ããæ®ããªãïŒæ®ããšãæ¶ããã®ã«ãã£ã¹ã¯ã«æ®ããã¶ããèŠããªãè² åµã«ãªãïŒ |
| åé€ã§ worktree ã®é€å»ã«å€±æãããè¡ãæ®ã | ãã£ã¹ã¯ã«ãã£ã¬ã¯ããªãæ®ã£ãŠããã®ã«äžèЧããæ¶ããšãååšãããã®ãèŠããªããªãããšã©ãŒãåºããŠè¡ãæ®ãã/clear ã¯æåããä»¶æ°ã ãæ°ãã |
| éç¥ã®çºç«å€å®ã¯çŽç²é¢æ°ã»é·ç§»æã®ã¿ | ãã¹ãå¯èœã«ããã¹ããªãŒãã³ã°ã®é£ç¶æŽæ°ã§é³Žãç¶ããã®ãé²ããOS I/O 㯠utils ã«éé¢ã best-effort |
èšå®æ€èšŒã¯ toConfig() ã«éçŽã»äžæ£å€ã¯æ¢å®ãž |
èšå®ãã¹ã§ TUI ãã¯ã©ãã·ã¥ãããªããSDK union ã¯å®è¡æãªãã©ã«ã§æ€èšŒïŒåãå€ããã°åãšã©ãŒïŒ |
| åé¢ææ®µã¯ git worktree | åäžãªããžããªã®äžŠåäœæ¥ã§ã¯æè»œéããã©ã³ãããã®ãŸãŸææç©ã«ãªããDocker çã¯MVPã§ã¯ãªãŒããŒãã« |
| ç«¶åã¯ãæ€ç¥ã®ã¿ãã§èªåè§£æ¶ããªã | æ±çšçã«å®å
šãªããŒãžç«¶åã®èªåè§£æ¶ã¯ååšããªãïŒ-X ours/theirs ã¯ã³ãŒããç¡èšã«æšãŠãïŒãå¯èŠåïŒconflict ãããžïŒã«çããè§£æ¶ã¯äººæã«å§ãã |
| PR 㯠draft ã§äœããç·ã«ãªã£ãŠãã ready å | ãã§ãã¯ã¯ PR ãç¡ããšèµ°ããªãïŒé¶åµïŒã宿åã« pushâdraft ã§è¶³å Žãäœããgh pr checks ãç·ã«ãªã£ãæç¹ã§ ready ãžãç¢ºå®æäœã¯èªåã§ãâã¬ãã¥ãŒå¯èœâç¶æ
ãŸã§ã«çãã |
| origin 远åŸã¯äœææã®ã¿ïŒçšŒåäžã¯ pull ããªãïŒ | 皌åäž worktree ãžåã蟌ããšæªã³ããã倿Žãšç«¶åãåŸããäœææã« origin/<base> ããåãå®å
šãªéšåéåã«éå® |
PR èªåå㯠PrAutomation ãšã㊠DIã»best-effort |
gh æªå°å
¥/æªèªèšŒ/ãªãã©ã€ã³ã§ãã»ãã·ã§ã³ãå£ããªããcore 㯠gh ãçŽæ¥ç¥ãããutils/pr.ts ã«éé¢ |
| èªå·±æŽæ°ã¯çµè·¯ãå€å®ã§ãããšãã ãå®è¡ãã | npm i -g 㯠npx ãã£ãã·ã¥ã»volta é
äžã»å¥ prefix ã§ã¯å®å
ãéããç°å¢ãå£ããå€å®äžèœïŒunknownïŒãªãã³ãã³ãã®æç€ºã ãã«çãã誀çã®ã³ã¹ãããèªååãããªããã«éå®ãã |
æŽæ°ãã§ãã¯ã¯ latest ã® 1 ãªã¯ãšã¹ãã»3 ç§ã§æã¡åãã»await ããªã |
èµ·åã絶察ã«ãããã¯ããªãããªãã©ã€ã³/ã¬ãžã¹ããªé害ã§ã unavailable ã«èœã¡ãã ãã§ TUI ãå£ããªããå
š packumentïŒ21KBïŒã§ã¯ãªã /latestïŒ2.3KBïŒãåŒã |
| ãææ°ã ã£ãããšã確èªã§ããªãã£ãããåã§åºå¥ãã | ãªãã©ã€ã³ããææ°ã§ãããšè¡šç€ºãããšåã«ãªããUpdateCheck ã® union ã§ UI ãåãéããããªãããã«ãã |
| UI æååã¯ã«ã¿ãã°éçŽ + èšå®ã§èšèªåæ¿ | æ¥æ¬èª/è±èªã®å©çšè
ãæ··åšãããããŒãã³ãŒããæãã远å èšèªã Lang/messages æ¡åŒµã ãã§æžã |
ã»ãã·ã§ã³ = SDK query() 1æ¬ïŒãµãããã»ã¹1æ¬ïŒ |
SDK ã®èšèšåäœã«çŽ çŽãããã»ã¹åé¢ã«ãã1ã»ãã·ã§ã³ã®ã¯ã©ãã·ã¥ãä»ã«æ³¢åããªã |
| streaming input ãåžžçšïŒåçº prompt ã䜿ããªãïŒ | è¿œå æç€ºïŒF-6ïŒãšè³ªåãžã®åçïŒF-7ïŒãåäžæ©æ§ã§å®çŸã§ããã»ãã·ã§ã³ãéãããŸãŸç¶æã§ãã |
| ã³ã¢ãš UI ã®åé¢ + queryFn ã® DI | SDK ããããã¯ãŒã¯ãäžèŠãªãŠããããã¹ããå¯èœã«ããïŒN-3 ã® 80% ã«ãã¬ããžã¯ãããåæïŒ |
worktree 㯠.codiva/worktrees/ é
äžãignore 㯠.codiva/.gitignoreïŒ*ïŒã§èªå·±å®çµ |
察象ãªããžããªã®ãã¡ã€ã«ã .git/ ã®äžãæ±æããªãã.git ããã¡ã€ã«ã®ç°å¢ïŒlinked worktree / submoduleïŒã§ãåã |
| ã¢ããªçµäºæã« worktree ãæ¶ããªã | N-4ïŒäœæ¥å 容ã®ä¿å šïŒãæç€ºçãªå逿äœã®ã¿ã§æ¶ã |
| ãªã¹ã¯ | å¯Ÿå¿ |
|---|---|
| SDK ã¡ãã»ãŒãžåœ¢åŒã®æ³å®éã | Phase 1 ã®ã¹ãã€ã¯ã§å®ã¡ãã»ãŒãžã JSONL åéããreducer ã®ãã¹ããã£ã¯ã¹ãã£ã«äœ¿ãïŒæ³å®ã§æžããªãïŒ |
| 倧éã¹ããªãŒã ã§ Ink åæç»ãéã | äžèЧã¯ã¹ããŒã¿ã¹è¡ã®ã¿æç»ïŒãã°ã¯è©³çްãã¥ãŒã§ã®ã¿ãæ«å°Ÿãã¥ãŒããŒãã«ã¯ãªããïŒ+ 賌èªã¹ããããªã³ã° |
| è³ªåæ€åºã®èª€å€å® | MVP ã¯ãã¥ãŒãªã¹ãã£ã㯠+ 詳现ãã¥ãŒã§è¿œå æç€ºãéã£ãŠå¯Ÿè©±ãç¶ããããã®ã§èª€å€å®ã®å®å®³ã¯å°ãããã¹ãã€ã¯çµæã§æ¹å |
| 䞊åã»ãã·ã§ã³ã®APIã³ã¹ã | Backlog ã§ã³ã¹ã衚瀺ã远å ãMVP ã§ã¯ result ã¡ãã»ãŒãžã® usage ããã°ã«æ®ãã®ã¿ |
| ãŠãŒã¶ãŒã®ã¡ã€ã³worktreeã dirty | worktree 㯠HEAD ããåããã圱é¿ãªããèµ·åæãã§ãã¯ã§èŠåã®ã¿è¡šç€º |