gadget-drone now presents an ApiClient _id value as the Gadget Key,
allowing gadget-code to reference the client, determine the associated
User, and invoke logic on the User's behalf as an authenticated and
authorized client.
- JWT refresh logic to prevent dead sessions
- drone status messages now arrive in IDE for display
- WorkspaceService.deployProject method added to clone into a repo or
create the directory (new project not yet in git)
- Add isProcessingWorkOrder flag to track Agent work order processing
- Update onRequestWorkspaceMode with mode transition matrix validation
- Idle → User/Agent: Always allowed
- User → Agent: Always allowed (file editor checks for future)
- Agent → User: Only if !isProcessingWorkOrder
- All other transitions: Rejected with reason
- Extend RequestWorkspaceModeCallback with optional reason parameter
- Update frontend socket client to capture rejection reason
- Update handleWorkspaceModeChange to display rejection reason in toast
- Update WorkspaceModeIndicator to allow mode transitions per matrix
- Fix FilesPanel RW/RO indicator swap bug
- Document mode transition matrix and behavior in workspace-management.md
- Create WorkspaceService for managing .gadget/ directory
- Implement workspace.json for persistent identity (workspaceId UUID)
- Add work order cache for crash recovery
- Update drone registration to include workspaceId
- Add crash recovery socket events (requestCrashRecovery, crashRecoveryResponse)
- Implement crash recovery handler in DroneSession
- Write work order cache before processing, remove after completion
- Resolve duplicate DroneStatus enum (import from @gadget/api)
- Fix IAiProvider interface conflict with DB→runtime mapper
- Add callId to ToolCallMessage and ChatToolCallSchema
- Fix ChatTurnStats schema field name (thinkingTokenCount)
- Add provider/selectedModel to ChatSession interface and model
- Implement CodeSession.onSubmitPrompt() to create ChatTurn and send work orders
- Add drone/chat session tracking to CodeSession
- Add unit tests for CodeSession (9 tests, all passing)
We want to speak only one language when dealing with AI content to
minimize the number of maps, transforms, and copies. This initiative
isn't done, this is a checkpoint along the way while conducting
experiments.