ThoughtFrame Eclipse agent surface =================================== HTTP verbs against a running Eclipse, served by the ThoughtFrame plugin. Everything here is stateful: it reads or mutates the live workspace, editor, debug, build and repository state. Java semantic search (find / references / hierarchy) is served by Eclipse's own JDT index - the proper search engine for code - via the Search verbs below. Discovery The plugin writes its port to: ~/.thoughtframe/instances/HASH.json (field "port", loopback only) Base URL: http://127.0.0.1:PORT/tf-eclipse//VERB.html Verb pages are grouped by category: search/ read/ edit/ run/ debug/ agent/ engine/. The tf client maps verb names to their folder, so you still call: tf VERB k=v Calling GET or POST with form parameters. Examples: curl "http://127.0.0.1:PORT/tf-eclipse/read/glob.html?pattern=**/Foo.java" curl -X POST ".../write.html" --data-urlencode "path=/proj/src/Foo.java" --data-urlencode "text=..." Response is plain text. Failures render as: error: Paths Most file verbs take "path": a WORKSPACE path, not an OS path, e.g. /thoughtframe/src/main/java/org/acme/Foo.java Get the list of projects with the "projects" verb. Project names are the first segment. git verbs take "project" and (for diff) a repo-relative "path". VERBS ----- Search (Eclipse JDT index) find?name= type declarations by name/pattern (e.g. *Manager) references?class=&[method=|field=][&kind=read|write] incoming references to a type/method/field implementors?class=&[method=] subtypes of a type, or overriding methods hierarchy?class= supertypes and subtypes type-info?class= class overview: fields, methods, supertypes source?class= the type's source Read status one-call dashboard: active editor, open editors, problems, launches, tests projects list workspace projects (with java flags) project?name= one project: natures, charset, location, output projectState?name=&op=open|close open or close a project editors open editors; the active one marked with * selection active editor file, offset, length, selected text stat?path= exists, type, bytes, lines, charset, modified properties?path= derived/team flags, marker count, persistent props classpath?project= resolved classpath (src/lib/proj entries) markers?[project=][severity=error|warning][limit=] workspace problem markers tasks?[project=][limit=] TODO/FIXME task markers bookmarks?op=list workspace bookmarks console?[name=][lines=] console text tail tests?op=runs|status&id= JUnit run sessions and results git?project=&op=status|log|branch|diff&[path=][limit=] repository state (diff needs path) debug?op=targets|threads|variables&thread=&frame= debug sessions, stacks, variables glob?pattern= workspace files matching a glob grep?query=&[path=][regex=] text search in workspace files peek?path=&[startLine=][count=] read file contents without opening it problems?[path=] problem markers for one file (or active editor) Edit open?path=&[line=] open a file in the editor, optionally at a line close?[title=][all=true] close active editor, one by title, or all write?path=&text= create/overwrite a file (creates parent folders) save?[all=true] save active editor, or all dirty editors delete?path= delete a file or folder (not a project) mkdir?path= create a folder (parents included) moveFile?path=&to= move/rename any resource copy?path=&to= copy any resource move?class=&target=[&dryRun=true] refactor: move a type to another package rename?class=&newName=[&method=|&field=][&dryRun=true] refactor: rename type/method/field format format the active editor formatAll?path= format every .java under a path (rewrites files) organizeImports organize imports in the active editor replaceSelection?path=&text=&before=|from=&to=&[offset=] content-addressed edit highlight?path=&symbol=|startLine=&endLine= reveal/select in the editor; returns offset+length refresh?[path=] re-sync Eclipse with the filesystem encoding?path=&[charset=] read or set a resource charset Build / run / debug build incremental workspace build clean?[name=] clean build a project (or all) run run the active editor runTests?project=&command= run a project's tests launch?op=configs|running|run|stop|runClass&name=|project=&class= launch configs and runs launchConfig?op=delete&name= delete a launch configuration maven?[name=] update Maven project configuration breakpoints?op=list|set|clear&path=&line=&type= Java line breakpoints debug?op=launch&name= launch a config in debug mode debug?op=resume|suspend|stepOver|stepInto|stepReturn control suspended threads runCommand?command= run any workbench command id Extend reloadframeplugins re-scan frames/*/plugin.xml to register new Groovy modules Engine (tf engine ) status catalog + frame list frames?op=connect&from=&to=[label=] author an edge X->Y; queues a BACKGROUND re-index of the connected nodes' thoughts (sync=true to block, reindex=false to skip) frames?op=neighbours&framepath=[depth=1] walk the frame graph: neighbour frames + their thoughts frames?op=near&framepath=[radius=1][walk=true] thoughts within radius hops; default = indexed framewithinN (fast); walk=true = live edge walk (slower, exact) frames?op=here&framepath= thoughts anchored exactly at a frame Topics: tf thought op=add topic=X creates frame topic/X and anchors the thought there; frames link via authored edges (FrameWalker walks them). Frame paths are also an implicit ancestry (git/repo/123 -> git/repo -> git) used by findValue, not by the walk. Agent thought?op=add&message=&[name=][tags=][status=][topic=|framepath=] remember a thought (the "thought" searcher); topic=X creates frame topic/X thought?op=search&[q=][tag=][status=][topic=][framepath=][all=] recall thoughts; filter by text/tag/status/topic thought?op=delete&id= forget a thought by id thought?op=taxonomy list the tag taxonomy (hierarchical) + status values websearch?query=&[max=][provider=][key=] web search via a WebSearcher provider webfetch?url=&[format=text] fetch a URL and return it as text scratch run the scratch Groovy page (draft it in the IDE, run it here) clearCache clear compiled-script / page-definition caches (run after edits) errors?[lines=] engine error log tail Working memory (do this WHILE you work, not just at the end) The graph is the scratchpad of record - not the conversation. Check it as you go: recall tf thought op=search [q=|topic=|tag=|status=] relate tf engine frames op=near framepath=topic/ (indexed - fast) inspect tf engine frames op=neighbours framepath= [depth=1] Before a task: read topic/. After a decision: write it there (op=add topic=X, tags=, status=). Park "we can measure later" items with status=parked instead of holding them in context. Load the relevant topic(s) at the start of a session. Git (mutating) git?project=&op=add&path= stage a path git?project=&op=unstage&path= unstage a path git?project=&op=checkout&branch= switch branch git?project=&op=commit&message=&[path=] commit (optionally staging one path first) git?project=&op=push&[remote=][&dryRun=] push the current branch (uses EGit's stored credentials) git?project=&op=fetch&[remote=] fetch a remote git?project=&op=pull pull git?project=&op=creds&[remote=] check whether EGit has stored credentials for a remote Search and the index (OpenSearch) -- READ BEFORE DIGGING INTO THE FRAMEWORK Every search in the system goes through ONE interface: org.openedit.data.Searcher, handed out by bench.getSearcher(""), plus its QueryBuilder (searcher.query()). It is backed by the embedded OpenSearch node. Frames, thoughts, git repositories, notes, framememory/RAG - all the same API. It is already wired: do NOT reverse-engineer the search/index layer. Find the one existing entry point and copy its pattern; deep-reading the framework is how agent context explodes. Query: searcher.query().exact("f","v").contains("f","v").sort("f").search() -> HitTracker (an iterable of Data; .size(), .first()) semantic / kNN: term.setOperation("deepsearch") (already wired, no new code) Read/write/delete: searchById(id) / saveData(data, user) / delete(data, user) / createNewData() Add a type: drop WEB-INF/base/tf-eclipse/system/data/fields/.xml (copy an existing one, e.g. comment.xml; beanname="dataSearcher" = OpenSearch-backed). The filename IS the searchtype; the index is created on demand. Then call bench.getSearcher(""). Minimal add/search/delete example: agent/thought.*. Agent memory: the "thought" searcher (beanname="thoughtSearcher", fields/thought.xml) is the agent's persistent, frame-linked memory (it indexes framepath + proximity). Write rows with messagetype=note to share that index but stay filterable. Lists / taxonomy: a list-typed field is ``; the target type needs fields/.xml (id, name, [parent for hierarchy]) + lists/.xml (the values). See thoughttag (hierarchical) and thoughtstatus. Multi-value fields use "|" between values. Query keyword/list fields with .exact (or .orgroup for a set): .contains/.match are full-text and will NOT match them (e.g. framewithinN, tags, status). Notes - rename and move run Eclipse's real refactoring engine (LTK) and update references. - formatAll, write, delete, moveFile, copy, git commit mutate the real workspace. - "path" is a reserved OpenEdit page value; these verbs read the request parameter directly, so passing ?path= works as documented. - Debug/test verbs return empty/zero when nothing is running - that is not an error. - Adding a verb: a script page (write NAME.groovy + NAME.xconf + NAME.html in this folder) is the fastest path. A Groovy module (class + plugin.xml under frames/MODULE/) needs reloadframeplugins after adding or editing it. A Java module needs an engine rebuild and a plugin restart. - Golden rule: if a capability feels like it "should already exist", it probably does and is already wired (search, index, memory, git, frames). Find the single existing entry point and copy its pattern - do not reverse-engineer the framework top-to-bottom. Deep-reading source to rediscover a wired API is what makes agent context explode. - If it looks unwired and you are about to deep-read to find out, STOP AND ASK the user first. Spelunking is how the context blows up; the user knows what is already there.