TidGi-Desktop/docs/internal/PromptTreeNavigation.md
lin onetwo 3718d0bd39
Fix/edit agent and several bugs (#670)
* refactor: simplify tool writing

* feat: load prompt from plugin in a wiki, let agent know what to do

based on https://github.com/TiddlyWiki/TiddlyWiki5/issues/9378

* fix: i18n

fix: i18n

fix: wrong i18n structure

fix: empty i18n

* Add ContentLoading component and suspense fallback

* fix: monaco loading

* docs: usage of chrome mcp to contron during dev

* fix: provider config truncate user input when typing

* fix: legacy usage

* Update package.json

* fix: not loadin initial data

* feat: better prompt sort

* fix: sorting of array

* fix: drag

* Create DragAndDrop.md

* feat: directly enter edit mode

* fix: workspace config change cause immediate main wiki restart

* Add 'Press Enter to confirm' to tag help texts

* fix: dont show system tag when adding sub wiki

* feat: inform user to press enter on tag auto complete

* refactor: let sub wiki auto complete tag

* Revert Add 'Press Enter to confirm' to tag help texts

* fix: not able to open prompt editor by click prompt tree

* fix: click to open plugin config

* chore: remove log

* feat: Auto-select the first file if none is selected

* fix: don't preview not enabled prompt parts

* fix: Keep i18n ally think these keys exist, otherwise it will delete them during "check usage"

* lint: fix

* Update externalAPI.logging.test.ts
2025-12-15 17:33:59 +08:00

156 lines
5.5 KiB
Markdown

# Prompt Tree Navigation to Form Editor
## Overview
Click on any prompt item in the tree view and automatically open the corresponding form editor with the correct tab and expanded state.
## Implementation Details
### 1. Source Path Tracking
When plugins inject content into the prompt tree using `injectToolList()` or `injectContent()`, the system automatically adds a `source` field to track the original configuration location.
**File**: `src/services/agentInstance/tools/defineTool.ts`
```typescript
// Build source path pointing to the plugin configuration
const pluginIndex = context.pluginIndex;
const source = pluginIndex !== undefined ? ['plugins', toolConfig.id] : undefined;
const toolPrompt: IPrompt = {
id: `${toolId}-tool-list-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
text: toolContent,
caption: options.caption ?? `${definition.displayName} Tools`,
enabled: true,
source, // ['plugins', 'plugin-id']
};
```
The `source` array format: `['plugins', pluginId]` or `['prompts', promptId, ...]`
### 2. Navigation Trigger
**File**: `src/pages/ChatTabContent/components/PromptTree.tsx`
When a user clicks a tree node:
```typescript
const handleNodeClick = useCallback((event: React.MouseEvent) => {
event.stopPropagation();
// Use source path if available, otherwise construct from fieldPath
const targetFieldPath = (node.source && node.source.length > 0)
? node.source
: [...fieldPath, node.id];
setFormFieldsToScrollTo(targetFieldPath);
}, [node.source, node.id, fieldPath, setFormFieldsToScrollTo]);
```
### 3. Tab Switching
**File**: `src/pages/ChatTabContent/components/PromptPreviewDialog/PromptConfigForm/templates/RootObjectFieldTemplate.tsx`
The root form template listens to the navigation path and switches to the appropriate tab:
```typescript
useEffect(() => {
if (formFieldsToScrollTo.length > 0) {
const targetTab = formFieldsToScrollTo[0]; // 'prompts', 'plugins', or 'response'
const tabIndex = properties.findIndex(property => property.name === targetTab);
if (tabIndex !== -1 && tabIndex !== activeTab) {
setActiveTab(tabIndex);
}
}
}, [formFieldsToScrollTo, properties, activeTab]);
```
### 4. Item Expansion
**File**: `src/pages/ChatTabContent/components/PromptPreviewDialog/EditView.tsx`
The EditView component handles the expansion of nested items:
```typescript
useEffect(() => {
if (formFieldsToScrollTo.length > 0 && editorMode === 'form') {
const savedPath = [...formFieldsToScrollTo];
// Wait for RootObjectFieldTemplate to switch tabs
setTimeout(() => {
setFormFieldsToScrollTo([]); // Clear after tab switches
// Step 1: Expand top-level item
const topLevelKey = savedPath[0];
const firstItemId = savedPath[1];
expandItemsByPath(topLevelKey, [firstItemId]);
// Step 2: Expand nested children if present
if (savedPath.length > 2) {
setTimeout(() => {
const parentIndex = findParentIndex(topLevelKey, firstItemId);
const nestedFieldPath = `${topLevelKey}_${parentIndex}_children`;
const nestedItemIds = savedPath.slice(2);
expandItemsByPath(nestedFieldPath, nestedItemIds);
}, 300);
}
}, 100);
}
}, [formFieldsToScrollTo, editorMode, agentFrameworkConfig]);
```
### 5. Store Management
**File**: `src/pages/Agent/store/agentChatStore/PromptPreviewStore.ts`
The store maintains:
- Expansion state for all array fields
- Navigation path queue
- Helper functions to expand/collapse items
```typescript
interface PromptPreviewStore {
arrayExpansionStore: Record<string, Record<number, boolean>>;
formFieldsToScrollTo: string[];
setItemExpanded: (fieldPath: string, index: number, expanded: boolean) => void;
setFormFieldsToScrollTo: (path: string[]) => void;
}
```
## Data Flow
1. User clicks "Git Tools" in tree view
2. `PromptTree` reads `node.source``['plugins', 'g3f4e5d6-7e8f-9g0h-1i2j-l3m4n5o6p7q8']`
3. Calls `setFormFieldsToScrollTo(['plugins', 'g3f4e5d6-7e8f-9g0h-1i2j-l3m4n5o6p7q8'])`
4. `RootObjectFieldTemplate` detects path[0] = 'plugins' → switches to plugins tab
5. `EditView` expands the plugin item with id 'g3f4e5d6-7e8f-9g0h-1i2j-l3m4n5o6p7q8'
6. Form scrolls to and highlights the target element
## Timing Considerations
The implementation uses careful timing to ensure proper rendering:
- **100ms delay**: Wait for tab switch before expanding items
- **300ms delay**: Wait for parent expansion before expanding nested children
- **500ms delay**: Wait for all expansions before scrolling to target
These delays account for React's rendering cycles and DOM updates.
## Extension Points
To add navigation support for custom components:
1. Add `source` field when creating prompts
2. Ensure `source` points to the configuration location: `['topLevelKey', 'itemId', ...]`
3. The navigation system will automatically handle the rest
## Related Files
- `src/services/agentInstance/tools/defineTool.ts` - Source path injection
- `src/services/agentInstance/tools/types.ts` - Context types with pluginIndex
- `src/services/agentInstance/promptConcat/promptConcat.ts` - Plugin index passing
- `src/pages/ChatTabContent/components/PromptTree.tsx` - Click handler
- `src/pages/ChatTabContent/components/PromptPreviewDialog/EditView.tsx` - Expansion logic
- `src/pages/ChatTabContent/components/PromptPreviewDialog/PromptConfigForm/templates/RootObjectFieldTemplate.tsx` - Tab switching
- `src/pages/Agent/store/agentChatStore/PromptPreviewStore.ts` - State management