Skip to content

compact the architecture around the catalog, one connector per collection and one contract - #167

Merged
hkonsti merged 11 commits into
mainfrom
hkonsti/codebase-architecture-refactoring
Oct 30, 2026
Merged

hkonsti merged 11 commits into
mainfrom
hkonsti/codebase-architecture-refactoring

Conversation

@hkonsti

@hkonsti hkonsti commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Restructures the codebase so each concept lives in one place: a connector per collection, checked against the catalog by a test instead of refusing at run time; the home page's widget capabilities on those connectors, so a new integration joins the widgets by its connector alone; one @proxy/contracts package of zod schemas that the api types its handlers with and the web app parses with, the widget and field ids among them; and one api module per integration declaring its connectors, how it connects, what to revoke and what its sign-in didn't cover, from which the router mounts and disconnect and access checks run.

It also runs the two startup conversions once as data migrations, keeps the task column nothing reads one deploy longer (the instances before returned it on an update; finishAgentTask now selects what it updates, so the migration after the next deploy drops it), merges the two OpenRouter clients, keeps @proxy/db to its transactions with the harness rules and organization provisioning in the api on one store the tests fake, moves the seed onto the same functions and cipher, and documents the agent pages.

Behaviour to know: a built-in MCP integration added from now on needs its own data-migration entry to take over matching custom connections; a custom connection or old vault record that can't be read is logged and stays as it is rather than holding its data migration open on every start, only the provider or database out of reach leaves it to the next start; listing a run-only collection through the records routes answers 403 rather than 400; OpenRouter 401/402/403 for the widgets' model is unavailable rather than provider_unreachable; the web app rejects a widget id it doesn't know, so api and web deploy together; the seed's slug goes through the normal slug rules and a re-run also clears the demo user's pending tokens and grants.


Open workspace in Conductor

… them, and put the web app's error checks and loader unwrapping in one place
…ask column nothing read, call OpenRouter from one client, and move the agent and email provider lists out of the integrations
…ecords are only run, and check every one against the catalog instead of refusing at run time
…r, a notetaker or a drive on the collection's connector, so a widget works with any integration whose connector offers it
…chemas, the home page's widgets and their fields among them, so neither side retypes the other
…ts own, its connectors, how it is connected, what is undone at the provider and what its sign-in didn't cover, and mount, disconnect and check from the list of them
…h its login and works with the same tasks, connections, tools and activity log as over MCP
…hat a thread is told and the api provisions an organization, both on one store the tests fake, and the seed runs on the same functions and cipher as the api
… the contracts package the api now depends on
…s over what no start could do differently

Dropping AgentTask.lastStartedAt now would fail finishing a task on the instances still on the version before while a deploy replaces them: their update of a task returned every column. finishAgentTask selects what it updates, so the migration after the next deploy can drop it.

A custom connection whose credential can't be read, or an old vault record that can't be, no longer holds its data migration open, tried again and failing on every start of every instance: it is logged and stays as it is, and only what the next start might not meet, the provider or the database out of reach, leaves the migration to it.

A sub-agent is started on at least one entry, so it is run at all. The widget and field ids are written out, so the web app takes none of what the widgets tell the model into the browser. An integration's module is read by its id. A custom MCP server's callback route is named as its connect route is.
@hkonsti
hkonsti force-pushed the hkonsti/codebase-architecture-refactoring branch from 932ed39 to b2e406c Compare October 30, 2026 23:48
@hkonsti
hkonsti merged commit 7212b6d into main Oct 30, 2026
3 checks passed
@hkonsti
hkonsti deleted the hkonsti/codebase-architecture-refactoring branch October 30, 2026 23:51
ilya-bogin-keenable added a commit to keenableai/proxy that referenced this pull request Oct 31, 2026
A page Keenable found nothing at is not found, and one whose site turned its fetcher away for too many requests is out of reach for now, each with the address and what to try next, as Exa's and Parallel's are since personalagentproxy#165; one it couldn't reach is out of reach in its own words, and anything else stays in its words. As Exa is, it is asked for a little more of a page than is kept, so a page cut at 100,000 characters ends with the note saying so, and an empty page fails. Custom connections to api.keenable.ai move over on the next start through a data migration of their own, since instances have already run the one that moved the others'.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant