Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ Spec drift is never "someone else's problem to fix later." It compounds.

---

## Rule 7: Place helper functions at the end of implementation files

When adding or refactoring helper functions in source files, place them after the main class/function implementations (i.e. helper functions last in the file), unless language constraints require otherwise.

---

## Verification Checklist

Run this checklist after every non-trivial change:
Expand Down
12 changes: 11 additions & 1 deletion packages/core/src/agent-session-do.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import type {
} from "@piccolo/api";
import type { FinishReason, LanguageModel, LanguageModelUsage, ModelMessage } from "ai";
import { stepCountIs, streamText } from "ai";
import { createAiGateway } from "ai-gateway-provider";
import { createUnified } from "ai-gateway-provider/providers/unified";
import { agentCompact, splitForCompaction } from "./agent-compact.ts";
import { toAiSdkTools } from "./agent-tools.ts";
import type {
Expand All @@ -57,7 +59,6 @@ import type {
import { generateEntryId, isLegacySystemMessageData, parseEntry } from "./db/entry-types.ts";
import { getEntries, getSession } from "./db/schema.ts";
import { ExtensionRunner } from "./extension-runner.ts";
import { createModel } from "./gateway.ts";
import { Messages } from "./messages.ts";
import { ObservableImpl } from "./observable-impl.ts";
import { buildSessionContext, walkToRoot } from "./session/context.ts";
Expand Down Expand Up @@ -1196,3 +1197,12 @@ function estimateTokens(messages: ModelMessage[]): number {
}
return Math.ceil(chars / 4);
}

function createModel(env: Env, modelId: string): LanguageModel {
const gateway = createAiGateway({
accountId: env.CF_ACCOUNT_ID,
gateway: env.CF_AI_GATEWAY_NAME,
apiKey: env.CF_AI_GATEWAY_TOKEN,
});
return gateway(createUnified()(modelId)) as LanguageModel;
}
41 changes: 0 additions & 41 deletions packages/core/src/gateway.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/core/test/do/mock-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* Mirrors packages/agent/test/mock-gateway.ts but is kept separate so
* packages/agent's test helpers do not need to be part of its public API.
*
* The `AgentSessionDO` constructor calls `createModel(env, modelId)` from
* gateway.ts which uses ai-gateway-provider. Tests bypass the real gateway by
* The `AgentSessionDO` constructor calls an internal `createModel(env, modelId)`
* helper that uses ai-gateway-provider. Tests bypass the real gateway because
* overriding `createModel` is not viable inside a Durable Object context.
*
* Instead, tests use `runInDurableObject` to reach directly into the DO
Expand Down
4 changes: 2 additions & 2 deletions specs/core.md
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ async newSession(
b. Derive `sessionId = this.ctx.id.name` (the DO was named with `idFromName(uuid)`).
c. Set `state.sessionId`, `state.userId`, `state.modelId`, `state.name` where `state.name = options.name ?? sessionId`.
d. Persist `sessionId`, `modelId`, and `name` to DO storage for cold-start recovery.
e. Reconstruct the `LanguageModel` via `createModel(env, modelId)`.
e. Reconstruct the `LanguageModel` via the internal `createModel(env, modelId)` helper in `agent-session-do.ts`.
2. Return `getSession(userId)` — the DO's own `SessionImpl` RpcTarget.

The D1 `sessions` row is **not** written here — it is written lazily on the first persisted entry append (see §Lazy session creation).
Expand Down Expand Up @@ -871,4 +871,4 @@ Uses `generateText` (non-streaming) with the same `LanguageModel` as the DO. Cal

### LLM Backend

All LLM calls go through the **Cloudflare AI Gateway** unified endpoint. `createModel(env, modelId)` in `gateway.ts` constructs the `LanguageModel` via `ai-gateway-provider`. Models are addressed as `{provider}/{model-id}` (e.g. `anthropic/claude-sonnet-4-5`). `piccolo-core` constructs the model; the `Agent` class has no knowledge of how it was built.
All LLM calls go through the **Cloudflare AI Gateway** unified endpoint. `createModel(env, modelId)` in `agent-session-do.ts` constructs the `LanguageModel` via `ai-gateway-provider`. Models are addressed as `{provider}/{model-id}` (e.g. `anthropic/claude-sonnet-4-5`). `piccolo-core` constructs the model; the `Agent` class has no knowledge of how it was built.
4 changes: 2 additions & 2 deletions specs/implementation_plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ The Durable Object that owns a live session. Wires `piccolo-agent` to persistenc
| `packages/core/src/do/agent-session.ts` | `AgentSessionDO` class — full DO implementation |
| `packages/core/src/do/compaction.ts` | `compact()` helper; creates `CompactionEntry`, calls `agentCompact()` |
| `packages/core/src/do/retry.ts` | `checkRetry()` with exponential backoff, transient/overflow classification |
| `packages/core/src/do/gateway.ts` | `createModel()` — wraps `ai-gateway-provider` with env bindings |
| `packages/core/src/agent-session-do.ts` | Internal `createModel()` helper — wraps `ai-gateway-provider` with env bindings |
| `packages/core/src/do/system-prompt.ts` | `buildBasePrompt(agentName)` — renders the base prompt template |
| `packages/core/src/do/stubs.ts` | `ExtensionRunnerStub`, `SystemPromptAssemblerStub` — no-op stubs for steps 6–7 |
| `packages/core/src/do/types-internal.ts` | `SystemPromptAddition`, `MODEL_CATALOG`, `resolveModel()` |
Expand Down Expand Up @@ -514,7 +514,7 @@ The Worker that serves the Cap'n Web RPC endpoint and proxies to `piccolo-core`.

### 10.1 Implementation Notes

**Status:** Complete. 51 tests pass (383 total across all packages), coverage above thresholds. `pnpm biome check .` passes with 1 pre-existing `noNonNullAssertion` warning. `pnpm -r exec tsc --noEmit` has one pre-existing error in `packages/core/src/gateway.ts` (unrelated to step 10).
**Status:** Complete. 51 tests pass (383 total across all packages), coverage above thresholds. `pnpm biome check .` passes with 1 pre-existing `noNonNullAssertion` warning. `pnpm -r exec tsc --noEmit` had one historical pre-existing error in the former `packages/core/src/gateway.ts` (unrelated to step 10).

**Post-review corrections (all changes fully spec-synced):**
1. `ITextUI.show*()` → `ITextUI.get*()` — direction fix: tool provides rendering text to gateway (pull), not gateway pushes to tool.
Expand Down
Loading