# ThoughtFrame Eclipse plugin — TODO Everything the agent can do to the IDE is a **command**: a named action with an implementation behind the workspace bridge. This is the list of commands to implement, plus the plumbing still owed. Two kinds, and the difference matters: - **Model tools** — declared in `frames/tui/functions/*.json` and offered to the model, so it can choose to call them (`open`, `replaceSelection`). - **Machine steps / hotkey actions** — not offered to the model; the FSM or the developer runs them (`organizeImports`, `format` are the machine's tidy-up after an edit). Same registry, different driver. Most of these are Eclipse command ids run through `ide/command` (the model pressing the button the IDE already ships, dialogs and undo included). Where a command id is uncertain it is marked **(?)** — verify in the IDE before wiring. --- ## Implemented - [x] `ide/open` — open a workspace file, optionally reveal a line - [x] `ide/peek` — read a file window (path, startLine, count) without opening it or moving the active editor; returns the text, headed by path/range/total - [x] `ide/glob` — find files whose path matches a glob (`**/*.java`); all workspace projects, skips build/VCS folders - [x] `ide/grep` — search text files for a literal or regex string, scoped or whole-workspace; returns `path:line: text` - [x] `ide/write` — create or overwrite a workspace file; the host confirms first - [x] `ide/console` — read the Eclipse consoles' buffered text (build/run/test output) - [x] `ide/build` — build every project incrementally and return problem markers - [x] `ide/runTests` — run the project's test command and return the output tail - [x] `ide/replaceSelection` — replace a range, one undoable change - [x] `ide/command` — run any workbench command id on the active editor - [x] `ide/format` — format the whole active file (select-all, then Format) - [x] `organizeImports` — `org.eclipse.jdt.ui.edit.text.java.organize.imports` - [x] `format` — `org.eclipse.jdt.ui.edit.text.java.format` ## Editor / source actions - [ ] organize imports on a *given* file, not just the active one - [ ] add import — `org.eclipse.jdt.ui.edit.text.java.add.import` - [ ] sort members — `org.eclipse.jdt.ui.edit.text.java.sort.members` - [ ] clean up (the whole Source > Clean Up profile) — `org.eclipse.jdt.ui.edit.text.java.clean.up` - [ ] toggle comment — `org.eclipse.jdt.ui.edit.text.java.toggle.comment` - [ ] add / remove block comment — `org.eclipse.jdt.ui.edit.text.java.add.block.comment`, `…remove.block.comment` - [ ] correct indentation — `org.eclipse.jdt.ui.edit.text.java.indent` - [ ] generate getters and setters **(?)** - [ ] generate `hashCode()` / `equals()` **(?)** - [ ] generate `toString()` **(?)** - [ ] generate constructor from fields **(?)** - [ ] override / implement methods **(?)** - [ ] quick fix (Ctrl+1) — `org.eclipse.jdt.ui.edit.text.java.correction.assist.proposals` (interactive) ## Refactorings (LTK — programmatic, one undoable step) - [ ] rename element — `org.eclipse.jdt.ui.edit.text.java.rename.element` - [ ] move element — `org.eclipse.jdt.ui.edit.text.java.move.element` - [ ] change signature — `org.eclipse.jdt.ui.edit.text.java.change.signature` - [ ] extract method — `org.eclipse.jdt.ui.edit.text.java.extract.method` - [ ] extract local variable — `…extract.local.variable` - [ ] extract constant — `…extract.constant` - [ ] extract interface — `…extract.interface` - [ ] extract superclass — `…extract.superclass` - [ ] inline — `org.eclipse.jdt.ui.edit.text.java.inline` - [ ] pull up / push down — `…pull.up`, `…push.down` - [ ] introduce parameter / factory / indirection — `…introduce.parameter`, `…introduce.factory`, `…introduce.indirection` - [ ] use supertype where possible — `…use.supertype` - [ ] infer generic type arguments — `…infer.generic.type.arguments` Most of these open the IDE's own preview dialog. That is fine — the agent presses the button, the developer confirms, the IDE does the transformation. Running them programmatically (no dialog) is the alternative, via `PerformRefactoringOperation`, when we want the machine to drive them. ## Navigation - [ ] open declaration — `org.eclipse.jdt.ui.edit.text.java.open.editor` - [ ] open type hierarchy — `org.eclipse.jdt.ui.edit.text.java.open.type.hierarchy` - [ ] open call hierarchy — `org.eclipse.jdt.ui.edit.text.java.open.call.hierarchy` - [ ] reveal in Outline / Package Explorer **(?)** — so the developer sees what the agent is looking at ## Search - [ ] find references in workspace — `org.eclipse.jdt.ui.edit.text.java.search.references.in.workspace` - [ ] find declarations in workspace — `org.eclipse.jdt.ui.edit.text.java.search.declarations.in.workspace` - [ ] find implementors — `org.eclipse.jdt.ui.edit.text.java.search.implementors.in.workspace` - [ ] find read / write access **(?)** These want a structured result (list of matches as plain data) more than the IDE's Search view, so the model can reason about them. ## Build and verify (the oracle) - [ ] build project / workspace — `org.eclipse.ui.project.buildAll`, or `IProject.build` for one project - [ ] problems for a file / project — markers as plain data (message, severity, symbol) - [ ] show the Problems view / jump to next problem **(?)** - [ ] run JUnit tests — a launch configuration, not a command id; results as structured data - [ ] run / debug last launch — `org.eclipse.debug.ui.commands.RunLast`, `…DebugLast` ## Workspace / files - [ ] save / save all — `org.eclipse.ui.file.saveAll` - [ ] revert file — `org.eclipse.ui.file.revert` - [ ] refresh from disk — `org.eclipse.ui.file.refresh` (needed if the engine ever writes bytes directly) - [ ] create file / class — wizard, or a custom action writing through the Java model - [ ] delete file - [ ] compare with HEAD / show diff — for reviewing a proposal before applying ## Git (EGit) - [ ] stage / commit — `org.eclipse.egit.ui` commands **(?)** - [ ] diff working tree vs HEAD - [ ] branch / checkout — one per agent attempt, mirroring the student-sandbox model ## Debug - [ ] toggle breakpoint — `org.eclipse.debug.ui.commands.ToggleBreakpoint` - [ ] step over / into / return, resume, terminate — `org.eclipse.debug.ui.commands.*` --- ## How to add one (the recipe) 1. `frames//functions/.json` — the schema, if the model should call it. 2. **Register the name in `frames//ai/framemessage.xconf`** — `llm-functions` is an allow-list, split on commas. `resolveAllowedFunctions` returns exactly those names, and `deepseek.html` loads `frames//functions/.json` for each. A schema file that is not named there is never sent to the model — the folder is not scanned. 3. `frames//actions/.html` — the response template (`$actionresult` / `$error`). 4. `frames//actions/.xconf` — one ``. 5. `IdeModule.(WebPageRequest)` — read the args, `invoke(inReq, "", "ide/", args)`. 6. `EclipseWorkspaceBridge.invokeAction` — the host verb for `ide/`. That's all. `TuiModule.runTool` runs `actions/` directly and returns its rendered output as the tool's `function_response` — the function name IS the action name, so no `session.groovy` handler is needed just to return data. An action that renders `$error` still returns as data. Arguments arrive as page values on the action request, keyed exactly as the schema's property names (camelCase matters): the module reads them with `value(inReq, "")`. A frame only needs a `thought:` handler when it wants to *transition* on a tool; for that, have the action fire its `ide:` observation (which `IdeModule.invoke` does) and listen for that. Conversions, code conventions: fields `protected` not `private`, no `static` fields (constants included), everything accessed through getters. `FrameViewer` still needs this sweep. --- ## Plumbing owed - [ ] Stop `transition()` firing its event from inside the pipeline states — it re-enters a frame we hold, which is the `Could not acquire lock` noise. Set the state directly in those states. - [ ] Make the pipeline declarative on the frame: the frame declares its auto-advance states and a tick budget, so `pump` stops hardcoding `organize` / `format`. - [ ] Seed the model's tool list from the developer's own keybindings (`IBindingService`) — the commands someone bound a key to are the ones they care about, and the list is personal and small. - [ ] Record a tool's *outcome* in the conversation. Today `replaceSelection` records "proposed (awaiting the developer's confirmation)"; nothing records applied / rejected, so the model never learns what happened. The frame handler for `thought:replaceSelection` is the natural place. - [ ] Render engine-side steps (`open`) in the transcript, not just the pump's steps. - [ ] A failed action should stop or branch the machine. `action(...)` currently gets `error: …` back as page text, so the pipeline marches on regardless. ## Packaging - [ ] Preference for the webapp root — `EclipseWorkspaceBridge.resolveWebappRoot` hardcodes `/home/ian/git/thoughtframe-core/thoughtframe/webapp`. - [ ] Preference for the engine dir — `EngineIsland.resolveEngineDir` already honours `-Dthoughtframe.engine.dir`; make it a real preference. - [ ] Thin bundle: drop `engine/` from `bin.includes` and load an external engine dir, instead of carrying 189 MB / 253 jars inside the plugin. The fat bundle stays the "mail it to someone" option, with `unpack="true"` so `engine/` stays a directory. - [ ] A `feature/` project so an export produces an installable p2 update site.