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
5 changes: 5 additions & 0 deletions .changeset/fresh-connection-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eve": patch
---

Compile `connection_search` as an ordinary dynamic tool source and keep discovered connection tools exclusively in durable context. Existing sessions without that context search again instead of reconstructing tools from message history.
1 change: 1 addition & 0 deletions packages/eve/src/cli/dev/tui/tool-presentation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ describe("presentTool", () => {
agent: { message: "audit the auth flow" },
ask_question: { prompt: "Which environment?" },
bash: { command: "ls" },
connection_search: { keywords: "linear issues" },
glob: { pattern: "**/*.ts" },
grep: { pattern: "useEve" },
load_skill: { skill: "commit" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe("composeFrameworkSources", () => {

expect(result.manifest.tools.map((tool) => tool.logicalPath)).toEqual([
"tools/bash.ts",
"tools/connection_search.ts",
"tools/read_file.ts",
"tools/todo.ts",
"tools/web_fetch.ts",
Expand Down
38 changes: 38 additions & 0 deletions packages/eve/src/compiler/normalize-manifest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,13 @@ describe("compileAgentManifest", () => {
"web_fetch",
"write_file",
]);
expect(compiled.dynamicTools).toContainEqual(
expect.objectContaining({
logicalPath: "tools/connection_search.ts",
slug: "connection_search",
sourceId: "eve.framework-defaults:tools/connection_search.ts",
}),
);
});

it("compiles framework defaults through ordinary module bindings", async () => {
Expand Down Expand Up @@ -379,6 +386,37 @@ describe("compileAgentManifest", () => {
expect(compiled.bindings["eve.framework-defaults:tools/bash.ts"]).toBeUndefined();
});

it("lets an application tool replace the framework connection search resolver", async () => {
mocks.compileAgentConfig.mockResolvedValue(createConfig({ name: "root" }));
mocks.applicationDefinition.mockResolvedValue(
defineTool({
description: "Search a fixed connection index",
inputSchema: z.object({}),
execute: () => [],
}),
);

const compiled = await compileAgentManifest(
createAgentSourceManifest({
agentId: "root",
agentRoot: "/app/agent",
appRoot: "/app",
tools: [createModuleSourceRef({ logicalPath: "tools/connection_search.ts" })],
}),
);

expect(compiled.tools).toContainEqual(
expect.objectContaining({
name: "connection_search",
sourceId: "tools/connection_search.ts",
}),
);
expect(compiled.dynamicTools).not.toContainEqual(
expect.objectContaining({ slug: "connection_search" }),
);
expect(compiled.bindings["eve.framework-defaults:tools/connection_search.ts"]).toBeUndefined();
});

it("preserves ordered static instruction content, roles, and legacy definitions", async () => {
const manifest = createAgentSourceManifest({
agentId: "root",
Expand Down
2 changes: 2 additions & 0 deletions packages/eve/src/framework-sources/registry.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as bash from "./tools/bash.js";
import * as connectionSearch from "./tools/connection_search.js";
import * as readFile from "./tools/read_file.js";
import * as sandbox from "./sandbox.js";
import * as todo from "./tools/todo.js";
Expand All @@ -13,6 +14,7 @@ const frameworkAgentSource = defineProgrammaticAgentSource({
modules: [
{ logicalPath: "sandbox.ts", namespace: sandbox },
{ logicalPath: "tools/bash.ts", namespace: bash },
{ logicalPath: "tools/connection_search.ts", namespace: connectionSearch },
{ logicalPath: "tools/read_file.ts", namespace: readFile },
{ logicalPath: "tools/todo.ts", namespace: todo },
{ logicalPath: "tools/web_fetch.ts", namespace: webFetch },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "#runtime/framework-tools/connection-search-dynamic.js";
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import {
getAllFrameworkToolNames,
getFrameworkDynamicToolResolvers,
} from "#runtime/framework-tools/index.js";
import { getAllFrameworkToolNames } from "#runtime/framework-tools/index.js";
import {
getAllFrameworkChannelNames,
getFrameworkChannelDefinitions,
Expand Down Expand Up @@ -221,14 +218,14 @@ export function buildAgentInfoResponseFromManifest(
available: [...frameworkToolInfo.available, ...authoredTools],
authored: authoredTools,
disabledFramework: [...manifest.disabledFrameworkTools],
dynamic: [
...getFrameworkDynamicToolResolvers().map((resolver) =>
renderDynamicResolver(resolver, { origin: "framework" }),
),
...manifest.dynamicTools.map((resolver) =>
renderDynamicResolver(resolver, { origin: "authored" }),
),
],
dynamic: manifest.dynamicTools.map((resolver) =>
renderDynamicResolver(resolver, {
origin:
manifest.bindings[resolver.sourceId]?.owner.kind === "framework"
? "framework"
: "authored",
}),
),
framework: frameworkToolInfo.framework,
reserved: [WORKFLOW_TOOL_NAME, LOAD_SKILL_TOOL_NAME],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ROOT_COMPILED_AGENT_NODE_ID } from "#compiler/manifest.js";
import {
getAllFrameworkToolDefinitions,
getAllFrameworkToolNames,
getFrameworkDynamicToolResolvers,
getOptInFrameworkToolNames,
} from "#runtime/framework-tools/index.js";
import {
Expand Down Expand Up @@ -239,7 +238,7 @@ export function buildAgentInfoResponse(
if (config === undefined) {
throw new Error("Cannot inspect unresolved dynamic subagent resources as a root agent.");
}
const tools = buildToolInfo(agent, getRootDelegationToolNames(data.manifest));
const tools = buildToolInfo(agent, getRootDelegationToolNames(data.manifest), data.manifest);

return {
agent: {
Expand Down Expand Up @@ -384,11 +383,11 @@ function buildChannelInfo(agent: ResolvedAgent): AgentInfoChannels {
function buildToolInfo(
agent: ResolvedAgent,
delegationToolNames: ReadonlySet<string>,
manifest: CompiledAgentManifest,
): AgentInfoTools {
const authoredToolNames = new Set(agent.tools.map((tool) => tool.name));
const disabledFrameworkTools = new Set(agent.disabledFrameworkTools);
const allFrameworkToolNames = getAllFrameworkToolNames();
const dynamicFrameworkResolvers = getFrameworkDynamicToolResolvers();
const authored = agent.tools.map((tool) =>
renderTool(tool, {
origin: "authored",
Expand All @@ -405,14 +404,14 @@ function buildToolInfo(
available: [...frameworkInfo.available, ...authored],
authored,
disabledFramework: [...agent.disabledFrameworkTools],
dynamic: [
...dynamicFrameworkResolvers.map((resolver) =>
renderDynamicResolver(resolver, { origin: "framework" }),
),
...agent.dynamicToolResolvers.map((resolver) =>
renderDynamicResolver(resolver, { origin: "authored" }),
),
],
dynamic: agent.dynamicToolResolvers.map((resolver) =>
renderDynamicResolver(resolver, {
origin:
manifest.bindings[resolver.sourceId]?.owner.kind === "framework"
? "framework"
: "authored",
}),
),
framework: frameworkInfo.framework,
reserved: [WORKFLOW_TOOL_NAME, LOAD_SKILL_TOOL_NAME],
};
Expand Down
Loading
Loading