You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: remove hosted provider and expand agent workflows
## Related Issue
No linked issue. This is a maintainer-directed repository update.
## Problem
The built-in hosted-provider path duplicated provider configuration,
authentication, usage, feedback, model aliases, and SDK behavior. Agent
runtime ownership and MCP management also needed one consistent engine
boundary.
## What changed
- Remove the built-in hosted provider, its bundled datasource plugin,
and the related sign-in, usage, feedback, model-alias, web, CLI, ACP,
and SDK surfaces.
- Move durable agent features onto per-agent actor runtimes. Add
`xstate` because these runtimes use explicit state machines for goals,
cron, todo, interaction, and dynamic-workflow state.
- Add MCP management through agent-core-v2, klient, node-sdk, and
`/api/v2/mcp`. The management surface is disabled unless
`PYTHINKER_CODE_EXPERIMENTAL_MCP_MANAGEMENT=1`; the versioned `/api/v2`
route prefix stays stable.
- Add `@fastify/rate-limit` because the five MCP authentication routes
need one shared source limit through Fastify's supported request
lifecycle. The package is Fastify-maintained, MIT-licensed, and has no
production audit findings.
- Add workspace-independent multi-root file suggestions, Tower mode
wiring, fork parameters, dynamic-workflow timeouts, turn-level
tool-repeat tracking, and the matching web and transcript behavior.
- Harden storage-path resolution, model-catalog writes, prompt
redaction, OAuth normalization, Vertex endpoint parsing, and browser
asset reads.
- Update user documentation, release changesets, Nix inputs, generated
web assets, and product-boundary checks.
## Breaking change
The built-in hosted provider and its public authentication and SDK
methods are removed. Configure a supported provider with its own API key
or OAuth flow instead. The approved changeset gives
`@pymodel/pythinker-code` a major bump.
## Verification
- `pnpm install --frozen-lockfile`
- `pnpm build`
- `pnpm test` — 1,215 files passed; 20,299 tests passed
- `pnpm lint` — 0 errors
- `pnpm typecheck`
- `npx tsgo -p packages/agent-core-v2/tsconfig.json --noEmit`
- `npx tsgo -p packages/agent-gateway/tsconfig.json --noEmit`
- `nix build .#pythinker-code`
- `node scripts/check-nix-workspace.mjs` — 18/18 workspaces
- `pnpm --filter pythinker-code-docs run build`
- `pnpm sherif`
- `pnpm audit --prod` — no known vulnerabilities
## Checklist
- [x] I have read the
[CONTRIBUTING](https://github.com/PyModel/pythinker-code/blob/main/CONTRIBUTING.md)
document.
- [ ] I have linked a related issue. No issue exists for this
maintainer-directed update.
- [x] I have added tests that prove the behavior works.
- [x] Ran `gen-changesets` skill.
- [x] Ran `gen-docs` skill.
Copy file name to clipboardExpand all lines: .agents/skills/agent-core-dev/SKILL.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,7 +33,7 @@ End-to-end procedures that span the stages. Reach for these before reading the s
33
33
34
34
## Stages
35
35
36
-
-[Stage 1 — Orient](orient.md): the DI black box (identity / dependencies / lifetime), the four`LifecycleScope` tiers and visibility, and the no-comment convention. Read before touching business code.
36
+
-[Stage 1 — Orient](orient.md): the DI black box (identity / dependencies / lifetime), the three`LifecycleScope` tiers and visibility, the separate workspace program lifetime, and the no-comment convention. Read before touching business code.
37
37
-[Stage 2 — Design a service](design.md): pick a scope, split a domain across scopes, choose a calling style (direct call vs event vs hook), and direct dependencies. Decide *where things live and who knows whom* before coding.
38
38
- Topic: [Domain boundaries vs Scope](domain-boundaries.md) — keep `session` / `agent` / `turn` from becoming god objects; data-ownership test and their split conclusions.
39
39
- Topic: [Persistence layering](persistence.md) — the three-layer `Store → Storage → backend` model, naming Stores by access pattern, and which layer business code should depend on.
└─ App services @App direct — persistence, config, telemetry, events
266
236
```
267
237
268
-
How the three lenses shaped it:
238
+
The App-scoped `IWorkspaceInstanceManager` owns `WorkspaceInstance` objects. Each instance owns a
239
+
`Program`. The Program constructs workspace resources and creates a `SessionLifecycleService`
240
+
with them. That service creates real `LifecycleScope.Session` children, and each session creates
241
+
`LifecycleScope.Agent` children. There is no workspace `IScopeHandle` and no Workspace value in
242
+
`LifecycleScope`.
269
243
270
-
-**Scope (§2)** → the live registry of one workspace's session scopes is per-handler, so it is Workspace-scoped; the process-wide handler registry lives in the App-scoped `workspaceLifecycle`; per-session data stays in Session-scoped services, reached through the handle's `accessor`.
271
-
-**Dependency direction (§5)** → `sessionLifecycle` is consumed by the edge via `accessor` borrows; it never imports the edge. Every downward arrow lands on a peer or a more foundational Service.
272
-
-**Extension points (§4)** → new per-session behavior plugs into the Session-scoped services (`sessionMetadata`, `agentLifecycle`, `sessionActivity`); new transports stay at the edge. Neither edits `sessionLifecycle`.
244
+
How the three lenses shape it:
273
245
246
+
-**Lifetime (§2)** → workspace state belongs to the Program; per-session state belongs to Session
247
+
scopes; per-agent state belongs to Agent scopes.
248
+
-**Dependency direction (§5)** → the Program receives App dependencies and passes workspace
249
+
resources into the session controller; business code does not import the edge.
250
+
-**Extension points (§4)** → new per-session behavior belongs in Session-scoped services; new
251
+
transports stay at the edge.
274
252
For a multi-scope split, the `exposes` block fills more than one scope — see the `records` pattern in §3.
| Open session scope registry |`sessionLifecycle`|Workspace-scope live handles, one registry per workspace handler (the process-wide handler registry is `workspaceLifecycle`); not the persisted entity table |
85
+
| Open session scope registry |`sessionLifecycle`|Program-owned controller with live Session handles; each workspace Program creates it from current workspace resources; not the persisted entity table |
86
86
| Session commands such as `archive()`|`session`| Orchestrates metadata, agent teardown, and events |
87
87
| Persisted session list / get / count |`sessionIndex`| Backend-neutral read model |
88
88
| Running / idle / awaiting status |`sessionActivity`| Derived from interactions and active turns; owns no state |
- The dispatcher resolves the **scope** from the URL, the **Service** from an `actionMap`, calls the method, wraps the result.
32
+
- The original dispatcher design resolves an address from the URL, selects a Service from an `actionMap`, calls the method, and wraps the result. A workspace URL identifies a program-owned resource; Workspace is not a `LifecycleScope` value.
33
33
34
34
```ts
35
35
// actionMap — the allowlist; hides internal domain names.
Copy file name to clipboardExpand all lines: .agents/skills/agent-core-dev/orient.md
+10-10Lines changed: 10 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -12,28 +12,28 @@ When writing business code you declare three things; the container handles the r
12
12
13
13
Classes talk only to interfaces and never care how an implementation is constructed.
14
14
15
-
## The four`LifecycleScope` tiers
15
+
## The three`LifecycleScope` tiers
16
16
17
-
Lifetimes form a tree, from longest to shortest:
17
+
DI lifetimes form a tree, from longest to shortest:
18
18
19
19
```text
20
20
App process-wide, single global instance
21
-
└── Workspace one workspace handler (a materialized workspace root)
22
-
└── Session one session
23
-
└── Agent one agent
21
+
└── Session one session
22
+
└── Agent one agent
24
23
```
25
24
26
25
```ts
27
-
// src/app/scopes.ts — the business layer declares the tiers and their order;
28
-
// the DI kernel only knows opaque string kinds plus the declared topology.
29
26
exportenumLifecycleScope {
30
27
App='app',
31
-
Workspace='workspace',
32
28
Session='session',
33
29
Agent='agent',
34
30
}
35
31
```
36
32
33
+
Workspace resources have a separate lifetime. The App-scoped `IWorkspaceInstanceManager`
34
+
materializes one `WorkspaceInstance` per workspace. Its `Program` constructs and disposes the
35
+
workspace services. `Workspace` is a domain identity, not a `LifecycleScope` value.
36
+
37
37
- Later in the topology = shorter life = closer to a leaf.
38
38
- "Singleton" means **one per scope**: `ILogService` is global once; each `Session` scope has its own `ISessionMetadata`.
39
39
-`kind` must advance along the declared topology in the parent→child direction.
@@ -49,7 +49,7 @@ A child scope sees its ancestors; a parent never sees its children. Resolution w
49
49
50
50
### Disposal order
51
51
52
-
Deterministic: **child scopes die first; within one scope, teardown runs in strict reverse registration order, one entry at a time.** The mechanism is the Ledger (`src/_base/lifecycle/`): ordered effect bookkeeping, dual-track (sync + async disposers), serial reverse-order teardown (never parallel), with the teardown reason (`'scope-close' | 'cascade' | 'unload'`) passed through to every disposer. `Disposable` / `DisposableStore` (`src/_base/di/lifecycle.ts`) delegate to it — "reverse construction order" is a Ledger property, not a container convention. Business code declares which tier it lives in and never disposes by hand.
52
+
Deterministic: **child scopes die first; within one scope, teardown runs in strict reverse registration order, one entry at a time.** The mechanism is the Ledger (`src/_base/lifecycle/`): ordered effect bookkeeping, dual-track (sync + async disposers), serial reverse-order teardown (never parallel), with the teardown reason (`'scope-close' | 'cascade' | 'unload'`) passed through to every disposer. `Disposable` / `DisposableStore` (`src/_base/di/lifecycle.ts`) delegate to it — "reverse construction order" is a Ledger property, not a container convention. Scoped business code declares its DI tier. Workspace programs explicitly own their manually constructed resources.
53
53
54
54
## Dynamic DI: units and cascades
55
55
@@ -68,7 +68,7 @@ There is no domain-layer numbering — a domain may import any other domain, gui
68
68
69
69
## Comment convention
70
70
71
-
`packages/agent-core-v2/AGENTS.md` bans comments: no file headers, no section banners, no statement-level narration — the code is the source of truth. The only exception is JSDoc attached to exported symbols, which flows into the generated `.d.ts` and the consumers' IDE hover. Tooling directives (`eslint-disable`, `@ts-expect-error`, …) are banned too: fix the underlying lint/type problem instead, and put negative type-safety cases in compiler-asserted fixtures. Scope is carried by the filename: `workspace*.ts` = Workspace, `session*.ts` = Session, `agent*.ts` = Agent, no prefix = App (see service-authoring.md).
71
+
`packages/agent-core-v2/AGENTS.md` bans comments: no file headers, no section banners, no statement-level narration — the code is the source of truth. The only exception is JSDoc attached to exported symbols, which flows into the generated `.d.ts` and the consumers' IDE hover. Tooling directives (`eslint-disable`, `@ts-expect-error`, …) are banned too: fix the underlying lint/type problem instead, and put negative type-safety cases in compiler-asserted fixtures. DI scope is carried by registration: `LifecycleScope.App`, `LifecycleScope.Session`, or `LifecycleScope.Agent`. A `workspace*` filename marks workspace-domain ownership, not a DI scope (see service-authoring.md).
0 commit comments