Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
feb91d1
test(server): pin a headless turn that waits on a person through the …
guidovizoso Oct 13, 2026
17481b1
test(server): pin how a hop treats a failed lock renewal and a Bot pa…
guidovizoso Oct 13, 2026
fcbb9db
refactor: make shared/ the @openbot/shared workspace and import it by…
guidovizoso Oct 13, 2026
c33f0d3
refactor(server): lift the hop's thread lock out of mountCopilotRunti…
guidovizoso Oct 13, 2026
17bb2dc
refactor(server): give the thread-history helpers their own module so…
guidovizoso Oct 13, 2026
903d635
refactor(server): move the headless tool contract and middleware to s…
guidovizoso Oct 13, 2026
3af0051
refactor(server): move the GrantedTool contract and parametersFor to …
guidovizoso Oct 13, 2026
0b6261f
refactor(server): inject a turn's admission into the turn runner inst…
guidovizoso Oct 13, 2026
684325d
refactor(server): hand the headless component tools an AuditSink inst…
guidovizoso Oct 13, 2026
a9f5aee
refactor(server): define AuditInitiator in src/toolkit and re-export …
guidovizoso Oct 13, 2026
2b2193d
refactor(server): move the approval continuation and the waiting meta…
guidovizoso Oct 13, 2026
647e776
refactor(server): give a headless turn its components through a Compo…
guidovizoso Oct 13, 2026
3b383ae
refactor(server): move the headless turn runner, its types and the hi…
guidovizoso Oct 13, 2026
1b0329b
chore(lint): forbid server, CopilotKit, Drizzle and Hono imports insi…
guidovizoso Oct 13, 2026
c90311e
refactor(toolkit): decide how a headless turn ended in one pure settl…
guidovizoso Oct 13, 2026
654f317
refactor: make the toolkit its own @openbot/toolkit workspace, outsid…
guidovizoso Oct 13, 2026
9f378bf
fix(toolkit): stop a turn only when its lock is renewed as somebody e…
guidovizoso Oct 13, 2026
afb2182
fix(server): admit a hop before it locks the conversation, and stop i…
guidovizoso Oct 13, 2026
a1ceb39
refactor(toolkit): name a headless turn's limits in TURN_LIMITS and d…
guidovizoso Oct 13, 2026
1f56cbb
docs(server): say that the platform applies its own lock lifetime wha…
guidovizoso Oct 13, 2026
671152f
refactor(server): name the built-in Bot's OpenAI fallback model and r…
guidovizoso Oct 13, 2026
af4d4f3
refactor(server): name the OAuth and delivery request timeouts that s…
guidovizoso Oct 13, 2026
dc3d752
fix(toolkit): ask for the platform's own 120-second lock lifetime on …
guidovizoso Oct 13, 2026
722e2b0
refactor(server): move Composio's vendor shapes and parsers out of th…
guidovizoso Oct 13, 2026
0ecf7de
refactor(server): split the plugin routes into one module per route g…
guidovizoso Oct 13, 2026
59ea7ce
refactor(server): move the approval resume loop out of index.ts into …
guidovizoso Oct 13, 2026
1e348c7
refactor(server): move the person-response loop out of index.ts into …
guidovizoso Oct 13, 2026
2e9aed2
refactor(server): move the Bun server and its websocket dispatch out …
guidovizoso Oct 13, 2026
21a7bfd
refactor(server): move starting handoff delivery out of index.ts into…
guidovizoso Oct 13, 2026
a038258
refactor(server): move the coordination tools and their per-run wrapp…
guidovizoso Oct 13, 2026
23ef858
refactor(server): split the plugin store into its model, a shared con…
guidovizoso Oct 13, 2026
1227508
refactor(server): split the Composio client into a shared context, it…
guidovizoso Oct 13, 2026
4ffe5db
refactor(toolkit): move the native approval wrapper into the toolkit …
guidovizoso Oct 13, 2026
a840426
refactor(toolkit): add the copilotkit adapters folder, starting with …
guidovizoso Oct 13, 2026
35281a5
refactor(toolkit): move the CopilotKit agent classes into the toolkit…
guidovizoso Oct 13, 2026
43bdcd4
refactor(server): declare what the approval service reads before it i…
guidovizoso Oct 13, 2026
c0a6a18
refactor(server): move the approval service's construction out of ind…
guidovizoso Oct 13, 2026
a2bb216
refactor(server): move the responsibility engine's construction out o…
guidovizoso Oct 13, 2026
d8ebe69
style(server): format copilot.ts's imports after moving the agent cla…
guidovizoso Oct 13, 2026
876a2ae
refactor(server): declare what index.ts's statements read before them…
guidovizoso Oct 13, 2026
d6e9f0b
Merge remote-tracking branch 'origin/main' into guido-refactor-8
guidovizoso Oct 13, 2026
efd8ef8
docs(changelog): say how Bot turns hold their conversation more caref…
guidovizoso Oct 13, 2026
0bc802f
fix(desktop): copy the toolkit workspace into a deployment, and finge…
guidovizoso Oct 13, 2026
2976821
fix(lint): stop the toolkit core importing its copilotkit folder thro…
guidovizoso Oct 13, 2026
68dc477
fix(server): normalise the model base URLs before the runtime model r…
guidovizoso Oct 13, 2026
7b18de8
fix(toolkit): lose a lease whose renewals have failed for its whole l…
guidovizoso Oct 13, 2026
135cbe2
test: pin the 120-second lock lifetime with a literal, not the consta…
guidovizoso Oct 13, 2026
c8eee04
fix(toolkit): give up on a lease one interval before its lock lapses,…
guidovizoso Oct 13, 2026
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
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,26 @@ Newest first. `Unreleased` is what is on `main` and not yet tagged.
`code_required` (below). A server and a computer must be upgraded together: an older computer has
no `/sign-in/code`.

### Bot turns hold their conversation more carefully

Routines, responsibilities, background research, wake-ups, group turns and Bot-to-Bot handoffs keep a
lock on the conversation while they run and renew it as they go.

- **A failed renewal no longer stops the turn.** Before, any failed renewal stopped a routine or
responsibility turn, including a network blip. A stopped turn is retried from the start, so a Bot
that had already sent an email could send it again. Now a turn stops when Intelligence says the
conversation belongs to another run (409), or when renewals have failed for so long that the lock
(120 seconds) would lapse before the next one, whatever the failures were. It stops while the lock
is still its own. A shorter blip rides through.
- **A handoff that loses its lock now stops.** Before, a handoff ignored every failed renewal and
kept writing, even into a person's own channel after they started typing there. Now it stops, gives
the conversation back and is retried a minute later.
- **A paused Bot's handoff no longer locks the conversation.** A handoff now checks that the Bot is
not paused, and that "Use Bots" and the model allowlist allow it, before taking the lock. Before,
every retry took the lock briefly and could refuse the person's own message.
- **Routine turns ask for a 120-second lock.** This is the lifetime Intelligence already applies, so
nothing changes on today's platform.

### A sign-in's verification code is asked for after the password

The private sign-in form used to ask for a username, a password and "a verification code, if the
Expand Down
9 changes: 8 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ COPY tsconfig.base.json bunfig.toml ./
COPY app/package.json app/package.json
COPY server/package.json server/package.json
COPY worker/package.json worker/package.json
COPY shared/package.json shared/package.json
COPY toolkit/package.json toolkit/package.json
RUN bun install --frozen-lockfile

# The lockfile travels with the manifest, because `--frozen-lockfile` with no lockfile in the context
Expand All @@ -68,10 +70,12 @@ RUN cd agent-computer && bun install --frozen-lockfile
# A second tree with the build-time dependencies left out, for the runtime stage to take. Vite,
# biome and the test tooling are a gigabyte that nothing in a running container imports.
RUN mkdir -p /prod && cp package.json bun.lock /prod/ \
&& cd /prod && mkdir -p app server worker \
&& cd /prod && mkdir -p app server worker shared toolkit \
&& cp /src/app/package.json app/package.json \
&& cp /src/server/package.json server/package.json \
&& cp /src/worker/package.json worker/package.json \
&& cp /src/shared/package.json shared/package.json \
&& cp /src/toolkit/package.json toolkit/package.json \
&& bun install --frozen-lockfile --production


Expand All @@ -80,6 +84,7 @@ FROM deps AS app-build
COPY app app
COPY scripts scripts
COPY shared shared
COPY toolkit toolkit
# The server's source as well: the app's prebuild step reads the tenant package through
# `server/src/tenant-package`, so the app cannot be built without it.
COPY server server
Expand Down Expand Up @@ -121,6 +126,7 @@ WORKDIR /app
# present and broken.
COPY --from=deps /prod/node_modules node_modules
COPY --from=deps /prod/server/node_modules server/node_modules
COPY --from=deps /prod/toolkit/node_modules toolkit/node_modules
COPY --from=deps /src/package.json package.json
COPY --from=deps /src/bun.lock bun.lock
# The browser's tree is a separate install root with its own lockfile rather than a workspace of the
Expand All @@ -130,6 +136,7 @@ COPY --from=deps /src/agent-computer/node_modules agent-computer/node_modules

