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
3 changes: 1 addition & 2 deletions packages/core/examples/sampling/01-basic-composition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ export const toolDefinitions: ComposeDefinition[] = [
{
name: "file-organizer",
options: {
sampling: true,
mode: "agentic_workflow",
mode: "agentic_sampling",
},
description:
`I am a smart file organizer that helps users manage their files efficiently.
Expand Down
74 changes: 74 additions & 0 deletions packages/core/src/executors/agentic/agentic-sampling-registrar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { jsonSchema } from "../../utils/schema.ts";
import type { SamplingConfig } from "../../types.ts";
import { createGoogleCompatibleJSONSchema } from "../../utils/common/provider.ts";
import type { ComposableMCPServer } from "../../compose.ts";
import { CompiledPrompts } from "../../prompts/index.ts";
import { SamplingExecutor } from "../sampling/agentic-sampling-executor.ts";
import type { ExternalTool } from "../sampling/base-sampling-executor.ts";
import { createArgsDefFactory } from "../../factories/args-def-factory.ts";

export interface RegisterAgenticSamplingToolParams {
description: string;
name: string;
allToolNames: string[];
depGroups: Record<string, unknown>;
toolNameToDetailList: [string, unknown][];
samplingConfig?: SamplingConfig;
}

export function registerAgenticSamplingTool(
server: ComposableMCPServer,
{
description,
name,
allToolNames,
depGroups,
toolNameToDetailList,
samplingConfig,
}: RegisterAgenticSamplingToolParams,
) {
const createArgsDef = createArgsDefFactory(
name,
allToolNames,
depGroups,
undefined,
undefined,
);

// Create sampling executor
const samplingExecutor = new SamplingExecutor(
name,
description,
allToolNames,
toolNameToDetailList as [string, ExternalTool][],
server,
samplingConfig,
);

// Use sampling-specific prompt
description = CompiledPrompts.samplingExecution({
toolName: name,
description,
toolList: allToolNames.map((name) => `- ${name}`).join("\n"),
});

// Use sampling-specific args definition
const argsDef = createArgsDef.forSampling();
const schema = allToolNames.length > 0
? argsDef
: { type: "object", properties: {} };

server.tool(
name,
description,
jsonSchema<Record<string, unknown>>(
createGoogleCompatibleJSONSchema(schema as Record<string, unknown>),
),
async (args: Record<string, unknown>) => {
return await samplingExecutor.executeSampling(
args,
schema as Record<string, unknown>,
);
},
);
}
48 changes: 9 additions & 39 deletions packages/core/src/executors/agentic/agentic-tool-registrar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import { createGoogleCompatibleJSONSchema } from "../../utils/common/provider.ts
import type { ComposableMCPServer } from "../../compose.ts";
import { CompiledPrompts } from "../../prompts/index.ts";
import { AgenticExecutor } from "./agentic-executor.ts";
import { SamplingExecutor } from "../sampling/agentic-sampling-executor.ts";
import type { ExternalTool } from "../sampling/base-sampling-executor.ts";
import { createArgsDefFactory } from "../../factories/args-def-factory.ts";

export function registerAgenticTool(
Expand All @@ -16,7 +14,6 @@ export function registerAgenticTool(
allToolNames,
depGroups,
toolNameToDetailList,
sampling = false,
}: RegisterToolParams,
) {
const createArgsDef = createArgsDefFactory(
Expand All @@ -27,44 +24,25 @@ export function registerAgenticTool(
undefined,
);

// Determine if sampling mode is enabled and extract config
const isSamplingMode = sampling === true || typeof sampling === "object";
const samplingConfig = typeof sampling === "object" ? sampling : undefined;

// Create executors
// Create executor
const agenticExecutor = new AgenticExecutor(
name,
allToolNames,
toolNameToDetailList,
server,
);

const samplingExecutor = new SamplingExecutor(
name,
description = CompiledPrompts.autonomousExecution({
toolName: name,
description,
allToolNames,
toolNameToDetailList as [string, ExternalTool][],
server,
samplingConfig,
);

description = isSamplingMode
? CompiledPrompts.samplingExecution({
toolName: name,
description,
toolList: allToolNames.map((name) => `- ${name}`).join("\n"),
})
: CompiledPrompts.autonomousExecution({
toolName: name,
description,
});
});

const agenticArgsDef = createArgsDef.forAgentic(
toolNameToDetailList,
false, // not sampling mode
);
const argsDef: Schema<Record<PropertyKey, never>>["jsonSchema"] =
isSamplingMode ? createArgsDef.forSampling() : agenticArgsDef;
agenticArgsDef;
const schema = allToolNames.length > 0
? argsDef
: { type: "object", properties: {} };
Expand All @@ -76,18 +54,10 @@ export function registerAgenticTool(
createGoogleCompatibleJSONSchema(schema as Record<string, unknown>),
),
async (args: Record<string, unknown>) => {
// Use appropriate executor based on mode
if (isSamplingMode) {
return await samplingExecutor.executeSampling(
args,
schema as Record<string, unknown>,
);
} else {
return await agenticExecutor.execute(
args,
schema as Record<string, unknown>,
);
}
return await agenticExecutor.execute(
args,
schema as Record<string, unknown>,
);
},
);
}
101 changes: 101 additions & 0 deletions packages/core/src/executors/workflow/workflow-sampling-registrar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { jsonSchema } from "../../utils/schema.ts";
import type { SamplingConfig } from "../../types.ts";
import type { MCPCStep } from "../../utils/state.ts";
import { WorkflowState } from "../../utils/state.ts";
import { createGoogleCompatibleJSONSchema } from "../../utils/common/provider.ts";
import type { ComposableMCPServer } from "../../compose.ts";
import { CompiledPrompts } from "../../prompts/index.ts";
import { createArgsDefFactory } from "../../factories/args-def-factory.ts";
import { WorkflowSamplingExecutor } from "../sampling/workflow-sampling-executor.ts";
import type { ExternalTool } from "../sampling/base-sampling-executor.ts";

export interface RegisterWorkflowSamplingToolParams {
description: string;
name: string;
allToolNames: string[];
depGroups: Record<string, unknown>;
toolNameToDetailList: [string, unknown][];
predefinedSteps?: MCPCStep[];
samplingConfig?: SamplingConfig;
ensureStepActions?: string[];
toolNameToIdMapping?: Map<string, string>;
}

export function registerWorkflowSamplingTool(
server: ComposableMCPServer,
{
description,
name,
allToolNames,
depGroups,
toolNameToDetailList,
predefinedSteps,
samplingConfig,
ensureStepActions,
toolNameToIdMapping: _toolNameToIdMapping,
}: RegisterWorkflowSamplingToolParams,
) {
const createArgsDef = createArgsDefFactory(
name,
allToolNames,
depGroups,
predefinedSteps,
ensureStepActions,
);

// Create sampling executor
const workflowSamplingExecutor = new WorkflowSamplingExecutor(
name,
description,
allToolNames,
toolNameToDetailList as [string, ExternalTool][],
createArgsDef,
server,
predefinedSteps,
samplingConfig,
);

const workflowState = new WorkflowState();

// Use sampling-specific prompt
const baseDescription = CompiledPrompts.samplingExecution({
toolName: name,
description,
toolList: allToolNames.map((name) => `- ${name}`).join("\n"),
});

// Use sampling-specific args definition
const argsDef = createArgsDef.forSampling();

const schema = allToolNames.length > 0
? argsDef
: { type: "object", properties: {} };

server.tool(
name,
baseDescription,
jsonSchema<Record<string, unknown>>(
createGoogleCompatibleJSONSchema(schema as Record<string, unknown>),
),
async (args: Record<string, unknown>) => {
try {
return await workflowSamplingExecutor.executeWorkflowSampling(
args,
schema as Record<string, unknown>,
workflowState,
);
} catch (error) {
workflowState.reset();
return {
content: [
{
type: "text",
text: `Workflow execution error: ${(error as Error).message}`,
},
],
isError: true,
};
}
},
);
}
62 changes: 14 additions & 48 deletions packages/core/src/executors/workflow/workflow-tool-registrar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { WorkflowExecutor } from "./workflow-executor.ts";
import type { ComposableMCPServer } from "../../compose.ts";
import { CompiledPrompts } from "../../prompts/index.ts";
import { createArgsDefFactory } from "../../factories/args-def-factory.ts";
import { WorkflowSamplingExecutor } from "../sampling/workflow-sampling-executor.ts";
import type { ExternalTool } from "../sampling/base-sampling-executor.ts";

export function registerAgenticWorkflowTool(
server: ComposableMCPServer,
Expand All @@ -18,7 +16,6 @@ export function registerAgenticWorkflowTool(
depGroups,
toolNameToDetailList,
predefinedSteps,
sampling = false,
ensureStepActions,
toolNameToIdMapping,
}: RegisterWorkflowToolParams,
Expand All @@ -31,11 +28,7 @@ export function registerAgenticWorkflowTool(
ensureStepActions,
);

// Determine if sampling mode is enabled and extract config
const isSamplingMode = sampling === true || typeof sampling === "object";
const samplingConfig = typeof sampling === "object" ? sampling : undefined;

// Create executors
// Create executor
const workflowExecutor = new WorkflowExecutor(
name,
allToolNames,
Expand All @@ -47,44 +40,26 @@ export function registerAgenticWorkflowTool(
toolNameToIdMapping,
);

const workflowSamplingExecutor = new WorkflowSamplingExecutor(
name,
description,
allToolNames,
toolNameToDetailList as [string, ExternalTool][],
createArgsDef,
server,
predefinedSteps,
samplingConfig,
);

const workflowState = new WorkflowState();

const planningInstructions = predefinedSteps
? "- Set `init: true` (steps are predefined)"
: "- Set `init: true` and define complete `steps` array";

// Generate description based on mode
const baseDescription = isSamplingMode
? CompiledPrompts.samplingExecution({
toolName: name,
description,
toolList: allToolNames.map((name) => `- ${name}`).join("\n"),
})
: CompiledPrompts.workflowExecution({
toolName: name,
description: description,
planningInstructions,
});
// Generate description
const baseDescription = CompiledPrompts.workflowExecution({
toolName: name,
description: description,
planningInstructions,
});

// Generate schema based on mode
const argsDef = isSamplingMode
? createArgsDef.forSampling()
: createArgsDef.forTool();
// Generate schema
const argsDef = createArgsDef.forTool();

const toolDescription = isSamplingMode
? baseDescription
: createArgsDef.forToolDescription(baseDescription, workflowState);
const toolDescription = createArgsDef.forToolDescription(
baseDescription,
workflowState,
);

server.tool(
name,
Expand All @@ -94,16 +69,7 @@ export function registerAgenticWorkflowTool(
),
async (args: Record<string, unknown>) => {
try {
// Use appropriate executor based on mode
if (isSamplingMode) {
return await workflowSamplingExecutor.executeWorkflowSampling(
args as Record<string, unknown>,
argsDef as Record<string, unknown>,
workflowState,
);
} else {
return await workflowExecutor.execute(args, workflowState);
}
return await workflowExecutor.execute(args, workflowState);
} catch (error) {
workflowState.reset();
return {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/plugin-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export interface AgentToolRegistrationContext {
hiddenToolNames: string[];
options: {
mode?: string;
sampling?: boolean | { maxIterations?: number; summarize?: boolean };
samplingConfig?: { maxIterations?: number; summarize?: boolean };
steps?: Array<{ description: string; actions: string[] }>;
ensureStepActions?: string[];
[key: string]: unknown;
Expand Down
Loading