Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled
108 lines
3.5 KiB
TypeScript
108 lines
3.5 KiB
TypeScript
import type { AgentRequest } from '../../shared/types/AgentRequest'
|
|
import type { TldrawAgent } from '../agent/TldrawAgent'
|
|
import type { AgentModeDefinition, AgentModeType } from './AgentModeDefinitions'
|
|
|
|
/**
|
|
* Lifecycle hooks for an agent mode.
|
|
* Each mode can optionally implement these hooks to respond to state changes.
|
|
*/
|
|
export interface AgentModeNode {
|
|
onEnter?(agent: TldrawAgent, fromMode: AgentModeType): void
|
|
onExit?(agent: TldrawAgent, toMode: AgentModeType): void
|
|
onPromptStart?(agent: TldrawAgent, request: AgentRequest): void
|
|
onPromptEnd?(agent: TldrawAgent, request: AgentRequest): void
|
|
onPromptCancel?(agent: TldrawAgent, request: AgentRequest): void
|
|
}
|
|
|
|
/**
|
|
* Lifecycle implementations for each agent mode.
|
|
*
|
|
* This chart maps mode types to their lifecycle hooks.
|
|
* Modes can implement any subset of hooks (all are optional).
|
|
* Not all modes need an entry - modes without entries simply have no lifecycle behavior.
|
|
*
|
|
* To add lifecycle behavior for a new mode:
|
|
* 1. Add the mode to AGENT_MODE_DEFINITIONS in AgentModeDefinitions.ts
|
|
* 2. Add an entry here with the lifecycle hooks you need
|
|
*/
|
|
const _AGENT_MODE_CHART: Record<AgentModeDefinition['type'], AgentModeNode> = {
|
|
idling: {
|
|
onPromptStart(agent) {
|
|
agent.mode.setMode('working')
|
|
},
|
|
onEnter(agent, _fromMode) {
|
|
agent.todos.reset()
|
|
agent.userAction.clearHistory()
|
|
},
|
|
},
|
|
working: {
|
|
onEnter(agent, fromMode) {
|
|
// Reset state when entering working mode
|
|
agent.todos.reset()
|
|
// agent.userAction.clearHistory()
|
|
agent.context.clear()
|
|
|
|
// When entering working mode from idling, clear created shapes tracking
|
|
// This handles the case where a user prompt starts while in idling mode,
|
|
// which transitions to working before working.onPromptStart is called
|
|
if (fromMode === 'idling') {
|
|
agent.lints.clearCreatedShapes()
|
|
}
|
|
},
|
|
|
|
onExit(agent, _toMode) {
|
|
// Unlock all shapes created during the prompt when exiting working mode
|
|
agent.lints.unlockCreatedShapes()
|
|
},
|
|
|
|
onPromptStart(agent, request) {
|
|
// Clear created shapes tracking and flush todos when a new user prompt starts
|
|
// This handles cases where a prompt starts while already in working mode (e.g., continuation, interrupt)
|
|
if (request.source === 'user') {
|
|
agent.todos.flush()
|
|
agent.lints.clearCreatedShapes()
|
|
}
|
|
},
|
|
|
|
onPromptEnd(agent, _request) {
|
|
// Check if there are incomplete todos
|
|
const todoList = agent.todos.getTodos()
|
|
const incompleteTodos = todoList.filter((item) => item.status !== 'done')
|
|
|
|
if (incompleteTodos.length > 0) {
|
|
// Schedule continuation to complete remaining work
|
|
agent.schedule(
|
|
"Continue until all your todo items are marked as done. If you've completed the work, mark them as done, otherwise keep going."
|
|
)
|
|
return
|
|
}
|
|
|
|
// Check if there are unsurfaced lints on created shapes
|
|
if (agent.lints.hasUnsurfacedLints(agent.lints.getCreatedShapes())) {
|
|
agent.schedule({
|
|
agentMessages: [
|
|
'The automated linter has detected potential visual problems in the canvas. Decide if they need to be addressed.',
|
|
],
|
|
})
|
|
return
|
|
}
|
|
|
|
// All work complete - return to idling
|
|
agent.mode.setMode('idling')
|
|
},
|
|
|
|
onPromptCancel(agent, _request) {
|
|
// Return to idling on cancel
|
|
agent.mode.setMode('idling')
|
|
},
|
|
},
|
|
}
|
|
|
|
/**
|
|
* Get the lifecycle node for a mode, if one exists.
|
|
* This function helps TypeScript resolve types correctly with circular imports.
|
|
*/
|
|
export function getModeNode(mode: AgentModeType): AgentModeNode {
|
|
return _AGENT_MODE_CHART[mode]
|
|
}
|