COPY server server
COPY shared shared
COPY toolkit toolkit
COPY examples examples
COPY agent-computer/src agent-computer/src
COPY agent-computer/package.json agent-computer/package.json
Expand Down
1 change: 1 addition & 0 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@copilotkit/a2ui-renderer": "1.77.0",
"@copilotkit/react-core": "1.77.0",
"@fontsource-variable/inter": "^5.3.0",
"@openbot/shared": "workspace:*",
"@shadcn/react": "^0.3.0",
"@tabler/icons-react": "^3.36.1",
"@tanstack/react-form": "^1.33.5",
Expand Down
4 changes: 2 additions & 2 deletions app/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
*/

import { join, normalize, sep } from "node:path";
import { DICTATION_HTTP_IDLE_SECONDS } from "@openbot/shared/dictation";
import { listenPort } from "@openbot/shared/listen-port";
import { file, type ServerWebSocket } from "bun";
import { listenPort } from "../shared/listen-port";
import { DICTATION_HTTP_IDLE_SECONDS } from "../shared/dictation";

const DIST = join(import.meta.dir, "dist");
const appPort = listenPort(process.env.APP_PORT, 3010);
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/channels/attachments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ export {
mediaTypeOf,
namesNoFormat,
shouldClaimPaste,
} from "../../../../shared/attachments";
} from "@openbot/shared/attachments";
2 changes: 1 addition & 1 deletion app/src/lib/channels/responsibility-turn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
* See `routine-firing.ts` beside this file: the server builds the message from `shared/`, and the
* browser keeps importing through `@/`.
*/
export { readResponsibilityTurn } from "../../../../shared/responsibility-turn";
export { readResponsibilityTurn } from "@openbot/shared/responsibility-turn";
2 changes: 1 addition & 1 deletion app/src/lib/channels/routine-firing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
* once. This file exists so the browser code keeps importing through `@/`, and so the path to
* `shared/` is written down once rather than in every renderer.
*/
export { readFiring } from "../../../../shared/routine-firing";
export { readFiring } from "@openbot/shared/routine-firing";
4 changes: 2 additions & 2 deletions app/src/lib/computers/control.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import { tryClient } from "@/lib/client";
* should say nothing, not tear down the screen the person is looking at.
*/

export type { ComputerControlState as ControlState } from "../../../../shared/computer-control";
import type { ComputerControlState as ControlState } from "../../../../shared/computer-control";
export type { ComputerControlState as ControlState } from "@openbot/shared/computer-control";
import type { ComputerControlState as ControlState } from "@openbot/shared/computer-control";

async function callControl(
computerId: string,
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/computers/handoff.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {
BrowserChallenge,
HandoffRequest,
} from "../../../../shared/computer-control";
} from "@openbot/shared/computer-control";
import { callComputer, type ToolOutcome } from "./call";
import { cancelControl, readControl } from "./control";

Expand Down
5 changes: 1 addition & 4 deletions app/src/lib/copilot/gallery-tools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import {
type GalleryComponent,
galleryManifest,
} from "@/lib/copilot/gallery-registry";
import {
NOT_SHOWN,
NOT_SHOWN_TAIL,
} from "../../../../shared/component-markers";
import { NOT_SHOWN, NOT_SHOWN_TAIL } from "@openbot/shared/component-markers";

/**
* Register compiled gallery components once per name, scoped to the active Bot with `available`.
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/copilot/markers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
* file exists so the browser code keeps importing through `@/`, and so the path to `shared/` is
* written down once rather than in every renderer.
*/
export { HANDED_OVER, PUT_TO } from "../../../../shared/handoff-markers";
export { HANDED_OVER, PUT_TO } from "@openbot/shared/handoff-markers";
2 changes: 1 addition & 1 deletion app/src/lib/dictation/recording.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
dictationExtension,
dictationMediaType,
MAX_DICTATION_BYTES,
} from "../../../../shared/dictation";
} from "@openbot/shared/dictation";

export interface Recording {
/** Shared with the visualizer; the recorder owns this stream's lifetime. */
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/dictation/session.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MAX_DICTATION_SECONDS } from "../../../../shared/dictation";
import { MAX_DICTATION_SECONDS } from "@openbot/shared/dictation";
import type { Recording } from "./recording";

