@combycode/llm-sdk 1.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/LICENSE +21 -0
- package/README.md +103 -0
- package/dist/agent/approval-types.d.ts +49 -0
- package/dist/agent/context-registry/layers.d.ts +39 -0
- package/dist/agent/context-registry/registry-internal.d.ts +14 -0
- package/dist/agent/context-registry/registry.d.ts +104 -0
- package/dist/agent/context-registry/types.d.ts +110 -0
- package/dist/agent/guardrail-types.d.ts +58 -0
- package/dist/agent/history-types.d.ts +40 -0
- package/dist/agent/history.d.ts +111 -0
- package/dist/agent/loop-config.d.ts +67 -0
- package/dist/agent/loop-internals.d.ts +46 -0
- package/dist/agent/loop-step-state.d.ts +20 -0
- package/dist/agent/loop.d.ts +133 -0
- package/dist/agent/tool-key.d.ts +3 -0
- package/dist/agent/types.d.ts +138 -0
- package/dist/bus/agent-bus.d.ts +99 -0
- package/dist/bus/async-context.browser.d.ts +13 -0
- package/dist/bus/async-context.d.ts +11 -0
- package/dist/bus/async-context.types.d.ts +14 -0
- package/dist/bus/hook-bus.d.ts +43 -0
- package/dist/bus/hook-map.d.ts +592 -0
- package/dist/helpers/agent.d.ts +32 -0
- package/dist/helpers/batch.d.ts +74 -0
- package/dist/helpers/calibration-store.d.ts +27 -0
- package/dist/helpers/calibration-types.d.ts +64 -0
- package/dist/helpers/chain.d.ts +30 -0
- package/dist/helpers/client-pool.d.ts +15 -0
- package/dist/helpers/client-resolver.d.ts +62 -0
- package/dist/helpers/collection.d.ts +19 -0
- package/dist/helpers/consolidate.d.ts +66 -0
- package/dist/helpers/content.d.ts +25 -0
- package/dist/helpers/conversation-export.d.ts +14 -0
- package/dist/helpers/conversation-zip.d.ts +28 -0
- package/dist/helpers/count-tokens.d.ts +26 -0
- package/dist/helpers/define-tool.d.ts +66 -0
- package/dist/helpers/delegate.d.ts +6 -0
- package/dist/helpers/embed.d.ts +24 -0
- package/dist/helpers/engine.d.ts +121 -0
- package/dist/helpers/estimate-types.d.ts +67 -0
- package/dist/helpers/estimate.d.ts +45 -0
- package/dist/helpers/estimator.d.ts +48 -0
- package/dist/helpers/handoff-types.d.ts +18 -0
- package/dist/helpers/handoff.d.ts +14 -0
- package/dist/helpers/llm.d.ts +24 -0
- package/dist/helpers/mcp.d.ts +82 -0
- package/dist/helpers/media.d.ts +58 -0
- package/dist/helpers/models.d.ts +36 -0
- package/dist/helpers/moderate-types.d.ts +73 -0
- package/dist/helpers/moderate.d.ts +13 -0
- package/dist/helpers/moderation-guardrail.d.ts +29 -0
- package/dist/helpers/observer.d.ts +36 -0
- package/dist/helpers/one-shot.d.ts +86 -0
- package/dist/helpers/parallel.d.ts +16 -0
- package/dist/helpers/realtime.d.ts +25 -0
- package/dist/helpers/route.d.ts +29 -0
- package/dist/helpers/select-model.d.ts +41 -0
- package/dist/helpers/server.d.ts +32 -0
- package/dist/helpers/transcribe.d.ts +36 -0
- package/dist/index.browser.js +38047 -0
- package/dist/index.d.ts +275 -0
- package/dist/index.js +37974 -0
- package/dist/llm/audio/voices.d.ts +7 -0
- package/dist/llm/client-config.d.ts +37 -0
- package/dist/llm/client-internal.d.ts +28 -0
- package/dist/llm/client.d.ts +68 -0
- package/dist/llm/providers/_shared/constants.d.ts +5 -0
- package/dist/llm/providers/_shared/response-utils.d.ts +8 -0
- package/dist/llm/providers/anthropic/batch.d.ts +19 -0
- package/dist/llm/providers/anthropic/constants.d.ts +13 -0
- package/dist/llm/providers/anthropic/files.d.ts +23 -0
- package/dist/llm/providers/anthropic/messages.d.ts +30 -0
- package/dist/llm/providers/google/batch.d.ts +20 -0
- package/dist/llm/providers/google/constants.d.ts +6 -0
- package/dist/llm/providers/google/embeddings.d.ts +15 -0
- package/dist/llm/providers/google/files.d.ts +22 -0
- package/dist/llm/providers/google/generate.d.ts +27 -0
- package/dist/llm/providers/google/interactions.d.ts +30 -0
- package/dist/llm/providers/google/media.d.ts +27 -0
- package/dist/llm/providers/google/realtime.d.ts +27 -0
- package/dist/llm/providers/openai/batch.d.ts +19 -0
- package/dist/llm/providers/openai/completions.d.ts +25 -0
- package/dist/llm/providers/openai/embeddings.d.ts +16 -0
- package/dist/llm/providers/openai/files.d.ts +23 -0
- package/dist/llm/providers/openai/media.d.ts +28 -0
- package/dist/llm/providers/openai/moderations.d.ts +19 -0
- package/dist/llm/providers/openai/realtime.d.ts +24 -0
- package/dist/llm/providers/openai/responses.d.ts +29 -0
- package/dist/llm/providers/openai/tiers.d.ts +13 -0
- package/dist/llm/providers/openai/transcription.d.ts +20 -0
- package/dist/llm/providers/openrouter/completions.d.ts +15 -0
- package/dist/llm/providers/openrouter/embeddings.d.ts +7 -0
- package/dist/llm/providers/openrouter/media.d.ts +25 -0
- package/dist/llm/providers/openrouter/responses.d.ts +17 -0
- package/dist/llm/providers/xai/batch.d.ts +19 -0
- package/dist/llm/providers/xai/completions.d.ts +24 -0
- package/dist/llm/providers/xai/files.d.ts +23 -0
- package/dist/llm/providers/xai/media.d.ts +27 -0
- package/dist/llm/providers/xai/responses.d.ts +20 -0
- package/dist/llm/realtime/session.d.ts +34 -0
- package/dist/llm/realtime/types.d.ts +66 -0
- package/dist/llm/server-state.d.ts +32 -0
- package/dist/llm/types/audio.d.ts +18 -0
- package/dist/llm/types/messages.d.ts +125 -0
- package/dist/llm/types/options.d.ts +51 -0
- package/dist/llm/types/provider.d.ts +39 -0
- package/dist/llm/types/request.d.ts +51 -0
- package/dist/llm/types/response.d.ts +36 -0
- package/dist/llm/types/schema-utils.d.ts +8 -0
- package/dist/llm/types/stream.d.ts +42 -0
- package/dist/llm/types/tiers.d.ts +11 -0
- package/dist/llm/types/tools.d.ts +20 -0
- package/dist/network/engine.d.ts +87 -0
- package/dist/network/errors.d.ts +14 -0
- package/dist/network/queue-state-config.d.ts +41 -0
- package/dist/network/queue-state.d.ts +45 -0
- package/dist/network/rate-limiter.d.ts +49 -0
- package/dist/network/realtime-connection.d.ts +40 -0
- package/dist/network/request-queue.d.ts +40 -0
- package/dist/network/semaphore.d.ts +12 -0
- package/dist/network/sse.d.ts +3 -0
- package/dist/network/types.d.ts +127 -0
- package/dist/plugins/batch/batcher.d.ts +45 -0
- package/dist/plugins/batch/strategy.d.ts +20 -0
- package/dist/plugins/batch/types.d.ts +54 -0
- package/dist/plugins/cache/cache.d.ts +50 -0
- package/dist/plugins/cache/file-store.d.ts +15 -0
- package/dist/plugins/cache/memory-store.d.ts +10 -0
- package/dist/plugins/cache/types.d.ts +28 -0
- package/dist/plugins/configuration/configuration.d.ts +71 -0
- package/dist/plugins/context-guard/facts.d.ts +14 -0
- package/dist/plugins/context-guard/guard.d.ts +27 -0
- package/dist/plugins/context-guard/strategies/layered.d.ts +24 -0
- package/dist/plugins/context-guard/strategies/truncate.d.ts +19 -0
- package/dist/plugins/context-guard/tools.d.ts +50 -0
- package/dist/plugins/context-guard/types.d.ts +110 -0
- package/dist/plugins/context-measurer/calibration/store.d.ts +19 -0
- package/dist/plugins/context-measurer/counter/count-api.d.ts +41 -0
- package/dist/plugins/context-measurer/counter/heuristic.d.ts +25 -0
- package/dist/plugins/context-measurer/counter/hybrid.d.ts +33 -0
- package/dist/plugins/context-measurer/counter/tiktoken.d.ts +13 -0
- package/dist/plugins/context-measurer/measurer.d.ts +49 -0
- package/dist/plugins/context-measurer/types.d.ts +40 -0
- package/dist/plugins/cost-collector/collector.d.ts +42 -0
- package/dist/plugins/cost-collector/cost-collector-internal.d.ts +58 -0
- package/dist/plugins/cost-collector/cost-collector-types.d.ts +42 -0
- package/dist/plugins/embeddings/types.d.ts +23 -0
- package/dist/plugins/files/attachment.d.ts +79 -0
- package/dist/plugins/files/provider-adapter.d.ts +37 -0
- package/dist/plugins/files/registry.d.ts +48 -0
- package/dist/plugins/files/strategy.d.ts +38 -0
- package/dist/plugins/internal-tools/backends/local.d.ts +12 -0
- package/dist/plugins/internal-tools/builtin/builtin.d.ts +21 -0
- package/dist/plugins/internal-tools/builtin/clarify.d.ts +12 -0
- package/dist/plugins/internal-tools/builtin/classify.d.ts +12 -0
- package/dist/plugins/internal-tools/builtin/score.d.ts +13 -0
- package/dist/plugins/internal-tools/builtin/structure.d.ts +11 -0
- package/dist/plugins/internal-tools/builtin/summarize.d.ts +19 -0
- package/dist/plugins/internal-tools/id.d.ts +12 -0
- package/dist/plugins/internal-tools/registry.d.ts +24 -0
- package/dist/plugins/internal-tools/runner/define.d.ts +7 -0
- package/dist/plugins/internal-tools/runner/json-enforcement.d.ts +3 -0
- package/dist/plugins/internal-tools/runner/runner.d.ts +47 -0
- package/dist/plugins/internal-tools/runner/template.d.ts +10 -0
- package/dist/plugins/internal-tools/runner/types.d.ts +57 -0
- package/dist/plugins/internal-tools/runner/variants.d.ts +34 -0
- package/dist/plugins/internal-tools/types.d.ts +80 -0
- package/dist/plugins/logger/console-sink.d.ts +26 -0
- package/dist/plugins/logger/logger.d.ts +38 -0
- package/dist/plugins/logger/types.d.ts +25 -0
- package/dist/plugins/mcp/base-transport.d.ts +58 -0
- package/dist/plugins/mcp/client.d.ts +92 -0
- package/dist/plugins/mcp/jsonrpc.d.ts +20 -0
- package/dist/plugins/mcp/oauth.d.ts +122 -0
- package/dist/plugins/mcp/sampling.d.ts +17 -0
- package/dist/plugins/mcp/tools.d.ts +20 -0
- package/dist/plugins/mcp/transport-http.d.ts +50 -0
- package/dist/plugins/mcp/transport-stdio.d.ts +23 -0
- package/dist/plugins/mcp/transport-ws.d.ts +32 -0
- package/dist/plugins/mcp/transport.d.ts +29 -0
- package/dist/plugins/mcp/types.d.ts +202 -0
- package/dist/plugins/mcp/url-guard.d.ts +70 -0
- package/dist/plugins/mcp/win-spawn.d.ts +20 -0
- package/dist/plugins/media/file-store.d.ts +24 -0
- package/dist/plugins/media/memory-store.d.ts +17 -0
- package/dist/plugins/media/output.d.ts +44 -0
- package/dist/plugins/media/source-image.d.ts +36 -0
- package/dist/plugins/media/types.d.ts +146 -0
- package/dist/plugins/model-catalog/catalog.d.ts +152 -0
- package/dist/plugins/permissions/glob.d.ts +6 -0
- package/dist/plugins/permissions/matchers.d.ts +7 -0
- package/dist/plugins/permissions/policy.d.ts +10 -0
- package/dist/plugins/permissions/types.d.ts +22 -0
- package/dist/plugins/persistence/file.d.ts +25 -0
- package/dist/plugins/persistence/memory.d.ts +23 -0
- package/dist/plugins/persistence/types.d.ts +21 -0
- package/dist/plugins/retrieval/chunker.d.ts +28 -0
- package/dist/plugins/retrieval/hosted-google.d.ts +60 -0
- package/dist/plugins/retrieval/hosted-openai.d.ts +45 -0
- package/dist/plugins/retrieval/hosted-xai.d.ts +57 -0
- package/dist/plugins/retrieval/index.d.ts +70 -0
- package/dist/plugins/retrieval/local.d.ts +50 -0
- package/dist/plugins/retrieval/types.d.ts +161 -0
- package/dist/plugins/retrieval/vector-store.d.ts +70 -0
- package/dist/plugins/scheduler/scheduler.d.ts +31 -0
- package/dist/plugins/telemetry/telemetry.d.ts +118 -0
- package/dist/plugins/tool-catalog/catalog.d.ts +31 -0
- package/dist/plugins/tool-catalog/errors.d.ts +22 -0
- package/dist/plugins/tool-catalog/types.d.ts +44 -0
- package/dist/runtime/runtime.d.ts +20 -0
- package/dist/server/auth.d.ts +25 -0
- package/dist/server/dispatch.d.ts +35 -0
- package/dist/server/loaders.d.ts +26 -0
- package/dist/server/oai-adapter.d.ts +30 -0
- package/dist/server/oai-types.d.ts +114 -0
- package/dist/server/response-store.d.ts +59 -0
- package/dist/server/router.d.ts +59 -0
- package/dist/server/server.d.ts +61 -0
- package/dist/types/request-context.d.ts +46 -0
- package/dist/util/async.d.ts +3 -0
- package/dist/util/base64.d.ts +8 -0
- package/dist/util/duration.d.ts +12 -0
- package/dist/util/http.d.ts +9 -0
- package/dist/util/image-mime.d.ts +8 -0
- package/dist/util/json-schema.d.ts +7 -0
- package/dist/util/wav.d.ts +20 -0
- package/package.json +95 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** InternalToolRunner — executes InternalTools with client pooling, fallback, hooks.
|
|
2
|
+
*
|
|
3
|
+
* Contract:
|
|
4
|
+
* 1. run(toolId, input) resolves tool → validates input → resolves models → executes.
|
|
5
|
+
* 2. Key availability is checked IMMEDIATELY after tool lookup, before execution:
|
|
6
|
+
* if no configured API key matches any of tool's required providers → throws.
|
|
7
|
+
* 3. Per attempt, skip models whose providers lack keys.
|
|
8
|
+
* 4. Emits onInternalToolCallStart/Complete/Error hooks.
|
|
9
|
+
* 5. Cost of underlying LLM calls is tracked via existing onCompletion (CostCollector).
|
|
10
|
+
*
|
|
11
|
+
* v2 adaptation: clients are built via the engine handle's adapter resolver
|
|
12
|
+
* (auto-discovers default adapter). The engine wires every LLMClient through
|
|
13
|
+
* the network queue; every tool's underlying HTTP therefore inherits queue
|
|
14
|
+
* rate-limit / retry / hook behavior automatically.
|
|
15
|
+
*/
|
|
16
|
+
import type { InternalTool } from '../types';
|
|
17
|
+
import type { InternalToolRunnerConfig } from './types';
|
|
18
|
+
export declare class InternalToolRunner {
|
|
19
|
+
private readonly config;
|
|
20
|
+
private clients;
|
|
21
|
+
private counter;
|
|
22
|
+
constructor(config: InternalToolRunnerConfig);
|
|
23
|
+
/** Execute a tool by ID. */
|
|
24
|
+
run<T = unknown>(toolId: string, input: unknown): Promise<T>;
|
|
25
|
+
/** Execute a tool instance directly (bypasses registry). */
|
|
26
|
+
runDirect<T = unknown>(tool: InternalTool, input: unknown): Promise<T>;
|
|
27
|
+
/** Close all pooled clients. */
|
|
28
|
+
destroy(): Promise<void>;
|
|
29
|
+
get poolSize(): number;
|
|
30
|
+
/** Expose the registry so adjacent tooling can resolve tools. */
|
|
31
|
+
get registry(): import("../registry").ToolRegistry;
|
|
32
|
+
private validateInput;
|
|
33
|
+
private validateOutput;
|
|
34
|
+
/** Build ordered model list. Precedence:
|
|
35
|
+
* 1. compat.recommended for this tool (benchmark-derived, cost-ranked).
|
|
36
|
+
* 2. tool.modelPreference.preferredModel.
|
|
37
|
+
* 3. tool.modelPreference.fallbackModels.
|
|
38
|
+
* 4. runner.defaultModel.
|
|
39
|
+
*/
|
|
40
|
+
private resolveModels;
|
|
41
|
+
private assertKeyAvailability;
|
|
42
|
+
private parseModelId;
|
|
43
|
+
/** Build (or fetch from pool) a client pinned to (provider, model). */
|
|
44
|
+
private getClient;
|
|
45
|
+
private executeNonLLM;
|
|
46
|
+
private executeLLM;
|
|
47
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Template rendering — Mustache-style {{var}} substitution with dot-path support.
|
|
2
|
+
* Strict: throws on missing variables. No conditionals or loops. */
|
|
3
|
+
export declare function renderTemplate(template: string, vars: Record<string, unknown>): string;
|
|
4
|
+
/**
|
|
5
|
+
* Parse JSON from text, tolerating common LLM preambles/postscripts.
|
|
6
|
+
* Handles markdown code fences, leading/trailing prose, extra whitespace.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseJsonWithFences(text: string): unknown;
|
|
9
|
+
export declare function formatNumberedList(items: readonly (string | number)[], startIndex?: number): string;
|
|
10
|
+
export declare function formatBulletedList(items: readonly (string | number)[], bullet?: string): string;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/** Types for InternalToolRunner — config, LLM tool definition. */
|
|
2
|
+
import type { HookBus } from '../../../bus/hook-bus';
|
|
3
|
+
import type { LLMClientConfig } from '../../../llm/client-config';
|
|
4
|
+
import type { ProviderName } from '../../../llm/types/provider';
|
|
5
|
+
import type { JsonSchema } from '../../../llm/types/tools';
|
|
6
|
+
import type { ModelCatalog } from '../../model-catalog/catalog';
|
|
7
|
+
import type { ToolRegistry } from '../registry';
|
|
8
|
+
import type { CompatFile, ModelPreference } from '../types';
|
|
9
|
+
import type { TokenCounter } from '../../../agent/types';
|
|
10
|
+
import type { EngineHandle } from '../../../helpers/engine';
|
|
11
|
+
export interface InternalToolRunnerConfig {
|
|
12
|
+
hooks: HookBus;
|
|
13
|
+
registry: ToolRegistry;
|
|
14
|
+
catalog?: ModelCatalog;
|
|
15
|
+
/** Engine handle — supplies fetch/hooks/adapter wiring for pooled clients.
|
|
16
|
+
* When omitted, the runner can still execute non-LLM tools but every
|
|
17
|
+
* LLM-backed tool will throw on first call. */
|
|
18
|
+
engine?: EngineHandle;
|
|
19
|
+
/** Map of provider → API key. A tool's model requires the matching key. */
|
|
20
|
+
apiKeys: Partial<Record<ProviderName, string>>;
|
|
21
|
+
/** Fallback model when a tool has no modelPreference and needs LLM. */
|
|
22
|
+
defaultModel?: string;
|
|
23
|
+
/** Benchmark-derived recommendations, keyed by tool ID. Optional. */
|
|
24
|
+
compat?: CompatFile;
|
|
25
|
+
/** Shared client options applied to every pooled LLMClient. */
|
|
26
|
+
clientOptions?: Partial<Omit<LLMClientConfig, 'provider' | 'apiKey' | 'model' | 'hooks' | 'fetch' | 'fetchStream' | 'adapter'>>;
|
|
27
|
+
/** Token counter used by tools to convert char-length to max-tokens.
|
|
28
|
+
* Auto-created from catalog (HybridTokenCounter) when not provided. */
|
|
29
|
+
counter?: TokenCounter;
|
|
30
|
+
}
|
|
31
|
+
/** Context passed to a tool's resolveMaxTokens() function. */
|
|
32
|
+
export interface ResolveMaxTokensContext {
|
|
33
|
+
provider: string;
|
|
34
|
+
model: string;
|
|
35
|
+
counter: TokenCounter;
|
|
36
|
+
}
|
|
37
|
+
/** Declarative LLM tool — prompt template + schema. Convert via defineLLMTool(). */
|
|
38
|
+
export interface LLMToolDefinition {
|
|
39
|
+
id: string;
|
|
40
|
+
namespace: string;
|
|
41
|
+
name: string;
|
|
42
|
+
version: string;
|
|
43
|
+
description: string;
|
|
44
|
+
inputSchema: JsonSchema;
|
|
45
|
+
outputSchema?: JsonSchema;
|
|
46
|
+
systemPrompt?: string;
|
|
47
|
+
userTemplate?: string;
|
|
48
|
+
outputFormat?: 'text' | 'json';
|
|
49
|
+
prepareInput?: (input: Record<string, unknown>) => Record<string, unknown>;
|
|
50
|
+
resolveMaxTokens?: (input: Record<string, unknown>, ctx: ResolveMaxTokensContext) => number;
|
|
51
|
+
outputExample?: unknown;
|
|
52
|
+
variants?: import('./variants').PromptVariant[];
|
|
53
|
+
modelPreference: ModelPreference;
|
|
54
|
+
recommendedThreshold?: number;
|
|
55
|
+
tags?: string[];
|
|
56
|
+
signature?: string;
|
|
57
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Prompt variant system — one tool, many prompts. Matched by mode, provider, or model. */
|
|
2
|
+
import type { JsonSchema } from '../../../llm/types/tools';
|
|
3
|
+
import type { ResolveMaxTokensContext } from './types';
|
|
4
|
+
export interface PromptVariant {
|
|
5
|
+
/** Unique identifier within a tool. Conventions: "default", "strict", "for-haiku", "tool-mode". */
|
|
6
|
+
id: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
systemPrompt: string;
|
|
9
|
+
userTemplate: string;
|
|
10
|
+
outputExample?: unknown;
|
|
11
|
+
outputSchema?: JsonSchema;
|
|
12
|
+
resolveMaxTokens?: (input: Record<string, unknown>, ctx: ResolveMaxTokensContext) => number;
|
|
13
|
+
modes?: string[];
|
|
14
|
+
supportedProviders?: string[];
|
|
15
|
+
supportedModels?: string[];
|
|
16
|
+
isDefault?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface VariantSelectorContext {
|
|
19
|
+
provider: string;
|
|
20
|
+
model: string;
|
|
21
|
+
mode?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Pick the best-matching variant for the given context.
|
|
25
|
+
*
|
|
26
|
+
* Priority (most-specific wins):
|
|
27
|
+
* 1. mode + supportedModels match
|
|
28
|
+
* 2. mode + supportedProviders match
|
|
29
|
+
* 3. mode + isDefault within mode filter
|
|
30
|
+
* 4. no mode + supportedModels match
|
|
31
|
+
* 5. no mode + supportedProviders match
|
|
32
|
+
* 6. global isDefault
|
|
33
|
+
*/
|
|
34
|
+
export declare function selectVariant(variants: PromptVariant[], ctx: VariantSelectorContext): PromptVariant;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/** Tool catalog types — InternalTool, backends, filters, compatibility.
|
|
2
|
+
*
|
|
3
|
+
* Ported from llm-sdk/src/tools/types.ts. The `execute` signature still
|
|
4
|
+
* takes a free-form context bag; the runner populates `client`, `modelId`,
|
|
5
|
+
* `counter`, `recordLLMResponse` at execution time. */
|
|
6
|
+
import type { JsonSchema } from '../../llm/types/tools';
|
|
7
|
+
import type { HookBus } from '../../bus/hook-bus';
|
|
8
|
+
import type { CompletionResponse } from '../../llm/types/response';
|
|
9
|
+
import type { TokenCounter } from '../../agent/types';
|
|
10
|
+
export interface InternalTool {
|
|
11
|
+
id: string;
|
|
12
|
+
namespace: string;
|
|
13
|
+
name: string;
|
|
14
|
+
version: string;
|
|
15
|
+
description: string;
|
|
16
|
+
inputSchema: JsonSchema;
|
|
17
|
+
outputSchema?: JsonSchema;
|
|
18
|
+
execute: (input: unknown, ctx: InternalToolContext) => Promise<unknown>;
|
|
19
|
+
modelPreference?: ModelPreference;
|
|
20
|
+
/** Minimum average benchmark score (0-100) for a model to enter the tool's
|
|
21
|
+
* compat `recommended` chain. Defaults to 100. */
|
|
22
|
+
recommendedThreshold?: number;
|
|
23
|
+
signature?: string;
|
|
24
|
+
signedBy?: string;
|
|
25
|
+
tags?: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface ModelPreference {
|
|
28
|
+
preferredModel?: string;
|
|
29
|
+
fallbackModels?: string[];
|
|
30
|
+
maxTokens?: number;
|
|
31
|
+
temperature?: number;
|
|
32
|
+
}
|
|
33
|
+
export interface InternalToolContext {
|
|
34
|
+
hooks?: HookBus;
|
|
35
|
+
/** LLMClient pinned to the chosen model — populated by the runner. */
|
|
36
|
+
client?: unknown;
|
|
37
|
+
/** "provider/model" string for the chosen model — populated by the runner. */
|
|
38
|
+
modelId?: string;
|
|
39
|
+
/** Tool ID under execution. */
|
|
40
|
+
toolId?: string;
|
|
41
|
+
/** Token counter — populated by the runner (defaults to HybridTokenCounter). */
|
|
42
|
+
counter?: TokenCounter;
|
|
43
|
+
/** Tool implementations (e.g. defineLLMTool) invoke this after each LLM call
|
|
44
|
+
* so the runner can capture usage/latency for cost tracking and benchmarks. */
|
|
45
|
+
recordLLMResponse?: (response: CompletionResponse) => void;
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
export interface ToolBackend {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
list(): Promise<InternalTool[]>;
|
|
51
|
+
get(id: string): Promise<InternalTool | null>;
|
|
52
|
+
}
|
|
53
|
+
export interface ToolFilter {
|
|
54
|
+
namespace?: string;
|
|
55
|
+
prefix?: string;
|
|
56
|
+
tag?: string;
|
|
57
|
+
model?: {
|
|
58
|
+
provider: string;
|
|
59
|
+
model: string;
|
|
60
|
+
minScore?: number;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export interface SearchOptions {
|
|
64
|
+
namespace?: string;
|
|
65
|
+
limit?: number;
|
|
66
|
+
}
|
|
67
|
+
export interface ToolCompatScore {
|
|
68
|
+
score: number;
|
|
69
|
+
testedAt: number;
|
|
70
|
+
version?: string;
|
|
71
|
+
}
|
|
72
|
+
/** Per-tool benchmark record used by InternalToolRunner to pick a recommended
|
|
73
|
+
* chain. The runner ships without a bench subsystem, so the shape is declared
|
|
74
|
+
* inline so consumers can pass a CompatFile from elsewhere (or omit it
|
|
75
|
+
* entirely). */
|
|
76
|
+
export interface ToolCompat {
|
|
77
|
+
/** Models that scored at/above the threshold, ordered by est. cost (cheapest first). */
|
|
78
|
+
recommended: string[];
|
|
79
|
+
}
|
|
80
|
+
export type CompatFile = Record<string, ToolCompat>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** ConsoleSink — writes LogEvents to stdout/stderr with simple formatting.
|
|
2
|
+
*
|
|
3
|
+
* - error/warn → stderr
|
|
4
|
+
* - info/debug/trace → stdout
|
|
5
|
+
*
|
|
6
|
+
* Format (default): `[ISO_TIMESTAMP] [LEVEL] [source] kind: message {data}`
|
|
7
|
+
* Caller may pass a custom `format` callback for full control. */
|
|
8
|
+
import type { LogEvent, LogSink } from './types';
|
|
9
|
+
export interface ConsoleSinkConfig {
|
|
10
|
+
/** Custom formatter overrides the default `[ts] [level] [source] kind: message`. */
|
|
11
|
+
format?: (event: LogEvent) => string;
|
|
12
|
+
/** Writers (test override). Defaults to process.stderr / process.stdout. */
|
|
13
|
+
stderr?: {
|
|
14
|
+
write: (s: string) => unknown;
|
|
15
|
+
};
|
|
16
|
+
stdout?: {
|
|
17
|
+
write: (s: string) => unknown;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export declare class ConsoleSink implements LogSink {
|
|
21
|
+
private readonly format;
|
|
22
|
+
private readonly stderr;
|
|
23
|
+
private readonly stdout;
|
|
24
|
+
constructor(config?: ConsoleSinkConfig);
|
|
25
|
+
log(event: LogEvent): void;
|
|
26
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Logger — fan-out from HookBus events into one or more LogSinks.
|
|
2
|
+
*
|
|
3
|
+
* Two ways to feed the Logger:
|
|
4
|
+
* 1. `attach(hooks)` — subscribes to known SDK hook events (onWarning today;
|
|
5
|
+
* more added as later phases land). Converts each to a LogEvent.
|
|
6
|
+
* 2. `log(event)` — direct entry for plugins that want to log without
|
|
7
|
+
* going through HookBus.
|
|
8
|
+
*
|
|
9
|
+
* Level filtering: events below `minLevel` are dropped before reaching sinks.
|
|
10
|
+
*
|
|
11
|
+
* Multiple sinks are dispatched in parallel; sink errors are caught and
|
|
12
|
+
* re-emitted as `system.logger-sink-error` to stderr (so a bad sink can't
|
|
13
|
+
* silently kill log delivery). */
|
|
14
|
+
import type { HookBus } from '../../bus/hook-bus';
|
|
15
|
+
import { type LogEvent, type LogLevel, type LogSink } from './types';
|
|
16
|
+
export interface LoggerConfig {
|
|
17
|
+
sinks: LogSink[];
|
|
18
|
+
/** Drop events with rank below this level. Default: 'info'. */
|
|
19
|
+
minLevel?: LogLevel;
|
|
20
|
+
}
|
|
21
|
+
export declare class Logger {
|
|
22
|
+
private readonly sinks;
|
|
23
|
+
private readonly minRank;
|
|
24
|
+
private detachers;
|
|
25
|
+
constructor(config: LoggerConfig);
|
|
26
|
+
/** Manually log an event. Bypasses HookBus. */
|
|
27
|
+
log(event: LogEvent): void;
|
|
28
|
+
/** Subscribe to known hook events on a HookBus, converting each to a leveled
|
|
29
|
+
* LogEvent (carrying the request's correlation ids). Returns this. */
|
|
30
|
+
attach(hooks: HookBus): this;
|
|
31
|
+
/** Unsubscribe from any HookBus(es) attached to. */
|
|
32
|
+
detach(): void;
|
|
33
|
+
/** Flush any buffering sinks (best-effort; errors swallowed per-sink). */
|
|
34
|
+
flush(): Promise<void>;
|
|
35
|
+
/** Detach + flush. */
|
|
36
|
+
destroy(): Promise<void>;
|
|
37
|
+
private handleSinkError;
|
|
38
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Logger types — sinks, levels, events. */
|
|
2
|
+
import type { RequestContext } from '../../types/request-context';
|
|
3
|
+
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error';
|
|
4
|
+
/** Numeric ranking — higher is more severe. Used to compare against minLevel. */
|
|
5
|
+
export declare const LOG_LEVEL_RANK: Record<LogLevel, number>;
|
|
6
|
+
export interface LogEvent {
|
|
7
|
+
timestamp: number;
|
|
8
|
+
level: LogLevel;
|
|
9
|
+
/** Logical source: 'network', 'llm', 'agent', 'server', or a plugin name. */
|
|
10
|
+
source: string;
|
|
11
|
+
/** Hook name or short identifier of the kind of event. */
|
|
12
|
+
kind: string;
|
|
13
|
+
/** Optional human-readable message. */
|
|
14
|
+
message?: string;
|
|
15
|
+
/** Accumulating IDs (userId, requestId, conversationId, callId, ...). */
|
|
16
|
+
ctx?: RequestContext;
|
|
17
|
+
/** Arbitrary structured data — sinks decide how to render. */
|
|
18
|
+
data?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/** A LogSink consumes LogEvents. Built-in: ConsoleSink. Future: OTel, Sentry, File. */
|
|
21
|
+
export interface LogSink {
|
|
22
|
+
log(event: LogEvent): void | Promise<void>;
|
|
23
|
+
/** Optional flush hook — called by Logger.flush() / destroy(). */
|
|
24
|
+
flush?(): void | Promise<void>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** Shared JSON-RPC dispatch logic for MCP transports (stdio, WebSocket, HTTP).
|
|
2
|
+
*
|
|
3
|
+
* Owns:
|
|
4
|
+
* - `pending` map + `nextId` counter (client-initiated requests)
|
|
5
|
+
* - `handlers` field + `setHandlers()`
|
|
6
|
+
* - `routeIncoming(msg)` — dispatch: response | server-request | notification
|
|
7
|
+
* - `resolveResponse(msg)` — settle a pending promise from a response message
|
|
8
|
+
* - `handleRequest(msg)` — call `handlers.onRequest` and send back the result
|
|
9
|
+
* - `failAll(err)` — reject all in-flight pending requests
|
|
10
|
+
* - `allocateId()` — return the next monotonic request id
|
|
11
|
+
* - `registerPending(id, resolve, reject, timeoutMs, method)` — set up timer
|
|
12
|
+
*
|
|
13
|
+
* Each concrete transport implements:
|
|
14
|
+
* - `protected abstract sendMessage(obj: unknown): void | Promise<void>`
|
|
15
|
+
* Write a serialised JSON-RPC object back to the peer.
|
|
16
|
+
* - The medium-specific lifecycle (connect / close / listen) and inbound
|
|
17
|
+
* parsing, which ends with a call to `this.routeIncoming(parsedMsg)`.
|
|
18
|
+
*/
|
|
19
|
+
import { McpError } from './jsonrpc';
|
|
20
|
+
import type { IncomingMcpHandlers } from './transport';
|
|
21
|
+
/** A loosely-typed inbound JSON-RPC message (response, request, or notification). */
|
|
22
|
+
export interface InboundMessage {
|
|
23
|
+
id?: number | string;
|
|
24
|
+
method?: string;
|
|
25
|
+
params?: unknown;
|
|
26
|
+
result?: unknown;
|
|
27
|
+
error?: {
|
|
28
|
+
code: number;
|
|
29
|
+
message: string;
|
|
30
|
+
data?: unknown;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export interface Pending {
|
|
34
|
+
resolve: (v: unknown) => void;
|
|
35
|
+
reject: (e: unknown) => void;
|
|
36
|
+
timer: ReturnType<typeof setTimeout>;
|
|
37
|
+
}
|
|
38
|
+
export declare abstract class BaseJsonRpcTransport {
|
|
39
|
+
protected nextId: number;
|
|
40
|
+
protected handlers: IncomingMcpHandlers;
|
|
41
|
+
protected readonly pending: Map<number, Pending>;
|
|
42
|
+
setHandlers(handlers: IncomingMcpHandlers): void;
|
|
43
|
+
/** Write a serialised JSON-RPC object back to the peer. */
|
|
44
|
+
protected abstract sendMessage(obj: unknown): void | Promise<void>;
|
|
45
|
+
/** Allocate the next monotonic request id. */
|
|
46
|
+
protected allocateId(): number;
|
|
47
|
+
/** Register a pending request and arm its timeout. */
|
|
48
|
+
protected registerPending(id: number, resolve: (v: unknown) => void, reject: (e: unknown) => void, timeoutMs: number, method: string): void;
|
|
49
|
+
/** Dispatch a parsed inbound message to the correct handler. */
|
|
50
|
+
protected routeIncoming(msg: InboundMessage): void;
|
|
51
|
+
/** Settle a pending client-initiated request from its response message. */
|
|
52
|
+
protected resolveResponse(msg: InboundMessage): void;
|
|
53
|
+
/** Handle a server-initiated request: call the registered handler and send
|
|
54
|
+
* the result (or an error) back via `sendMessage`. */
|
|
55
|
+
protected handleRequest(msg: InboundMessage): Promise<void>;
|
|
56
|
+
/** Reject all in-flight pending requests with the given error. */
|
|
57
|
+
protected failAll(err: McpError): void;
|
|
58
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** McpClient — the protocol layer over a (bidirectional) transport: initialize
|
|
2
|
+
* handshake, tools/list (paginated), tools/call, resources, prompts, and
|
|
3
|
+
* routing of server->client requests (ping, sampling, elicitation, roots) and
|
|
4
|
+
* notifications. */
|
|
5
|
+
import type { HookBus } from '../../bus/hook-bus';
|
|
6
|
+
import type { McpTransport } from './transport';
|
|
7
|
+
import type { TraceContext } from '../../network/types';
|
|
8
|
+
import type { McpCallResult, McpCompletionRef, McpCompletionResult, McpGetPromptResult, McpInitializeResult, McpLogLevel, McpPrompt, McpResource, McpResourceContent, McpResourceTemplate, McpTask, McpTaskMetadata, McpToolDef } from './types';
|
|
9
|
+
export interface McpClientOptions {
|
|
10
|
+
clientInfo?: {
|
|
11
|
+
name: string;
|
|
12
|
+
version: string;
|
|
13
|
+
};
|
|
14
|
+
/** Capabilities to advertise in `initialize` (e.g. sampling/roots/elicitation). */
|
|
15
|
+
capabilities?: Record<string, unknown>;
|
|
16
|
+
/** Every server->client notification (logging, *_changed, progress, …). */
|
|
17
|
+
onNotification?: (method: string, params: unknown) => void;
|
|
18
|
+
/** Handle a server->client request we don't answer internally (sampling,
|
|
19
|
+
* elicitation/create, roots/list). Return the result or throw McpError. */
|
|
20
|
+
onServerRequest?: (method: string, params: unknown) => Promise<unknown>;
|
|
21
|
+
/** Primary hooks bus for unconditional MCP telemetry (onMcpToolCall / onMcpError).
|
|
22
|
+
* When set, emission is unconditional — no telemetry adapter is required.
|
|
23
|
+
* `server` is the namespace label emitted in MCP hook contexts. */
|
|
24
|
+
hooks?: HookBus;
|
|
25
|
+
/** MCP namespace / server label (paired with `hooks`). */
|
|
26
|
+
server?: string;
|
|
27
|
+
/** @deprecated Use `hooks` + `server` instead. Kept for backward compatibility. */
|
|
28
|
+
telemetry?: {
|
|
29
|
+
hooks: HookBus;
|
|
30
|
+
server: string;
|
|
31
|
+
};
|
|
32
|
+
/** Send a `ping` every N ms to keep the connection alive (0/undefined = off). */
|
|
33
|
+
keepAliveMs?: number;
|
|
34
|
+
}
|
|
35
|
+
export declare class McpClient {
|
|
36
|
+
private readonly transport;
|
|
37
|
+
private readonly opts;
|
|
38
|
+
private serverInfo;
|
|
39
|
+
private pingTimer;
|
|
40
|
+
constructor(transport: McpTransport, opts?: McpClientOptions);
|
|
41
|
+
/** The server's `initialize` result, or null before `connect()`. */
|
|
42
|
+
get info(): McpInitializeResult | null;
|
|
43
|
+
/** Open the transport, run the initialize handshake, and start listening for
|
|
44
|
+
* server-initiated messages. */
|
|
45
|
+
connect(): Promise<McpInitializeResult>;
|
|
46
|
+
/** List every tool the server exposes (follows cursor pagination). */
|
|
47
|
+
listTools(): Promise<McpToolDef[]>;
|
|
48
|
+
/** Follow cursor pagination for a list method, collecting `field` from each page. */
|
|
49
|
+
private paginate;
|
|
50
|
+
/** Invoke a tool by its (un-namespaced) server name.
|
|
51
|
+
* Pass `trace` when the call originates from an AgentLoop run so that
|
|
52
|
+
* `onMcpToolCall` and `onMcpError` carry the run's sessionId/requestId. */
|
|
53
|
+
callTool(name: string, args?: Record<string, unknown>, trace?: TraceContext): Promise<McpCallResult>;
|
|
54
|
+
/** List the server's resources (follows cursor pagination). */
|
|
55
|
+
listResources(): Promise<McpResource[]>;
|
|
56
|
+
/** List the server's resource templates. */
|
|
57
|
+
listResourceTemplates(): Promise<McpResourceTemplate[]>;
|
|
58
|
+
/** Read a resource's contents by URI. */
|
|
59
|
+
readResource(uri: string): Promise<McpResourceContent[]>;
|
|
60
|
+
/** Subscribe to updates for a resource (server sends `notifications/resources/updated`). */
|
|
61
|
+
subscribeResource(uri: string): Promise<void>;
|
|
62
|
+
unsubscribeResource(uri: string): Promise<void>;
|
|
63
|
+
/** List the server's prompts (follows cursor pagination). */
|
|
64
|
+
listPrompts(): Promise<McpPrompt[]>;
|
|
65
|
+
/** Render a prompt by name with arguments → its messages. */
|
|
66
|
+
getPrompt(name: string, args?: Record<string, string>): Promise<McpGetPromptResult>;
|
|
67
|
+
/** Set the server's log verbosity (it then sends `notifications/message`). */
|
|
68
|
+
setLogLevel(level: McpLogLevel): Promise<void>;
|
|
69
|
+
/** Argument autocompletion for a prompt or resource template. */
|
|
70
|
+
completeArgument(ref: McpCompletionRef, argument: {
|
|
71
|
+
name: string;
|
|
72
|
+
value: string;
|
|
73
|
+
}): Promise<McpCompletionResult>;
|
|
74
|
+
/** Call a tool as a long-running task; returns the created task immediately. */
|
|
75
|
+
callToolTask(name: string, args?: Record<string, unknown>, meta?: McpTaskMetadata): Promise<McpTask>;
|
|
76
|
+
/** Current status of a task. */
|
|
77
|
+
getTask(taskId: string): Promise<McpTask>;
|
|
78
|
+
/** The final result of a completed task. */
|
|
79
|
+
getTaskResult(taskId: string): Promise<McpCallResult>;
|
|
80
|
+
/** List the server's tasks. */
|
|
81
|
+
listTasks(): Promise<McpTask[]>;
|
|
82
|
+
cancelTask(taskId: string): Promise<void>;
|
|
83
|
+
/** Poll `tasks/get` until the task reaches a terminal status. */
|
|
84
|
+
awaitTask(taskId: string, opts?: {
|
|
85
|
+
pollIntervalMs?: number;
|
|
86
|
+
timeoutMs?: number;
|
|
87
|
+
}): Promise<McpTask>;
|
|
88
|
+
/** Low-level escape hatch: send any request method. */
|
|
89
|
+
request(method: string, params?: unknown): Promise<unknown>;
|
|
90
|
+
close(): Promise<void>;
|
|
91
|
+
private handleServerRequest;
|
|
92
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** JSON-RPC 2.0 error codes + the error type the MCP client throws on a
|
|
2
|
+
* protocol-level failure (distinct from a tool-level `isError` result). */
|
|
3
|
+
import type { JsonRpcError } from './types';
|
|
4
|
+
export declare const McpErrorCode: {
|
|
5
|
+
readonly ConnectionClosed: -32000;
|
|
6
|
+
readonly RequestTimeout: -32001;
|
|
7
|
+
readonly ParseError: -32700;
|
|
8
|
+
readonly InvalidRequest: -32600;
|
|
9
|
+
readonly MethodNotFound: -32601;
|
|
10
|
+
readonly InvalidParams: -32602;
|
|
11
|
+
readonly InternalError: -32603;
|
|
12
|
+
};
|
|
13
|
+
/** A JSON-RPC / transport level error (server unreachable, error response,
|
|
14
|
+
* timeout). Tool execution failures arrive as a normal result with
|
|
15
|
+
* `isError: true` and are NOT thrown. */
|
|
16
|
+
export declare class McpError extends Error {
|
|
17
|
+
readonly code: number;
|
|
18
|
+
readonly data?: unknown;
|
|
19
|
+
constructor(err: JsonRpcError);
|
|
20
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/** OAuth 2.1 + PKCE for MCP servers that require authorization (zero-dep).
|
|
2
|
+
*
|
|
3
|
+
* The library owns the non-interactive machinery — metadata discovery, PKCE,
|
|
4
|
+
* dynamic client registration, authorization-code exchange, and token refresh —
|
|
5
|
+
* and delegates the inherently-interactive bits (storing tokens, redirecting
|
|
6
|
+
* the user, capturing the callback code) to an `McpAuthProvider` the consumer
|
|
7
|
+
* implements. All HTTP goes through the engine's fetch. */
|
|
8
|
+
import type { EngineFetch } from '../../network/types';
|
|
9
|
+
import type { SsrfGuardOptions } from './url-guard';
|
|
10
|
+
export interface McpOAuthTokens {
|
|
11
|
+
access_token: string;
|
|
12
|
+
token_type?: string;
|
|
13
|
+
expires_in?: number;
|
|
14
|
+
refresh_token?: string;
|
|
15
|
+
scope?: string;
|
|
16
|
+
/** Stamped by us when the tokens were obtained (for expiry math). */
|
|
17
|
+
obtained_at?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface McpOAuthClientInfo {
|
|
20
|
+
client_id: string;
|
|
21
|
+
client_secret?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface McpOAuthClientMetadata {
|
|
24
|
+
redirect_uris: string[];
|
|
25
|
+
client_name?: string;
|
|
26
|
+
scope?: string;
|
|
27
|
+
grant_types?: string[];
|
|
28
|
+
response_types?: string[];
|
|
29
|
+
token_endpoint_auth_method?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Consumer-implemented storage + interactive redirect. */
|
|
32
|
+
export interface McpAuthProvider {
|
|
33
|
+
/** Where the authorization server redirects back to. */
|
|
34
|
+
readonly redirectUrl: string;
|
|
35
|
+
/** Metadata used for dynamic client registration. */
|
|
36
|
+
readonly clientMetadata: McpOAuthClientMetadata;
|
|
37
|
+
clientInformation(): McpOAuthClientInfo | undefined | Promise<McpOAuthClientInfo | undefined>;
|
|
38
|
+
saveClientInformation?(info: McpOAuthClientInfo): void | Promise<void>;
|
|
39
|
+
tokens(): McpOAuthTokens | undefined | Promise<McpOAuthTokens | undefined>;
|
|
40
|
+
saveTokens(tokens: McpOAuthTokens): void | Promise<void>;
|
|
41
|
+
/** Open / navigate to the authorization URL. */
|
|
42
|
+
redirectToAuthorization(authorizationUrl: string): void | Promise<void>;
|
|
43
|
+
saveCodeVerifier(verifier: string): void | Promise<void>;
|
|
44
|
+
codeVerifier(): string | Promise<string>;
|
|
45
|
+
/** Persist the CSRF state token generated during redirect (required for validation). */
|
|
46
|
+
saveState(state: string): void | Promise<void>;
|
|
47
|
+
/** Retrieve the persisted state token for comparison on callback. */
|
|
48
|
+
state(): string | undefined | Promise<string | undefined>;
|
|
49
|
+
}
|
|
50
|
+
export interface AuthServerMetadata {
|
|
51
|
+
authorization_endpoint: string;
|
|
52
|
+
token_endpoint: string;
|
|
53
|
+
registration_endpoint?: string;
|
|
54
|
+
}
|
|
55
|
+
/** Security options for the OAuth flow. All fields default to the most
|
|
56
|
+
* restrictive posture. Re-exported from `url-guard` for consumer convenience. */
|
|
57
|
+
export type { SsrfGuardOptions as McpOAuthSecurityOptions };
|
|
58
|
+
/** Thrown when an interactive authorization is required (the provider's
|
|
59
|
+
* `redirectToAuthorization` has been called; finish via `finishMcpAuth`). */
|
|
60
|
+
export declare class McpUnauthorizedError extends Error {
|
|
61
|
+
constructor(message?: string);
|
|
62
|
+
}
|
|
63
|
+
/** Generate a PKCE code verifier + S256 challenge. */
|
|
64
|
+
export declare function generatePkce(): Promise<{
|
|
65
|
+
verifier: string;
|
|
66
|
+
challenge: string;
|
|
67
|
+
}>;
|
|
68
|
+
/** Generate a cryptographically-random CSRF state token (32 bytes, base64url). */
|
|
69
|
+
export declare function generateState(): string;
|
|
70
|
+
/** Discover the authorization-server metadata for an MCP server URL.
|
|
71
|
+
* All discovered endpoint URLs are validated against the SSRF guard before
|
|
72
|
+
* being returned; pass `security` to configure the allowlist or escape hatches. */
|
|
73
|
+
export declare function discoverMetadata(fetch: EngineFetch, serverUrl: string, security?: SsrfGuardOptions): Promise<AuthServerMetadata>;
|
|
74
|
+
/** Dynamic Client Registration (RFC 7591).
|
|
75
|
+
* The `serverUrl` anchor is required so the SSRF guard can check the endpoint origin. */
|
|
76
|
+
export declare function registerClient(fetch: EngineFetch, registrationEndpoint: string, metadata: McpOAuthClientMetadata, serverUrl: string, security?: SsrfGuardOptions): Promise<McpOAuthClientInfo>;
|
|
77
|
+
/** Build the authorization URL (code flow + PKCE). */
|
|
78
|
+
export declare function buildAuthorizationUrl(authorizationEndpoint: string, params: {
|
|
79
|
+
client_id: string;
|
|
80
|
+
redirect_uri: string;
|
|
81
|
+
code_challenge: string;
|
|
82
|
+
scope?: string;
|
|
83
|
+
state?: string;
|
|
84
|
+
resource?: string;
|
|
85
|
+
}): string;
|
|
86
|
+
/** Exchange an authorization code for tokens. */
|
|
87
|
+
export declare function exchangeCode(fetch: EngineFetch, tokenEndpoint: string, p: {
|
|
88
|
+
code: string;
|
|
89
|
+
code_verifier: string;
|
|
90
|
+
client_id: string;
|
|
91
|
+
client_secret?: string;
|
|
92
|
+
redirect_uri: string;
|
|
93
|
+
resource?: string;
|
|
94
|
+
}): Promise<McpOAuthTokens>;
|
|
95
|
+
/** Refresh tokens with a refresh_token. */
|
|
96
|
+
export declare function refreshTokens(fetch: EngineFetch, tokenEndpoint: string, p: {
|
|
97
|
+
refresh_token: string;
|
|
98
|
+
client_id: string;
|
|
99
|
+
client_secret?: string;
|
|
100
|
+
}): Promise<McpOAuthTokens>;
|
|
101
|
+
export declare class McpOAuth {
|
|
102
|
+
private readonly serverUrl;
|
|
103
|
+
private readonly provider;
|
|
104
|
+
private readonly fetch;
|
|
105
|
+
private readonly security;
|
|
106
|
+
private metadata;
|
|
107
|
+
constructor(serverUrl: string, provider: McpAuthProvider, fetch: EngineFetch, security?: SsrfGuardOptions);
|
|
108
|
+
/** Ensure a usable access token exists. Returns 'redirect' if the user must
|
|
109
|
+
* authorize interactively (the provider has been asked to redirect). */
|
|
110
|
+
authorize(): Promise<'authorized' | 'redirect'>;
|
|
111
|
+
/** Bearer header for a request (refreshing a stale token if possible). */
|
|
112
|
+
authHeader(): Promise<Record<string, string>>;
|
|
113
|
+
/** Handle a 401: refresh if we can (return true -> retry), else start a redirect. */
|
|
114
|
+
reauthorize(): Promise<boolean>;
|
|
115
|
+
/** Finish the interactive flow: exchange the callback code for tokens.
|
|
116
|
+
* The `returnedState` MUST match the state persisted during redirect (CSRF guard). */
|
|
117
|
+
finish(code: string, returnedState: string): Promise<void>;
|
|
118
|
+
private startRedirect;
|
|
119
|
+
private tryRefresh;
|
|
120
|
+
private ensureMetadata;
|
|
121
|
+
private ensureClient;
|
|
122
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Sampling (P3): when an MCP server sends `sampling/createMessage`, it is asking
|
|
2
|
+
* US to run an LLM completion on its behalf. We fulfill it with our own engine —
|
|
3
|
+
* so the server borrows our multi-provider brain. The caller either supplies a
|
|
4
|
+
* custom handler or a model id to auto-wire. */
|
|
5
|
+
import type { EngineHandle } from '../../helpers/engine';
|
|
6
|
+
import type { ProviderName } from '../../llm/types/provider';
|
|
7
|
+
import type { McpCreateMessageParams, McpCreateMessageResult } from './types';
|
|
8
|
+
export type McpSamplingHandler = (params: McpCreateMessageParams) => Promise<McpCreateMessageResult>;
|
|
9
|
+
/** Auto-wire sampling to our LLM. */
|
|
10
|
+
export interface McpSamplingViaLLM {
|
|
11
|
+
model: string;
|
|
12
|
+
provider?: ProviderName;
|
|
13
|
+
engine?: EngineHandle;
|
|
14
|
+
}
|
|
15
|
+
export type McpSamplingConfig = McpSamplingHandler | McpSamplingViaLLM;
|
|
16
|
+
/** Build a sampling handler: pass-through a custom function, or auto-wire a model. */
|
|
17
|
+
export declare function samplingHandler(config: McpSamplingConfig): McpSamplingHandler;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Adapt MCP results into our shapes: tool-call results -> AgentTool results,
|
|
2
|
+
* and prompt results -> Message[]. */
|
|
3
|
+
import type { AgentTool } from '../../agent/types';
|
|
4
|
+
import type { ContentPart, Message } from '../../llm/types/messages';
|
|
5
|
+
import type { McpClient } from './client';
|
|
6
|
+
import type { McpCallResult, McpGetPromptResult, McpToolDef } from './types';
|
|
7
|
+
export interface McpToolAdapterOptions {
|
|
8
|
+
/** Validate `structuredContent` against the tool's `outputSchema`; on mismatch
|
|
9
|
+
* the tool returns an error string instead of the content. Default false. */
|
|
10
|
+
validateOutput?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Map a `tools/call` result to our tool-result shape: a plain string when the
|
|
13
|
+
* content is text-only, else a ContentPart[] (images/audio kept as base64).
|
|
14
|
+
* A tool-level `isError` is surfaced to the model as text, not thrown. */
|
|
15
|
+
export declare function mcpContentToResult(res: McpCallResult): string | ContentPart[];
|
|
16
|
+
/** Map a `prompts/get` result to our Message[] (drop straight into a request). */
|
|
17
|
+
export declare function mcpPromptToMessages(result: McpGetPromptResult): Message[];
|
|
18
|
+
/** Wrap one MCP tool as an `AgentTool`. The model sees `<namespace>__<tool>`
|
|
19
|
+
* (collision-free across servers); execution calls the server with the raw name. */
|
|
20
|
+
export declare function mcpToolToAgentTool(client: McpClient, tool: McpToolDef, namespace: string, opts?: McpToolAdapterOptions): AgentTool;
|