@llm4ts/core 2.54.1 → 3.1.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/README.md +1 -1
- package/dist/Capability.d.ts +0 -9
- package/dist/Capability.d.ts.map +1 -1
- package/dist/Capability.js +0 -38
- package/dist/Capability.js.map +1 -1
- package/dist/Connector.d.ts +2 -3
- package/dist/Connector.d.ts.map +1 -1
- package/dist/Connector.js +0 -5
- package/dist/Connector.js.map +1 -1
- package/dist/ConnectorRegistry.d.ts +0 -3
- package/dist/ConnectorRegistry.d.ts.map +1 -1
- package/dist/ConnectorRegistry.js +0 -3
- package/dist/ConnectorRegistry.js.map +1 -1
- package/dist/HttpClient.d.ts +0 -2
- package/dist/HttpClient.d.ts.map +1 -1
- package/dist/HttpClient.js +0 -2
- package/dist/HttpClient.js.map +1 -1
- package/dist/LlmService.d.ts +1 -2
- package/dist/LlmService.d.ts.map +1 -1
- package/dist/LlmService.js.map +1 -1
- package/dist/Models.d.ts +0 -21
- package/dist/Models.d.ts.map +1 -1
- package/dist/Models.js +0 -19
- package/dist/Models.js.map +1 -1
- package/dist/Streaming.d.ts +4 -11
- package/dist/Streaming.d.ts.map +1 -1
- package/dist/Streaming.js +2 -29
- package/dist/Streaming.js.map +1 -1
- package/dist/providers/AnthropicModels.d.ts +0 -43
- package/dist/providers/AnthropicModels.d.ts.map +1 -1
- package/dist/providers/AnthropicModels.js +0 -39
- package/dist/providers/AnthropicModels.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts +2 -3
- package/dist/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/providers/AnthropicProvider.js +2 -49
- package/dist/providers/AnthropicProvider.js.map +1 -1
- package/dist/providers/GeminiApiProvider.d.ts +2 -3
- package/dist/providers/GeminiApiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiApiProvider.js +2 -44
- package/dist/providers/GeminiApiProvider.js.map +1 -1
- package/dist/providers/GeminiModels.d.ts +0 -48
- package/dist/providers/GeminiModels.d.ts.map +1 -1
- package/dist/providers/GeminiModels.js +0 -40
- package/dist/providers/GeminiModels.js.map +1 -1
- package/dist/providers/LmStudioProvider.d.ts.map +1 -1
- package/dist/providers/LmStudioProvider.js +1 -4
- package/dist/providers/LmStudioProvider.js.map +1 -1
- package/dist/providers/MlxLmProvider.d.ts.map +1 -1
- package/dist/providers/MlxLmProvider.js +1 -2
- package/dist/providers/MlxLmProvider.js.map +1 -1
- package/dist/providers/MockProvider.d.ts.map +1 -1
- package/dist/providers/MockProvider.js +1 -6
- package/dist/providers/MockProvider.js.map +1 -1
- package/dist/providers/OllamaProvider.d.ts.map +1 -1
- package/dist/providers/OllamaProvider.js +1 -4
- package/dist/providers/OllamaProvider.js.map +1 -1
- package/dist/providers/OpenAIModels.d.ts +0 -58
- package/dist/providers/OpenAIModels.d.ts.map +1 -1
- package/dist/providers/OpenAIModels.js +0 -51
- package/dist/providers/OpenAIModels.js.map +1 -1
- package/dist/providers/OpenAIProvider.d.ts +2 -3
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +2 -46
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/package.json +2 -14
- package/src/Capability.ts +0 -50
- package/src/Connector.ts +2 -20
- package/src/ConnectorRegistry.ts +0 -15
- package/src/HttpClient.ts +0 -15
- package/src/LlmService.ts +1 -13
- package/src/Models.ts +0 -22
- package/src/Streaming.ts +3 -99
- package/src/providers/AnthropicModels.ts +0 -47
- package/src/providers/AnthropicProvider.ts +1 -87
- package/src/providers/GeminiApiProvider.ts +2 -83
- package/src/providers/GeminiModels.ts +0 -46
- package/src/providers/LmStudioProvider.ts +1 -7
- package/src/providers/MlxLmProvider.ts +1 -3
- package/src/providers/MockProvider.ts +0 -9
- package/src/providers/OllamaProvider.ts +1 -7
- package/src/providers/OpenAIModels.ts +0 -64
- package/src/providers/OpenAIProvider.ts +2 -83
- package/dist/ContextManagement.d.ts +0 -78
- package/dist/ContextManagement.d.ts.map +0 -1
- package/dist/ContextManagement.js +0 -222
- package/dist/ContextManagement.js.map +0 -1
- package/dist/Conversation.d.ts +0 -18
- package/dist/Conversation.d.ts.map +0 -1
- package/dist/Conversation.js +0 -17
- package/dist/Conversation.js.map +0 -1
- package/dist/RateLimiter.d.ts +0 -44
- package/dist/RateLimiter.d.ts.map +0 -1
- package/dist/RateLimiter.js +0 -155
- package/dist/RateLimiter.js.map +0 -1
- package/dist/observability/MeteredLlmService.d.ts +0 -16
- package/dist/observability/MeteredLlmService.d.ts.map +0 -1
- package/dist/observability/MeteredLlmService.js +0 -72
- package/dist/observability/MeteredLlmService.js.map +0 -1
- package/dist/observability/Metrics.d.ts +0 -76
- package/dist/observability/Metrics.d.ts.map +0 -1
- package/dist/observability/Metrics.js +0 -152
- package/dist/observability/Metrics.js.map +0 -1
- package/dist/observability/StructuredLogger.d.ts +0 -31
- package/dist/observability/StructuredLogger.d.ts.map +0 -1
- package/dist/observability/StructuredLogger.js +0 -39
- package/dist/observability/StructuredLogger.js.map +0 -1
- package/dist/observability/Tracing.d.ts +0 -38
- package/dist/observability/Tracing.d.ts.map +0 -1
- package/dist/observability/Tracing.js +0 -80
- package/dist/observability/Tracing.js.map +0 -1
- package/dist/providers/OpenCodeModels.d.ts +0 -61
- package/dist/providers/OpenCodeModels.d.ts.map +0 -1
- package/dist/providers/OpenCodeModels.js +0 -53
- package/dist/providers/OpenCodeModels.js.map +0 -1
- package/dist/providers/OpenCodeProvider.d.ts +0 -10
- package/dist/providers/OpenCodeProvider.d.ts.map +0 -1
- package/dist/providers/OpenCodeProvider.js +0 -154
- package/dist/providers/OpenCodeProvider.js.map +0 -1
- package/dist/tools/Tool.d.ts +0 -83
- package/dist/tools/Tool.d.ts.map +0 -1
- package/dist/tools/Tool.js +0 -278
- package/dist/tools/Tool.js.map +0 -1
- package/dist/tools/ToolCallingExecutor.d.ts +0 -18
- package/dist/tools/ToolCallingExecutor.d.ts.map +0 -1
- package/dist/tools/ToolCallingExecutor.js +0 -64
- package/dist/tools/ToolCallingExecutor.js.map +0 -1
- package/dist/tools/ToolRegistry.d.ts +0 -45
- package/dist/tools/ToolRegistry.d.ts.map +0 -1
- package/dist/tools/ToolRegistry.js +0 -133
- package/dist/tools/ToolRegistry.js.map +0 -1
- package/src/ContextManagement.ts +0 -367
- package/src/Conversation.ts +0 -21
- package/src/RateLimiter.ts +0 -238
- package/src/observability/MeteredLlmService.ts +0 -168
- package/src/observability/Metrics.ts +0 -200
- package/src/observability/StructuredLogger.ts +0 -67
- package/src/observability/Tracing.ts +0 -146
- package/src/providers/OpenCodeModels.ts +0 -60
- package/src/providers/OpenCodeProvider.ts +0 -278
- package/src/tools/Tool.ts +0 -376
- package/src/tools/ToolCallingExecutor.ts +0 -106
- package/src/tools/ToolRegistry.ts +0 -224
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import * as Context from "effect/Context";
|
|
2
|
-
import * as Effect from "effect/Effect";
|
|
3
|
-
import * as Layer from "effect/Layer";
|
|
4
|
-
import * as Schema from "effect/Schema";
|
|
5
|
-
import type { LlmError } from "../Errors.ts";
|
|
6
|
-
import type { ToolCall } from "../Models.ts";
|
|
7
|
-
import type { JsonValue } from "../providers/CliSupport.ts";
|
|
8
|
-
import { type Tool, type ToolExecutionError } from "./Tool.ts";
|
|
9
|
-
declare const ToolSucceeded_base: Schema.Class<ToolSucceeded, Schema.TaggedStruct<"Succeeded", {
|
|
10
|
-
readonly value: Schema.Codec<Schema.Json, Schema.Json, never, never>;
|
|
11
|
-
}>, {}>;
|
|
12
|
-
export declare class ToolSucceeded extends ToolSucceeded_base {
|
|
13
|
-
}
|
|
14
|
-
declare const ToolFailed_base: Schema.Class<ToolFailed, Schema.TaggedStruct<"Failed", {
|
|
15
|
-
readonly message: Schema.String;
|
|
16
|
-
}>, {}>;
|
|
17
|
-
export declare class ToolFailed extends ToolFailed_base {
|
|
18
|
-
}
|
|
19
|
-
export declare const ToolResultValue: Schema.Union<readonly [typeof ToolSucceeded, typeof ToolFailed]>;
|
|
20
|
-
export type ToolResultValue = typeof ToolResultValue.Type;
|
|
21
|
-
declare const ToolResult_base: Schema.Class<ToolResult, Schema.Struct<{
|
|
22
|
-
readonly toolCallId: Schema.String;
|
|
23
|
-
readonly result: Schema.Union<readonly [typeof ToolSucceeded, typeof ToolFailed]>;
|
|
24
|
-
readonly denied: Schema.withConstructorDefault<Schema.Boolean>;
|
|
25
|
-
}>, {}>;
|
|
26
|
-
export declare class ToolResult extends ToolResult_base {
|
|
27
|
-
}
|
|
28
|
-
export interface ToolRegistryShape {
|
|
29
|
-
readonly register: (tool: Tool) => Effect.Effect<void, ToolExecutionError>;
|
|
30
|
-
readonly registerAll: (tools: ReadonlyArray<Tool>) => Effect.Effect<void, ToolExecutionError>;
|
|
31
|
-
readonly get: (name: string) => Effect.Effect<Tool, LlmError>;
|
|
32
|
-
readonly list: Effect.Effect<ReadonlyArray<Tool>>;
|
|
33
|
-
readonly select: (prompt: string, limit?: number) => Effect.Effect<ReadonlyArray<Tool>>;
|
|
34
|
-
readonly validate: (call: ToolCall) => Effect.Effect<readonly [tool: Tool, parameters: JsonValue], LlmError>;
|
|
35
|
-
readonly execute: (call: ToolCall) => Effect.Effect<ToolResult, LlmError>;
|
|
36
|
-
readonly executeAll: (calls: ReadonlyArray<ToolCall>, concurrency?: number) => Effect.Effect<ReadonlyArray<ToolResult>, LlmError>;
|
|
37
|
-
}
|
|
38
|
-
declare const ToolRegistry_base: Context.ServiceClass<ToolRegistry, "@llm4ts/core/tools/ToolRegistry", ToolRegistryShape>;
|
|
39
|
-
export declare class ToolRegistry extends ToolRegistry_base {
|
|
40
|
-
}
|
|
41
|
-
export declare const makeToolRegistry: () => Effect.Effect<ToolRegistryShape, never, never>;
|
|
42
|
-
export declare const ToolRegistryLive: Layer.Layer<ToolRegistry, never, never>;
|
|
43
|
-
export declare const toolResultValue: (result: ToolResult) => JsonValue;
|
|
44
|
-
export {};
|
|
45
|
-
//# sourceMappingURL=ToolRegistry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ToolRegistry.d.ts","sourceRoot":"","sources":["../../src/tools/ToolRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAA;AACzC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAGL,KAAK,IAAI,EACT,KAAK,kBAAkB,EACxB,MAAM,WAAW,CAAA;;;;AAElB,qBAAa,aAAc,SAAQ,kBAEjC;CAAG;;;;AAEL,qBAAa,UAAW,SAAQ,eAE9B;CAAG;AAEL,eAAO,MAAM,eAAe,kEAA4C,CAAA;AACxE,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;;;;;;AAEzD,qBAAa,UAAW,SAAQ,eAI9B;CAAG;AAEL,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAA;IAC1E,QAAQ,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAA;IAC7F,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;IACjD,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;IACvF,QAAQ,CAAC,QAAQ,EAAE,CACjB,IAAI,EAAE,QAAQ,KACX,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,EAAE,QAAQ,CAAC,CAAA;IAC1E,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IACzE,QAAQ,CAAC,UAAU,EAAE,CACnB,KAAK,EAAE,aAAa,CAAC,QAAQ,CAAC,EAC9B,WAAW,CAAC,EAAE,MAAM,KACjB,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;CACxD;;AAED,qBAAa,YAAa,SAAQ,iBAEjC;CAAG;AAiCJ,eAAO,MAAM,gBAAgB,sDAiI5B,CAAA;AAED,eAAO,MAAM,gBAAgB,yCAAiD,CAAA;AAE9E,eAAO,MAAM,eAAe,GAAI,QAAQ,UAAU,KAAG,SAK9C,CAAA"}
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import * as Context from "effect/Context";
|
|
2
|
-
import * as Effect from "effect/Effect";
|
|
3
|
-
import * as Layer from "effect/Layer";
|
|
4
|
-
import * as Ref from "effect/Ref";
|
|
5
|
-
import * as Schema from "effect/Schema";
|
|
6
|
-
import { allows, currentGrants } from "../Capability.js";
|
|
7
|
-
import { InvalidRequestError, ToolError } from "../Errors.js";
|
|
8
|
-
import { DuplicateToolName, validateToolParameters } from "./Tool.js";
|
|
9
|
-
export class ToolSucceeded extends Schema.TaggedClass()("Succeeded", {
|
|
10
|
-
value: Schema.Json
|
|
11
|
-
}) {
|
|
12
|
-
}
|
|
13
|
-
export class ToolFailed extends Schema.TaggedClass()("Failed", {
|
|
14
|
-
message: Schema.String
|
|
15
|
-
}) {
|
|
16
|
-
}
|
|
17
|
-
export const ToolResultValue = Schema.Union([ToolSucceeded, ToolFailed]);
|
|
18
|
-
export class ToolResult extends Schema.Class("ToolResult")({
|
|
19
|
-
toolCallId: Schema.String,
|
|
20
|
-
result: ToolResultValue,
|
|
21
|
-
denied: Schema.Boolean.pipe(Schema.withConstructorDefault(Effect.succeed(false)))
|
|
22
|
-
}) {
|
|
23
|
-
}
|
|
24
|
-
export class ToolRegistry extends Context.Service()("@llm4ts/core/tools/ToolRegistry") {
|
|
25
|
-
}
|
|
26
|
-
const capabilityName = (capability) => capability._tag === "Exec" ? `Exec(${capability.command})` : capability._tag;
|
|
27
|
-
const promptWords = (prompt) => new Set(prompt
|
|
28
|
-
.toLowerCase()
|
|
29
|
-
.split(/[^a-z0-9_]+/)
|
|
30
|
-
.filter((word) => word.length > 0));
|
|
31
|
-
const toolScore = (tool, words) => {
|
|
32
|
-
let score = 0;
|
|
33
|
-
for (const word of words) {
|
|
34
|
-
score += tool.name.toLowerCase().includes(word) ? 5 : 0;
|
|
35
|
-
score += [...tool.tags].some((tag) => tag.toLowerCase() === word) ? 4 : 0;
|
|
36
|
-
score += tool.description.toLowerCase().includes(word) ? 2 : 0;
|
|
37
|
-
}
|
|
38
|
-
return score;
|
|
39
|
-
};
|
|
40
|
-
const parseArguments = (call) => Schema.decodeUnknownEffect(Schema.fromJsonString(Schema.Json))(call.arguments).pipe(Effect.mapError((error) => ToolError.make({
|
|
41
|
-
toolName: call.name,
|
|
42
|
-
detail: `Invalid arguments JSON: ${String(error)}`
|
|
43
|
-
})));
|
|
44
|
-
export const makeToolRegistry = Effect.fn("@llm4ts/core/tools/ToolRegistry.make")(function* () {
|
|
45
|
-
const state = yield* Ref.make(new Map());
|
|
46
|
-
const register = (tool) => Ref.modify(state, (current) => {
|
|
47
|
-
if (current.has(tool.name)) {
|
|
48
|
-
return [false, current];
|
|
49
|
-
}
|
|
50
|
-
const next = new Map(current);
|
|
51
|
-
next.set(tool.name, tool);
|
|
52
|
-
return [true, next];
|
|
53
|
-
}).pipe(Effect.flatMap((registered) => registered ? Effect.void : Effect.fail(DuplicateToolName.make({ name: tool.name }))));
|
|
54
|
-
const registerAll = (tools) => Effect.forEach(tools, register, {
|
|
55
|
-
discard: true
|
|
56
|
-
});
|
|
57
|
-
const get = (name) => Effect.flatMap(Ref.get(state), (tools) => {
|
|
58
|
-
const tool = tools.get(name);
|
|
59
|
-
return tool === undefined
|
|
60
|
-
? Effect.fail(ToolError.make({
|
|
61
|
-
toolName: name,
|
|
62
|
-
detail: `Tool not found: ${name}`
|
|
63
|
-
}))
|
|
64
|
-
: Effect.succeed(tool);
|
|
65
|
-
});
|
|
66
|
-
const list = Ref.get(state).pipe(Effect.map((tools) => [...tools.values()].sort((left, right) => left.name.localeCompare(right.name))));
|
|
67
|
-
const select = (prompt, limit = 8) => Effect.map(list, (tools) => tools
|
|
68
|
-
.map((tool) => ({
|
|
69
|
-
tool,
|
|
70
|
-
score: toolScore(tool, promptWords(prompt))
|
|
71
|
-
}))
|
|
72
|
-
.filter(({ score }) => score > 0)
|
|
73
|
-
.sort((left, right) => right.score - left.score || left.tool.name.localeCompare(right.tool.name))
|
|
74
|
-
.slice(0, Math.max(0, limit))
|
|
75
|
-
.map(({ tool }) => tool));
|
|
76
|
-
const validate = Effect.fn("@llm4ts/core/tools/ToolRegistry.validate")(function* (call) {
|
|
77
|
-
const tool = yield* get(call.name);
|
|
78
|
-
const parameters = yield* parseArguments(call);
|
|
79
|
-
yield* validateToolParameters(tool.parameters, parameters).pipe(Effect.mapError((error) => ToolError.make({
|
|
80
|
-
toolName: tool.name,
|
|
81
|
-
detail: error.message
|
|
82
|
-
})));
|
|
83
|
-
return [tool, parameters];
|
|
84
|
-
});
|
|
85
|
-
const execute = Effect.fn("@llm4ts/core/tools/ToolRegistry.execute")(function* (call) {
|
|
86
|
-
const [tool, parameters] = yield* validate(call);
|
|
87
|
-
const grants = yield* currentGrants;
|
|
88
|
-
const missing = tool.requires
|
|
89
|
-
.filter((capability) => !allows(grants, capability))
|
|
90
|
-
.sort((left, right) => capabilityName(left).localeCompare(capabilityName(right)));
|
|
91
|
-
if (missing.length > 0) {
|
|
92
|
-
return ToolResult.make({
|
|
93
|
-
toolCallId: call.id,
|
|
94
|
-
denied: true,
|
|
95
|
-
result: ToolFailed.make({
|
|
96
|
-
message: `Tool '${tool.name}' requires ungranted capabilities: ` +
|
|
97
|
-
missing.map(capabilityName).join(", ")
|
|
98
|
-
})
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
const result = yield* Effect.result(tool.execute(parameters));
|
|
102
|
-
return ToolResult.make({
|
|
103
|
-
toolCallId: call.id,
|
|
104
|
-
result: result._tag === "Success"
|
|
105
|
-
? ToolSucceeded.make({ value: result.success })
|
|
106
|
-
: ToolFailed.make({ message: result.failure.message })
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
const executeAll = (calls, concurrency = 1) => !Number.isInteger(concurrency) || concurrency <= 0
|
|
110
|
-
? Effect.fail(InvalidRequestError.make({
|
|
111
|
-
message: `Tool execution concurrency must be a positive integer; received ${concurrency}`
|
|
112
|
-
}))
|
|
113
|
-
: Effect.forEach(calls, execute, {
|
|
114
|
-
concurrency
|
|
115
|
-
});
|
|
116
|
-
return {
|
|
117
|
-
register,
|
|
118
|
-
registerAll,
|
|
119
|
-
get,
|
|
120
|
-
list,
|
|
121
|
-
select,
|
|
122
|
-
validate,
|
|
123
|
-
execute,
|
|
124
|
-
executeAll
|
|
125
|
-
};
|
|
126
|
-
});
|
|
127
|
-
export const ToolRegistryLive = Layer.effect(ToolRegistry, makeToolRegistry());
|
|
128
|
-
export const toolResultValue = (result) => result.result._tag === "Succeeded"
|
|
129
|
-
? result.result.value
|
|
130
|
-
: {
|
|
131
|
-
error: result.result.message
|
|
132
|
-
};
|
|
133
|
-
//# sourceMappingURL=ToolRegistry.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ToolRegistry.js","sourceRoot":"","sources":["../../src/tools/ToolRegistry.ts"],"names":[],"mappings":"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"}
|
package/src/ContextManagement.ts
DELETED
|
@@ -1,367 +0,0 @@
|
|
|
1
|
-
import * as Crypto from "effect/Crypto"
|
|
2
|
-
import * as DateTime from "effect/DateTime"
|
|
3
|
-
import * as Effect from "effect/Effect"
|
|
4
|
-
import * as Schema from "effect/Schema"
|
|
5
|
-
import { ConversationMessage, type PromptRole } from "./Conversation.ts"
|
|
6
|
-
import type { LlmProvider } from "./Models.ts"
|
|
7
|
-
|
|
8
|
-
export class ContextInvalidInput extends Schema.TaggedError<ContextInvalidInput>()("InvalidInput", {
|
|
9
|
-
message: Schema.String
|
|
10
|
-
}) {}
|
|
11
|
-
|
|
12
|
-
export class ContextParseFailed extends Schema.TaggedError<ContextParseFailed>()("ParseFailed", {
|
|
13
|
-
message: Schema.String
|
|
14
|
-
}) {}
|
|
15
|
-
|
|
16
|
-
export class ContextSummarizationFailed extends Schema.TaggedError<ContextSummarizationFailed>()(
|
|
17
|
-
"SummarizationFailed",
|
|
18
|
-
{
|
|
19
|
-
message: Schema.String
|
|
20
|
-
}
|
|
21
|
-
) {}
|
|
22
|
-
|
|
23
|
-
export class ContextToolLoopFailed extends Schema.TaggedError<ContextToolLoopFailed>()(
|
|
24
|
-
"ToolLoopFailed",
|
|
25
|
-
{
|
|
26
|
-
message: Schema.String
|
|
27
|
-
}
|
|
28
|
-
) {}
|
|
29
|
-
|
|
30
|
-
export const ContextError = Schema.Union([
|
|
31
|
-
ContextInvalidInput,
|
|
32
|
-
ContextParseFailed,
|
|
33
|
-
ContextSummarizationFailed,
|
|
34
|
-
ContextToolLoopFailed
|
|
35
|
-
])
|
|
36
|
-
export type ContextError = typeof ContextError.Type
|
|
37
|
-
|
|
38
|
-
export class ContextLimits extends Schema.Class<ContextLimits>("ContextLimits")({
|
|
39
|
-
maxTokens: Schema.Int,
|
|
40
|
-
warningThresholdPct: Schema.Number.pipe(Schema.withConstructorDefault(Effect.succeed(0.85)))
|
|
41
|
-
}) {}
|
|
42
|
-
|
|
43
|
-
export class ContextWindow extends Schema.Class<ContextWindow>("ContextWindow")({
|
|
44
|
-
messages: Schema.Array(ConversationMessage),
|
|
45
|
-
totalTokens: Schema.Int,
|
|
46
|
-
approachingLimit: Schema.Boolean,
|
|
47
|
-
trimmed: Schema.Boolean
|
|
48
|
-
}) {}
|
|
49
|
-
|
|
50
|
-
export class DropOldestFifo extends Schema.TaggedClass<DropOldestFifo>()("DropOldestFifo", {}) {}
|
|
51
|
-
|
|
52
|
-
export class SlidingWindow extends Schema.TaggedClass<SlidingWindow>()("SlidingWindow", {}) {}
|
|
53
|
-
|
|
54
|
-
export class PriorityBased extends Schema.TaggedClass<PriorityBased>()("PriorityBased", {}) {}
|
|
55
|
-
|
|
56
|
-
export class SummarizeOldMessages extends Schema.TaggedClass<SummarizeOldMessages>()(
|
|
57
|
-
"SummarizeOldMessages",
|
|
58
|
-
{
|
|
59
|
-
summaryTargetTokens: Schema.Int.pipe(Schema.withConstructorDefault(Effect.succeed(256)))
|
|
60
|
-
}
|
|
61
|
-
) {}
|
|
62
|
-
|
|
63
|
-
export const ContextTrimmingStrategy = Schema.Union([
|
|
64
|
-
DropOldestFifo,
|
|
65
|
-
SlidingWindow,
|
|
66
|
-
PriorityBased,
|
|
67
|
-
SummarizeOldMessages
|
|
68
|
-
])
|
|
69
|
-
export type ContextTrimmingStrategy = typeof ContextTrimmingStrategy.Type
|
|
70
|
-
|
|
71
|
-
export const ContextTrimmingStrategies = Object.freeze({
|
|
72
|
-
DropOldestFifo: DropOldestFifo.make({}),
|
|
73
|
-
SlidingWindow: SlidingWindow.make({}),
|
|
74
|
-
PriorityBased: PriorityBased.make({}),
|
|
75
|
-
SummarizeOldMessages: (summaryTargetTokens = 256): SummarizeOldMessages =>
|
|
76
|
-
SummarizeOldMessages.make({ summaryTargetTokens })
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
export interface TokenCounter {
|
|
80
|
-
readonly countText: (provider: LlmProvider, text: string) => number
|
|
81
|
-
readonly countMessage: (provider: LlmProvider, message: ConversationMessage) => number
|
|
82
|
-
readonly countMessages: (provider: LlmProvider, messages: Iterable<ConversationMessage>) => number
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const roleOverhead = (role: PromptRole): number => {
|
|
86
|
-
switch (role) {
|
|
87
|
-
case "System":
|
|
88
|
-
return 6
|
|
89
|
-
case "User":
|
|
90
|
-
case "Assistant":
|
|
91
|
-
return 5
|
|
92
|
-
case "Tool":
|
|
93
|
-
return 8
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const providerCharactersPerToken = (provider: LlmProvider): number => {
|
|
98
|
-
switch (provider) {
|
|
99
|
-
case "OpenAI":
|
|
100
|
-
case "OpenCode":
|
|
101
|
-
return 4
|
|
102
|
-
case "Anthropic":
|
|
103
|
-
return 3.8
|
|
104
|
-
case "GeminiApi":
|
|
105
|
-
case "GeminiCli":
|
|
106
|
-
return 4.2
|
|
107
|
-
case "LmStudio":
|
|
108
|
-
case "Ollama":
|
|
109
|
-
case "MlxLm":
|
|
110
|
-
case "Mock":
|
|
111
|
-
return 4.5
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const countText = (provider: LlmProvider, text: string): number =>
|
|
116
|
-
Math.max(1, Math.ceil(Math.max(text.length, 1) / providerCharactersPerToken(provider)))
|
|
117
|
-
|
|
118
|
-
const countMessage = (provider: LlmProvider, message: ConversationMessage): number =>
|
|
119
|
-
countText(provider, message.content) + roleOverhead(message.role)
|
|
120
|
-
|
|
121
|
-
export const defaultTokenCounter: TokenCounter = {
|
|
122
|
-
countText,
|
|
123
|
-
countMessage,
|
|
124
|
-
countMessages: (provider, messages) =>
|
|
125
|
-
Array.from(messages).reduce((total, message) => total + countMessage(provider, message), 0)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export interface MessageSummarizer<R = never> {
|
|
129
|
-
readonly summarize: (
|
|
130
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
131
|
-
targetTokens: number
|
|
132
|
-
) => Effect.Effect<ConversationMessage, ContextError, R>
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export const simpleMessageSummarizer: MessageSummarizer<Crypto.Crypto> = {
|
|
136
|
-
summarize: (messages, targetTokens) => {
|
|
137
|
-
if (messages.length === 0) {
|
|
138
|
-
return Effect.fail(
|
|
139
|
-
ContextInvalidInput.make({
|
|
140
|
-
message: "Cannot summarize empty messages"
|
|
141
|
-
})
|
|
142
|
-
)
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const summaryText = messages
|
|
146
|
-
.slice(0, 8)
|
|
147
|
-
.map((message) => `${message.role.toLowerCase()}: ${message.content.slice(0, 160)}`)
|
|
148
|
-
.join("\n")
|
|
149
|
-
|
|
150
|
-
return Effect.gen(function* () {
|
|
151
|
-
const crypto = yield* Crypto.Crypto
|
|
152
|
-
const id = yield* crypto.randomUUIDv4.pipe(
|
|
153
|
-
Effect.mapError((error) =>
|
|
154
|
-
ContextSummarizationFailed.make({
|
|
155
|
-
message: `Failed to generate summary id: ${error.message}`
|
|
156
|
-
})
|
|
157
|
-
)
|
|
158
|
-
)
|
|
159
|
-
const timestamp = yield* DateTime.now
|
|
160
|
-
|
|
161
|
-
return ConversationMessage.make({
|
|
162
|
-
id,
|
|
163
|
-
role: "Assistant",
|
|
164
|
-
content: `Summary of previous context:\n${summaryText}`,
|
|
165
|
-
timestamp,
|
|
166
|
-
tokens: Math.max(1, targetTokens),
|
|
167
|
-
metadata: { summary: "true" },
|
|
168
|
-
important: true
|
|
169
|
-
})
|
|
170
|
-
})
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const annotateTokens = (
|
|
175
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
176
|
-
provider: LlmProvider,
|
|
177
|
-
tokenCounter: TokenCounter
|
|
178
|
-
): ReadonlyArray<ConversationMessage> =>
|
|
179
|
-
messages.map((message) =>
|
|
180
|
-
message.tokens > 0
|
|
181
|
-
? message
|
|
182
|
-
: ConversationMessage.make({
|
|
183
|
-
...message,
|
|
184
|
-
tokens: tokenCounter.countMessage(provider, message)
|
|
185
|
-
})
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
const dropOldest = (
|
|
189
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
190
|
-
maxTokens: number
|
|
191
|
-
): ReadonlyArray<ConversationMessage> => {
|
|
192
|
-
let used = 0
|
|
193
|
-
let kept: ReadonlyArray<ConversationMessage> = []
|
|
194
|
-
|
|
195
|
-
for (const message of Array.from(messages).reverse()) {
|
|
196
|
-
if (used + message.tokens <= maxTokens) {
|
|
197
|
-
used += message.tokens
|
|
198
|
-
kept = [message, ...kept]
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
return kept
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const slidingWindow = (
|
|
206
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
207
|
-
maxTokens: number
|
|
208
|
-
): ReadonlyArray<ConversationMessage> => {
|
|
209
|
-
const system = messages.filter((message) => message.role === "System")
|
|
210
|
-
const recentNonSystem = messages.filter((message) => message.role !== "System")
|
|
211
|
-
const systemTokens = system.reduce((total, message) => total + message.tokens, 0)
|
|
212
|
-
const tail = dropOldest(recentNonSystem, Math.max(0, maxTokens - systemTokens))
|
|
213
|
-
return [...system, ...tail].slice(-messages.length)
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
const priorityWindow = (
|
|
217
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
218
|
-
maxTokens: number
|
|
219
|
-
): ReadonlyArray<ConversationMessage> => {
|
|
220
|
-
const scored = messages.map((message, index) => ({
|
|
221
|
-
message,
|
|
222
|
-
score:
|
|
223
|
-
(message.role === "System" ? 1_000 : 0) +
|
|
224
|
-
(message.role === "Tool" ? 600 : 0) +
|
|
225
|
-
(message.important ? 400 : 0) +
|
|
226
|
-
index
|
|
227
|
-
}))
|
|
228
|
-
scored.sort(
|
|
229
|
-
(left, right) =>
|
|
230
|
-
right.score - left.score ||
|
|
231
|
-
DateTime.toEpochMillis(left.message.timestamp) -
|
|
232
|
-
DateTime.toEpochMillis(right.message.timestamp)
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
let used = 0
|
|
236
|
-
const selected: Array<ConversationMessage> = []
|
|
237
|
-
for (const candidate of scored) {
|
|
238
|
-
if (used + candidate.message.tokens <= maxTokens) {
|
|
239
|
-
used += candidate.message.tokens
|
|
240
|
-
selected.push(candidate.message)
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
return selected.sort(
|
|
245
|
-
(left, right) =>
|
|
246
|
-
DateTime.toEpochMillis(left.timestamp) - DateTime.toEpochMillis(right.timestamp)
|
|
247
|
-
)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const summarizeOldMessages = <R>(
|
|
251
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
252
|
-
maxTokens: number,
|
|
253
|
-
summaryTargetTokens: number,
|
|
254
|
-
provider: LlmProvider,
|
|
255
|
-
tokenCounter: TokenCounter,
|
|
256
|
-
summarizer: MessageSummarizer<R>
|
|
257
|
-
): Effect.Effect<ReadonlyArray<ConversationMessage>, ContextError, R> => {
|
|
258
|
-
if (messages.length <= 2) {
|
|
259
|
-
return Effect.succeed(dropOldest(messages, maxTokens))
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const splitIndex = Math.max(1, Math.floor(messages.length / 2))
|
|
263
|
-
const oldMessages = messages.slice(0, splitIndex)
|
|
264
|
-
const recentMessages = messages.slice(splitIndex)
|
|
265
|
-
|
|
266
|
-
return Effect.map(summarizer.summarize(oldMessages, summaryTargetTokens), (summary) => {
|
|
267
|
-
const annotatedSummary = ConversationMessage.make({
|
|
268
|
-
...summary,
|
|
269
|
-
tokens: tokenCounter.countMessage(provider, summary)
|
|
270
|
-
})
|
|
271
|
-
return dropOldest([annotatedSummary, ...recentMessages], maxTokens)
|
|
272
|
-
})
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
export function applyContextWindow(
|
|
276
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
277
|
-
provider: LlmProvider,
|
|
278
|
-
limits: ContextLimits,
|
|
279
|
-
strategy: DropOldestFifo | SlidingWindow | PriorityBased,
|
|
280
|
-
tokenCounter?: TokenCounter
|
|
281
|
-
): Effect.Effect<ContextWindow, ContextError>
|
|
282
|
-
export function applyContextWindow(
|
|
283
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
284
|
-
provider: LlmProvider,
|
|
285
|
-
limits: ContextLimits,
|
|
286
|
-
strategy: ContextTrimmingStrategy,
|
|
287
|
-
tokenCounter?: TokenCounter
|
|
288
|
-
): Effect.Effect<ContextWindow, ContextError, Crypto.Crypto>
|
|
289
|
-
export function applyContextWindow<R>(
|
|
290
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
291
|
-
provider: LlmProvider,
|
|
292
|
-
limits: ContextLimits,
|
|
293
|
-
strategy: ContextTrimmingStrategy,
|
|
294
|
-
tokenCounter: TokenCounter,
|
|
295
|
-
summarizer: MessageSummarizer<R>
|
|
296
|
-
): Effect.Effect<ContextWindow, ContextError, R>
|
|
297
|
-
export function applyContextWindow<R>(
|
|
298
|
-
messages: ReadonlyArray<ConversationMessage>,
|
|
299
|
-
provider: LlmProvider,
|
|
300
|
-
limits: ContextLimits,
|
|
301
|
-
strategy: ContextTrimmingStrategy,
|
|
302
|
-
tokenCounter: TokenCounter = defaultTokenCounter,
|
|
303
|
-
summarizer?: MessageSummarizer<R>
|
|
304
|
-
): Effect.Effect<ContextWindow, ContextError, R | Crypto.Crypto> {
|
|
305
|
-
if (limits.maxTokens <= 0) {
|
|
306
|
-
return Effect.fail(
|
|
307
|
-
ContextInvalidInput.make({
|
|
308
|
-
message: "maxTokens must be > 0"
|
|
309
|
-
})
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const withTokens = annotateTokens(messages, provider, tokenCounter)
|
|
314
|
-
const totalBefore = withTokens.reduce((total, message) => total + message.tokens, 0)
|
|
315
|
-
|
|
316
|
-
const trimmed: Effect.Effect<
|
|
317
|
-
readonly [messages: ReadonlyArray<ConversationMessage>, wasTrimmed: boolean],
|
|
318
|
-
ContextError,
|
|
319
|
-
R | Crypto.Crypto
|
|
320
|
-
> =
|
|
321
|
-
totalBefore <= limits.maxTokens
|
|
322
|
-
? Effect.succeed([withTokens, false])
|
|
323
|
-
: (() => {
|
|
324
|
-
switch (strategy._tag) {
|
|
325
|
-
case "DropOldestFifo":
|
|
326
|
-
return Effect.succeed([dropOldest(withTokens, limits.maxTokens), true])
|
|
327
|
-
case "SlidingWindow":
|
|
328
|
-
return Effect.succeed([slidingWindow(withTokens, limits.maxTokens), true])
|
|
329
|
-
case "PriorityBased":
|
|
330
|
-
return Effect.succeed([priorityWindow(withTokens, limits.maxTokens), true])
|
|
331
|
-
case "SummarizeOldMessages": {
|
|
332
|
-
const summarized: Effect.Effect<
|
|
333
|
-
ReadonlyArray<ConversationMessage>,
|
|
334
|
-
ContextError,
|
|
335
|
-
R | Crypto.Crypto
|
|
336
|
-
> = summarizer === undefined
|
|
337
|
-
? summarizeOldMessages(
|
|
338
|
-
withTokens,
|
|
339
|
-
limits.maxTokens,
|
|
340
|
-
strategy.summaryTargetTokens,
|
|
341
|
-
provider,
|
|
342
|
-
tokenCounter,
|
|
343
|
-
simpleMessageSummarizer
|
|
344
|
-
)
|
|
345
|
-
: summarizeOldMessages(
|
|
346
|
-
withTokens,
|
|
347
|
-
limits.maxTokens,
|
|
348
|
-
strategy.summaryTargetTokens,
|
|
349
|
-
provider,
|
|
350
|
-
tokenCounter,
|
|
351
|
-
summarizer
|
|
352
|
-
)
|
|
353
|
-
return Effect.map(summarized, (messages) => [messages, true])
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
})()
|
|
357
|
-
|
|
358
|
-
return Effect.map(trimmed, ([finalMessages, wasTrimmed]) => {
|
|
359
|
-
const totalTokens = finalMessages.reduce((total, message) => total + message.tokens, 0)
|
|
360
|
-
return ContextWindow.make({
|
|
361
|
-
messages: finalMessages,
|
|
362
|
-
totalTokens,
|
|
363
|
-
approachingLimit: totalTokens >= limits.maxTokens * limits.warningThresholdPct,
|
|
364
|
-
trimmed: wasTrimmed
|
|
365
|
-
})
|
|
366
|
-
})
|
|
367
|
-
}
|
package/src/Conversation.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import * as Effect from "effect/Effect"
|
|
2
|
-
import * as Schema from "effect/Schema"
|
|
3
|
-
|
|
4
|
-
export const PromptRole = Schema.Literals(["System", "User", "Assistant", "Tool"])
|
|
5
|
-
export type PromptRole = typeof PromptRole.Type
|
|
6
|
-
|
|
7
|
-
const emptyMetadata: Readonly<Record<string, string>> = Object.freeze({})
|
|
8
|
-
|
|
9
|
-
export class ConversationMessage extends Schema.Class<ConversationMessage>("ConversationMessage")({
|
|
10
|
-
id: Schema.String,
|
|
11
|
-
role: PromptRole,
|
|
12
|
-
content: Schema.String,
|
|
13
|
-
timestamp: Schema.DateTimeUtc,
|
|
14
|
-
tokens: Schema.Int.pipe(Schema.withConstructorDefault(Effect.succeed(0))),
|
|
15
|
-
model: Schema.optionalKey(Schema.String),
|
|
16
|
-
costUsd: Schema.optionalKey(Schema.Number),
|
|
17
|
-
metadata: Schema.Record(Schema.String, Schema.String).pipe(
|
|
18
|
-
Schema.withConstructorDefault(Effect.succeed(emptyMetadata))
|
|
19
|
-
),
|
|
20
|
-
important: Schema.Boolean.pipe(Schema.withConstructorDefault(Effect.succeed(false)))
|
|
21
|
-
}) {}
|