export type DictationState = {
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/learning/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
LearningDeliveryStatus,
LearningOverview,
LearningSettings,
} from "../../../../shared/learning";
} from "@openbot/shared/learning";

export const learningKeys = {
all: ["learning"] as const,
Expand Down
4 changes: 2 additions & 2 deletions app/src/lib/settings/message-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import {
} from "@tanstack/react-query";
import { currentUserQueryOptions } from "@/lib/auth/queries";
import { client } from "@/lib/client";
import type { UserPreferences } from "../../../../shared/user-preferences";
import type { UserPreferences } from "@openbot/shared/user-preferences";
import { settingsKeys } from "./queries";

export type { MessageListEmphasis } from "../../../../shared/user-preferences";
export type { MessageListEmphasis } from "@openbot/shared/user-preferences";

export function userPreferencesQueryOptions(userId: string | undefined) {
return queryOptions({
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/voice/archive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
SaveVoiceSessionInput,
VoiceSessionPage,
VoiceSessionRecord,
} from "../../../../shared/voice-session";
} from "@openbot/shared/voice-session";
import { closingOf } from "./cut";
import {
forgetVoiceCall,
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/voice/outbox.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SaveVoiceSessionInput } from "../../../../shared/voice-session";
import type { SaveVoiceSessionInput } from "@openbot/shared/voice-session";
import { authKeys, type AuthenticatedUser } from "@/lib/auth/queries";
import { queryClient } from "@/query-client";

Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/voice/session.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { SaveVoiceSessionInput } from "../../../../shared/voice-session";
import type { SaveVoiceSessionInput } from "@openbot/shared/voice-session";
import { closingOf, openingOf } from "./cut";
import { VOICE_CONTEXT_ITEM_ID, VoiceTranscript } from "./transcript";
import type { ConnectVoice, VoiceConnection, VoiceEvent } from "./types";
Expand Down
2 changes: 1 addition & 1 deletion app/src/lib/voice/transcript.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { VoiceTranscriptEntry } from "../../../../shared/voice-session";
import type { VoiceTranscriptEntry } from "@openbot/shared/voice-session";
import type { VoiceEvent } from "./types";

export const VOICE_CONTEXT_ITEM_ID = "openbot-voice-context";
Expand Down
2 changes: 1 addition & 1 deletion app/src/routes/_authed/admin/learning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type {
LearningAutoAssignState,
LearningSettings,
LearningTarget,
} from "../../../../../shared/learning";
} from "@openbot/shared/learning";

export const Route = createFileRoute("/_authed/admin/learning")({
component: LearningPage,
Expand Down
2 changes: 1 addition & 1 deletion app/tests/computer-handoff.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import type {
ComputerControlState,
HandoffStatus,
} from "../../shared/computer-control";
} from "@openbot/shared/computer-control";
import {
awaitHandoff,
runHelpRequest,
Expand Down
2 changes: 1 addition & 1 deletion app/tests/learning-admin.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "@tanstack/react-router";
import { cleanup, fireEvent, render, waitFor } from "@testing-library/react";
import { LearningPage } from "@/routes/_authed/admin/learning";
import type { LearningSettings } from "../../shared/learning";
import type { LearningSettings } from "@openbot/shared/learning";

beforeAll(() => GlobalRegistrator.register());
afterAll(() => GlobalRegistrator.unregister());
Expand Down
2 changes: 1 addition & 1 deletion app/tests/person-sent-message.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
import { frameFiring } from "../../shared/routine-firing";
import { frameFiring } from "@openbot/shared/routine-firing";
import { isPersonSentMessage } from "../src/components/channels/chat-transcript";

/**
Expand Down
2 changes: 1 addition & 1 deletion app/tests/self-host-banner.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
import { authKeys } from "@/lib/auth/queries";
import { deploymentKeys } from "@/lib/deployment/queries";
import { userPreferencesQueryOptions } from "@/lib/settings/message-list";
import type { UserPreferences } from "../../shared/user-preferences";
import type { UserPreferences } from "@openbot/shared/user-preferences";

const originalFetch = globalThis.fetch;
const clients: QueryClient[] = [];
Expand Down
2 changes: 1 addition & 1 deletion app/tests/transcript-attachments.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from "@/components/channels/chat-transcript";
import type { QueuedMessage } from "@/components/channels/composer";
import { attachmentUrl } from "@/lib/channels/attachments";
import { frameFiring } from "../../shared/routine-firing";
import { frameFiring } from "@openbot/shared/routine-firing";
import { settleReactWork } from "./settle-react-work";

/**
Expand Down
2 changes: 1 addition & 1 deletion app/tests/user-preferences.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
saveUserPreferencesMutationOptions,
userPreferencesQueryOptions,
} from "@/lib/settings/message-list";
import type { UserPreferences } from "../../shared/user-preferences";
import type { UserPreferences } from "@openbot/shared/user-preferences";

const originalFetch = globalThis.fetch;
const clients: QueryClient[] = [];
Expand Down
2 changes: 1 addition & 1 deletion app/tests/voice-archive.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { afterEach, expect, mock, spyOn, test } from "bun:test";
import type { VoiceSessionRecord } from "../../shared/voice-session";
import type { VoiceSessionRecord } from "@openbot/shared/voice-session";
import {
loadVoiceArchive,
saveVoiceSession,
Expand Down
2 changes: 1 addition & 1 deletion app/tests/voice-outbox.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { afterAll, afterEach, beforeAll, expect, test } from "bun:test";
import { GlobalRegistrator } from "@happy-dom/global-registrator";
import type { SaveVoiceSessionInput } from "../../shared/voice-session";
import type { SaveVoiceSessionInput } from "@openbot/shared/voice-session";
import { authKeys } from "../src/lib/auth/queries";
import {
forgetVoiceCall,
Expand Down
2 changes: 1 addition & 1 deletion app/tests/voice-transcript.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect, test } from "bun:test";
import type { SaveVoiceSessionInput } from "../../shared/voice-session";
import type { SaveVoiceSessionInput } from "@openbot/shared/voice-session";
import {
VoiceTranscript,
VOICE_CONTEXT_ITEM_ID,
Expand Down
8 changes: 1 addition & 7 deletions app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,5 @@
"jsx": "react-jsx",
"lib": ["ES2024", "DOM", "DOM.Iterable"]
},
"include": [
"src",
"tests",
"vite.config.ts",
"../shared/handoff-markers.ts",
"../shared/listen-port.ts"
]
"include": ["src", "tests", "vite.config.ts"]
}
2 changes: 1 addition & 1 deletion app/vite-listen-port.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, test } from "bun:test";
import { listenPort } from "../shared/listen-port";
import { listenPort } from "@openbot/shared/listen-port";

/**
* The app Vite config used `Number.parseInt(process.env.APP_PORT ?? "3010", 10)` (and the same
Expand Down
2 changes: 1 addition & 1 deletion app/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import tailwindcss from "@tailwindcss/vite";
import { tanstackRouter } from "@tanstack/router-plugin/vite";
import react from "@vitejs/plugin-react";
import { defineConfig, type Plugin } from "vite";
import { listenPort } from "../shared/listen-port";
import { listenPort } from "@openbot/shared/listen-port";

/*
* Announce the server's port to the two runtimes that serve the app through Vite, and to no other.
Expand Down
67 changes: 67 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,73 @@
}
}
},
{
"includes": ["toolkit/src/**", "!toolkit/src/copilotkit/**"],
"linter": {
"rules": {
"style": {
"noRestrictedImports": {
"level": "error",
"options": {
"patterns": [
{
"group": ["../**"],
"message": "The toolkit runs turns without the server. Take what it needs as a port in toolkit/ports.ts instead of importing server code."
},
{
"group": [
"./copilotkit/**",
"@openbot/toolkit/copilotkit",
"@openbot/toolkit/copilotkit/**"
],
"message": "The toolkit core does not depend on CopilotKit. Code that needs @copilotkit/runtime lives in toolkit/src/copilotkit and imports the core, not the other way round."
},
{
"group": [
"@copilotkit/**",
"drizzle-orm",
"drizzle-orm/**",
"hono",
"hono/**"
],
"message": "The toolkit core depends on @ag-ui, rxjs, zod and @openbot/shared only. CopilotKit-specific code goes in toolkit/src/copilotkit."
}
]
}
}
}
}
}
},
{
"includes": ["toolkit/src/copilotkit/**"],
"linter": {
"rules": {
"style": {
"noRestrictedImports": {
"level": "error",
"options": {
"patterns": [
{
"group": ["../../**"],
"message": "The CopilotKit adapters run without the server. Take what they need as a port or a constructor option instead of importing server code."
},
{
"group": [
"drizzle-orm",
"drizzle-orm/**",
"hono",
"hono/**"
],
"message": "The CopilotKit adapters do not reach the database or the HTTP framework."
}
]
}
}
}
}
}
},
{
"includes": ["app/src/components/ui/**"],
"linter": {
Expand Down
Loading
Loading